117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
"""Tests for web AppState."""
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from impakt.web.state import AppState
|
|
|
|
MME_DATA = Path(__file__).parent.parent / "mme_data"
|
|
FIXTURE_DATA = Path(__file__).parent.parent / "fixtures" / "sample_mme"
|
|
|
|
|
|
class TestAppState:
|
|
def test_initially_empty(self):
|
|
state = AppState()
|
|
assert state.is_empty
|
|
assert state.total_channels == 0
|
|
assert state.primary_test is None
|
|
|
|
def test_load_test(self):
|
|
state = AppState()
|
|
session = state.load_test(FIXTURE_DATA)
|
|
assert not state.is_empty
|
|
assert session.test_id == "IMPAKT_SYNTH_001"
|
|
assert len(session) == 26
|
|
assert state.primary_test is session
|
|
|
|
def test_load_multiple_tests(self):
|
|
state = AppState()
|
|
t1 = state.load_test(FIXTURE_DATA)
|
|
|
|
if (MME_DATA / "VW1FGS15").exists():
|
|
t2 = state.load_test(MME_DATA / "VW1FGS15")
|
|
assert len(state.tests) == 2
|
|
assert state.primary_test is t1
|
|
assert state.total_channels == 26 + 10
|
|
|
|
def test_remove_test(self):
|
|
state = AppState()
|
|
session = state.load_test(FIXTURE_DATA)
|
|
state.remove_test(session.test_id)
|
|
assert state.is_empty
|
|
|
|
def test_get_channel(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
ch = state.get_channel("IMPAKT_SYNTH_001", "11HEAD0000ACXA")
|
|
assert ch is not None
|
|
assert ch.name == "11HEAD0000ACXA"
|
|
|
|
def test_get_channel_missing(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
ch = state.get_channel("IMPAKT_SYNTH_001", "NONEXISTENT")
|
|
assert ch is None
|
|
|
|
def test_get_channel_via_session(self):
|
|
"""Channels can be accessed through the Session scripting API."""
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
session = state.primary_test
|
|
assert session is not None
|
|
ch_handle = session.channel("11HEAD0000ACXA")
|
|
assert ch_handle.name == "11HEAD0000ACXA"
|
|
|
|
def test_session_fluent_transforms(self):
|
|
"""Fluent transform chaining works through the Session API."""
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
session = state.primary_test
|
|
ch = session.channel("11HEAD0000ACXA")
|
|
filtered = ch.transform.cfc(600).transform.y_align()
|
|
assert filtered.raw.cfc_class == 600
|
|
assert len(filtered.raw.transform_history) == 2
|
|
|
|
def test_session_compute_criteria(self):
|
|
"""Session.compute_criteria() auto-detects channels."""
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
criteria = state.primary_test.compute_criteria()
|
|
assert len(criteria) > 0
|
|
assert "HIC15" in criteria or "Chest Deflection" in criteria
|
|
|
|
def test_build_channel_tree(self):
|
|
state = AppState()
|
|
state.load_test(FIXTURE_DATA)
|
|
tree = state.build_channel_tree()
|
|
assert "IMPAKT_SYNTH_001" in tree
|
|
test_tree = tree["IMPAKT_SYNTH_001"]
|
|
assert len(test_tree) > 0
|
|
|
|
|
|
@pytest.mark.skipif(not (MME_DATA / "3239").exists(), reason="Real MME data not available")
|
|
class TestAppStateRealData:
|
|
def test_load_real_mme(self):
|
|
state = AppState()
|
|
session = state.load_test(MME_DATA / "3239")
|
|
assert session.test_id == "3239"
|
|
assert len(session) == 133
|
|
|
|
def test_channel_tree_real_data(self):
|
|
state = AppState()
|
|
state.load_test(MME_DATA / "3239")
|
|
tree = state.build_channel_tree()
|
|
assert "3239" in tree
|
|
test_tree = tree["3239"]
|
|
assert any("Driver" in k for k in test_tree)
|
|
|
|
def test_session_evaluate_real_data(self):
|
|
"""Full pipeline through Session API on real data."""
|
|
state = AppState()
|
|
state.load_test(MME_DATA / "3239")
|
|
result = state.primary_test.evaluate("euro_ncap")
|
|
assert result.stars is not None
|
|
assert result.stars >= 0
|
|
assert len(result.region_scores) > 0
|