MIL-002: Step 1 - User interface

Review record RC-024 (Go, autonomous mode, not independent).

Task: MIL-002#1
Task: MIL-002#2
Task: MIL-002#3
Task: MIL-002#4
This commit is contained in:
2026-10-14 21:53:07 +08:00
parent aecf7ad43c
commit 019565635d
18 changed files with 828 additions and 33 deletions
+20 -4
View File
@@ -1,11 +1,27 @@
"""Tests of the entry point.
@file test_app.py
@brief Checks main of flash_card.presentation.app.
@brief Checks main of flash_card.presentation.app without opening a window.
"""
from flash_card.presentation.app import main
import pytest
from flash_card.presentation import app
def test_main_returns_zero_without_arguments() -> None:
assert main([]) == 0
class _FakeRoot:
def __init__(self) -> None:
self.mainloop_calls = 0
def mainloop(self) -> None:
self.mainloop_calls += 1
def test_main_runs_main_loop_and_returns_zero(
monkeypatch: pytest.MonkeyPatch,
) -> None:
root = _FakeRoot()
monkeypatch.setattr(app, "create_application", lambda: (root, object()))
assert app.main([]) == 0
assert root.mainloop_calls == 1
+18
View File
@@ -0,0 +1,18 @@
"""Tests of the flash card view model.
@file test_flash_card_view_model.py
@brief Checks the placeholder texts of FlashCardViewModel.
"""
from flash_card.constants import PLACEHOLDER_LANGUAGE_NAME, PLACEHOLDER_WORD
from flash_card.presentation.features.flash_card.flash_card_view_model import (
FlashCardViewModel,
)
def test_language_name_returns_placeholder() -> None:
assert FlashCardViewModel().language_name == PLACEHOLDER_LANGUAGE_NAME
def test_text_returns_placeholder_word() -> None:
assert FlashCardViewModel().text == PLACEHOLDER_WORD
+58
View File
@@ -0,0 +1,58 @@
"""Tests of the image generator tool.
@file test_generate_images.py
@brief Checks the PNG files written by tools/generate_images.py.
"""
import importlib.util
import struct
from pathlib import Path
from types import ModuleType
import pytest
from flash_card.constants import (
CARD_BACK_IMAGE_NAME,
CARD_FRONT_IMAGE_NAME,
CARD_HEIGHT,
CARD_WIDTH,
RIGHT_IMAGE_NAME,
WRONG_IMAGE_NAME,
)
_TOOL_PATH = Path(__file__).resolve().parents[2] / "tools" / "generate_images.py"
_SIGNATURE = b"\x89PNG\r\n\x1a\n"
def _load_tool() -> ModuleType:
spec = importlib.util.spec_from_file_location("generate_images", _TOOL_PATH)
assert spec is not None
assert spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
@pytest.fixture(scope="module")
def generated(tmp_path_factory: pytest.TempPathFactory) -> Path:
output_dir = tmp_path_factory.mktemp("assets")
assert _load_tool().main(["--output-dir", str(output_dir)]) == 0
return output_dir
@pytest.mark.parametrize(
("name", "width", "height"),
[
(CARD_FRONT_IMAGE_NAME, CARD_WIDTH, CARD_HEIGHT),
(CARD_BACK_IMAGE_NAME, CARD_WIDTH, CARD_HEIGHT),
(RIGHT_IMAGE_NAME, 100, 100),
(WRONG_IMAGE_NAME, 100, 100),
],
)
def test_generate_images_writes_png_with_expected_size(
generated: Path, name: str, width: int, height: int
) -> None:
data = (generated / name).read_bytes()
assert data.startswith(_SIGNATURE)
assert data[12:16] == b"IHDR"
assert struct.unpack(">II", data[16:24]) == (width, height)