clone

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

chore/app-model-decomp
puzzletea / config / config_test.go
config_test.go 3.5K
1package config23import (4 "os"5 "path/filepath"6 "testing"78 "github.com/FelineStateMachine/puzzletea/puzzle"9)1011// --- Load / Save round-trip (P0) ---1213func TestLoadMissingFile(t *testing.T) {14 cfg, err := Load("/tmp/puzzletea-test-nonexistent/config.json")15 if err != nil {16 t.Fatalf("expected no error for missing file, got: %v", err)17 }18 if cfg.Theme != "" {19 t.Errorf("expected empty theme for default config, got %q", cfg.Theme)20 }21}2223func TestSaveAndLoad(t *testing.T) {24 dir := t.TempDir()25 path := filepath.Join(dir, "config.json")2627 cfg := &Config{Theme: "Dracula"}28 if err := cfg.Save(path); err != nil {29 t.Fatalf("Save failed: %v", err)30 }3132 loaded, err := Load(path)33 if err != nil {34 t.Fatalf("Load failed: %v", err)35 }36 if loaded.Theme != "Dracula" {37 t.Errorf("expected theme Dracula, got %q", loaded.Theme)38 }39}4041func TestSaveAndLoadExportConfig(t *testing.T) {42 dir := t.TempDir()43 path := filepath.Join(dir, "config.json")4445 cfg := &Config{46 Theme: "Dracula",47 Export: ExportConfig{48 Title: "Sampler",49 Volume: 2,50 SheetLayout: "duplex-booklet",51 PDFOutputPath: filepath.Join(dir, "sample.pdf"),52 JSONLEnabled: true,53 JSONLOutputPath: filepath.Join(dir, "sample.jsonl"),54 Counts: map[puzzle.GameID]map[puzzle.ModeID]int{55 puzzle.CanonicalGameID("Sudoku"): {56 puzzle.CanonicalModeID("Easy"): 2,57 },58 },59 },60 }61 if err := cfg.Save(path); err != nil {62 t.Fatalf("Save failed: %v", err)63 }6465 loaded, err := Load(path)66 if err != nil {67 t.Fatalf("Load failed: %v", err)68 }69 if loaded.Export.Title != cfg.Export.Title {70 t.Fatalf("loaded export title = %q, want %q", loaded.Export.Title, cfg.Export.Title)71 }72 if !loaded.Export.JSONLEnabled {73 t.Fatal("expected jsonl toggle to round-trip")74 }75 if got := loaded.Export.Counts[puzzle.CanonicalGameID("Sudoku")][puzzle.CanonicalModeID("Easy")]; got != 2 {76 t.Fatalf("loaded export count = %d, want 2", got)77 }78}7980func TestSaveAndLoadCreateConfig(t *testing.T) {81 dir := t.TempDir()82 path := filepath.Join(dir, "config.json")8384 cfg := &Config{85 Create: CreateConfig{86 SelectedLeafIDs: []string{"nonogram/5x5", "takuzu/takuzu/6x6"},87 Elo: 1400,88 },89 }90 if err := cfg.Save(path); err != nil {91 t.Fatalf("Save failed: %v", err)92 }9394 loaded, err := Load(path)95 if err != nil {96 t.Fatalf("Load failed: %v", err)97 }98 if loaded.Create.Elo != 1400 {99 t.Fatalf("loaded create Elo = %d, want 1400", loaded.Create.Elo)100 }101 if len(loaded.Create.SelectedLeafIDs) != 2 || loaded.Create.SelectedLeafIDs[1] != "takuzu/takuzu/6x6" {102 t.Fatalf("loaded create leaves = %#v", loaded.Create.SelectedLeafIDs)103 }104}105106func TestSaveCreatesDirectory(t *testing.T) {107 dir := t.TempDir()108 path := filepath.Join(dir, "nested", "deep", "config.json")109110 cfg := &Config{Theme: "Monokai Pro"}111 if err := cfg.Save(path); err != nil {112 t.Fatalf("Save failed: %v", err)113 }114115 if _, err := os.Stat(path); err != nil {116 t.Fatalf("expected config file to exist: %v", err)117 }118}119120func TestLoadInvalidJSON(t *testing.T) {121 dir := t.TempDir()122 path := filepath.Join(dir, "config.json")123 if err := os.WriteFile(path, []byte("{invalid"), 0o644); err != nil {124 t.Fatal(err)125 }126127 cfg, err := Load(path)128 if err == nil {129 t.Fatal("expected error for invalid JSON")130 }131 // Should still return a usable default.132 if cfg.Theme != "" {133 t.Errorf("expected default theme on error, got %q", cfg.Theme)134 }135}136137func TestDefaultConfig(t *testing.T) {138 cfg := Default()139 if cfg.Theme != "" {140 t.Errorf("expected empty theme, got %q", cfg.Theme)141 }142}