1package app23import (4 "testing"56 tea "charm.land/bubbletea/v2"7 "github.com/FelineStateMachine/puzzletea/game"8)910func TestHandleSpawnCompleteIgnoresStaleJob(t *testing.T) {11 called := false12 m := model{13 state: generatingView,14 session: sessionState{15 generating: true,16 spawnJobID: 7,17 spawnCancel: func() { called = true },18 },19 }2021 newSessionController(&m).handleSpawnComplete(6, game.SpawnCompleteMsg{Err: nil})2223 if !m.session.generating {24 t.Fatal("expected stale completion to be ignored")25 }26 if called {27 t.Fatal("stale completion should not cancel active spawn")28 }29}3031func TestGeneratingEscapeCancelsActiveSpawn(t *testing.T) {32 called := false33 m := model{34 state: generatingView,35 session: sessionState{36 generating: true,37 spawnJobID: 3,38 spawnCancel: func() { called = true },39 spawn: &spawnRequest{40 source: spawnSourceSeed,41 returnState: playMenuView,42 },43 },44 }4546 next, _ := m.Update(tea.KeyPressMsg{Code: tea.KeyEscape})47 got := next.(model)4849 if !called {50 t.Fatal("expected spawn cancellation callback to run")51 }52 if got.session.generating {53 t.Fatal("expected generating to be false after escape")54 }55 if got.state != playMenuView {56 t.Fatalf("expected playMenuView after seeded generation escape, got %d", got.state)57 }58 if got.session.spawnCancel != nil {59 t.Fatal("expected spawnCancel to be cleared")60 }61}6263func TestHandleSpawnCompleteSurfacingErrors(t *testing.T) {64 m := model{65 state: generatingView,66 session: sessionState{67 generating: true,68 spawnJobID: 9,69 spawn: &spawnRequest{70 returnState: playMenuView,71 },72 },73 }7475 newSessionController(&m).handleSpawnComplete(9, game.SpawnCompleteMsg{Err: assertiveError("boom")})7677 if m.state != playMenuView {78 t.Fatalf("state = %d, want %d", m.state, playMenuView)79 }80 if m.notice.message == "" {81 t.Fatal("expected spawn error notice to be populated")82 }83}8485type assertiveError string8687func (e assertiveError) Error() string { return string(e) }