05/23 Phase 16
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"""
|
||||
tests/test_widgets.py
|
||||
---------------------
|
||||
Tests for ui/widgets.py — ball_color() is pure and testable without a display.
|
||||
BallsBar creation tests require Tkinter and are skipped when unavailable.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from ui.widgets import ball_color, BallsBar
|
||||
|
||||
|
||||
def _has_display():
|
||||
try:
|
||||
import tkinter as tk
|
||||
r = tk.Tk(); r.withdraw(); r.destroy()
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
# ── ball_color — pure function, no display needed ─────────────────────────────
|
||||
|
||||
def test_ball_color_returns_two_hex_strings():
|
||||
bg, fg = ball_color(7)
|
||||
assert bg.startswith("#") and len(bg) == 7
|
||||
assert fg.startswith("#") and len(fg) == 7
|
||||
|
||||
def test_ball_color_bonus_is_red():
|
||||
bg, _ = ball_color(7, is_bonus=True)
|
||||
assert bg == "#e74c3c"
|
||||
|
||||
def test_ball_color_bonus_same_regardless_of_number():
|
||||
assert ball_color(1, is_bonus=True) == ball_color(26, is_bonus=True)
|
||||
assert ball_color(99, is_bonus=True) == ball_color(5, is_bonus=True)
|
||||
|
||||
def test_ball_color_different_ranges_have_different_colors():
|
||||
bgs = {ball_color(n)[0] for n in [1, 15, 25, 35, 45, 55, 65, 75]}
|
||||
assert len(bgs) >= 5 # at least 5 distinct background colors
|
||||
|
||||
def test_ball_color_boundary_values():
|
||||
# Each range boundary should resolve without error
|
||||
for n in [1, 9, 10, 19, 20, 29, 30, 39, 40, 49, 50, 59, 60, 69, 70, 99]:
|
||||
bg, fg = ball_color(n)
|
||||
assert bg.startswith("#")
|
||||
assert fg.startswith("#")
|
||||
|
||||
def test_ball_color_out_of_defined_range():
|
||||
# Number > 99 falls back gracefully
|
||||
bg, fg = ball_color(200)
|
||||
assert bg.startswith("#")
|
||||
assert fg.startswith("#")
|
||||
|
||||
def test_ball_color_is_deterministic():
|
||||
for n in [1, 7, 14, 22, 35, 49, 69]:
|
||||
assert ball_color(n) == ball_color(n)
|
||||
|
||||
def test_ball_color_non_bonus_not_red():
|
||||
# Main balls in defined ranges should not be the bonus red
|
||||
for n in range(1, 70):
|
||||
bg, _ = ball_color(n, is_bonus=False)
|
||||
assert bg != "#e74c3c" or n >= 60 # only 60-69 range is red
|
||||
|
||||
|
||||
# ── BallsBar — needs display ──────────────────────────────────────────────────
|
||||
|
||||
@pytest.mark.skipif(not _has_display(), reason="no display available")
|
||||
def test_ballsbar_creates_widget():
|
||||
import tkinter as tk
|
||||
try:
|
||||
root = tk.Tk(); root.withdraw()
|
||||
except Exception:
|
||||
pytest.skip("Tkinter init failed")
|
||||
try:
|
||||
bar = BallsBar(root, numbers=[1, 7, 14, 22, 35], bonus=3)
|
||||
assert bar.winfo_exists()
|
||||
finally:
|
||||
root.destroy()
|
||||
|
||||
|
||||
@pytest.mark.skipif(not _has_display(), reason="no display available")
|
||||
def test_ballsbar_no_bonus():
|
||||
import tkinter as tk
|
||||
try:
|
||||
root = tk.Tk(); root.withdraw()
|
||||
except Exception:
|
||||
pytest.skip("Tkinter init failed")
|
||||
try:
|
||||
bar = BallsBar(root, numbers=[5, 12, 30, 44, 66])
|
||||
assert bar.winfo_exists()
|
||||
assert int(bar.cget("width")) > 0
|
||||
finally:
|
||||
root.destroy()
|
||||
|
||||
|
||||
@pytest.mark.skipif(not _has_display(), reason="no display available")
|
||||
def test_ballsbar_with_highlights():
|
||||
import tkinter as tk
|
||||
try:
|
||||
root = tk.Tk(); root.withdraw()
|
||||
except Exception:
|
||||
pytest.skip("Tkinter init failed")
|
||||
try:
|
||||
hi = {7: ("#27ae60", "#ffffff"), 14: ("#cccccc", "#888888")}
|
||||
bar = BallsBar(root, numbers=[1, 7, 14, 22, 35], highlights=hi)
|
||||
assert bar.winfo_exists()
|
||||
finally:
|
||||
root.destroy()
|
||||
|
||||
|
||||
@pytest.mark.skipif(not _has_display(), reason="no display available")
|
||||
def test_ballsbar_larger_radius():
|
||||
import tkinter as tk
|
||||
try:
|
||||
root = tk.Tk(); root.withdraw()
|
||||
except Exception:
|
||||
pytest.skip("Tkinter init failed")
|
||||
try:
|
||||
bar_small = BallsBar(root, numbers=[1, 2, 3], radius=11)
|
||||
bar_normal = BallsBar(root, numbers=[1, 2, 3], radius=14)
|
||||
w_small = int(bar_small.cget("width"))
|
||||
w_normal = int(bar_normal.cget("width"))
|
||||
assert w_normal > w_small
|
||||
finally:
|
||||
root.destroy()
|
||||
Reference in New Issue
Block a user