Files
lottosight/tests/test_dashboard.py
T
2026-05-23 12:11:14 -04:00

149 lines
4.6 KiB
Python

"""
tests/test_dashboard.py
------------------------
Tests for the Dashboard screen data layer and UI smoke tests.
"""
import pytest
from db.models import (
get_all_games, get_game_by_name, get_last_draw,
insert_draw, insert_prediction,
)
from db.database import get_db_stats
from core.analyzer import frequency_analysis
# ── Data-layer checks used by the Dashboard ───────────────────────────────────
def test_last_draw_none_on_empty_db(tmp_db):
pb = get_game_by_name("Powerball")
assert get_last_draw(pb["id"]) is None
def test_last_draw_returns_most_recent(tmp_db):
pb = get_game_by_name("Powerball")
insert_draw(pb["id"], "2024-01-01", [1, 2, 3, 4, 5], bonus=7)
insert_draw(pb["id"], "2024-01-05", [5, 10, 20, 30, 40], bonus=15)
last = get_last_draw(pb["id"])
assert last["draw_date"] == "2024-01-05"
def test_last_draw_numbers_parseable(tmp_db):
pb = get_game_by_name("Powerball")
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7)
last = get_last_draw(pb["id"])
nums = [int(n) for n in last["numbers"].split(",")]
assert sorted(nums) == [1, 13, 36, 61, 69]
def test_db_stats_all_games_present(tmp_db):
stats = get_db_stats()
assert "Powerball" in stats
assert "Mega Millions" in stats
def test_db_stats_counts_correct_after_inserts(tmp_db):
pb = get_game_by_name("Powerball")
insert_draw(pb["id"], "2024-01-01", [1, 2, 3, 4, 5], bonus=7)
insert_draw(pb["id"], "2024-01-03", [5, 10, 20, 30, 40], bonus=15)
stats = get_db_stats()
assert stats["Powerball"] == 2
assert stats["Mega Millions"] == 0
def test_hot_numbers_empty_returns_empty(tmp_db):
pb = get_game_by_name("Powerball")
assert frequency_analysis(pb["id"], last_n=100) == {}
def test_hot_numbers_top5_correct(tmp_db):
pb = get_game_by_name("Powerball")
# Insert 3 draws; numbers 1 and 13 appear most (3 times each)
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7)
insert_draw(pb["id"], "2024-01-03", [1, 2, 13, 45, 69], bonus=15)
insert_draw(pb["id"], "2024-01-05", [1, 13, 22, 36, 55], bonus=3)
freq = frequency_analysis(pb["id"], last_n=100)
top5 = sorted(freq, key=freq.get, reverse=True)[:5]
assert 1 in top5
assert 13 in top5
def test_predictions_count_correct(tmp_db):
from db.models import get_predictions
pb = get_game_by_name("Powerball")
insert_prediction(pb["id"], "Hot Numbers", [1, 2, 3, 4, 5], bonus=7)
insert_prediction(pb["id"], "Due Numbers", [5, 10, 20, 30, 40], bonus=15)
assert len(get_predictions(limit=100_000)) == 2
# ── UI smoke tests ────────────────────────────────────────────────────────────
def _has_display():
try:
import tkinter as tk
r = tk.Tk(); r.withdraw(); r.destroy()
return True
except Exception:
return False
@pytest.mark.skipif(not _has_display(), reason="no display available")
def test_dashboard_instantiates(tmp_db):
import tkinter as tk
from ui.dashboard import DashboardScreen
root = tk.Tk(); root.withdraw()
try:
screen = DashboardScreen(root)
screen.refresh()
assert screen.winfo_exists()
finally:
root.destroy()
@pytest.mark.skipif(not _has_display(), reason="no display available")
def test_dashboard_refresh_with_data(tmp_db):
import tkinter as tk
from ui.dashboard import DashboardScreen
pb = get_game_by_name("Powerball")
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7, multiplier="2x")
root = tk.Tk(); root.withdraw()
try:
screen = DashboardScreen(root)
screen.refresh()
assert screen.winfo_exists()
finally:
root.destroy()
@pytest.mark.skipif(not _has_display(), reason="no display available")
def test_dashboard_refresh_empty_db(tmp_db):
import tkinter as tk
from ui.dashboard import DashboardScreen
root = tk.Tk(); root.withdraw()
try:
screen = DashboardScreen(root)
screen.refresh()
assert screen.winfo_exists()
finally:
root.destroy()
@pytest.mark.skipif(not _has_display(), reason="no display available")
def test_dashboard_on_fetch_callback(tmp_db):
import tkinter as tk
from ui.dashboard import DashboardScreen
called = []
root = tk.Tk(); root.withdraw()
try:
screen = DashboardScreen(root, on_fetch=lambda: called.append(1))
screen.refresh()
assert screen.winfo_exists()
finally:
root.destroy()