180 lines
5.6 KiB
Python
180 lines
5.6 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from engine.character_creator import CharacterCreator
|
|
from engine.defs import DefRegistry
|
|
from engine.game_modes import CharacterCreationFlow, MainMenu, PauseMenu
|
|
|
|
DEFS_DIR = Path(__file__).resolve().parent.parent / "resources" / "defs"
|
|
|
|
|
|
@pytest.fixture()
|
|
def registry():
|
|
return DefRegistry.load(DEFS_DIR)
|
|
|
|
|
|
# --- MainMenu -----------------------------------------------------------------------------------
|
|
|
|
|
|
def test_main_menu_without_a_save_has_no_continue_option():
|
|
menu = MainMenu(has_existing_save=False)
|
|
assert "continue" not in menu.options()
|
|
assert menu.selected() == "new_game"
|
|
|
|
|
|
def test_main_menu_with_a_save_offers_continue_first():
|
|
menu = MainMenu(has_existing_save=True)
|
|
assert menu.options()[0] == "continue"
|
|
assert menu.selected() == "continue"
|
|
|
|
|
|
def test_main_menu_move_wraps_around():
|
|
menu = MainMenu(has_existing_save=False)
|
|
assert menu.options() == ["new_game", "controls"]
|
|
menu.move(-1)
|
|
assert menu.selected() == "controls"
|
|
menu.move(1)
|
|
assert menu.selected() == "new_game"
|
|
|
|
|
|
# --- PauseMenu ------------------------------------------------------------------------------------
|
|
|
|
|
|
def test_pause_menu_defaults_to_resume():
|
|
assert PauseMenu().selected() == "resume"
|
|
|
|
|
|
def test_pause_menu_cycles_through_all_options():
|
|
menu = PauseMenu()
|
|
seen = {menu.selected()}
|
|
for _ in range(len(PauseMenu.OPTIONS)):
|
|
menu.move(1)
|
|
seen.add(menu.selected())
|
|
assert seen == set(PauseMenu.OPTIONS)
|
|
|
|
|
|
# --- CharacterCreationFlow -------------------------------------------------------------------------
|
|
|
|
|
|
def test_flow_locks_in_a_default_species_on_creation(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
assert flow.creator.species_id == flow.species_list()[0]
|
|
|
|
|
|
def test_cycle_species_updates_the_creator(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
first = flow.creator.species_id
|
|
flow.cycle_species(1)
|
|
assert flow.creator.species_id != first
|
|
assert flow.creator.species_id == flow.species_list()[1 % len(flow.species_list())]
|
|
|
|
|
|
def test_advance_from_species_moves_to_name_step_without_finishing(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
assert flow.advance() is False
|
|
assert flow.step == "name"
|
|
|
|
|
|
def test_typing_only_applies_during_the_name_step(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
flow.type_char("x") # still on species step
|
|
assert flow.creator.name == ""
|
|
flow.advance()
|
|
flow.type_char("V")
|
|
flow.type_char("e")
|
|
flow.type_char("x")
|
|
assert flow.creator.name == "Vex"
|
|
|
|
|
|
def test_backspace_removes_the_last_character(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
flow.advance()
|
|
flow.type_char("V")
|
|
flow.type_char("x")
|
|
flow.backspace()
|
|
assert flow.creator.name == "V"
|
|
|
|
|
|
def test_advance_on_name_step_requires_a_non_empty_name(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
flow.advance()
|
|
assert flow.advance() is False
|
|
assert flow.step == "name"
|
|
flow.type_char("V")
|
|
assert flow.advance() is False # moves on to the password step, not finished yet
|
|
assert flow.step == "password"
|
|
|
|
|
|
def test_typing_is_capped_at_max_name_length(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
flow.advance()
|
|
for ch in "x" * 30:
|
|
flow.type_char(ch)
|
|
assert len(flow.creator.name) == 20
|
|
|
|
|
|
def test_go_back_from_name_returns_to_species(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
flow.advance()
|
|
assert flow.go_back() is True
|
|
assert flow.step == "species"
|
|
|
|
|
|
def test_go_back_from_species_reports_theres_nowhere_further_back(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
assert flow.go_back() is False
|
|
|
|
|
|
def _advance_to_password_step(flow: CharacterCreationFlow, name: str = "Vex") -> None:
|
|
flow.advance() # species -> name
|
|
for ch in name:
|
|
flow.type_char(ch)
|
|
flow.advance() # name -> password
|
|
|
|
|
|
def test_advance_from_name_moves_to_password_step_without_finishing(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
_advance_to_password_step(flow)
|
|
assert flow.step == "password"
|
|
|
|
|
|
def test_advance_on_password_step_finishes_even_with_no_password_typed(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
_advance_to_password_step(flow)
|
|
assert flow.advance() is True
|
|
|
|
|
|
def test_typing_during_password_step_updates_the_creator(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
_advance_to_password_step(flow)
|
|
flow.type_char("T")
|
|
flow.type_char("h")
|
|
assert flow.creator.secret_password == "Th"
|
|
assert flow.creator.name == "Vex" # unaffected by typing during the password step
|
|
|
|
|
|
def test_backspace_during_password_step_only_affects_the_password(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
_advance_to_password_step(flow)
|
|
flow.type_char("T")
|
|
flow.type_char("h")
|
|
flow.backspace()
|
|
assert flow.creator.secret_password == "T"
|
|
assert flow.creator.name == "Vex"
|
|
|
|
|
|
def test_typing_during_password_step_is_capped_at_max_name_length(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
_advance_to_password_step(flow)
|
|
for ch in "x" * 30:
|
|
flow.type_char(ch)
|
|
assert len(flow.creator.secret_password) == 20
|
|
|
|
|
|
def test_go_back_from_password_returns_to_name(registry):
|
|
flow = CharacterCreationFlow(CharacterCreator(registry))
|
|
_advance_to_password_step(flow)
|
|
assert flow.go_back() is True
|
|
assert flow.step == "name"
|