test: close coverage gaps and add frontend test infrastructure

Backend (516 tests, 94% coverage):
- Add azure_openai endpoint/deployment validation tests (config.py -> 100%)
- Add _total_conversations and _avg_turns direct tests (queries.py -> 100%)
- Add transformer edge cases: list content, string checkpoint, invalid JSON,
  malformed message graceful skip (transformer.py -> 93%)
- Add safety combined status_code+error_message interaction tests
- Fix ambiguous 200/422 assertion to strict 422
- Add E2E pagination shape assertions (total, page, per_page, row count)
- Fix ReplayPool mock to respect LIMIT/OFFSET params

Frontend (23 tests, vitest + happy-dom + @testing-library/react):
- Add vitest infrastructure with happy-dom environment
- Add api.ts tests: success, HTTP error, success=false, URL encoding
- Add DashboardPage tests: loading, data, error, empty states
- Add ReplayListPage tests: loading, empty, data, error, status badge classes
- Add ReplayPage tests: loading, steps, empty, error states
This commit is contained in:
Yaojia Wang
2026-04-06 13:32:10 +02:00
parent 036e12349d
commit 19fc9f3289
15 changed files with 1270 additions and 7 deletions

View File

@@ -153,3 +153,105 @@ class TestTransformCheckpoints:
rows = [_make_row([{"type": "human", "content": "Hi"}])]
steps = transform_checkpoints(rows)
assert isinstance(steps[0].timestamp, str)
def test_list_content_joined_to_string(self) -> None:
from app.replay.transformer import transform_checkpoints
rows = [
_make_row(
[
{
"type": "human",
"content": [
{"text": "Hello"},
{"text": " world"},
],
}
]
)
]
steps = transform_checkpoints(rows)
assert len(steps) == 1
assert steps[0].content == "Hello world"
def test_checkpoint_as_string_skipped(self) -> None:
from app.replay.transformer import transform_checkpoints
rows = [
{
"thread_id": "t1",
"checkpoint_id": "cp1",
"checkpoint": "not-a-dict",
"metadata": {},
}
]
steps = transform_checkpoints(rows)
assert steps == []
def test_channel_values_not_dict_skipped(self) -> None:
from app.replay.transformer import transform_checkpoints
rows = [
{
"thread_id": "t1",
"checkpoint_id": "cp1",
"checkpoint": {"channel_values": "bad"},
"metadata": {},
}
]
steps = transform_checkpoints(rows)
assert steps == []
def test_tool_result_valid_json_parsed(self) -> None:
from app.replay.transformer import transform_checkpoints
rows = [
_make_row(
[
{
"type": "tool",
"content": '{"order_id": "123", "status": "shipped"}',
"name": "get_order_status",
}
]
)
]
steps = transform_checkpoints(rows)
assert len(steps) == 1
assert steps[0].result == {"order_id": "123", "status": "shipped"}
def test_tool_result_invalid_json_wrapped(self) -> None:
from app.replay.transformer import transform_checkpoints
rows = [
_make_row(
[
{
"type": "tool",
"content": "not valid json",
"name": "some_tool",
}
]
)
]
steps = transform_checkpoints(rows)
assert len(steps) == 1
assert steps[0].result == {"raw": "not valid json"}
def test_malformed_message_skipped_gracefully(self) -> None:
from app.replay.transformer import transform_checkpoints
rows = [
_make_row(
[
{"type": "human", "content": "Good message"},
42, # not a dict -- will raise in _step_from_message
{"type": "ai", "content": "Response", "tool_calls": []},
]
)
]
steps = transform_checkpoints(rows)
# The malformed message is skipped; the other two produce steps.
assert len(steps) == 2
assert steps[0].step == 1
assert steps[1].step == 2