e122f6435a
Add spruce scraper with CLI, session management, parsers, progress tracking, recheck logic, and test suite. Includes example config and README.
154 lines
4.0 KiB
Python
154 lines
4.0 KiB
Python
"""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)
|