package main import ( "regexp" "sort" "strings" "testing" "countrygame/web" ) var placeholder = regexp.MustCompile(`\{(\w+)\}`) func placeholders(s string) string { var found []string for _, m := range placeholder.FindAllStringSubmatch(s, -1) { found = append(found, m[1]) } sort.Strings(found) return strings.Join(found, ",") } // English and French must offer exactly the same strings with the same {placeholders}. func TestI18nParity(t *testing.T) { en := load(t, "js/i18n/en.json") fr := load(t, "js/i18n/fr.json") for k, v := range en { other, ok := fr[k] if !ok { t.Errorf("fr.json is missing %q", k) continue } enText, _ := v.(string) frText, _ := other.(string) if strings.TrimSpace(enText) == "" || strings.TrimSpace(frText) == "" { t.Errorf("%q has an empty string in en or fr", k) } if placeholders(enText) != placeholders(frText) { t.Errorf("%q: placeholders differ (en %q, fr %q)", k, placeholders(enText), placeholders(frText)) } } for k := range fr { if _, ok := en[k]; !ok { t.Errorf("en.json is missing %q", k) } } } // Every scenario in the index exists, and every scenario file is in the index. func TestScenarioIndex(t *testing.T) { index := load(t, "data/scenarios/index.json") listed := map[string]bool{} for _, id := range index["scenarios"].([]any) { listed[id.(string)] = true sc := load(t, "data/scenarios/"+id.(string)+".json") if sc["id"] != id { t.Errorf("scenarios/%s.json has id %v", id, sc["id"]) } if !isLocalized(sc["name"]) { t.Errorf("scenario %s needs a name in en and fr", id) } } if len(listed) == 0 { t.Error("scenarios/index.json lists no scenario") } entries, err := web.Files.ReadDir("data/scenarios") if err != nil { t.Fatal(err) } for _, e := range entries { id := strings.TrimSuffix(e.Name(), ".json") if e.Name() != "index.json" && !listed[id] { t.Errorf("scenarios/%s is not listed in scenarios/index.json", e.Name()) } } }