clone

fifteen puzzle games for the terminal, with daily puzzles, weekly ladders and xp, built on bubble tea

bug/architecture-test-trim-path
puzzletea / cmd / new_spawn_test.go
new_spawn_test.go 5.0K
1package cmd23import (4 "math/rand/v2"5 "testing"67 "charm.land/bubbles/v2/key"8 tea "charm.land/bubbletea/v2"9 "github.com/FelineStateMachine/puzzletea/difficulty"10 "github.com/FelineStateMachine/puzzletea/game"11 "github.com/FelineStateMachine/puzzletea/puzzle"12 "github.com/FelineStateMachine/puzzletea/registry"13)1415type testSpawnGamer struct{}1617func (testSpawnGamer) GetDebugInfo() string { return "" }18func (testSpawnGamer) GetFullHelp() [][]key.Binding { return nil }19func (testSpawnGamer) GetSave() ([]byte, error) { return []byte(`{}`), nil }20func (testSpawnGamer) IsSolved() bool { return false }21func (testSpawnGamer) Reset() game.Gamer { return testSpawnGamer{} }22func (testSpawnGamer) SetTitle(string) game.Gamer { return testSpawnGamer{} }23func (testSpawnGamer) Init() tea.Cmd { return nil }24func (testSpawnGamer) View() string { return "" }25func (testSpawnGamer) Update(tea.Msg) (game.Gamer, tea.Cmd) { return testSpawnGamer{}, nil }2627type testLegacySpawner struct {28 spawned bool29 seeded bool30 seededCalled bool31}3233func (s *testLegacySpawner) Spawn() (game.Gamer, error) {34 s.spawned = true35 return testSpawnGamer{}, nil36}3738func (s *testLegacySpawner) SpawnSeeded(*rand.Rand) (game.Gamer, error) {39 s.seeded = true40 s.seededCalled = true41 return testSpawnGamer{}, nil42}4344type testEloSpawner struct {45 testLegacySpawner46 called bool47 seed string48 elo difficulty.Elo49}5051func (s *testEloSpawner) SpawnElo(seed string, elo difficulty.Elo) (game.Gamer, difficulty.Report, error) {52 s.called = true53 s.seed = seed54 s.elo = elo55 return testSpawnGamer{}, difficulty.Report{56 TargetElo: elo,57 ActualElo: elo,58 Confidence: difficulty.ConfidenceHigh,59 }, nil60}6162func TestSpawnFromModeUsesPresetEloWhenDifficultyOmitted(t *testing.T) {63 preset := difficulty.Elo(1200)64 spawner := &testEloSpawner{}65 mode := registry.ModeEntry{66 Definition: puzzle.ModeDef{Title: "Preset", PresetElo: &preset},67 Spawner: spawner,68 Elo: spawner,69 }7071 _, report, err := spawnFromMode(mode, "", nil, "generated-name")72 if err != nil {73 t.Fatalf("spawnFromMode returned error: %v", err)74 }75 if !spawner.called {76 t.Fatal("expected SpawnElo to be called")77 }78 if spawner.seed != "generated-name" {79 t.Fatalf("Elo seed = %q, want generated save name", spawner.seed)80 }81 if spawner.elo != preset || report.TargetElo != preset || report.Confidence == "" {82 t.Fatalf("Elo/report = (%d, %#v), want preset report", spawner.elo, report)83 }84}8586func TestSpawnFromVariantUsesDefaultEloWhenDifficultyOmitted(t *testing.T) {87 defaultElo := difficulty.Elo(1200)88 spawner := &testEloSpawner{}89 variant := registry.VariantEntry{90 Definition: puzzle.VariantDef{Title: "Rule", DefaultElo: defaultElo},91 Elo: spawner,92 }9394 _, report, err := spawnFromVariant(variant, "", nil, "generated-name")95 if err != nil {96 t.Fatalf("spawnFromVariant returned error: %v", err)97 }98 if !spawner.called {99 t.Fatal("expected SpawnElo to be called")100 }101 if spawner.seed != "generated-name" {102 t.Fatalf("Elo seed = %q, want generated save name", spawner.seed)103 }104 if spawner.elo != defaultElo || report.TargetElo != defaultElo || report.Confidence == "" {105 t.Fatalf("Elo/report = (%d, %#v), want default report", spawner.elo, report)106 }107}108109func TestSpawnFromVariantExplicitDifficultyOverridesDefault(t *testing.T) {110 explicit := difficulty.Elo(2200)111 spawner := &testEloSpawner{}112 variant := registry.VariantEntry{113 Definition: puzzle.VariantDef{Title: "Rule", DefaultElo: 800},114 Elo: spawner,115 }116117 _, _, err := spawnFromVariant(variant, "user-seed", &explicit, "generated-name")118 if err != nil {119 t.Fatalf("spawnFromVariant returned error: %v", err)120 }121 if spawner.elo != explicit {122 t.Fatalf("Elo = %d, want explicit %d", spawner.elo, explicit)123 }124 if spawner.seed != "user-seed" {125 t.Fatalf("seed = %q, want explicit seed", spawner.seed)126 }127}128129func TestSpawnFromModeExplicitDifficultyOverridesPreset(t *testing.T) {130 preset := difficulty.Elo(800)131 explicit := difficulty.Elo(2200)132 spawner := &testEloSpawner{}133 mode := registry.ModeEntry{134 Definition: puzzle.ModeDef{Title: "Preset", PresetElo: &preset},135 Spawner: spawner,136 Elo: spawner,137 }138139 _, _, err := spawnFromMode(mode, "user-seed", &explicit, "generated-name")140 if err != nil {141 t.Fatalf("spawnFromMode returned error: %v", err)142 }143 if spawner.elo != explicit {144 t.Fatalf("Elo = %d, want explicit %d", spawner.elo, explicit)145 }146 if spawner.seed != "user-seed" {147 t.Fatalf("seed = %q, want explicit seed", spawner.seed)148 }149}150151func TestSpawnFromModeFallsBackWithoutElo(t *testing.T) {152 spawner := &testLegacySpawner{}153 mode := registry.ModeEntry{154 Definition: puzzle.ModeDef{Title: "Legacy"},155 Spawner: spawner,156 Seeded: spawner,157 }158159 if _, _, err := spawnFromMode(mode, "", nil, "generated-name"); err != nil {160 t.Fatalf("random spawnFromMode returned error: %v", err)161 }162 if !spawner.spawned {163 t.Fatal("expected legacy Spawn to be called")164 }165}