Skip to content

Commit 5dee53f

Browse files
committed
add missing tests and organize existing tests better
1 parent e93d971 commit 5dee53f

13 files changed

Lines changed: 264 additions & 68 deletions

tests/test_code.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from xulbux.code import Code
22

3+
#
4+
################################################## Code TESTS ##################################################
5+
36

47
def test_add_indent():
58
sample = "def hello():\n return 'Hello, World!'"

tests/test_color.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from xulbux.color import Color, rgba, hsla, hexa
22

3+
#
4+
################################################## Color TESTS ##################################################
5+
36

47
def test_rgba_to_hex_int_and_back():
58
blue = Color.rgba_to_hex_int(0, 0, 255)

tests/test_color_types.py

Lines changed: 73 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ def assert_hexa_equal(actual: hexa, expected: str):
2222
assert str(actual) == expected
2323

2424

25+
################################################## rgba TESTS ##################################################
26+
27+
2528
def test_rgba_return_values():
2629
assert_rgba_equal(rgba(255, 0, 0, 0.5), (255, 0, 0, 0.5))
2730
assert_hsla_equal(rgba(255, 0, 0, 0.5).to_hsla(), (0, 100, 50, 0.5))
@@ -48,6 +51,41 @@ def test_rgba_return_values():
4851
assert_rgba_equal(rgba(255, 0, 0, 0.5).complementary(), (0, 255, 255, 0.5))
4952

5053

54+
def test_rgba_construction():
55+
assert rgba(100, 150, 200).values() == (100, 150, 200, None)
56+
assert rgba(100, 150, 200, 0.5).values() == (100, 150, 200, 0.5)
57+
assert rgba(0, 0, 0).values() == (0, 0, 0, None)
58+
assert rgba(255, 255, 255).values() == (255, 255, 255, None)
59+
try:
60+
rgba(300, 150, 200)
61+
assert False, "Should raise ValueError for invalid RGB values"
62+
except ValueError:
63+
pass
64+
try:
65+
rgba(100, 150, 200, 2.0)
66+
assert False, "Should raise ValueError for invalid alpha value"
67+
except ValueError:
68+
pass
69+
70+
71+
def test_rgba_dunder_methods():
72+
assert len(rgba(100, 150, 200)) == 3
73+
assert len(rgba(100, 150, 200, 0.5)) == 4
74+
color = rgba(100, 150, 200, 0.5)
75+
assert color[0] == 100
76+
assert color[1] == 150
77+
assert color[2] == 200
78+
assert color[3] == 0.5
79+
assert rgba(100, 150, 200) == rgba(100, 150, 200)
80+
assert rgba(100, 150, 200) != rgba(200, 100, 150)
81+
assert str(rgba(100, 150, 200)) == "(100, 150, 200)"
82+
assert str(rgba(100, 150, 200, 0.5)) == "(100, 150, 200, 0.5)"
83+
assert repr(rgba(100, 150, 200)).startswith("rgba(")
84+
85+
86+
################################################## hsla TESTS ##################################################
87+
88+
5189
def test_hsla_return_values():
5290
assert_hsla_equal(hsla(0, 100, 50, 0.5), (0, 100, 50, 0.5))
5391
assert_rgba_equal(hsla(0, 100, 50, 0.5).to_rgba(), (255, 0, 0, 0.5))
@@ -74,6 +112,41 @@ def test_hsla_return_values():
74112
assert_hsla_equal(hsla(0, 100, 50, 0.5).complementary(), (180, 100, 50, 0.5))
75113

76114

