05/23 Phase 11
This commit is contained in:
@@ -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()
|
||||
Reference in New Issue
Block a user