Always treat the call_script callback as a string of JS code (#3521)

This commit is contained in:
Masen Furer 2024-06-20 18:05:25 -07:00 committed by GitHub
parent 958c4fa7f2
commit c2c6286537
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 36 additions and 26 deletions

View File

@ -10,6 +10,8 @@ from selenium.webdriver.remote.webdriver import WebDriver
from reflex.testing import AppHarness from reflex.testing import AppHarness
from .utils import SessionStorage
def CallScript(): def CallScript():
"""A test app for browser javascript integration.""" """A test app for browser javascript integration."""
@ -43,6 +45,7 @@ def CallScript():
results: List[Optional[Union[str, Dict, List]]] = [] results: List[Optional[Union[str, Dict, List]]] = []
inline_counter: int = 0 inline_counter: int = 0
external_counter: int = 0 external_counter: int = 0
value: str = "Initial"
def call_script_callback(self, result): def call_script_callback(self, result):
self.results.append(result) self.results.append(result)
@ -145,25 +148,20 @@ def CallScript():
@app.add_page @app.add_page
def index(): def index():
return rx.vstack( return rx.vstack(
rx.chakra.input( rx.input(
value=CallScriptState.router.session.client_token,
is_read_only=True,
id="token",
),
rx.chakra.input(
value=CallScriptState.inline_counter.to(str), # type: ignore value=CallScriptState.inline_counter.to(str), # type: ignore
id="inline_counter", id="inline_counter",
is_read_only=True, read_only=True,
), ),
rx.chakra.input( rx.input(
value=CallScriptState.external_counter.to(str), # type: ignore value=CallScriptState.external_counter.to(str), # type: ignore
id="external_counter", id="external_counter",
is_read_only=True, read_only=True,
), ),
rx.text_area( rx.text_area(
value=CallScriptState.results.to_string(), # type: ignore value=CallScriptState.results.to_string(), # type: ignore
id="results", id="results",
is_read_only=True, read_only=True,
), ),
rx.script(inline_scripts), rx.script(inline_scripts),
rx.script(src="/external.js"), rx.script(src="/external.js"),
@ -227,6 +225,14 @@ def CallScript():
on_click=CallScriptState.get_external_counter, on_click=CallScriptState.get_external_counter,
id="update_external_counter", id="update_external_counter",
), ),
rx.button(
CallScriptState.value,
on_click=rx.call_script(
"'updated'",
callback=CallScriptState.set_value, # type: ignore
),
id="update_value",
),
rx.button("Reset", id="reset", on_click=CallScriptState.reset_), rx.button("Reset", id="reset", on_click=CallScriptState.reset_),
) )
@ -266,25 +272,18 @@ def driver(call_script: AppHarness) -> Generator[WebDriver, None, None]:
driver.quit() driver.quit()
def assert_token(call_script: AppHarness, driver: WebDriver) -> str: def assert_token(driver: WebDriver) -> str:
"""Get the token associated with backend state. """Get the token associated with backend state.
Args: Args:
call_script: harness for CallScript app.
driver: WebDriver instance. driver: WebDriver instance.
Returns: Returns:
The token visible in the driver browser. The token visible in the driver browser.
""" """
assert call_script.app_instance is not None ss = SessionStorage(driver)
token_input = driver.find_element(By.ID, "token") assert AppHarness._poll_for(lambda: ss.get("token") is not None), "token not found"
assert token_input return ss.get("token")
# wait for the backend connection to send the token
token = call_script.poll_for_value(token_input)
assert token is not None
return token
@pytest.mark.parametrize("script", ["inline", "external"]) @pytest.mark.parametrize("script", ["inline", "external"])
@ -300,7 +299,7 @@ def test_call_script(
driver: WebDriver instance. driver: WebDriver instance.
script: The type of script to test. script: The type of script to test.
""" """
assert_token(call_script, driver) assert_token(driver)
reset_button = driver.find_element(By.ID, "reset") reset_button = driver.find_element(By.ID, "reset")
update_counter_button = driver.find_element(By.ID, f"update_{script}_counter") update_counter_button = driver.find_element(By.ID, f"update_{script}_counter")
counter = driver.find_element(By.ID, f"{script}_counter") counter = driver.find_element(By.ID, f"{script}_counter")
@ -355,3 +354,12 @@ def test_call_script(
) )
reset_button.click() reset_button.click()
assert call_script.poll_for_value(counter, exp_not_equal="1") == "0" assert call_script.poll_for_value(counter, exp_not_equal="1") == "0"
# Check that triggering script from event trigger calls callback
update_value_button = driver.find_element(By.ID, "update_value")
update_value_button.click()
assert (
call_script.poll_for_content(update_value_button, exp_not_equal="Initial")
== "updated"
)

View File

@ -766,10 +766,12 @@ def call_script(
callback_kwargs = {} callback_kwargs = {}
if callback is not None: if callback is not None:
callback_kwargs = { callback_kwargs = {
"callback": format.format_queue_events( "callback": str(
callback, format.format_queue_events(
args_spec=lambda result: [result], callback,
) args_spec=lambda result: [result],
),
),
} }
return server_side( return server_side(
"_call_script", "_call_script",