22
33import pytest
44from PyQt6 .QtCore import Qt
5- from PyQt6 .QtGui import QGuiApplication
5+ from PyQt6 .QtGui import QColor , QGuiApplication , QPalette
66from PyQt6 .QtWidgets import QApplication
77
88from ert .gui .theme_manager import ColorSchemeManager , ColorTheme
99from ert .gui .theme_manager import theme_manager as manager_module
10+ from ert .gui .theme_manager .theme_manager import (
11+ _DARK_BASE_VALUE_THRESHOLD ,
12+ detect_system_color_theme ,
13+ )
1014
1115
1216@pytest .fixture (autouse = True )
@@ -16,6 +20,12 @@ def _restore_global_stylesheet(qapp):
1620 qapp .setStyleSheet (original )
1721
1822
23+ def _palette_with_base_value (value : int ) -> QPalette :
24+ palette = QPalette ()
25+ palette .setColor (QPalette .ColorRole .Base , QColor .fromHsv (0 , 0 , value ))
26+ return palette
27+
28+
1929def _pin_system_scheme (monkeypatch , scheme : Qt .ColorScheme ) -> None :
2030 monkeypatch .setattr (QGuiApplication .styleHints (), "colorScheme" , lambda : scheme )
2131
@@ -26,6 +36,79 @@ def _stub_qss_per_theme(monkeypatch) -> None:
2636 )
2737
2838
39+ @pytest .mark .parametrize (
40+ ("reported_scheme" , "expected_theme" ),
41+ [
42+ pytest .param (Qt .ColorScheme .Dark , ColorTheme .DARK , id = "dark" ),
43+ pytest .param (Qt .ColorScheme .Light , ColorTheme .LIGHT , id = "light" ),
44+ ],
45+ )
46+ def test_that_detection_mirrors_the_scheme_reported_by_style_hints (
47+ qtbot , monkeypatch , reported_scheme , expected_theme
48+ ) -> None :
49+ hints = QGuiApplication .styleHints ()
50+ monkeypatch .setattr (hints , "colorScheme" , lambda : reported_scheme )
51+ assert detect_system_color_theme (hints ) == expected_theme
52+
53+
54+ def test_that_detection_falls_back_to_palette_when_scheme_is_unknown (
55+ qtbot , monkeypatch
56+ ) -> None :
57+ hints = QGuiApplication .styleHints ()
58+ monkeypatch .setattr (hints , "colorScheme" , lambda : Qt .ColorScheme .Unknown )
59+ # The default Qt palette used in tests has a white base colour (value
60+ # 255), which is above _DARK_BASE_VALUE_THRESHOLD, so the fallback path
61+ # must resolve to LIGHT.
62+ assert detect_system_color_theme (hints ) == ColorTheme .LIGHT
63+
64+
65+ def test_that_require_style_hints_raises_when_style_hints_are_unavailable (
66+ monkeypatch ,
67+ ) -> None :
68+ monkeypatch .setattr (
69+ manager_module .QGuiApplication , "styleHints" , staticmethod (lambda : None )
70+ )
71+ with pytest .raises (RuntimeError , match = "styleHints" ):
72+ manager_module ._require_style_hints ()
73+
74+
75+ def test_that_palette_fallback_returns_light_when_no_qapplication_exists (
76+ monkeypatch ,
77+ ) -> None :
78+ monkeypatch .setattr (
79+ manager_module .QApplication , "instance" , staticmethod (lambda : None )
80+ )
81+ assert manager_module ._palette_fallback () == ColorTheme .LIGHT
82+
83+
84+ @pytest .mark .parametrize (
85+ ("base_value" , "expected_theme" ),
86+ [
87+ pytest .param (
88+ _DARK_BASE_VALUE_THRESHOLD - 1 ,
89+ ColorTheme .DARK ,
90+ id = "returns-dark-when-base-value-is-below-threshold" ,
91+ ),
92+ pytest .param (
93+ _DARK_BASE_VALUE_THRESHOLD + 1 ,
94+ ColorTheme .LIGHT ,
95+ id = "returns-light-when-base-value-is-above-threshold" ,
96+ ),
97+ pytest .param (
98+ _DARK_BASE_VALUE_THRESHOLD ,
99+ ColorTheme .LIGHT ,
100+ id = "returns-light-when-base-value-equals-threshold" ,
101+ ),
102+ ],
103+ )
104+ def test_that_palette_fallback_resolves_theme_from_base_value_threshold (
105+ qtbot , monkeypatch , base_value , expected_theme
106+ ) -> None :
107+ app = manager_module .QApplication .instance ()
108+ monkeypatch .setattr (app , "palette" , lambda : _palette_with_base_value (base_value ))
109+ assert manager_module ._palette_fallback () == expected_theme
110+
111+
29112def test_that_apply_raises_runtime_error_when_no_qapplication_exists (
30113 qtbot , monkeypatch
31114) -> None :
0 commit comments