"""Unit tests for the OfficeConnect HTML/JS parsers. Fixtures are real pages captured from an HPE OfficeConnect 1820 8G PoE+ (J9982A, firmware PT.02.19), scrubbed of serial number, MAC addresses, IP addresses and hostname. """ import pathlib import pytest from napalm_hpe_officeconnect import parsers FIXTURES = pathlib.Path(__file__).parent.parent / "fixtures" def fixture(name: str) -> str: return (FIXTURES / f"{name}.html").read_text(encoding="utf-8") # =========================================================================== # extract_data_set — the DataTables payload every list page ships # =========================================================================== def test_extract_data_set_returns_one_row_per_port(): """port_summary carries 8 physical ports plus 4 trunk interfaces.""" rows = parsers.extract_data_set(fixture("base_port_summary")) assert len(rows) == 12 assert all(isinstance(r, list) for r in rows) def test_extract_data_set_preserves_cell_values(): rows = parsers.extract_data_set(fixture("base_port_summary")) # Columns: [checkbox, interface, description, admin, phy type, status, ...] assert rows[0][1] == "1" assert rows[0][3] == "Enabled" assert rows[2][5] == "Link Up" assert rows[2][7] == "1000 Mbps" def test_extract_data_set_handles_rows_without_markup(): """mac_address_table rows are plain values, no embedded checkbox cell.""" rows = parsers.extract_data_set(fixture("base_mac_address_table")) assert len(rows) == 17 assert rows[0] == ["1", "00:11:22:33:44:01", "7", "7", "Learned"] def test_extract_data_set_handles_empty_cells(): """Counter columns are empty strings on a port that never linked up.""" rows = parsers.extract_data_set(fixture("base_port_summary_stats")) assert rows[0] == ["1", "", "", "", "", "", "", "", ""] def test_extract_data_set_returns_empty_list_when_absent(): assert parsers.extract_data_set("nothing here") == [] # =========================================================================== # extract_column_titles — used to assert the firmware layout hasn't shifted # =========================================================================== def test_extract_column_titles(): titles = parsers.extract_column_titles(fixture("switching_vlan_status")) assert titles == ["VLAN ID", "Name", "Type"] def test_extract_column_titles_skips_markup_only_header(): """The leading checkbox column has an as its title, not text.""" titles = parsers.extract_column_titles(fixture("base_mac_address_table")) assert titles == ["VLAN ID", "MAC Address", "Interface", "Interface Index", "Status"] # =========================================================================== # strip_markup — the checkbox cell must collapse to an empty string # =========================================================================== @pytest.mark.parametrize( "raw,expected", [ ('', ""), ("plain value", "plain value"), (" spaced&out ", "spaced&out"), ("", ""), ], ) def test_strip_markup(raw, expected): assert parsers.strip_markup(raw) == expected # =========================================================================== # parse_uptime # =========================================================================== @pytest.mark.parametrize( "raw,expected", [ ("0 days, 18 hours, 44 mins, 40 secs", 67480), ("3 days, 0 hours, 0 mins, 0 secs", 259200), ("0 days, 0 hours, 0 mins, 1 secs", 1), ], ) def test_parse_uptime(raw, expected): assert parsers.parse_uptime(raw) == expected def test_parse_uptime_returns_negative_one_when_unparseable(): """NAPALM's convention for 'uptime unknown' is -1, not 0.""" assert parsers.parse_uptime("nonsense") == -1 # =========================================================================== # parse_facts — dashboard.lsp # =========================================================================== def test_parse_facts(): facts = parsers.parse_facts(fixture("base_dashboard")) assert facts["hostname"] == "testswitch" assert facts["serial_number"] == "CN0FIXTURE0" assert facts["os_version"] == "PT.02.19" assert facts["model"] == "HPE OfficeConnect Switch 1820 8G PoE+ (65W) J9982A" assert facts["uptime"] == 67480 assert facts["sys_object_id"] == "1.3.6.1.4.1.11.2.3.7.11.170" def test_parse_facts_tolerates_missing_fields(): facts = parsers.parse_facts("") assert facts["hostname"] == "" assert facts["serial_number"] == "" assert facts["uptime"] == -1