Files
impakt/tests/test_web/test_channel_grid.py

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