|
@@ -0,0 +1,218 @@
|
|
|
+from typing import Generator
|
|
|
+
|
|
|
+import pytest
|
|
|
+from playwright.sync_api import Page, expect
|
|
|
+
|
|
|
+from reflex.testing import AppHarness
|
|
|
+
|
|
|
+
|
|
|
+def DefaultLightModeApp():
|
|
|
+ import reflex as rx
|
|
|
+ from reflex.style import color_mode
|
|
|
+
|
|
|
+ app = rx.App(theme=rx.theme(appearance="light"))
|
|
|
+
|
|
|
+ @app.add_page
|
|
|
+ def index():
|
|
|
+ return rx.text(color_mode)
|
|
|
+
|
|
|
+
|
|
|
+def DefaultDarkModeApp():
|
|
|
+ import reflex as rx
|
|
|
+ from reflex.style import color_mode
|
|
|
+
|
|
|
+ app = rx.App(theme=rx.theme(appearance="dark"))
|
|
|
+
|
|
|
+ @app.add_page
|
|
|
+ def index():
|
|
|
+ return rx.text(color_mode)
|
|
|
+
|
|
|
+
|
|
|
+def DefaultSystemModeApp():
|
|
|
+ import reflex as rx
|
|
|
+ from reflex.style import color_mode
|
|
|
+
|
|
|
+ app = rx.App()
|
|
|
+
|
|
|
+ @app.add_page
|
|
|
+ def index():
|
|
|
+ return rx.text(color_mode)
|
|
|
+
|
|
|
+
|
|
|
+def ColorToggleApp():
|
|
|
+ import reflex as rx
|
|
|
+ from reflex.style import color_mode, resolved_color_mode, set_color_mode
|
|
|
+
|
|
|
+ app = rx.App(theme=rx.theme(appearance="light"))
|
|
|
+
|
|
|
+ @app.add_page
|
|
|
+ def index():
|
|
|
+ return rx.box(
|
|
|
+ rx.segmented_control.root(
|
|
|
+ rx.segmented_control.item(
|
|
|
+ rx.icon(tag="monitor", size=20),
|
|
|
+ value="system",
|
|
|
+ ),
|
|
|
+ rx.segmented_control.item(
|
|
|
+ rx.icon(tag="sun", size=20),
|
|
|
+ value="light",
|
|
|
+ ),
|
|
|
+ rx.segmented_control.item(
|
|
|
+ rx.icon(tag="moon", size=20),
|
|
|
+ value="dark",
|
|
|
+ ),
|
|
|
+ on_change=set_color_mode,
|
|
|
+ variant="classic",
|
|
|
+ radius="large",
|
|
|
+ value=color_mode,
|
|
|
+ ),
|
|
|
+ rx.text(color_mode, id="current_color_mode"),
|
|
|
+ rx.text(resolved_color_mode, id="resolved_color_mode"),
|
|
|
+ rx.text(rx.color_mode_cond("LightMode", "DarkMode"), id="color_mode_cond"),
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture()
|
|
|
+def light_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
|
|
+ """Start DefaultLightMode 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("appearance_app"),
|
|
|
+ app_source=DefaultLightModeApp, # type: ignore
|
|
|
+ ) as harness:
|
|
|
+ assert harness.app_instance is not None, "app is not running"
|
|
|
+ yield harness
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture()
|
|
|
+def dark_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
|
|
+ """Start DefaultDarkMode 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("appearance_app"),
|
|
|
+ app_source=DefaultDarkModeApp, # type: ignore
|
|
|
+ ) as harness:
|
|
|
+ assert harness.app_instance is not None, "app is not running"
|
|
|
+ yield harness
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture()
|
|
|
+def system_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
|
|
+ """Start DefaultSystemMode 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("appearance_app"),
|
|
|
+ app_source=DefaultSystemModeApp, # type: ignore
|
|
|
+ ) as harness:
|
|
|
+ assert harness.app_instance is not None, "app is not running"
|
|
|
+ yield harness
|
|
|
+
|
|
|
+
|
|
|
+@pytest.fixture()
|
|
|
+def color_toggle_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
|
|
|
+ """Start ColorToggle 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("appearance_app"),
|
|
|
+ app_source=ColorToggleApp, # type: ignore
|
|
|
+ ) as harness:
|
|
|
+ assert harness.app_instance is not None, "app is not running"
|
|
|
+ yield harness
|
|
|
+
|
|
|
+
|
|
|
+def test_appearance_light_mode(light_mode_app: AppHarness, page: Page):
|
|
|
+ assert light_mode_app.frontend_url is not None
|
|
|
+ page.goto(light_mode_app.frontend_url)
|
|
|
+
|
|
|
+ expect(page.get_by_text("light")).to_be_visible()
|
|
|
+
|
|
|
+
|
|
|
+def test_appearance_dark_mode(dark_mode_app: AppHarness, page: Page):
|
|
|
+ assert dark_mode_app.frontend_url is not None
|
|
|
+ page.goto(dark_mode_app.frontend_url)
|
|
|
+
|
|
|
+ expect(page.get_by_text("dark")).to_be_visible()
|
|
|
+
|
|
|
+
|
|
|
+def test_appearance_system_mode(system_mode_app: AppHarness, page: Page):
|
|
|
+ assert system_mode_app.frontend_url is not None
|
|
|
+ page.goto(system_mode_app.frontend_url)
|
|
|
+
|
|
|
+ expect(page.get_by_text("system")).to_be_visible()
|
|
|
+
|
|
|
+
|
|
|
+def test_appearance_color_toggle(color_toggle_app: AppHarness, page: Page):
|
|
|
+ assert color_toggle_app.frontend_url is not None
|
|
|
+ page.goto(color_toggle_app.frontend_url)
|
|
|
+
|
|
|
+ # Radio buttons locators.
|
|
|
+ radio_system = page.get_by_role("radio").nth(0)
|
|
|
+ radio_light = page.get_by_role("radio").nth(1)
|
|
|
+ radio_dark = page.get_by_role("radio").nth(2)
|
|
|
+
|
|
|
+ # Text locators to check.
|
|
|
+ current_color_mode = page.locator("id=current_color_mode")
|
|
|
+ resolved_color_mode = page.locator("id=resolved_color_mode")
|
|
|
+ color_mode_cond = page.locator("id=color_mode_cond")
|
|
|
+ root_body = page.locator('div[data-is-root-theme="true"]')
|
|
|
+
|
|
|
+ # Background colors.
|
|
|
+ dark_background = "rgb(17, 17, 19)" # value based on dark native appearance, can change depending on the browser
|
|
|
+ light_background = "rgb(255, 255, 255)"
|
|
|
+
|
|
|
+ # check initial state
|
|
|
+ expect(current_color_mode).to_have_text("light")
|
|
|
+ expect(resolved_color_mode).to_have_text("light")
|
|
|
+ expect(color_mode_cond).to_have_text("LightMode")
|
|
|
+ expect(root_body).to_have_css("background-color", light_background)
|
|
|
+
|
|
|
+ # click dark mode
|
|
|
+ radio_dark.click()
|
|
|
+ expect(current_color_mode).to_have_text("dark")
|
|
|
+ expect(resolved_color_mode).to_have_text("dark")
|
|
|
+ expect(color_mode_cond).to_have_text("DarkMode")
|
|
|
+ expect(root_body).to_have_css("background-color", dark_background)
|
|
|
+
|
|
|
+ # click light mode
|
|
|
+ radio_light.click()
|
|
|
+ expect(current_color_mode).to_have_text("light")
|
|
|
+ expect(resolved_color_mode).to_have_text("light")
|
|
|
+ expect(color_mode_cond).to_have_text("LightMode")
|
|
|
+ expect(root_body).to_have_css("background-color", light_background)
|
|
|
+ page.reload()
|
|
|
+ expect(root_body).to_have_css("background-color", light_background)
|
|
|
+
|
|
|
+ # click system mode
|
|
|
+ radio_system.click()
|
|
|
+ expect(current_color_mode).to_have_text("system")
|
|
|
+ expect(resolved_color_mode).to_have_text("light")
|
|
|
+ expect(color_mode_cond).to_have_text("LightMode")
|
|
|
+ expect(root_body).to_have_css("background-color", light_background)
|