Files
lottosight/tests/test_importer.py
T
2026-05-23 16:31:55 -04:00

229 lines
8.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
tests/test_importer.py
----------------------
Tests for core/importer.py — CSV draw import.
Powerball config: 5 main from 169, 1 bonus from 126.
"""
import os
import pytest
from db.models import get_game_by_name, add_game, get_draws_with_game
from core.importer import import_draws_csv, _parse_date
# ── _parse_date ───────────────────────────────────────────────────────────────
def test_parse_date_iso():
assert _parse_date("2024-01-15") == "2024-01-15"
def test_parse_date_us_slash():
assert _parse_date("01/15/2024") == "2024-01-15"
def test_parse_date_us_dash():
assert _parse_date("01-15-2024") == "2024-01-15"
def test_parse_date_invalid():
assert _parse_date("not-a-date") is None
def test_parse_date_header_text():
assert _parse_date("Date") is None
assert _parse_date("draw_date") is None
# ── Wide format (Date, N1, N2, ...) ──────────────────────────────────────────
def test_wide_no_header(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
"2024-01-01,1,13,36,61,69,7\n"
"2024-01-03,2,7,22,45,61,15\n"
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 2
assert result["skipped"] == 0
assert result["errors"] == []
def test_wide_with_header(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
"Date,Ball1,Ball2,Ball3,Ball4,Ball5,Bonus\n"
"2024-01-01,1,13,36,61,69,7\n"
"2024-01-03,2,7,22,45,61,15\n"
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 2
assert result["errors"] == []
def test_wide_no_bonus_column(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text("2024-01-01,1,13,36,61,69\n")
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 1
draws = get_draws_with_game(game_id=game["id"])
assert draws[0]["bonus"] is None
def test_wide_us_date_format(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text("01/15/2024,5,14,22,36,69,7\n")
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 1
draws = get_draws_with_game(game_id=game["id"])
assert draws[0]["draw_date"] == "2024-01-15"
# ── Packed format (Date, "N1,N2,...", Bonus) ──────────────────────────────────
def test_packed_format(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text('2024-01-01,"1,13,36,61,69",7\n')
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 1
assert result["errors"] == []
def test_packed_with_header(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
'Date,Numbers,Bonus\n'
'2024-01-01,"1,13,36,61,69",7\n'
'2024-01-03,"2,7,22,45,61",15\n'
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 2
# ── LottoSight export format ──────────────────────────────────────────────────
def test_lottosight_export_format(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "export.csv"
csv_file.write_text(
"Game,Date,Numbers,Bonus,Multiplier,Source\n"
'Powerball,2024-01-01,"1,13,36,61,69",7,2x,powerball_ny\n'
'Powerball,2024-01-03,"2,7,22,45,61",15,3x,powerball_ny\n'
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 2
assert result["errors"] == []
# ── Duplicate detection ───────────────────────────────────────────────────────
def test_duplicate_skipped(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
"2024-01-01,1,13,36,61,69,7\n"
"2024-01-01,1,13,36,61,69,7\n" # same date → duplicate
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 1
assert result["skipped"] == 1
def test_reimport_all_skipped(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text("2024-01-01,1,13,36,61,69,7\n")
import_draws_csv(game["id"], str(csv_file))
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 0
assert result["skipped"] == 1
# ── Validation errors ─────────────────────────────────────────────────────────
def test_wrong_number_count(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text("2024-01-01,1,13,36,61\n") # only 4 numbers
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 0
assert len(result["errors"]) == 1 # rejected — too few numbers to parse
def test_number_out_of_range(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text("2024-01-01,1,13,36,61,99,7\n") # 99 > 69
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 0
assert len(result["errors"]) == 1
def test_mixed_valid_invalid(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
"2024-01-01,1,13,36,61,69,7\n"
"bad_date,1,2,3,4,5,6\n" # unparseable
"2024-01-03,2,7,22,45,61,15\n"
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 2
assert len(result["errors"]) == 1
# ── Edge cases ────────────────────────────────────────────────────────────────
def test_file_not_found(tmp_db):
game = get_game_by_name("Powerball")
result = import_draws_csv(game["id"], "/nonexistent/path/file.csv")
assert result["added"] == 0
assert len(result["errors"]) == 1
assert "not found" in result["errors"][0].lower()
def test_empty_file(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "empty.csv"
csv_file.write_text("")
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 0
assert result["errors"] == ["File is empty"]
def test_blank_lines_ignored(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
"2024-01-01,1,13,36,61,69,7\n"
"\n"
"2024-01-03,2,7,22,45,61,15\n"
"\n"
)
result = import_draws_csv(game["id"], str(csv_file))
assert result["added"] == 2
assert result["errors"] == []
def test_unknown_game_id(tmp_db, tmp_path):
csv_file = tmp_path / "draws.csv"
csv_file.write_text("2024-01-01,1,2,3,4,5\n")
result = import_draws_csv(99999, str(csv_file))
assert result["added"] == 0
assert len(result["errors"]) == 1
def test_custom_game_import(tmp_db, tmp_path):
gid = add_game("My Lotto", 6, 49, bonus_count=0, bonus_max=0)
csv_file = tmp_path / "draws.csv"
csv_file.write_text(
"2024-01-01,5,14,22,33,41,48\n"
"2024-01-08,3,17,28,35,44,49\n"
)
result = import_draws_csv(gid, str(csv_file))
assert result["added"] == 2
assert result["errors"] == []
def test_data_persisted_correctly(tmp_db, tmp_path):
game = get_game_by_name("Powerball")
csv_file = tmp_path / "draws.csv"
csv_file.write_text("2024-03-15,5,14,22,36,69,7\n")
import_draws_csv(game["id"], str(csv_file))
draws = get_draws_with_game(game_id=game["id"])
assert len(draws) == 1
assert draws[0]["draw_date"] == "2024-03-15"
nums = [int(n) for n in draws[0]["numbers"].split(",")]
assert sorted(nums) == [5, 14, 22, 36, 69]
assert str(draws[0]["bonus"]) == "7"