Files
031-flash-card/tests/e2e/test_flash_card_window.py
T
Tirsvad 8d66c43eea MIL-003: Step 2 - New flash cards
Review record RC-025 (Go, autonomous mode, not independent).

Task: MIL-003#1
Task: MIL-003#2
Task: MIL-003#3
Task: MIL-003#4
Task: MIL-003#5
2026-10-14 21:59:29 +08:00

137 lines
4.4 KiB
Python

"""End-to-end tests of the flash card window.
@file test_flash_card_window.py
@brief Builds the real window with Tk and checks it against the wireframe.
"""
import tkinter as tk
from collections.abc import Iterator, Sequence
import pytest
from flash_card.application.use_cases.study_session import StudySession
from flash_card.constants import (
BACKGROUND_COLOR,
CARD_HEIGHT,
CARD_WIDTH,
FRONT_TEXT_COLOR,
LANGUAGE_FONT,
WINDOW_PADDING,
WINDOW_TITLE,
WORD_FONT,
)
from flash_card.domain.entities.card import Card
from flash_card.domain.entities.deck import Deck
from flash_card.domain.value_objects.language_pair import LanguagePair
from flash_card.presentation.features.flash_card.flash_card_view import FlashCardView
from flash_card.presentation.features.flash_card.flash_card_view_model import (
FlashCardViewModel,
)
CARDS = (Card("aku", "mig"), Card("kau", "du"), Card("ini", "denne"))
def _first(cards: Sequence[Card]) -> Card:
return cards[0]
def _build_view(root: tk.Tk) -> FlashCardView:
deck = Deck(LanguagePair("ms", "da"), CARDS)
return FlashCardView(root, FlashCardViewModel(StudySession(deck, _first)))
def _shown(view: FlashCardView) -> tuple[str, str]:
return (
str(view.canvas.itemcget(view.language_text_id, "text")),
str(view.canvas.itemcget(view.word_text_id, "text")),
)
@pytest.fixture(scope="module")
def window() -> Iterator[tuple[tk.Tk, FlashCardView]]:
# One Tk per module: a second interpreter right after destroying the
# first fails to find init.tcl on some Windows Python installs.
try:
root = tk.Tk()
except tk.TclError:
pytest.skip("no display available for Tk")
view = _build_view(root)
root.update_idletasks()
yield root, view
root.destroy()
def test_window_has_title_background_and_padding(
window: tuple[tk.Tk, FlashCardView],
) -> None:
root, _view = window
assert root.title() == WINDOW_TITLE
assert root.cget("bg") == BACKGROUND_COLOR
assert int(str(root.cget("padx"))) == WINDOW_PADDING
assert int(str(root.cget("pady"))) == WINDOW_PADDING
def test_canvas_has_card_size_and_spans_two_columns(
window: tuple[tk.Tk, FlashCardView],
) -> None:
_root, view = window
assert int(str(view.canvas.cget("width"))) == CARD_WIDTH
assert int(str(view.canvas.cget("height"))) == CARD_HEIGHT
info = view.canvas.grid_info()
assert (int(info["row"]), int(info["column"])) == (0, 0)
assert int(info["columnspan"]) == 2
def test_canvas_holds_one_image_and_two_texts(
window: tuple[tk.Tk, FlashCardView],
) -> None:
_root, view = window
types = [view.canvas.type(item) for item in view.canvas.find_all()]
assert types.count("image") == 1
assert types.count("text") == 2
assert len(types) == 3
def test_texts_show_first_card_with_font_and_colour(
window: tuple[tk.Tk, FlashCardView],
) -> None:
_root, view = window
canvas = view.canvas
expected = [
(view.language_text_id, "Malay", LANGUAGE_FONT),
(view.word_text_id, "aku", WORD_FONT),
]
for item, text, font in expected:
assert canvas.itemcget(item, "text") == text
assert canvas.itemcget(item, "fill") == FRONT_TEXT_COLOR
family, size, style = font
assert canvas.itemcget(item, "font").split() == [family, str(size), style]
def test_buttons_sit_in_row_one_with_their_images(
window: tuple[tk.Tk, FlashCardView],
) -> None:
_root, view = window
wrong = view.wrong_button.grid_info()
right = view.right_button.grid_info()
assert (int(wrong["row"]), int(wrong["column"])) == (1, 0)
assert (int(right["row"]), int(right["column"])) == (1, 1)
wrong_image = str(view.wrong_button.cget("image"))
right_image = str(view.right_button.cget("image"))
assert wrong_image
assert right_image
assert wrong_image != right_image
assert str(view.wrong_button.cget("command"))
assert str(view.right_button.cget("command"))
def test_each_button_press_shows_next_card(
window: tuple[tk.Tk, FlashCardView],
) -> None:
_root, view = window
assert _shown(view) == ("Malay", "aku")
view.wrong_button.invoke()
assert _shown(view) == ("Malay", "kau")
view.right_button.invoke()
assert _shown(view) == ("Malay", "aku")