MIL-008: Choose level

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

Task: MIL-008#1
Task: MIL-008#2
Task: MIL-008#3
Task: MIL-008#4
Task: MIL-008#5
Task: MIL-008#6
Task: MIL-008#7
Task: MIL-008#8
This commit is contained in:
2026-10-14 23:58:31 +08:00
parent ee9c531ea6
commit f45d6036e4
40 changed files with 1483 additions and 102 deletions
+44
View File
@@ -71,3 +71,47 @@ def test_remove_raises_when_card_is_absent() -> None:
def test_is_empty_reflects_cards() -> None:
assert Deck(PAIR, []).is_empty
assert not Deck(PAIR, [A]).is_empty
def test_within_returns_deck_cards_found_in_given_cards_in_deck_order() -> None:
c = Card("ini", "denne")
deck = Deck(PAIR, [A, B, c])
assert deck.within([c, A]) == (A, c)
def test_within_respects_multiplicity() -> None:
deck = Deck(PAIR, [A, A, B])
assert deck.within([A, B]) == (A, B)
assert deck.within([A, A, A]) == (A, A)
def test_within_returns_empty_when_no_card_matches() -> None:
assert Deck(PAIR, [A]).within([B]) == ()
def test_within_does_not_change_the_deck() -> None:
deck = Deck(PAIR, [A, B])
deck.within([A])
assert deck.cards == (A, B)
def test_draw_chooses_among_given_candidates_only() -> None:
deck = Deck(PAIR, [A, B])
assert deck.draw(_first, among=[B]) == B
def test_draw_among_avoids_excluded_when_another_candidate_exists() -> None:
c = Card("ini", "denne")
deck = Deck(PAIR, [A, B, c])
assert deck.draw(_first, exclude=B, among=[B, c]) == c
def test_draw_among_returns_excluded_when_it_is_the_only_candidate() -> None:
deck = Deck(PAIR, [A, B])
assert deck.draw(_first, exclude=B, among=[B]) == B
def test_draw_among_empty_raises_empty_deck_error() -> None:
deck = Deck(PAIR, [A, B])
with pytest.raises(EmptyDeckError):
deck.draw(_first, among=[])
+42
View File
@@ -0,0 +1,42 @@
"""Tests of the Level value object."""
import dataclasses
import pytest
from flash_card.domain.entities.card import Card
from flash_card.domain.value_objects.level import Level
CARDS = tuple(Card(f"w{i}", f"v{i}") for i in range(1000))
@pytest.mark.parametrize("limit", [0, -1, -100])
def test_level_refuses_limit_not_above_zero(limit: int) -> None:
with pytest.raises(ValueError, match="above zero"):
Level(limit)
def test_level_accepts_no_limit() -> None:
assert Level(None).limit is None
def test_level_is_frozen() -> None:
level = Level(100)
with pytest.raises(dataclasses.FrozenInstanceError):
level.limit = 5 # type: ignore[misc]
def test_first_returns_first_hundred_cards_when_limit_is_100() -> None:
assert Level(100).first(CARDS) == CARDS[:100]
def test_first_returns_all_cards_when_there_is_no_limit() -> None:
assert Level(None).first(CARDS) == CARDS
def test_first_returns_all_cards_when_limit_exceeds_the_list() -> None:
assert Level(5000).first(CARDS) == CARDS
def test_first_returns_empty_when_list_is_empty() -> None:
assert Level(100).first(()) == ()