05/23 Phase 11

This commit is contained in:
2026-05-23 12:31:20 -04:00
parent f8c11b8979
commit 78e88ae8ab
5 changed files with 412 additions and 27 deletions
+168
View File
@@ -0,0 +1,168 @@
"""
tests/test_saved_predictions.py
--------------------------------
Tests for the saved-prediction model functions (delete_prediction,
delete_all_predictions) and the _count_matches helper in predictor_ui.
"""
import pytest
from db.models import (
get_game_by_name, insert_draw, insert_prediction,
get_predictions, delete_prediction, delete_all_predictions,
get_last_draw,
)
from ui.predictor_ui import _count_matches
# ── Fixtures ──────────────────────────────────────────────────────────────────
@pytest.fixture
def pb(tmp_db):
return get_game_by_name("Powerball")
@pytest.fixture
def mm(tmp_db):
return get_game_by_name("Mega Millions")
@pytest.fixture
def with_predictions(pb, mm):
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7)
p1 = insert_prediction(pb["id"], "Hot Numbers", [1, 13, 36, 61, 69], bonus=7)
p2 = insert_prediction(pb["id"], "Due Numbers", [5, 10, 20, 30, 40], bonus=15)
p3 = insert_prediction(mm["id"], "Monte Carlo", [2, 14, 37, 62, 70], bonus=5)
return p1, p2, p3
# ── delete_prediction ─────────────────────────────────────────────────────────
def test_delete_prediction_removes_row(pb, with_predictions):
p1, p2, p3 = with_predictions
delete_prediction(p1)
ids = [p["id"] for p in get_predictions(limit=100_000)]
assert p1 not in ids
assert p2 in ids
def test_delete_prediction_leaves_others_intact(pb, with_predictions):
p1, p2, p3 = with_predictions
delete_prediction(p1)
remaining = get_predictions(limit=100_000)
assert len(remaining) == 2
def test_delete_nonexistent_prediction_no_error(tmp_db):
delete_prediction(99999) # should not raise
# ── delete_all_predictions ────────────────────────────────────────────────────
def test_delete_all_clears_everything(pb, with_predictions):
delete_all_predictions()
assert get_predictions(limit=100_000) == []
def test_delete_all_with_game_id_only_removes_that_game(pb, mm, with_predictions):
p1, p2, p3 = with_predictions
delete_all_predictions(game_id=pb["id"])
remaining = get_predictions(limit=100_000)
assert len(remaining) == 1
assert remaining[0]["id"] == p3
def test_delete_all_empty_db_no_error(tmp_db):
delete_all_predictions() # should not raise
def test_delete_all_game_id_no_match_no_error(pb, tmp_db):
delete_all_predictions(game_id=pb["id"]) # nothing to delete
# ── _count_matches ────────────────────────────────────────────────────────────
def test_count_matches_full_match(pb):
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7)
last = get_last_draw(pb["id"])
assert _count_matches("1,13,36,61,69", last) == "5/5"
def test_count_matches_partial(pb):
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7)
last = get_last_draw(pb["id"])
assert _count_matches("1,13,2,3,4", last) == "2/5"
def test_count_matches_zero(pb):
insert_draw(pb["id"], "2024-01-01", [1, 13, 36, 61, 69], bonus=7)
last = get_last_draw(pb["id"])
assert _count_matches("2,3,4,5,6", last) == "0/5"
def test_count_matches_no_last_draw(tmp_db):
pb = get_game_by_name("Powerball")
assert _count_matches("1,2,3,4,5", None) == ""
# ── 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_predictor_screen_saved_tab_loads(tmp_db):
import tkinter as tk
from ui.predictor_ui import PredictorScreen
root = tk.Tk(); root.withdraw()
try:
screen = PredictorScreen(root)
screen.refresh()
assert screen.winfo_exists()
finally:
root.destroy()
@pytest.mark.skipif(not _has_display(), reason="no display available")
def test_saved_tab_shows_predictions(tmp_db):
import tkinter as tk
from ui.predictor_ui import PredictorScreen
pb = get_game_by_name("Powerball")
insert_prediction(pb["id"], "Hot Numbers", [1, 13, 36, 61, 69], bonus=7)
root = tk.Tk(); root.withdraw()
try:
screen = PredictorScreen(root)
screen.refresh()
children = screen._saved_tree.get_children()
assert len(children) == 1
finally:
root.destroy()
@pytest.mark.skipif(not _has_display(), reason="no display available")
def test_saved_tab_delete_selected(tmp_db):
import tkinter as tk
from ui.predictor_ui import PredictorScreen
pb = get_game_by_name("Powerball")
pid = insert_prediction(pb["id"], "Hot Numbers", [1, 13, 36, 61, 69], bonus=7)
root = tk.Tk(); root.withdraw()
try:
screen = PredictorScreen(root)
screen.refresh()
iid = screen._saved_tree.get_children()[0]
screen._saved_tree.selection_set(iid)
screen._delete_selected()
assert len(screen._saved_tree.get_children()) == 0
assert get_predictions(limit=100_000) == []
finally:
root.destroy()