170 lines
4.5 KiB
Python
170 lines
4.5 KiB
Python
"""Integration tests for var operations."""
|
|
|
|
import time
|
|
from typing import Callable, Generator, TypeVar
|
|
|
|
import pytest
|
|
from selenium.webdriver.common.by import By
|
|
|
|
from reflex.testing import AppHarness
|
|
|
|
# pyright: reportOptionalMemberAccess=false, reportGeneralTypeIssues=false, reportUnknownMemberType=false
|
|
|
|
|
|
def DynamicComponents():
|
|
"""App with var operations."""
|
|
import reflex as rx
|
|
|
|
class DynamicComponentsState(rx.State):
|
|
value: int = 10
|
|
|
|
button: rx.Component = rx.button(
|
|
"Click me",
|
|
custom_attrs={
|
|
"id": "button",
|
|
},
|
|
)
|
|
|
|
def got_clicked(self):
|
|
self.button = rx.button(
|
|
"Clicked",
|
|
custom_attrs={
|
|
"id": "button",
|
|
},
|
|
)
|
|
|
|
@rx.var
|
|
def client_token_component(self) -> rx.Component:
|
|
return rx.vstack(
|
|
rx.el.input(
|
|
custom_attrs={
|
|
"id": "token",
|
|
},
|
|
value=self.router.session.client_token,
|
|
is_read_only=True,
|
|
),
|
|
rx.button(
|
|
"Update",
|
|
custom_attrs={
|
|
"id": "update",
|
|
},
|
|
on_click=DynamicComponentsState.got_clicked,
|
|
),
|
|
)
|
|
|
|
app = rx.App()
|
|
|
|
def factorial(n: int) -> int:
|
|
if n == 0:
|
|
return 1
|
|
return n * factorial(n - 1)
|
|
|
|
@app.add_page
|
|
def index():
|
|
return rx.vstack(
|
|
DynamicComponentsState.client_token_component,
|
|
DynamicComponentsState.button,
|
|
rx.text(
|
|
DynamicComponentsState._evaluate(
|
|
lambda state: factorial(state.value), of_type=int
|
|
),
|
|
id="factorial",
|
|
),
|
|
)
|
|
|
|
|
|
@pytest.fixture(scope="module")
|
|
def dynamic_components(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
|
"""Start VarOperations app at tmp_path via AppHarness.
|
|
|
|
Args:
|
|
tmp_path_factory: pytest tmp_path_factory fixture
|
|
|
|
Yields:
|
|
running AppHarness instance
|
|
"""
|
|
with AppHarness.create(
|
|
root=tmp_path_factory.mktemp("dynamic_components"),
|
|
app_source=DynamicComponents,
|
|
) as harness:
|
|
assert harness.app_instance is not None, "app is not running"
|
|
yield harness
|
|
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
def poll_for_result(
|
|
f: Callable[[], T], exception=Exception, max_attempts=5, seconds_between_attempts=1
|
|
) -> T:
|
|
"""Poll for a result from a function.
|
|
|
|
Args:
|
|
f: function to call
|
|
exception: exception to catch
|
|
max_attempts: maximum number of attempts
|
|
seconds_between_attempts: seconds to wait between
|
|
|
|
Returns:
|
|
Result of the function
|
|
|
|
Raises:
|
|
AssertionError: if the function does not return a value
|
|
"""
|
|
attempts = 0
|
|
while attempts < max_attempts:
|
|
try:
|
|
return f()
|
|
except exception:
|
|
attempts += 1
|
|
time.sleep(seconds_between_attempts)
|
|
raise AssertionError("Function did not return a value")
|
|
|
|
|
|
@pytest.fixture
|
|
def driver(dynamic_components: AppHarness):
|
|
"""Get an instance of the browser open to the dynamic components app.
|
|
|
|
Args:
|
|
dynamic_components: AppHarness for the dynamic components
|
|
|
|
Yields:
|
|
WebDriver instance.
|
|
"""
|
|
driver = dynamic_components.frontend()
|
|
try:
|
|
token_input = poll_for_result(lambda: driver.find_element(By.ID, "token"))
|
|
assert token_input
|
|
# wait for the backend connection to send the token
|
|
token = dynamic_components.poll_for_value(token_input)
|
|
assert token is not None
|
|
|
|
yield driver
|
|
finally:
|
|
driver.quit()
|
|
|
|
|
|
def test_dynamic_components(driver, dynamic_components: AppHarness):
|
|
"""Test that the var operations produce the right results.
|
|
|
|
Args:
|
|
driver: selenium WebDriver open to the app
|
|
dynamic_components: AppHarness for the dynamic components
|
|
"""
|
|
button = poll_for_result(lambda: driver.find_element(By.ID, "button"))
|
|
assert button
|
|
assert button.text == "Click me"
|
|
|
|
update_button = driver.find_element(By.ID, "update")
|
|
assert update_button
|
|
update_button.click()
|
|
|
|
assert (
|
|
dynamic_components.poll_for_content(button, exp_not_equal="Click me")
|
|
== "Clicked"
|
|
)
|
|
|
|
factorial = poll_for_result(lambda: driver.find_element(By.ID, "factorial"))
|
|
assert factorial
|
|
assert factorial.text == "3628800"
|