""" Tests for House Stock Watcher client. """ from unittest.mock import MagicMock, patch from pote.ingestion.house_watcher import ( HouseWatcherClient, normalize_transaction_type, parse_amount_range, ) def test_parse_amount_range_with_range(): """Test parsing amount range string.""" min_val, max_val = parse_amount_range("$1,001 - $15,000") assert min_val == 1001.0 assert max_val == 15000.0 def test_parse_amount_range_single_value(): """Test parsing single value.""" min_val, max_val = parse_amount_range("$25,000") assert min_val == 25000.0 assert max_val == 25000.0 def test_parse_amount_range_invalid(): """Test parsing invalid amount.""" min_val, max_val = parse_amount_range("N/A") assert min_val is None assert max_val is None def test_normalize_transaction_type(): """Test normalizing transaction types.""" assert normalize_transaction_type("Purchase") == "buy" assert normalize_transaction_type("Sale") == "sell" assert normalize_transaction_type("Exchange") == "exchange" assert normalize_transaction_type("purchase") == "buy" assert normalize_transaction_type("SALE") == "sell" @patch("pote.ingestion.house_watcher.httpx.Client") def test_fetch_all_transactions(mock_client_class): """Test fetching all transactions.""" # Mock response mock_response = MagicMock() mock_response.json.return_value = [ { "representative": "Test Official", "ticker": "AAPL", "transaction_date": "2024-01-15", "disclosure_date": "2024-02-01", "transaction": "Purchase", "amount": "$1,001 - $15,000", "house": "House", "party": "Independent", } ] mock_response.raise_for_status = MagicMock() mock_client_instance = MagicMock() mock_client_instance.get.return_value = mock_response mock_client_class.return_value = mock_client_instance with HouseWatcherClient() as client: txns = client.fetch_all_transactions() assert len(txns) == 1 assert txns[0]["ticker"] == "AAPL" assert txns[0]["representative"] == "Test Official" @patch("pote.ingestion.house_watcher.httpx.Client") def test_fetch_all_transactions_with_limit(mock_client_class): """Test fetching transactions with limit.""" mock_response = MagicMock() mock_response.json.return_value = [{"id": i} for i in range(100)] mock_response.raise_for_status = MagicMock() mock_client_instance = MagicMock() mock_client_instance.get.return_value = mock_response mock_client_class.return_value = mock_client_instance with HouseWatcherClient() as client: txns = client.fetch_all_transactions(limit=10) assert len(txns) == 10 @patch("pote.ingestion.house_watcher.httpx.Client") def test_fetch_recent_transactions(mock_client_class): """Test filtering to recent transactions.""" from datetime import date, timedelta today = date.today() recent_date = (today - timedelta(days=5)).strftime("%m/%d/%Y") old_date = (today - timedelta(days=100)).strftime("%m/%d/%Y") mock_response = MagicMock() mock_response.json.return_value = [ {"disclosure_date": recent_date, "ticker": "AAPL"}, {"disclosure_date": old_date, "ticker": "MSFT"}, {"disclosure_date": recent_date, "ticker": "GOOGL"}, ] mock_response.raise_for_status = MagicMock() mock_client_instance = MagicMock() mock_client_instance.get.return_value = mock_response mock_client_class.return_value = mock_client_instance with HouseWatcherClient() as client: recent = client.fetch_recent_transactions(days=30) assert len(recent) == 2 assert recent[0]["ticker"] == "AAPL" assert recent[1]["ticker"] == "GOOGL" def test_house_watcher_client_context_manager(): """Test client as context manager.""" with HouseWatcherClient() as client: assert client is not None # Verify close was called (client should be closed after context)