"""Test SQLite cache operations.""" from __future__ import annotations import os import tempfile from datetime import date import pytest from src.cache import Cache from src.models import Bill, Legislator, Summary, Vote @pytest.fixture def cache() -> Cache: fd, path = tempfile.mkstemp(suffix=".db") c = Cache(path) yield c c.close() os.close(fd) os.unlink(path) # --- Legislators --- def test_save_and_get_legislator(cache: Cache): leg = Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", in_office=True, start_date=date(2025, 1, 3), end_date=None, ) cache.save_legislator(leg) fetched = cache.get_legislator("L001") assert fetched is not None assert fetched.id == "L001" assert fetched.full_name == "John Doe" assert fetched.party == "Democrat" assert fetched.start_date == date(2025, 1, 3) assert fetched.end_date is None def test_get_missing_legislator(cache: Cache): assert cache.get_legislator("MISSING") is None def test_search_legislators(cache: Cache): cache.save_legislator( Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", ) ) cache.save_legislator( Legislator( id="L002", first_name="Jane", last_name="Smith", full_name="Jane Smith", party="Republican", state="NY", chamber="House", ) ) results = cache.search_legislators("John") assert len(results) == 1 assert results[0].full_name == "John Doe" results = cache.search_legislators("Smith") assert len(results) == 1 assert results[0].last_name == "Smith" def test_legislator_retired(cache: Cache): leg = Legislator( id="M000355", first_name="Mitch", last_name="McConnell", full_name="Mitch McConnell", party="Republican", state="KY", chamber="Senate", in_office=False, start_date=date(1985, 1, 3), end_date=date(2025, 12, 31), ) cache.save_legislator(leg) fetched = cache.get_legislator("M000355") assert fetched is not None assert fetched.in_office is False assert fetched.start_date == date(1985, 1, 3) assert fetched.end_date == date(2025, 12, 31) def test_legislator_update(cache: Cache): """Updating a legislator preserves all fields.""" leg = Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", start_date=date(2025, 1, 3), end_date=None, ) cache.save_legislator(leg) leg.party = "Independent" leg.in_office = False leg.end_date = date(2027, 12, 31) cache.save_legislator(leg) fetched = cache.get_legislator("L001") assert fetched.party == "Independent" assert fetched.in_office is False assert fetched.end_date == date(2027, 12, 31) assert fetched.start_date == date(2025, 1, 3) # --- Bills --- def test_save_and_get_bill(cache: Cache): bill = Bill(bill_id="B100", title="Test Bill", subject="Education", text="Full text", enacted=True) cache.save_bill(bill) fetched = cache.get_bill("B100") assert fetched is not None assert fetched.title == "Test Bill" assert fetched.subject == "Education" assert fetched.enacted is True def test_get_missing_bill(cache: Cache): assert cache.get_bill("MISSING") is None # --- Votes --- def test_save_and_get_vote(cache: Cache): cache.save_legislator( Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", ) ) vote = Vote(legislator_id="L001", roll_call_id="RC001", vote_type="Yea", bill_id="B100", bill_title="Test Bill") cache.save_vote(vote) votes = cache.get_votes("L001") assert len(votes) == 1 assert votes[0].vote_type == "Yea" def test_save_multiple_votes(cache: Cache): cache.save_legislator( Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", ) ) cache.save_votes( [ Vote(legislator_id="L001", roll_call_id="RC001", vote_type="Yea", bill_id="B100", bill_title="Bill A"), Vote(legislator_id="L001", roll_call_id="RC002", vote_type="Nay", bill_id="B101", bill_title="Bill B"), ] ) votes = cache.get_votes("L001") assert len(votes) == 2 def test_vote_duplicate_ignored(cache: Cache): """INSERT OR IGNORE prevents duplicate votes.""" cache.save_legislator( Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", ) ) vote = Vote(legislator_id="L001", roll_call_id="RC001", vote_type="Yea", bill_id="B100", bill_title="Test Bill") cache.save_vote(vote) cache.save_vote(vote) votes = cache.get_votes("L001") assert len(votes) == 1 # --- Summaries --- def test_save_and_get_summary(cache: Cache): cache.save_bill(Bill(bill_id="B100", title="Test Bill", subject="Education")) summary = Summary( bill_id="B100", summary_text="This bill does X.", key_measures=["Measure A", "Measure B"], model_name="gpt-oss", ) cache.save_summary(summary) fetched = cache.get_summary("B100") assert fetched is not None assert fetched.summary_text == "This bill does X." assert fetched.key_measures == ["Measure A", "Measure B"] assert fetched.model_name == "gpt-oss" def test_get_missing_summary(cache: Cache): assert cache.get_summary("MISSING") is None # --- Voting Record --- def test_voting_record(cache: Cache): cache.save_legislator( Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", ) ) cache.save_bill(Bill(bill_id="B100", title="Test Bill", subject="Education")) cache.save_vote( Vote(legislator_id="L001", roll_call_id="RC001", vote_type="Yea", bill_id="B100", bill_title="Test Bill") ) records, total = cache.get_voting_record("L001") assert len(records) == 1 assert total == 1 assert records[0]["vote_type"] == "Yea" assert records[0]["bill_title"] == "Test Bill" def test_voting_record_empty(cache: Cache): records, total = cache.get_voting_record("MISSING") assert records == [] assert total == 0 def test_voting_record_pagination(cache: Cache): cache.save_legislator( Legislator( id="L001", first_name="John", last_name="Doe", full_name="John Doe", party="Democrat", state="CA", chamber="Senate", ) ) cache.save_votes( [ Vote(legislator_id="L001", roll_call_id=f"RC{i}", vote_type="Yea", bill_id=f"B{i}", bill_title=f"Bill {i}") for i in range(10) ] ) records, total = cache.get_voting_record("L001", limit=3, offset=0) assert len(records) == 3 assert total == 10 records, total = cache.get_voting_record("L001", limit=3, offset=3) assert len(records) == 3 records, total = cache.get_voting_record("L001", limit=3, offset=9) assert len(records) == 1