from __future__ import annotations import json from datetime import UTC, date, datetime from pathlib import Path from findata_fundamentals import ( SecEdgarConnector, available_at_policy, facts_from_companyfacts, facts_from_financials, ) FIX = Path(__file__).parent / "fixtures" / "fundamentals" NOW = datetime(2026, 11, 1, 12, 0, tzinfo=UTC) def test_available_at_policy_is_next_day_midnight_et(): # filing 2026-07-31 → available 2026-08-01 00:00 EDT = 2026-08-01 04:00 UTC assert available_at_policy(date(2026, 7, 31), date(2026, 6, 27)) == datetime(2026, 8, 1, 4, 0, tzinfo=UTC) # winter: 2026-01-30 → 2026-01-31 00:00 EST = 05:00 UTC assert available_at_policy(date(2026, 1, 30), date(2025, 12, 27)) == datetime(2026, 1, 31, 5, 0, tzinfo=UTC) # missing filing date → period_end + 90 d + 1 assert available_at_policy(None, date(2026, 6, 30)).date() == date(2026, 9, 29) def test_facts_from_financials_long_format(): payload = json.loads((FIX / "financials_all_AAPL_quarterly.json").read_text()) facts = list(facts_from_financials(payload, NOW)) assert len(facts) > 12 * 50 latest = [f for f in facts if f["fiscal_period_end"] == date(2026, 6, 27)] rev = next(f for f in latest if f["metric"] == "rev") assert rev["value"] == 109417000000.0 and rev["unit"] == "USD" and rev["fiscal_period_type"] == "q" assert rev["filing_date"] == date(2026, 7, 31) and rev["available_at"] == datetime(2026, 8, 1, 4, 0, tzinfo=UTC) assert rev["entity_id"] == "frd:AAPL" and rev["source_id"] == "firstrate_fundamentals" and rev["pit_fallback"] is False assert all(f["available_at"] > datetime.combine(f["fiscal_period_end"], datetime.min.time(), tzinfo=UTC) for f in facts) def test_sec_edgar_pending_without_user_agent(): c = SecEdgarConnector(user_agent="") assert c.status()["status"] == "pending_configuration" try: c.companyfacts(320193) raise AssertionError("must refuse without user agent") except RuntimeError as e: assert "pending configuration" in str(e) def test_companyfacts_parsing_keeps_each_filing_as_revision(): payload = {"cik": 320193, "entityName": "Apple Inc.", "facts": {"us-gaap": {"Revenues": {"units": {"USD": [ {"start": "2024-09-29", "end": "2024-12-28", "val": 124300000000, "accn": "0000320193-25-000008", "fy": 2025, "fp": "Q1", "form": "10-Q", "filed": "2025-01-31", "frame": "CY2024Q4"}, {"start": "2024-09-29", "end": "2024-12-28", "val": 124300000001, "accn": "0000320193-25-000999", "fy": 2025, "fp": "Q2", "form": "10-Q", "filed": "2025-05-02"}, {"start": "2023-10-01", "end": "2024-09-28", "val": 391035000000, "accn": "0000320193-24-000123", "fy": 2024, "fp": "FY", "form": "10-K", "filed": "2024-11-01"}, ]}}}}} facts = list(facts_from_companyfacts(payload, NOW)) assert len(facts) == 3 q = [f for f in facts if f["fiscal_period_end"] == date(2024, 12, 28)] assert sorted(f["filing_date"] for f in q) == [date(2025, 1, 31), date(2025, 5, 2)] assert q[0]["available_at"] == datetime(2025, 2, 1, 5, 0, tzinfo=UTC) fy = next(f for f in facts if f["fiscal_period_type"] == "a") assert fy["metric"] == "rev" and fy["entity_id"] == "sec:CIK0000320193"