"""Tests for the 271 (Eligibility Benefit Response) parser. SP3 Phase 4 (T21): single-pass segment walker that pulls the information source / receiver / subscriber / patient / EB coverage benefits out of a tokenized 271. The fixture (``tests/fixtures/minimal_271.txt``) has two EB segments with descriptions — one Medical Care, one Pharmacy — so we can assert both the count and the per-benefit resolution of service-type codes. """ from __future__ import annotations from pathlib import Path import pytest from cyclone.parsers.parse_271 import parse FIXTURE = Path(__file__).parent / "fixtures" / "minimal_271.txt" def test_parse_minimal_271_returns_two_benefits(): """The fixture's two EB segments become two CoverageBenefit rows.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") assert len(result.coverage_benefits) == 2 # First EB: medical care (code "1"). Second: pharmacy (code "88"). assert result.coverage_benefits[0].service_type_code == "1" assert result.coverage_benefits[1].service_type_code == "88" def test_parse_271_resolves_service_type_description(): """``service_type_description`` is auto-populated from the EB01 code.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") assert result.coverage_benefits[0].service_type_description == "Medical Care" assert result.coverage_benefits[1].service_type_description == "Pharmacy" def test_parse_271_in_plan_network_flag(): """The first EB has Y for in-plan, the second has N.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") assert result.coverage_benefits[0].in_plan_network is True assert result.coverage_benefits[1].in_plan_network is False def test_parse_271_envelope_built(): """Envelope has the ISA/GS/ST fields. ST03 = implementation guide.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") env = result.envelope assert env.sender_id.strip() == "PAYERID" assert env.receiver_id.strip() == "PROVIDERID" assert env.control_number == "000000002" assert env.implementation_guide == "005010X279A1" # GS04 supplies the transaction date. assert env.transaction_date.year == 2024 assert env.transaction_date.month == 1 assert env.transaction_date.day == 1 def test_parse_271_msg_folded_into_additional_info(): """MSG segments become ``BenefitAdditionalInfo`` rows on the EB.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") cb0 = result.coverage_benefits[0] assert len(cb0.additional_info) == 1 assert cb0.additional_info[0].description == "Patient has active coverage" cb1 = result.coverage_benefits[1] assert len(cb1.additional_info) == 1 assert cb1.additional_info[0].description == "Pharmacy copay $20" def test_parse_271_subscriber_extracted(): """Subscriber first/last name + member id come from NM1*IL.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") assert result.subscriber.first_name == "JOHN" assert result.subscriber.last_name == "DOE" assert result.subscriber.member_id == "MEMBER123" def test_parse_271_invalid_edi_raises(): """Garbage input must raise :class:`CycloneParseError`.""" from cyclone.parsers.exceptions import CycloneParseError with pytest.raises(CycloneParseError): parse("not edi at all", input_file="garbage.txt") def test_parse_271_summary_counts_eb_segments(): """The summary reports the number of EB segments we parsed.""" text = FIXTURE.read_text() result = parse(text, input_file="minimal_271.txt") assert result.summary.total_claims == 2 assert result.summary.passed == 2 assert result.summary.failed == 0 assert result.summary.input_file == "minimal_271.txt"