"""Tests for extract_categories.py - extracting unique categories from b4w CSV exports.""" import csv import sys from pathlib import Path sys.path.insert(0, str(Path(__file__).parent.parent / "scripts")) from scripts.initial_load.categories.extract_categories import extract_unique_categories def write_csv(path: Path, categories: list[str]) -> None: with open(path, "w", encoding="utf-8") as f: writer = csv.DictWriter(f, fieldnames=["Id", "AcctId", "Category"]) writer.writeheader() for i, category in enumerate(categories, 1): writer.writerow({"Id": str(i), "AcctId": "587713594", "Category": category}) def read_lines(path: Path) -> list[str]: return path.read_text(encoding="utf-8").splitlines() def test_extract_unique_categories_basic(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" write_csv(csv_file, ["Girokonto:Lebenshaltung", "Girokonto:Sparen"]) result = extract_unique_categories(str(csv_file), str(output_file)) assert result == ["Girokonto:Lebenshaltung", "Girokonto:Sparen"] assert read_lines(output_file) == ["Girokonto:Lebenshaltung", "Girokonto:Sparen"] def test_extract_unique_categories_no_duplicates(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" write_csv( csv_file, ["Girokonto:Lebenshaltung", "Girokonto:Sparen", "Girokonto:Lebenshaltung"], ) extract_unique_categories(str(csv_file), str(output_file)) assert len(read_lines(output_file)) == 2 def test_extract_unique_categories_output_format(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" write_csv( csv_file, ["Girokonto:Lebenshaltung", "Girokonto:Sparen", "Girokonto:Privat"], ) extract_unique_categories(str(csv_file), str(output_file)) lines = read_lines(output_file) assert len(lines) == 3 # Plain list: no numbering prefix, no blank lines. assert all(line == line.strip() and not line[0].isdigit() for line in lines) def test_extract_unique_categories_german_special_chars(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" write_csv( csv_file, ["Girokonto:Freizeit:Urlaub&Ausflüge", "Girokonto:Privat:Mitgliedsbeiträge"], ) extract_unique_categories(str(csv_file), str(output_file)) assert read_lines(output_file) == [ "Girokonto:Freizeit:Urlaub&Ausflüge", "Girokonto:Privat:Mitgliedsbeiträge", ] def test_extract_unique_categories_handles_empty_csv(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" csv_file.write_text("Id,AcctId,Category\n", encoding="utf-8") extract_unique_categories(str(csv_file), str(output_file)) assert output_file.exists() assert read_lines(output_file) == [] def test_extract_unique_categories_handles_csv_with_all_empty_categories(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" csv_file.write_text( "Id,AcctId,Category\n1,587713594,\n2,587713594,\n3,587713594,\n", encoding="utf-8", ) extract_unique_categories(str(csv_file), str(output_file)) assert read_lines(output_file) == [] def test_extract_unique_categories_rerun_is_idempotent(tmp_path): csv_file = tmp_path / "input.csv" output_file = tmp_path / "categories.txt" write_csv(csv_file, ["Girokonto:Lebenshaltung", "Girokonto:Sparen"]) extract_unique_categories(str(csv_file), str(output_file)) first_run = read_lines(output_file) # A new category appears in the CSV on the second run. write_csv( csv_file, ["Girokonto:Lebenshaltung", "Girokonto:Sparen", "Girokonto:Privat"] ) extract_unique_categories(str(csv_file), str(output_file)) second_run = read_lines(output_file) # Existing entries are merged, not duplicated; list stays sorted and plain. assert second_run == [ "Girokonto:Lebenshaltung", "Girokonto:Privat", "Girokonto:Sparen", ] assert first_run == ["Girokonto:Lebenshaltung", "Girokonto:Sparen"]