Skip to content

Commit 53654da

Browse files
committed
tests(cli[colors]): Convert class-based tests to functions
Follow project conventions per AGENTS.md - use function-based tests instead of class-based tests for color modules. Converted files: - test_colors.py - test_cli_colors_integration.py - test_convert_colors.py - test_edit_colors.py - test_freeze_colors.py - test_import_colors.py - test_shell_colors.py
1 parent 02e7f18 commit 53654da

File tree

7 files changed

+909
-807
lines changed

7 files changed

+909
-807
lines changed

tests/cli/test_cli_colors_integration.py

Lines changed: 180 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -9,189 +9,184 @@
99

1010
from tmuxp.cli._colors import ColorMode, Colors, get_color_mode
1111

12+
# Color flag integration tests
1213

13-
class TestColorFlagIntegration:
14-
"""Tests for --color flag integration across CLI."""
15-
16-
def test_color_flag_auto_with_tty(self, monkeypatch: pytest.MonkeyPatch) -> None:
17-
"""Verify --color=auto enables colors when stdout is TTY."""
18-
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
19-
monkeypatch.delenv("NO_COLOR", raising=False)
20-
monkeypatch.delenv("FORCE_COLOR", raising=False)
21-
22-
color_mode = get_color_mode("auto")
23-
colors = Colors(color_mode)
24-
assert colors._enabled is True
25-
26-
def test_color_flag_auto_without_tty(self, monkeypatch: pytest.MonkeyPatch) -> None:
27-
"""Verify --color=auto disables colors when stdout is not TTY."""
28-
monkeypatch.setattr(sys.stdout, "isatty", lambda: False)
29-
monkeypatch.delenv("NO_COLOR", raising=False)
30-
monkeypatch.delenv("FORCE_COLOR", raising=False)
31-
32-
color_mode = get_color_mode("auto")
33-
colors = Colors(color_mode)
34-
assert colors._enabled is False
35-
36-
def test_color_flag_always_forces_colors(
37-
self, monkeypatch: pytest.MonkeyPatch
38-
) -> None:
39-
"""Verify --color=always forces colors even without TTY."""
40-
monkeypatch.setattr(sys.stdout, "isatty", lambda: False)
41-
monkeypatch.delenv("NO_COLOR", raising=False)
42-
43-
color_mode = get_color_mode("always")
44-
colors = Colors(color_mode)
45-
assert colors._enabled is True
46-
# Verify output contains ANSI codes
47-
assert "\033[" in colors.success("test")
48-
49-
def test_color_flag_never_disables_colors(
50-
self, monkeypatch: pytest.MonkeyPatch
51-
) -> None:
52-
"""Verify --color=never disables colors even with TTY."""
53-
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
54-
monkeypatch.delenv("NO_COLOR", raising=False)
55-
56-
color_mode = get_color_mode("never")
57-
colors = Colors(color_mode)
58-
assert colors._enabled is False
59-
# Verify output is plain text
60-
assert colors.success("test") == "test"
61-
assert colors.error("test") == "test"
62-
assert colors.warning("test") == "test"
63-
64-
65-
class TestEnvironmentVariableIntegration:
66-
"""Tests for environment variable integration with color system."""
67-
68-
def test_no_color_env_overrides_always(
69-
self, monkeypatch: pytest.MonkeyPatch
70-
) -> None:
71-
"""Verify NO_COLOR environment variable overrides --color=always."""
72-
monkeypatch.setenv("NO_COLOR", "1")
73-
74-
color_mode = get_color_mode("always")
75-
colors = Colors(color_mode)
76-
assert colors._enabled is False
77-
assert colors.success("test") == "test"
78-
79-
def test_no_color_env_with_empty_value(
80-
self, monkeypatch: pytest.MonkeyPatch
81-
) -> None:
82-
"""Verify empty NO_COLOR is ignored (per spec)."""
83-
monkeypatch.setenv("NO_COLOR", "")
84-
monkeypatch.delenv("FORCE_COLOR", raising=False)
85-
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
86-
87-
colors = Colors(ColorMode.ALWAYS)
88-
# Empty NO_COLOR should be ignored, colors should be enabled
89-
assert colors._enabled is True
90-
91-
def test_force_color_env_with_auto(self, monkeypatch: pytest.MonkeyPatch) -> None:
92-
"""Verify FORCE_COLOR enables colors in auto mode without TTY."""
93-
monkeypatch.setattr(sys.stdout, "isatty", lambda: False)
94-
monkeypatch.setenv("FORCE_COLOR", "1")
95-
monkeypatch.delenv("NO_COLOR", raising=False)
96-
97-
colors = Colors(ColorMode.AUTO)
98-
assert colors._enabled is True
99-
100-
def test_no_color_takes_precedence_over_force_color(
101-
self, monkeypatch: pytest.MonkeyPatch
102-
) -> None:
103-
"""Verify NO_COLOR takes precedence over FORCE_COLOR."""
104-
monkeypatch.setenv("NO_COLOR", "1")
105-
monkeypatch.setenv("FORCE_COLOR", "1")
106-
107-
colors = Colors(ColorMode.ALWAYS)
108-
assert colors._enabled is False
109-
110-
111-
class TestColorModeConsistency:
112-
"""Tests verifying consistent color behavior across commands."""
113-
114-
@pytest.fixture()
115-
def colors_enabled(self, monkeypatch: pytest.MonkeyPatch) -> Colors:
116-
"""Create Colors with guaranteed enabled state."""
117-
monkeypatch.delenv("NO_COLOR", raising=False)
118-
return Colors(ColorMode.ALWAYS)
119-
120-
@pytest.fixture()
121-
def colors_disabled(self) -> Colors:
122-
"""Create Colors with guaranteed disabled state."""
123-
return Colors(ColorMode.NEVER)
124-
125-
def test_all_semantic_methods_respect_enabled_state(
126-
self, colors_enabled: Colors
127-
) -> None:
128-
"""Verify all semantic color methods include ANSI codes when enabled."""
129-
methods: list[t.Callable[..., str]] = [
130-
colors_enabled.success,
131-
colors_enabled.error,
132-
colors_enabled.warning,
133-
colors_enabled.info,
134-
colors_enabled.muted,
135-
]
136-
for method in methods:
137-
result = method("test")
138-
assert "\033[" in result, f"{method.__name__} should include ANSI codes"
139-
assert result.endswith("\033[0m"), f"{method.__name__} should reset color"
140-
141-
def test_all_semantic_methods_respect_disabled_state(
142-
self, colors_disabled: Colors
143-
) -> None:
144-
"""Verify all semantic color methods return plain text when disabled."""
145-
methods: list[t.Callable[..., str]] = [
146-
colors_disabled.success,
147-
colors_disabled.error,
148-
colors_disabled.warning,
149-
colors_disabled.info,
150-
colors_disabled.muted,
151-
]
152-
for method in methods:
153-
result = method("test")
154-
assert result == "test", f"{method.__name__} should return plain text"
155-
assert "\033[" not in result, (
156-
f"{method.__name__} should not have ANSI codes"
157-
)
158-
159-
def test_highlight_bold_parameter(self, colors_enabled: Colors) -> None:
160-
"""Verify highlight respects bold parameter."""
161-
with_bold = colors_enabled.highlight("test", bold=True)
162-
without_bold = colors_enabled.highlight("test", bold=False)
163-
164-
assert "\033[1m" in with_bold
165-
assert "\033[1m" not in without_bold
166-
# Both should have magenta
167-
assert "\033[35m" in with_bold
168-
assert "\033[35m" in without_bold
169-
170-
171-
class TestGetColorModeFunction:
172-
"""Tests for get_color_mode helper function."""
173-
174-
def test_none_defaults_to_auto(self) -> None:
175-
"""Verify None input returns AUTO mode."""
176-
assert get_color_mode(None) == ColorMode.AUTO
177-
178-
def test_valid_string_values(self) -> None:
179-
"""Verify all valid string values are converted correctly."""
180-
assert get_color_mode("auto") == ColorMode.AUTO
181-
assert get_color_mode("always") == ColorMode.ALWAYS
182-
assert get_color_mode("never") == ColorMode.NEVER
183-
184-
def test_case_insensitive(self) -> None:
185-
"""Verify string values are case insensitive."""
186-
assert get_color_mode("AUTO") == ColorMode.AUTO
187-
assert get_color_mode("Always") == ColorMode.ALWAYS
188-
assert get_color_mode("NEVER") == ColorMode.NEVER
189-
assert get_color_mode("aUtO") == ColorMode.AUTO
190-
191-
def test_invalid_values_fallback_to_auto(self) -> None:
192-
"""Verify invalid values fallback to AUTO mode."""
193-
assert get_color_mode("invalid") == ColorMode.AUTO
194-
assert get_color_mode("yes") == ColorMode.AUTO
195-
assert get_color_mode("no") == ColorMode.AUTO
196-
assert get_color_mode("true") == ColorMode.AUTO
197-
assert get_color_mode("") == ColorMode.AUTO
14+
15+
def test_color_flag_auto_with_tty(monkeypatch: pytest.MonkeyPatch) -> None:
16+
"""Verify --color=auto enables colors when stdout is TTY."""
17+
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
18+
monkeypatch.delenv("NO_COLOR", raising=False)
19+
monkeypatch.delenv("FORCE_COLOR", raising=False)
20+
21+
color_mode = get_color_mode("auto")
22+
colors = Colors(color_mode)
23+
assert colors._enabled is True
24+
25+
26+
def test_color_flag_auto_without_tty(monkeypatch: pytest.MonkeyPatch) -> None:
27+
"""Verify --color=auto disables colors when stdout is not TTY."""
28+
monkeypatch.setattr(sys.stdout, "isatty", lambda: False)
29+
monkeypatch.delenv("NO_COLOR", raising=False)
30+
monkeypatch.delenv("FORCE_COLOR", raising=False)
31+
32+
color_mode = get_color_mode("auto")
33+
colors = Colors(color_mode)
34+
assert colors._enabled is False
35+
36+
37+
def test_color_flag_always_forces_colors(monkeypatch: pytest.MonkeyPatch) -> None:
38+
"""Verify --color=always forces colors even without TTY."""
39+
monkeypatch.setattr(sys.stdout, "isatty", lambda: False)
40+
monkeypatch.delenv("NO_COLOR", raising=False)
41+
42+
color_mode = get_color_mode("always")
43+
colors = Colors(color_mode)
44+
assert colors._enabled is True
45+
# Verify output contains ANSI codes
46+
assert "\033[" in colors.success("test")
47+
48+
49+
def test_color_flag_never_disables_colors(monkeypatch: pytest.MonkeyPatch) -> None:
50+
"""Verify --color=never disables colors even with TTY."""
51+
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
52+
monkeypatch.delenv("NO_COLOR", raising=False)
53+
54+
color_mode = get_color_mode("never")
55+
colors = Colors(color_mode)
56+
assert colors._enabled is False
57+
# Verify output is plain text
58+
assert colors.success("test") == "test"
59+
assert colors.error("test") == "test"
60+
assert colors.warning("test") == "test"
61+
62+
63+
# Environment variable integration tests
64+
65+
66+
def test_no_color_env_overrides_always(monkeypatch: pytest.MonkeyPatch) -> None:
67+
"""Verify NO_COLOR environment variable overrides --color=always."""
68+
monkeypatch.setenv("NO_COLOR", "1")
69+
70+
color_mode = get_color_mode("always")
71+
colors = Colors(color_mode)
72+
assert colors._enabled is False
73+
assert colors.success("test") == "test"
74+
75+
76+
def test_no_color_env_with_empty_value(monkeypatch: pytest.MonkeyPatch) -> None:
77+
"""Verify empty NO_COLOR is ignored (per spec)."""
78+
monkeypatch.setenv("NO_COLOR", "")
79+
monkeypatch.delenv("FORCE_COLOR", raising=False)
80+
monkeypatch.setattr(sys.stdout, "isatty", lambda: True)
81+
82+
colors = Colors(ColorMode.ALWAYS)
83+
# Empty NO_COLOR should be ignored, colors should be enabled
84+
assert colors._enabled is True
85+
86+
87+
def test_force_color_env_with_auto(monkeypatch: pytest.MonkeyPatch) -> None:
88+
"""Verify FORCE_COLOR enables colors in auto mode without TTY."""
89+
monkeypatch.setattr(sys.stdout, "isatty", lambda: False)
90+
monkeypatch.setenv("FORCE_COLOR", "1")
91+
monkeypatch.delenv("NO_COLOR", raising=False)
92+
93+
colors = Colors(ColorMode.AUTO)
94+
assert colors._enabled is True
95+
96+
97+
def test_no_color_takes_precedence_over_force_color(
98+
monkeypatch: pytest.MonkeyPatch,
99+
) -> None:
100+
"""Verify NO_COLOR takes precedence over FORCE_COLOR."""
101+
monkeypatch.setenv("NO_COLOR", "1")
102+
monkeypatch.setenv("FORCE_COLOR", "1")
103+
104+
colors = Colors(ColorMode.ALWAYS)
105+
assert colors._enabled is False
106+
107+
108+
# Color mode consistency tests
109+
110+
111+
def test_all_semantic_methods_respect_enabled_state(
112+
monkeypatch: pytest.MonkeyPatch,
113+
) -> None:
114+
"""Verify all semantic color methods include ANSI codes when enabled."""
115+
monkeypatch.delenv("NO_COLOR", raising=False)
116+
colors = Colors(ColorMode.ALWAYS)
117+
118+
methods: list[t.Callable[..., str]] = [
119+
colors.success,
120+
colors.error,
121+
colors.warning,
122+
colors.info,
123+
colors.muted,
124+
]
125+
for method in methods:
126+
result = method("test")
127+
assert "\033[" in result, f"{method.__name__} should include ANSI codes"
128+
assert result.endswith("\033[0m"), f"{method.__name__} should reset color"
129+
130+
131+
def test_all_semantic_methods_respect_disabled_state() -> None:
132+
"""Verify all semantic color methods return plain text when disabled."""
133+
colors = Colors(ColorMode.NEVER)
134+
135+
methods: list[t.Callable[..., str]] = [
136+
colors.success,
137+
colors.error,
138+
colors.warning,
139+
colors.info,
140+
colors.muted,
141+
]
142+
for method in methods:
143+
result = method("test")
144+
assert result == "test", f"{method.__name__} should return plain text"
145+
assert "\033[" not in result, f"{method.__name__} should not have ANSI codes"
146+
147+
148+
def test_highlight_bold_parameter(monkeypatch: pytest.MonkeyPatch) -> None:
149+
"""Verify highlight respects bold parameter."""
150+
monkeypatch.delenv("NO_COLOR", raising=False)
151+
colors = Colors(ColorMode.ALWAYS)
152+
153+
with_bold = colors.highlight("test", bold=True)
154+
without_bold = colors.highlight("test", bold=False)
155+
156+
assert "\033[1m" in with_bold
157+
assert "\033[1m" not in without_bold
158+
# Both should have magenta
159+
assert "\033[35m" in with_bold
160+
assert "\033[35m" in without_bold
161+
162+
163+
# get_color_mode function tests
164+
165+
166+
def test_get_color_mode_none_defaults_to_auto() -> None:
167+
"""Verify None input returns AUTO mode."""
168+
assert get_color_mode(None) == ColorMode.AUTO
169+
170+
171+
def test_get_color_mode_valid_string_values() -> None:
172+
"""Verify all valid string values are converted correctly."""
173+
assert get_color_mode("auto") == ColorMode.AUTO
174+
assert get_color_mode("always") == ColorMode.ALWAYS
175+
assert get_color_mode("never") == ColorMode.NEVER
176+
177+
178+
def test_get_color_mode_case_insensitive() -> None:
179+
"""Verify string values are case insensitive."""
180+
assert get_color_mode("AUTO") == ColorMode.AUTO
181+
assert get_color_mode("Always") == ColorMode.ALWAYS
182+
assert get_color_mode("NEVER") == ColorMode.NEVER
183+
assert get_color_mode("aUtO") == ColorMode.AUTO
184+
185+
186+
def test_get_color_mode_invalid_values_fallback_to_auto() -> None:
187+
"""Verify invalid values fallback to AUTO mode."""
188+
assert get_color_mode("invalid") == ColorMode.AUTO
189+
assert get_color_mode("yes") == ColorMode.AUTO
190+
assert get_color_mode("no") == ColorMode.AUTO
191+
assert get_color_mode("true") == ColorMode.AUTO
192+
assert get_color_mode("") == ColorMode.AUTO

0 commit comments

Comments
 (0)