115+
def test_hsla_construction():
116+
assert hsla(210, 50, 60).values() == (210, 50, 60, None)
117+
assert hsla(210, 50, 60, 0.5).values() == (210, 50, 60, 0.5)
118+
assert hsla(0, 0, 0).values() == (0, 0, 0, None)
119+
assert hsla(360, 100, 100).values() == (360, 100, 100, None)
120+
try:
121+
hsla(361, 50, 60)
122+
assert False, "Should raise ValueError for invalid hue value"
123+
except ValueError:
124+
pass
125+
try:
126+
hsla(210, 101, 60)
127+
assert False, "Should raise ValueError for invalid saturation value"
128+
except ValueError:
129+
pass
130+
131+
132+
def test_hsla_dunder_methods():
133+
assert len(hsla(210, 50, 60)) == 3
134+
assert len(hsla(210, 50, 60, 0.5)) == 4
135+
color = hsla(210, 50, 60, 0.5)
136+
assert color[0] == 210
137+
assert color[1] == 50
138+
assert color[2] == 60
139+
assert color[3] == 0.5
140+
assert hsla(210, 50, 60) == hsla(210, 50, 60)
141+
assert hsla(210, 50, 60) != hsla(210, 60, 50)
142+
assert str(hsla(210, 50, 60)) == "(210°, 50%, 60%)"
143+
assert str(hsla(210, 50, 60, 0.5)) == "(210°, 50%, 60%, 0.5)"
144+
assert repr(hsla(210, 50, 60)).startswith("hsla(")
145+
146+
147+
################################################## hexa TESTS ##################################################
148+
149+
77150
def test_hexa_return_values():
78151
assert_hexa_equal(hexa("#F008"), "#FF000088")
79152
assert_rgba_equal(hexa("#FF00007F").to_rgba(), (255, 0, 0, 0.5))
@@ -100,40 +173,6 @@ def test_hexa_return_values():
100173
assert_hexa_equal(hexa("#FF00007F").complementary(), "#00FFFF7F")
101174

102175

103-
def test_rgba_construction():
104-
assert rgba(100, 150, 200).values() == (100, 150, 200, None)
105-
assert rgba(100, 150, 200, 0.5).values() == (100, 150, 200, 0.5)
106-
assert rgba(0, 0, 0).values() == (0, 0, 0, None)
107-
assert rgba(255, 255, 255).values() == (255, 255, 255, None)
108-
try:
109-
rgba(300, 150, 200)
110-
assert False, "Should raise ValueError for invalid RGB values"
111-
except ValueError:
112-
pass
113-
try:
114-
rgba(100, 150, 200, 2.0)
115-
assert False, "Should raise ValueError for invalid alpha value"
116-
except ValueError:
117-
pass
118-
119-
120-
def test_hsla_construction():
121-
assert hsla(210, 50, 60).values() == (210, 50, 60, None)
122-
assert hsla(210, 50, 60, 0.5).values() == (210, 50, 60, 0.5)
123-
assert hsla(0, 0, 0).values() == (0, 0, 0, None)
124-
assert hsla(360, 100, 100).values() == (360, 100, 100, None)
125-
try:
126-
hsla(361, 50, 60)
127-
assert False, "Should raise ValueError for invalid hue value"
128-
except ValueError:
129-
pass
130-
try:
131-
hsla(210, 101, 60)
132-
assert False, "Should raise ValueError for invalid saturation value"
133-
except ValueError:
134-
pass
135-
136-
137176
def test_hexa_construction():
138177
assert hexa("#F00").values() == (255, 0, 0, None)
139178
assert hexa("#F008").values(True) == (255, 0, 0, 0.53)
@@ -153,36 +192,6 @@ def test_hexa_construction():
153192
pass
154193

155194

156-
def test_rgba_dunder_methods():
157-
assert len(rgba(100, 150, 200)) == 3
158-
assert len(rgba(100, 150, 200, 0.5)) == 4
159-
color = rgba(100, 150, 200, 0.5)
160-
assert color[0] == 100
161-
assert color[1] == 150
162-
assert color[2] == 200
163-
assert color[3] == 0.5
164-
assert rgba(100, 150, 200) == rgba(100, 150, 200)
165-
assert rgba(100, 150, 200) != rgba(200, 100, 150)
166-
assert str(rgba(100, 150, 200)) == "(100, 150, 200)"
167-
assert str(rgba(100, 150, 200, 0.5)) == "(100, 150, 200, 0.5)"
168-
assert repr(rgba(100, 150, 200)).startswith("rgba(")
169-
170-
171-
def test_hsla_dunder_methods():
172-
assert len(hsla(210, 50, 60)) == 3
173-
assert len(hsla(210, 50, 60, 0.5)) == 4
174-
color = hsla(210, 50, 60, 0.5)
175-
assert color[0] == 210
176-
assert color[1] == 50
177-
assert color[2] == 60
178-
assert color[3] == 0.5
179-
assert hsla(210, 50, 60) == hsla(210, 50, 60)
180-
assert hsla(210, 50, 60) != hsla(210, 60, 50)
181-
assert str(hsla(210, 50, 60)) == "(210°, 50%, 60%)"
182-
assert str(hsla(210, 50, 60, 0.5)) == "(210°, 50%, 60%, 0.5)"
183-
assert repr(hsla(210, 50, 60)).startswith("hsla(")
184-
185-
186195
def test_hexa_dunder_methods():
187196
assert len(hexa("#F00")) == 3
188197
assert len(hexa("#F008")) == 4

