"""Tests for spruce.parsers — all pure, no network required.""" import pytest from spruce.parsers import ( _grid_count, _grid_values, parse_machine_option, parse_scan_row, parse_scan_view, ) # --------------------------------------------------------------------------- # parse_machine_option # --------------------------------------------------------------------------- def test_parse_machine_option_basic(): raw = "BW3%2D20%20%5BAMR%2D26%5D|205.149.147.130|17026|26|8026|3.0.0.33|50.00" m = parse_machine_option("BW3-20 [AMR-26]", raw) assert m["label"] == "BW3-20 [AMR-26]" assert m["machine_id"] == "26" assert m["ip"] == "205.149.147.130" assert m["version"] == "3.0.0.33" assert m["option_value"] == raw def test_parse_machine_option_short_value(): # Fewer pipe-delimited parts should not raise; missing fields return "" m = parse_machine_option("Lonely Machine", "LM|10.0.0.1") assert m["ip"] == "10.0.0.1" assert m["machine_id"] == "" assert m["port2"] == "" # --------------------------------------------------------------------------- # parse_scan_row # --------------------------------------------------------------------------- VALID_CELLS = [ "158374", "Plot 20 AMR26 Full Tube Scan", "2024-07-29 05:00", "mm", "(0,0)-(310,740)-(3.01,2.26)", "100", "Horizontal", "Raster", "2024-07-29 04:59:46", "2024-07-30 02:51:07", "0", "SPRUCE", "Completed", "X", ] def test_parse_scan_row_valid(): sc = parse_scan_row(VALID_CELLS) assert sc is not None assert sc["scan_id"] == 158374 assert sc["name"] == "Plot 20 AMR26 Full Tube Scan" assert sc["status"] == "Completed" assert sc["scan_time"] == "2024-07-29 05:00" def test_parse_scan_row_ignores_non_digit_first_cell(): assert parse_scan_row(["ID", "Name", "Scan Time"]) is None assert parse_scan_row(["Scan ID:", "158374"]) is None def test_parse_scan_row_empty(): assert parse_scan_row([]) is None def test_parse_scan_row_minimal(): sc = parse_scan_row(["42"]) assert sc is not None assert sc["scan_id"] == 42 assert sc["name"] == "" # --------------------------------------------------------------------------- # parse_scan_view (uses fixture HTML from conftest.py) # --------------------------------------------------------------------------- def test_parse_scan_view_scan_id(scan_view_html): meta = parse_scan_view(scan_view_html) assert meta.get("scan_id") == 158374 def test_parse_scan_view_grid_dimensions(scan_view_html): meta = parse_scan_view(scan_view_html) assert meta.get("nx") == 103 assert meta.get("ny") == 328 def test_parse_scan_view_step_sizes(scan_view_html): meta = parse_scan_view(scan_view_html) assert meta.get("dx") == pytest.approx(3.01) assert meta.get("dy") == pytest.approx(2.26) def test_parse_scan_view_total_tiles(scan_view_html): meta = parse_scan_view(scan_view_html) # 103 × 328 = 33784 assert meta.get("total_tiles") == 103 * 328 def test_parse_scan_view_empty_string(): meta = parse_scan_view("") assert meta == {} # --------------------------------------------------------------------------- # _grid_count # --------------------------------------------------------------------------- def test_grid_count_typical(): assert _grid_count(0, 310, 3.01) == 103 assert _grid_count(0, 740, 2.26) == 328 def test_grid_count_zero_step(): assert _grid_count(0, 100, 0) == 0 def test_grid_count_single(): assert _grid_count(0, 1, 1) == 1 # --------------------------------------------------------------------------- # _grid_values # --------------------------------------------------------------------------- def test_grid_values_basic(): vals = _grid_values(0.0, 3, 3.01) assert vals == [0.0, 3.01, 6.02] def test_grid_values_empty(): assert _grid_values(0.0, 0, 1.0) == [] def test_grid_values_rounded(): # Floating-point accumulation should be rounded to 2 dp vals = _grid_values(0.0, 4, 0.1) for v in vals: assert v == round(v, 2)