reflex/tests/integration/test_minified_states.py
2024-11-05 12:53:16 -08:00

174 lines
4.7 KiB
Python

"""Integration tests for minified state names."""
from __future__ import annotations
import os
from functools import partial
from typing import Generator, Optional, Type
import pytest
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webdriver import WebDriver
from reflex.constants.compiler import ENV_MINIFY_STATES
from reflex.testing import AppHarness, AppHarnessProd
def TestApp(minify: bool | None) -> None:
"""A test app for minified state names.
Args:
minify: whether to minify state names
"""
import reflex as rx
class TestAppState(rx.State):
"""State for the TestApp app."""
pass
app = rx.App()
def index():
return rx.vstack(
rx.input(
value=TestAppState.router.session.client_token,
is_read_only=True,
id="token",
),
rx.text(f"minify: {minify}", id="minify"),
rx.text(TestAppState.get_name(), id="state_name"),
rx.text(TestAppState.get_full_name(), id="state_full_name"),
)
app.add_page(index)
@pytest.fixture(
params=[
pytest.param(False),
pytest.param(True),
pytest.param(None),
],
)
def minify_state_env(
request: pytest.FixtureRequest,
) -> Generator[Optional[bool], None, None]:
"""Set the environment variable to minify state names.
Args:
request: pytest fixture request
Yields:
minify_states: whether to minify state names
"""
minify_states: Optional[bool] = request.param
if minify_states is None:
_ = os.environ.pop(ENV_MINIFY_STATES, None)
else:
os.environ[ENV_MINIFY_STATES] = str(minify_states).lower()
yield minify_states
if minify_states is not None:
os.environ.pop(ENV_MINIFY_STATES, None)
@pytest.fixture
def test_app(
app_harness_env: Type[AppHarness],
tmp_path_factory: pytest.TempPathFactory,
minify_state_env: Optional[bool],
) -> Generator[AppHarness, None, None]:
"""Start TestApp app at tmp_path via AppHarness.
Args:
app_harness_env: either AppHarness (dev) or AppHarnessProd (prod)
tmp_path_factory: pytest tmp_path_factory fixture
minify_state_env: need to request this fixture to set env before the app starts
Yields:
running AppHarness instance
"""
name = f"testapp_{app_harness_env.__name__.lower()}"
with app_harness_env.create(
root=tmp_path_factory.mktemp(name),
app_name=name,
app_source=partial(TestApp, minify=minify_state_env), # pyright: ignore[reportArgumentType]
) as harness:
yield harness
@pytest.fixture
def driver(test_app: AppHarness) -> Generator[WebDriver, None, None]:
"""Get an instance of the browser open to the test_app app.
Args:
test_app: harness for TestApp app
Yields:
WebDriver instance.
"""
assert test_app.app_instance is not None, "app is not running"
driver = test_app.frontend()
try:
yield driver
finally:
driver.quit()
def test_minified_states(
test_app: AppHarness,
driver: WebDriver,
minify_state_env: Optional[bool],
) -> None:
"""Test minified state names.
Args:
test_app: harness for TestApp
driver: WebDriver instance.
minify_state_env: whether state minification is enabled by env var.
"""
assert test_app.app_instance is not None, "app is not running"
is_prod = isinstance(test_app, AppHarnessProd)
# default to minifying in production
should_minify: bool = is_prod
# env overrides default
if minify_state_env is not None:
should_minify = minify_state_env
# TODO: reload internal states, or refactor VarData to reference state object instead of name
if should_minify:
pytest.skip(
"minify tests are currently not working, because _var_set_states writes the state names during import time"
)
# get a reference to the connected client
token_input = driver.find_element(By.ID, "token")
assert token_input
# wait for the backend connection to send the token
token = test_app.poll_for_value(token_input)
assert token
state_name_text = driver.find_element(By.ID, "state_name")
assert state_name_text
state_name = state_name_text.text
state_full_name_text = driver.find_element(By.ID, "state_full_name")
assert state_full_name_text
_ = state_full_name_text.text
assert test_app.app_module
module_state_prefix = test_app.app_module.__name__.replace(".", "___")
# prod_module_suffix = "prod" if is_prod else ""
if should_minify:
assert len(state_name) == 1
else:
assert state_name == f"{module_state_prefix}____test_app_state"