141 lines
4.7 KiB
Python
141 lines
4.7 KiB
Python
"""Tests for channel grid component."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from impakt.io.mme import MMEReader
|
|
from impakt.web.components.channel_grid import (
|
|
_build_channel_rows,
|
|
build_selected_channels_badges,
|
|
filter_rows,
|
|
)
|
|
from impakt.web.state import AppState
|
|
|
|
FIXTURE_DATA = Path(__file__).parent.parent / "fixtures" / "sample_mme"
|
|
MME_DATA = Path(__file__).parent.parent / "mme_data"
|
|
|
|
|
|
class TestChannelRows:
|
|
def test_build_rows_from_synthetic(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
rows = _build_channel_rows(state)
|
|
assert len(rows) == 26
|
|
# Each row should have required fields
|
|
for r in rows:
|
|
assert "key" in r
|
|
assert "iso_code" in r
|
|
assert "unit" in r
|
|
assert "min" in r
|
|
assert "max" in r
|
|
assert "::" in r["key"]
|
|
|
|
@pytest.mark.skipif(not (MME_DATA / "3239").exists(), reason="Real data not available")
|
|
def test_build_rows_from_real_data(self):
|
|
state = AppState()
|
|
state.load_test(MME_DATA / "3239")
|
|
rows = _build_channel_rows(state)
|
|
assert len(rows) == 133
|
|
|
|
def test_multi_test_rows_have_test_id(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
if (MME_DATA / "VW1FGS15").exists():
|
|
state.load_test(MME_DATA / "VW1FGS15")
|
|
rows = _build_channel_rows(state)
|
|
assert len(rows) == 36 # 26 + 10
|
|
# Multi-test rows should have test_id filled
|
|
test_ids = {r["test_id"] for r in rows}
|
|
assert len(test_ids) == 2
|
|
|
|
def test_rows_preserve_load_order(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
rows = _build_channel_rows(state)
|
|
# First channel in fixture should be first row
|
|
# (this depends on how MMEReader yields channels — sorted by name)
|
|
iso_codes = [r["iso_code"] for r in rows]
|
|
assert len(iso_codes) == 26
|
|
|
|
|
|
class TestFilterRows:
|
|
@pytest.fixture
|
|
def rows(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
return _build_channel_rows(state)
|
|
|
|
def test_no_filter_returns_all(self, rows):
|
|
result = filter_rows(rows)
|
|
assert len(result) == len(rows)
|
|
|
|
def test_wildcard_filter_head(self, rows):
|
|
result = filter_rows(rows, pattern="*HEAD*")
|
|
assert len(result) > 0
|
|
assert all("HEAD" in r["iso_code"] for r in result)
|
|
|
|
def test_wildcard_filter_accel(self, rows):
|
|
result = filter_rows(rows, pattern="*AC*")
|
|
assert len(result) > 0
|
|
assert all("AC" in r["iso_code"] for r in result)
|
|
|
|
def test_partial_text_auto_wrapped(self, rows):
|
|
"""Typing 'HEAD' without wildcards should auto-wrap to *HEAD*."""
|
|
result = filter_rows(rows, pattern="HEAD")
|
|
assert len(result) > 0
|
|
assert all("HEAD" in r["iso_code"] for r in result)
|
|
|
|
def test_filter_by_body_facet(self, rows):
|
|
result = filter_rows(rows, body="Head")
|
|
assert len(result) > 0
|
|
assert all(r["body"] == "Head" for r in result)
|
|
|
|
def test_filter_by_direction_facet(self, rows):
|
|
result = filter_rows(rows, direction="X")
|
|
assert len(result) > 0
|
|
assert all(r["direction"] == "X" for r in result)
|
|
|
|
def test_combined_filter(self, rows):
|
|
result = filter_rows(rows, pattern="*AC*", direction="X")
|
|
assert len(result) > 0
|
|
for r in result:
|
|
assert "AC" in r["iso_code"]
|
|
assert r["direction"] == "X"
|
|
|
|
def test_no_match_returns_empty(self, rows):
|
|
result = filter_rows(rows, pattern="NONEXISTENT")
|
|
assert len(result) == 0
|
|
|
|
@pytest.mark.skipif(not (MME_DATA / "3239").exists(), reason="Real data not available")
|
|
def test_wildcard_filter_real_data(self):
|
|
state = AppState()
|
|
state.load_test(MME_DATA / "3239")
|
|
rows = _build_channel_rows(state)
|
|
|
|
# Filter for head channels
|
|
head = filter_rows(rows, pattern="*HEAD*")
|
|
assert len(head) > 0
|
|
|
|
# Filter for barrier load cells
|
|
barrier = filter_rows(rows, pattern="B0FBAR*")
|
|
assert len(barrier) > 0
|
|
|
|
# Filter for femur
|
|
femur = filter_rows(rows, pattern="*FEMR*")
|
|
assert len(femur) >= 2 # Left and right
|
|
|
|
|
|
class TestSelectedBadges:
|
|
def test_empty_selection(self):
|
|
state = AppState()
|
|
badges = build_selected_channels_badges([], state)
|
|
assert len(badges) == 1 # "No channels selected"
|
|
|
|
def test_with_selection(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
keys = ["IMPAKT_SYNTH_001::11HEAD0000ACXA", "IMPAKT_SYNTH_001::11HEAD0000ACYA"]
|
|
badges = build_selected_channels_badges(keys, state)
|
|
assert len(badges) == 2
|