Files
transcription/tests/ui/test_error_presenter.py
T
Jim Lancaster d5e798825d
Quality Gate / gate (push) Successful in 2m31s
Implement Rec - Phase 1
2026-09-02 15:59:56 -05:00

102 lines
3.8 KiB
Python

import pytest
from transcription.errors import AppError
from transcription.errors import ErrorCategory
from transcription.ui.components.error_presenter import display_error_category
from transcription.ui.components.error_presenter import display_failure_detail
from transcription.ui.components.error_presenter import run_ui_action
def test_display_error_category_uses_canonical_taxonomy():
assert display_error_category(AppError("x", category=ErrorCategory.USER_INPUT)) == "validation"
assert display_error_category(AppError("x", category=ErrorCategory.NOT_FOUND)) == "not_found"
assert display_error_category(AppError("x", category=ErrorCategory.CONFLICT)) == "conflict"
assert display_error_category(AppError("x", category=ErrorCategory.EXTERNAL_PROVIDER)) == "external"
assert display_error_category(AppError("x", category=ErrorCategory.EXTERNAL_TIMEOUT)) == "timeout"
assert display_error_category(AppError("x", category=ErrorCategory.INFRA_TRANSIENT)) == "timeout"
assert display_error_category(AppError("x", category=ErrorCategory.PROCESSING)) == "internal"
assert display_error_category(AppError("x", category=ErrorCategory.INFRA_PERSISTENT)) == "internal"
def test_display_failure_detail_returns_none_for_missing_detail():
assert display_failure_detail(None) is None
@pytest.mark.parametrize(
("raw_detail", "expected_basename"),
[
(
(
"[internal_unexpected_error] Unexpected error during worker.process_job. | "
"detail=PermissionError: [Errno 13] Permission denied: '/app/uploads/documents/abc/page-1.jpg' | "
"suggestion=Retry once. | error_id=deadbeef"
),
"page-1.jpg",
),
(
(
"[infrastructure_persistent_error] Prompt file not found: transcribe_document.md | "
"detail=FileNotFoundError: [Errno 2] No such file or directory: "
r"'C:\app\prompts\transcribe_document.md' | "
"suggestion=Verify PROMPT_DIR. | error_id=feedface"
),
"transcribe_document.md",
),
],
)
def test_display_failure_detail_strips_absolute_paths_from_detail_segment(raw_detail, expected_basename):
rendered = display_failure_detail(raw_detail)
assert rendered is not None
assert rendered.startswith("[")
assert "suggestion=" in rendered
assert "error_id=" in rendered
assert expected_basename in rendered
assert "/app/uploads/documents/abc/page-1.jpg" not in rendered
assert r"C:\app\prompts\transcribe_document.md" not in rendered
@pytest.mark.asyncio
async def test_run_ui_action_returns_success_value():
outcome = await run_ui_action(
operation="ui.test.success",
title="Should not show",
action=lambda: _async_value(123),
)
assert outcome.ok is True
assert outcome.value == 123
@pytest.mark.asyncio
async def test_run_ui_action_shows_error_and_returns_failed(monkeypatch):
captured: dict[str, object] = {}
def _capture(exc: Exception, *, title: str, operation: str) -> None:
captured["exc"] = exc
captured["title"] = title
captured["operation"] = operation
monkeypatch.setattr("transcription.ui.components.error_presenter.show_error", _capture)
outcome = await run_ui_action(
operation="ui.test.failure",
title="Load failed",
action=lambda: _async_raises(RuntimeError("boom")),
)
assert outcome.ok is False
assert outcome.value is None
assert isinstance(captured["exc"], RuntimeError)
assert str(captured["exc"]) == "boom"
assert captured["title"] == "Load failed"
assert captured["operation"] == "ui.test.failure"
async def _async_value(value: int) -> int:
return value
async def _async_raises(exc: Exception) -> int:
raise exc