203 lines
6.3 KiB
Python
203 lines
6.3 KiB
Python
"""
|
|
tests/test_dashboard.py
|
|
------------------------
|
|
Tests for the Dashboard screen data layer and UI smoke tests.
|
|
"""
|
|
|
|
from datetime import date
|
|
|
|
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
|
|
from ui.dashboard import _next_draw_date
|
|
|
|
|
|
# ── 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
|
|
|
|
|
|
|
|
# ── _next_draw_date ───────────────────────────────────────────────────────────
|
|
|
|
def test_next_draw_powerball_from_friday():
|
|
# Friday → next Powerball is Saturday
|
|
fri = date(2024, 5, 24) # Friday, weekday=4
|
|
result = _next_draw_date("Powerball", from_date=fri)
|
|
assert "Sat" in result
|
|
|
|
|
|
def test_next_draw_powerball_from_saturday():
|
|
# Saturday → next Powerball is Monday
|
|
sat = date(2024, 5, 25) # Saturday, weekday=5
|
|
result = _next_draw_date("Powerball", from_date=sat)
|
|
assert "Mon" in result
|
|
|
|
|
|
def test_next_draw_mega_millions_from_friday():
|
|
# Friday → next MM is Tuesday (4 days away)
|
|
fri = date(2024, 5, 24)
|
|
result = _next_draw_date("Mega Millions", from_date=fri)
|
|
assert "Tue" in result
|
|
|
|
|
|
def test_next_draw_mega_millions_from_monday():
|
|
# Monday → next MM is Tuesday (1 day away)
|
|
mon = date(2024, 5, 20) # Monday, weekday=0
|
|
result = _next_draw_date("Mega Millions", from_date=mon)
|
|
assert "Tue" in result
|
|
|
|
|
|
def test_next_draw_unknown_game_returns_empty():
|
|
assert _next_draw_date("Unknown Game") == ""
|
|
|
|
|
|
def test_next_draw_always_in_future():
|
|
today = date.today()
|
|
for name in ("Powerball", "Mega Millions"):
|
|
result = _next_draw_date(name, from_date=today)
|
|
assert result != "" # always finds a future date within 7 days
|
|
|
|
|
|
# ── 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
|
|
|
|
try:
|
|
root = tk.Tk(); root.withdraw()
|
|
except Exception:
|
|
pytest.skip("Tkinter init failed")
|
|
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")
|
|
|
|
try:
|
|
root = tk.Tk(); root.withdraw()
|
|
except Exception:
|
|
pytest.skip("Tkinter init failed")
|
|
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
|
|
|
|
try:
|
|
root = tk.Tk(); root.withdraw()
|
|
except Exception:
|
|
pytest.skip("Tkinter init failed")
|
|
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()
|