package main import ( "os" "path/filepath" "regexp" "strings" "testing" ) // The builder must work the same for every game: no game's name, id or code in its source, its rules for // the model (AUTHORING.md), the schemas sent with every draft, or its docs. Games are read from games/, // so a newly merged template is covered as soon as it lands. func TestBuilderIsGameAgnostic(t *testing.T) { root := filepath.Join("..", "..") templates, _ := filepath.Glob(filepath.Join(root, "games", "*", "game.yaml")) if len(templates) == 0 { t.Fatal("no templates found to check against") } var names []string for _, f := range templates { g, err := loadMap(f) if err != nil { continue } for _, key := range []string{"id", "name"} { if s, _ := g[key].(string); len(s) > 2 { names = append(names, s) } } } files, _ := filepath.Glob("*.go") files = append(files, filepath.Join(root, "AUTHORING.md"), filepath.Join(root, "BUILDER.md")) schemas, _ := filepath.Glob(filepath.Join(root, "schema", "*.json")) files = append(files, schemas...) for _, f := range files { raw, err := os.ReadFile(f) if err != nil { t.Fatal(err) } text := string(raw) for _, n := range names { re := regexp.MustCompile(`(?i)(^|[^A-Za-z0-9])` + regexp.QuoteMeta(n) + `($|[^A-Za-z0-9])`) if loc := re.FindStringIndex(text); loc != nil { line := strings.Count(text[:loc[0]], "\n") + 1 t.Errorf("%s:%d mentions %q: the builder must not name or copy any game", f, line, n) } } } }