tests/test_console.py

Lines changed: 128 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from xulbux.console import ProgressBar, Console, ArgResult, Args
1+
from xulbux.console import Spinner, ProgressBar
2+
from xulbux.console import ArgResult, Args
3+
from xulbux.console import Console
24
from xulbux import console
35

46
from unittest.mock import MagicMock, patch, call
@@ -37,7 +39,7 @@ def mock_prompt_toolkit(monkeypatch):
3739
return mock
3840

3941

40-
################################################## CONSOLE TESTS ##################################################
42+
################################################## Console TESTS ##################################################
4143

4244

4345
def test_console_user():
@@ -928,7 +930,7 @@ def test_input_custom_style_object(mock_prompt_session, mock_formatcodes_print):
928930
assert hasattr(style, "style_rules") or hasattr(style, "_style")
929931

930932

931-
################################################## PROGRESSBAR TESTS ##################################################
933+
################################################## ProgressBar TESTS ##################################################
932934

933935

934936
def test_progressbar_init():
@@ -1117,3 +1119,126 @@ def test_progressbar_redraw_progress_bar():
11171119
pb._current_progress_str = "\x1b[2K\rLoading |████████████| 50%"
11181120
pb._redraw_display()
11191121
mock_stdout.flush.assert_called_once()
1122+
1123+
1124+
################################################## Spinner TESTS ##################################################
1125+
1126+
1127+
def test_spinner_init_defaults():
1128+
spinner = Spinner()
1129+
assert spinner.label is None
1130+
assert spinner.interval == 0.2
1131+
assert spinner.active is False
1132+
assert spinner.sep == " "
1133+
assert len(spinner.frames) > 0
1134+
1135+
1136+
def test_spinner_init_custom():
1137+
spinner = Spinner(label="Loading", interval=0.5, sep="-")
1138+
assert spinner.label == "Loading"
1139+
assert spinner.interval == 0.5
1140+
assert spinner.sep == "-"
1141+
1142+
1143+
def test_spinner_set_format_valid():
1144+
spinner = Spinner()
1145+
spinner.set_format(["{l}", "{a}"])
1146+
assert spinner.spinner_format == ["{l}", "{a}"]
1147+
1148+
1149+
def test_spinner_set_format_invalid():
1150+
spinner = Spinner()
1151+
with pytest.raises(ValueError):
1152+
spinner.set_format(["{l}"]) # MISSING {a}
1153+
1154+
1155+
def test_spinner_set_frames_valid():
1156+
spinner = Spinner()
1157+
spinner.set_frames(("a", "b"))
1158+
assert spinner.frames == ("a", "b")
1159+
1160+
1161+
def test_spinner_set_frames_invalid():
1162+
spinner = Spinner()
1163+
with pytest.raises(ValueError):
1164+
spinner.set_frames(("a", )) # LESS THAN 2 FRAMES
1165+
1166+
1167+
def test_spinner_set_interval_valid():
1168+
spinner = Spinner()
1169+
spinner.set_interval(1.0)
1170+
assert spinner.interval == 1.0
1171+
1172+
1173+
def test_spinner_set_interval_invalid():
1174+
spinner = Spinner()
1175+
with pytest.raises(ValueError):
1176+
spinner.set_interval(0)
1177+
with pytest.raises(ValueError):
1178+
spinner.set_interval(-1)
1179+
1180+
1181+
@patch("xulbux.console._threading.Thread")
1182+
@patch("xulbux.console._threading.Event")
1183+
@patch("sys.stdout", new_callable=MagicMock)
1184+
def test_spinner_start(mock_stdout, mock_event, mock_thread):
1185+
spinner = Spinner()
1186+
spinner.start("Test")
1187+
1188+
assert spinner.active is True
1189+
assert spinner.label == "Test"
1190+
mock_event.assert_called_once()
1191+
mock_thread.assert_called_once()
1192+
1193+
# TEST CALLING START AGAIN DOESN'T DO ANYTHING
1194+
spinner.start("Test2")
1195+
assert mock_event.call_count == 1
1196+
1197+
1198+
@patch("xulbux.console._threading.Thread")
1199+
@patch("xulbux.console._threading.Event")
1200+
def test_spinner_stop(mock_event, mock_thread):
1201+
spinner = Spinner()
1202+
# MANUALLY SET ACTIVE TO SIMULATE RUNNING
1203+
spinner.active = True
1204+
mock_stop_event = MagicMock()
1205+
spinner._stop_event = mock_stop_event
1206+
mock_animation_thread = MagicMock()
1207+
spinner._animation_thread = mock_animation_thread
1208+
1209+
spinner.stop()
1210+
1211+
assert spinner.active is False
1212+
mock_stop_event.set.assert_called_once()
1213+
mock_animation_thread.join.assert_called_once()
1214+
1215+
1216+
def test_spinner_update_label():
1217+
spinner = Spinner()
1218+
spinner.update_label("New Label")
1219+
assert spinner.label == "New Label"
1220+
1221+
1222+
def test_spinner_context_manager():
1223+
spinner = Spinner()
1224+
with patch.object(spinner, "start") as mock_start, patch.object(spinner, "stop") as mock_stop:
1225+
1226+
with spinner.context("Test") as update:
1227+
mock_start.assert_called_with("Test")
1228+
update("New Label")
1229+
assert spinner.label == "New Label"
1230+
1231+
mock_stop.assert_called_once()
1232+
1233+
1234+
def test_spinner_context_manager_exception():
1235+
spinner = Spinner()
1236+
with patch.object(spinner, "start"), patch.object(spinner, "stop") as mock_stop, \
1237+
patch.object(spinner, "_emergency_cleanup") as mock_cleanup:
1238+
1239+
with pytest.raises(ValueError):
1240+
with spinner.context("Test"):
1241+
raise ValueError("Oops")
1242+
1243+
mock_cleanup.assert_called_once()
1244+
mock_stop.assert_called_once()

