"""Unit tests for rule-based parser.""" SAMPLE_TEXT_POSITIVE = """ Item 2.02 Results of Operations Apple today announced record quarterly revenue of $124.3 billion, up 9 percent year over year. Guidance raised for Q2: The Company expects revenue to be between $125 billion and $131 billion. Demand remains strong across all product categories. Gross margin expansion driven by Services mix. Customer additions in enterprise continue to accelerate. Backlog increased significantly year over year. Adjusted EPS excludes certain non-GAAP items. """ SAMPLE_TEXT_NEGATIVE = """ Item 2.02 Results of Operations Company reported revenue of $5.2 billion, missing expectations. Guidance lowered for next quarter due to demand softness. Margin compression continues. Financing need announced with dilutive convertible note offering. """ SAMPLE_TEXT_CONTRACT = """ Item 1.01 Entry into Material Agreement The Company has entered into a definitive agreement with a major enterprise customer for a multi-year supply contract worth $500 million. The contract includes recurring revenue. """ def test_parse_earnings_positive(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29"}) assert out.event_type == "earnings_release" assert out.guidance.status == "raised" assert out.signals.demand_strength == "strong" assert out.event_direction == "bullish" def test_parse_earnings_negative(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_NEGATIVE, {"filing_date": "2026-02-01"}) assert out.event_type == "earnings_release" assert out.guidance.status == "lowered" assert out.event_direction in ("bearish", "mixed") def test_parse_material_contract(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_CONTRACT, {"filing_date": "2026-02-15"}) assert out.event_type == "material_contract" def test_parse_non_gaap_flag(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29"}) assert out.risk_flags.non_gaap_heavy is True def test_parse_margin_improving(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29"}) assert out.signals.margin_quality == "improving" def test_parse_confidence_range(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29"}) assert 0.0 <= out.confidence.overall <= 1.0 def test_parse_document_id_preserved(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::my-id", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29"}) assert out.document_id == "DOC::my-id" def test_parse_schema_version(): from libs.parser.rule_parser import SCHEMA_VERSION, RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29"}) assert out.schema_version == SCHEMA_VERSION def test_parse_unknown_event(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse("DOC::test", "8-K", "No items mentioned here.", {"filing_date": "2026-01-29"}) assert out.event_type == "unknown" assert len(out.warnings) > 0 def test_parse_filing_time_bucket_set(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() out = p.parse( "DOC::test", "8-K", SAMPLE_TEXT_POSITIVE, {"filing_date": "2026-01-29", "accepted_at_utc": "2026-01-29T21:05:00Z"}, ) assert out.filing_time_bucket == "post_market" def test_parse_html_earnings_release_without_item_numbers(): from libs.parser.rule_parser import RuleBasedParser from libs.parser.text_normalizer import normalize_text p = RuleBasedParser() html = """
FOR IMMEDIATE RELEASE
Ciena Reports Fiscal First Quarter 2026 Financial Results
Providing revenue guidance of $1.5 billion plus or minus $50 million.
Raising revenue guidance range for fiscal year 2026.
""" out = p.parse( "DOC::test", "8-K", normalize_text(html, is_html=True), {"filing_date": "2026-03-05"}, ) assert out.event_type == "earnings_release" assert out.guidance.status == "raised" assert out.event_direction == "bullish" def test_guidance_withdrawn_does_not_match_distant_words(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() text = ( "The company may withdraw from certain trade agreements. " "Management also discussed guidance measures for fiscal 2026." ) out = p.parse("DOC::test", "8-K", text, {"filing_date": "2026-03-05"}) assert out.guidance.status == "not_provided" def test_positive_backlog_and_customer_signals_outweigh_single_financing_flag(): from libs.parser.rule_parser import RuleBasedParser p = RuleBasedParser() text = """ Company reports first quarter financial results. Raising full-year guidance. Backlog increased significantly year over year. Added new enterprise customers during the quarter. The release also references refinancing our term loan. """ out = p.parse("DOC::test", "8-K", text, {"filing_date": "2026-03-05"}) assert out.event_direction == "bullish"