|
@@ -0,0 +1,136 @@
|
|
|
+"""Integration tests for forms."""
|
|
|
+import time
|
|
|
+from typing import Generator
|
|
|
+
|
|
|
+import pytest
|
|
|
+from selenium.webdriver.common.by import By
|
|
|
+from selenium.webdriver.common.keys import Keys
|
|
|
+
|
|
|
+from reflex.testing import AppHarness
|
|
|
+
|
|
|
+
|
|
|
+def FormSubmit():
|
|
|
+ """App with a form using on_submit."""
|
|
|
+ import reflex as rx
|
|
|
+
|
|
|
+ class FormState(rx.State):
|
|
|
+ form_data: dict = {}
|
|
|
+
|
|
|
+ def form_submit(self, form_data: dict):
|
|
|
+ self.form_data = form_data
|
|
|
+
|
|
|
+ app = rx.App(state=FormState)
|
|
|
+
|
|
|
+ @app.add_page
|
|
|
+ def index():
|
|
|
+ return rx.vstack(
|
|
|
+ rx.form(
|
|
|
+ rx.vstack(
|
|
|
+ rx.input(id="name_input"),
|
|
|
+ rx.hstack(rx.pin_input(length=4, id="pin_input")),
|
|
|
+ rx.number_input(id="number_input"),
|
|
|
+ rx.checkbox(id="bool_input"),
|
|
|
+ rx.switch(id="bool_input2"),
|
|
|
+ rx.slider(id="slider_input"),
|
|
|
+ rx.range_slider(id="range_input"),
|
|
|
+ rx.radio_group(["option1", "option2"], id="radio_input"),
|
|
|
+ rx.select(["option1", "option2"], id="select_input"),
|
|
|
+ rx.text_area(id="text_area_input"),
|
|
|
+ rx.button("Submit", type_="submit"),
|
|
|
+ ),
|
|
|
+ on_submit=FormState.form_submit,
|
|
|
+ ),
|
|
|
+ rx.spacer(),
|
|
|
+ height="100vh",
|
|
|
+ )
|
|
|
+
|
|
|
+ app.compile()
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture(scope="session")
|
|
|
+def form_submit(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
|
|
+ """Start FormSubmit 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("form_submit"),
|
|
|
+ app_source=FormSubmit, # type: ignore
|
|
|
+ ) as harness:
|
|
|
+ assert harness.app_instance is not None, "app is not running"
|
|
|
+ yield harness
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture
|
|
|
+def driver(form_submit: AppHarness):
|
|
|
+ """GEt an instance of the browser open to the form_submit app.
|
|
|
+
|
|
|
+ Args:
|
|
|
+ form_submit: harness for ServerSideEvent app
|
|
|
+
|
|
|
+ Yields:
|
|
|
+ WebDriver instance.
|
|
|
+ """
|
|
|
+ driver = form_submit.frontend()
|
|
|
+ try:
|
|
|
+ assert form_submit.poll_for_clients()
|
|
|
+ yield driver
|
|
|
+ finally:
|
|
|
+ driver.quit()
|
|
|
+
|
|
|
+
|
|
|
+def test_submit(driver, form_submit: AppHarness):
|
|
|
+ """Fill a form with various different output, submit it to backend and verify
|
|
|
+ the output.
|
|
|
+
|
|
|
+ Args:
|
|
|
+ driver: selenium WebDriver open to the app
|
|
|
+ form_submit: harness for FormSubmit app
|
|
|
+ """
|
|
|
+ assert form_submit.app_instance is not None, "app is not running"
|
|
|
+ _, backend_state = list(form_submit.app_instance.state_manager.states.items())[0]
|
|
|
+
|
|
|
+ name_input = driver.find_element(By.ID, "name_input")
|
|
|
+ name_input.send_keys("foo")
|
|
|
+
|
|
|
+ pin_inputs = driver.find_elements(By.CLASS_NAME, "chakra-pin-input")
|
|
|
+ pin_values = ["8", "1", "6", "4"]
|
|
|
+ for i, pin_input in enumerate(pin_inputs):
|
|
|
+ pin_input.send_keys(pin_values[i])
|
|
|
+
|
|
|
+ number_input = driver.find_element(By.CLASS_NAME, "chakra-numberinput")
|
|
|
+ buttons = number_input.find_elements(By.XPATH, "//div[@role='button']")
|
|
|
+ for _ in range(3):
|
|
|
+ buttons[1].click()
|
|
|
+
|
|
|
+ checkbox_input = driver.find_element(By.CLASS_NAME, "chakra-checkbox__control")
|
|
|
+ checkbox_input.click()
|
|
|
+
|
|
|
+ switch_input = driver.find_element(By.CLASS_NAME, "chakra-switch__track")
|
|
|
+ switch_input.click()
|
|
|
+
|
|
|
+ radio_buttons = driver.find_elements(By.CLASS_NAME, "chakra-radio__control")
|
|
|
+ radio_buttons[1].click()
|
|
|
+
|
|
|
+ textarea_input = driver.find_element(By.CLASS_NAME, "chakra-textarea")
|
|
|
+ textarea_input.send_keys("Some", Keys.ENTER, "Text")
|
|
|
+
|
|
|
+ time.sleep(1)
|
|
|
+
|
|
|
+ submit_input = driver.find_element(By.CLASS_NAME, "chakra-button")
|
|
|
+ submit_input.click()
|
|
|
+
|
|
|
+ assert backend_state.form_data["name_input"] == "foo"
|
|
|
+ assert backend_state.form_data["pin_input"] == pin_values
|
|
|
+ assert backend_state.form_data["number_input"] == "-3"
|
|
|
+ assert backend_state.form_data["bool_input"] is True
|
|
|
+ assert backend_state.form_data["bool_input2"] is True
|
|
|
+ assert backend_state.form_data["slider_input"] == "50"
|
|
|
+ assert backend_state.form_data["range_input"] == ["25", "75"]
|
|
|
+ assert backend_state.form_data["radio_input"] == "option2"
|
|
|
+ assert backend_state.form_data["select_input"] == "option1"
|
|
|
+ assert backend_state.form_data["text_area_input"] == "Some\nText"
|