tests/test_data.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
d1_path_id = {"healthy": {"fruit": ["apples", "bananas", "oranges"], "vegetables": ["carrots", "broccoli", "celery"]}}
3030
d2_path_id = {"school": {"material": ["pencil", "paper", "rubber"], "subjects": ["math", "science", "history"]}}
3131

32+
#
33+
################################################## Data TESTS ##################################################
34+
3235

3336
def test_serialize_bytes():
3437
utf8_bytes = b"Hello"

tests/test_env_path.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from xulbux.env_path import EnvPath
22

3+
#
4+
################################################## EnvPath TESTS ##################################################
5+
36

47
def test_get_paths():
58
paths = EnvPath.paths()

tests/test_file.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import pytest
55
import os
66

7+
#
8+
################################################## File TESTS ##################################################
9+
710

811
@pytest.mark.parametrize(
912
"input_file, new_extension, camel_case, full_extension, expected_output", [

tests/test_format_codes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
reset_invert = f"{ANSI.CHAR}{ANSI.START}{ANSI.CODES_MAP[('_inverse', '_invert', '_in')]}{ANSI.END}"
2121
reset_underline = f"{ANSI.CHAR}{ANSI.START}{ANSI.CODES_MAP[('_underline', '_u')]}{ANSI.END}"
2222

23+
#
24+
################################################## FormatCodes TESTS ##################################################
25+
2326

2427
def test_to_ansi():
2528
assert (

tests/test_json.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ def create_test_json_string(tmp_path, filename, content):
8080
"user": {"name": "Test User", "admin": True},
8181
}
8282

83+
#
84+
################################################## Json TESTS ##################################################
85+
8386

8487
def test_read_simple(tmp_path):
8588
file_path = create_test_json(tmp_path, "simple.json", SIMPLE_DATA)

0 commit comments

Comments
 (0)