package game // Guard for the last per-game presentation seam: the Snapshot marker interface // guarantees an event carries a structured view, but renderCasinoSnapshot's // type switch silently returns "" for a snapshot it does not know. This // source-level test pairs every `func (*X) snapshot() {}` in the casino package // with a `case *casino.X:` in the renderer, so adding a game cannot silently // drop its view (the text message would still appear, hiding the loss). import ( "os" "path/filepath" "regexp" "strings" "testing" ) func TestEveryCasinoSnapshotHasARenderer(t *testing.T) { typesSrc, err := os.ReadFile(filepath.Join("..", "casino", "types.go")) if err != nil { t.Fatalf("read casino types: %v", err) } renderSrc, err := os.ReadFile("casino.go") if err != nil { t.Fatalf("read renderer: %v", err) } re := regexp.MustCompile(`func \(\*(\w+)\) snapshot\(\)`) matches := re.FindAllStringSubmatch(string(typesSrc), -1) if len(matches) == 0 { t.Fatal("no Snapshot implementations found in casino/types.go") } for _, m := range matches { name := m[1] want := "case *casino." + name + ":" if !strings.Contains(string(renderSrc), want) { t.Errorf("snapshot %s has no renderer: add `%s` to renderCasinoSnapshot", name, want) } } }