test_appearance.py 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. from typing import Generator
  2. import pytest
  3. from playwright.sync_api import Page, expect
  4. from reflex.testing import AppHarness
  5. def DefaultLightModeApp():
  6. import reflex as rx
  7. from reflex.style import color_mode
  8. app = rx.App(theme=rx.theme(appearance="light"))
  9. @app.add_page
  10. def index():
  11. return rx.text(color_mode)
  12. def DefaultDarkModeApp():
  13. import reflex as rx
  14. from reflex.style import color_mode
  15. app = rx.App(theme=rx.theme(appearance="dark"))
  16. @app.add_page
  17. def index():
  18. return rx.text(color_mode)
  19. def DefaultSystemModeApp():
  20. import reflex as rx
  21. from reflex.style import color_mode
  22. app = rx.App()
  23. @app.add_page
  24. def index():
  25. return rx.text(color_mode)
  26. def ColorToggleApp():
  27. import reflex as rx
  28. from reflex.style import color_mode, resolved_color_mode, set_color_mode
  29. app = rx.App(theme=rx.theme(appearance="light"))
  30. @app.add_page
  31. def index():
  32. return rx.box(
  33. rx.segmented_control.root(
  34. rx.segmented_control.item(
  35. rx.icon(tag="monitor", size=20),
  36. value="system",
  37. ),
  38. rx.segmented_control.item(
  39. rx.icon(tag="sun", size=20),
  40. value="light",
  41. ),
  42. rx.segmented_control.item(
  43. rx.icon(tag="moon", size=20),
  44. value="dark",
  45. ),
  46. on_change=set_color_mode, # pyright: ignore[reportArgumentType]
  47. variant="classic",
  48. radius="large",
  49. value=color_mode,
  50. ),
  51. rx.text(color_mode, id="current_color_mode"),
  52. rx.text(resolved_color_mode, id="resolved_color_mode"),
  53. rx.text(rx.color_mode_cond("LightMode", "DarkMode"), id="color_mode_cond"),
  54. )
  55. @pytest.fixture()
  56. def light_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
  57. """Start DefaultLightMode app at tmp_path via AppHarness.
  58. Args:
  59. tmp_path_factory: pytest tmp_path_factory fixture
  60. Yields:
  61. running AppHarness instance
  62. """
  63. with AppHarness.create(
  64. root=tmp_path_factory.mktemp("appearance_app"),
  65. app_source=DefaultLightModeApp,
  66. ) as harness:
  67. assert harness.app_instance is not None, "app is not running"
  68. yield harness
  69. @pytest.fixture()
  70. def dark_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
  71. """Start DefaultDarkMode app at tmp_path via AppHarness.
  72. Args:
  73. tmp_path_factory: pytest tmp_path_factory fixture
  74. Yields:
  75. running AppHarness instance
  76. """
  77. with AppHarness.create(
  78. root=tmp_path_factory.mktemp("appearance_app"),
  79. app_source=DefaultDarkModeApp,
  80. ) as harness:
  81. assert harness.app_instance is not None, "app is not running"
  82. yield harness
  83. @pytest.fixture()
  84. def system_mode_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
  85. """Start DefaultSystemMode app at tmp_path via AppHarness.
  86. Args:
  87. tmp_path_factory: pytest tmp_path_factory fixture
  88. Yields:
  89. running AppHarness instance
  90. """
  91. with AppHarness.create(
  92. root=tmp_path_factory.mktemp("appearance_app"),
  93. app_source=DefaultSystemModeApp,
  94. ) as harness:
  95. assert harness.app_instance is not None, "app is not running"
  96. yield harness
  97. @pytest.fixture()
  98. def color_toggle_app(tmp_path_factory) -> Generator[AppHarness, None, None]:
  99. """Start ColorToggle app at tmp_path via AppHarness.
  100. Args:
  101. tmp_path_factory: pytest tmp_path_factory fixture
  102. Yields:
  103. running AppHarness instance
  104. """
  105. with AppHarness.create(
  106. root=tmp_path_factory.mktemp("appearance_app"),
  107. app_source=ColorToggleApp,
  108. ) as harness:
  109. assert harness.app_instance is not None, "app is not running"
  110. yield harness
  111. def test_appearance_light_mode(light_mode_app: AppHarness, page: Page):
  112. assert light_mode_app.frontend_url is not None
  113. page.goto(light_mode_app.frontend_url)
  114. expect(page.get_by_text("light")).to_be_visible()
  115. def test_appearance_dark_mode(dark_mode_app: AppHarness, page: Page):
  116. assert dark_mode_app.frontend_url is not None
  117. page.goto(dark_mode_app.frontend_url)
  118. expect(page.get_by_text("dark")).to_be_visible()
  119. def test_appearance_system_mode(system_mode_app: AppHarness, page: Page):
  120. assert system_mode_app.frontend_url is not None
  121. page.goto(system_mode_app.frontend_url)
  122. expect(page.get_by_text("system")).to_be_visible()
  123. def test_appearance_color_toggle(color_toggle_app: AppHarness, page: Page):
  124. assert color_toggle_app.frontend_url is not None
  125. page.goto(color_toggle_app.frontend_url)
  126. # Radio buttons locators.
  127. radio_system = page.get_by_role("radio").nth(0)
  128. radio_light = page.get_by_role("radio").nth(1)
  129. radio_dark = page.get_by_role("radio").nth(2)
  130. # Text locators to check.
  131. current_color_mode = page.locator("id=current_color_mode")
  132. resolved_color_mode = page.locator("id=resolved_color_mode")
  133. color_mode_cond = page.locator("id=color_mode_cond")
  134. root_body = page.locator('div[data-is-root-theme="true"]')
  135. # Background colors.
  136. dark_background = "rgb(17, 17, 19)" # value based on dark native appearance, can change depending on the browser
  137. light_background = "rgb(255, 255, 255)"
  138. # check initial state
  139. expect(current_color_mode).to_have_text("light")
  140. expect(resolved_color_mode).to_have_text("light")
  141. expect(color_mode_cond).to_have_text("LightMode")
  142. expect(root_body).to_have_css("background-color", light_background)
  143. # click dark mode
  144. radio_dark.click()
  145. expect(current_color_mode).to_have_text("dark")
  146. expect(resolved_color_mode).to_have_text("dark")
  147. expect(color_mode_cond).to_have_text("DarkMode")
  148. expect(root_body).to_have_css("background-color", dark_background)
  149. # click light mode
  150. radio_light.click()
  151. expect(current_color_mode).to_have_text("light")
  152. expect(resolved_color_mode).to_have_text("light")
  153. expect(color_mode_cond).to_have_text("LightMode")
  154. expect(root_body).to_have_css("background-color", light_background)
  155. page.reload()
  156. expect(root_body).to_have_css("background-color", light_background)
  157. # click system mode
  158. radio_system.click()
  159. expect(current_color_mode).to_have_text("system")
  160. expect(resolved_color_mode).to_have_text("light")
  161. expect(color_mode_cond).to_have_text("LightMode")
  162. expect(root_body).to_have_css("background-color", light_background)