05/23 Phase 18,19
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
"""
|
||||
tests/test_importer.py
|
||||
----------------------
|
||||
Tests for core/importer.py — CSV draw import.
|
||||
|
||||
Powerball config: 5 main from 1–69, 1 bonus from 1–26.
|
||||
"""
|
||||
|
||||
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"
|
||||
Reference in New Issue
Block a user