rastrillo / fiesta Public

Clone
git clone https://amadan.net/rastrillo/fiesta

Plain git — no account needed to clone.

Download

Download this file

1package www_test
2
3import (
4 "io/fs"
5 "os"
6 "path/filepath"
7 "slices"
8 "strings"
9 "testing"
10 "testing/fstest"
11
12 "amadan.net/rastrillo/fiesta/internal/www"
13)
14
15// realSite is the repository's site/ directory, the site source the
16// landing page is built from.
17func realSite() fs.FS {
18 return os.DirFS(filepath.Join("..", "..", "site"))
19}
20
21// catalogs is a site source holding one landing catalog per language,
22// each written as Strings reads it.
23func catalogs(t *testing.T, langs map[string]map[string]string) fstest.MapFS {
24 t.Helper()
25 m := fstest.MapFS{}
26 for lang, strs := range langs {
27 var b strings.Builder
28 b.WriteString("{\n")
29 keys := make([]string, 0, len(strs))
30 for k := range strs {
31 keys = append(keys, k)
32 }
33 slices.Sort(keys)
34 for i, k := range keys {
35 if i > 0 {
36 b.WriteString(",\n")
37 }
38 b.WriteString(" " + quote(k) + ": " + quote(strs[k]))
39 }
40 b.WriteString("\n}\n")
41 m["landing/strings/"+lang+".json"] = &fstest.MapFile{Data: []byte(b.String())}
42 }
43 return m
44}
45
46// quote is a JSON string literal, enough for the fixtures here.
47func quote(s string) string {
48 return `"` + strings.NewReplacer(`\`, `\\`, `"`, `\"`, "\n", `\n`).Replace(s) + `"`
49}
50
51// complete is a catalog with every required key, each valued by text.
52func complete(text func(key string) string) map[string]string {
53 out := make(map[string]string, len(www.RequiredKeys))
54 for _, k := range www.RequiredKeys {
55 out[k] = text(k)
56 }
57 return out
58}
59
60// keyItself values a key by its own name.
61func keyItself(key string) string { return key }
62
63// keysOf is m's keys, sorted.
64func keysOf(m map[string]string) []string {
65 keys := make([]string, 0, len(m))
66 for k := range m {
67 keys = append(keys, k)
68 }
69 slices.Sort(keys)
70 return keys
71}
72
73// TestEveryLanguageHasEveryKey: every site language has a catalog in
74// the site source, and each holds exactly RequiredKeys with nothing
75// empty. A catalog that lacks a key, adds one, leaves one empty or is
76// not there at all is refused, and the error names what is wrong.
77func TestEveryLanguageHasEveryKey(t *testing.T) {
78 if !slices.IsSorted(www.RequiredKeys) || len(slices.Compact(slices.Clone(www.RequiredKeys))) != len(www.RequiredKeys) {
79 t.Fatal("RequiredKeys is not sorted and unique")
80 }
81 if len(www.Languages) != 11 || www.Languages[0] != "en" {
82 t.Fatalf("Languages is %v", www.Languages)
83 }
84 for _, lang := range www.Languages {
85 got, err := www.Strings(realSite(), lang)
86 if err != nil {
87 t.Errorf("%s: %v", lang, err)
88 continue
89 }
90 if keys := keysOf(got); !slices.Equal(keys, www.RequiredKeys) {
91 t.Errorf("%s has keys %v, want RequiredKeys", lang, keys)
92 }
93 for k, v := range got {
94 if strings.TrimSpace(v) == "" {
95 t.Errorf("%s: %s is empty", lang, k)
96 }
97 }
98 }
99
100 short := complete(keyItself)
101 delete(short, "sample.saved")
102 _, err := www.Strings(catalogs(t, map[string]map[string]string{"en": short}), "en")
103 if err == nil || !strings.Contains(err.Error(), "sample.saved") {
104 t.Errorf("a catalog lacking sample.saved was accepted, or the error does not name it: %v", err)
105 }
106
107 extra := complete(keyItself)
108 extra["sample.extra"] = "x"
109 _, err = www.Strings(catalogs(t, map[string]map[string]string{"en": extra}), "en")
110 if err == nil || !strings.Contains(err.Error(), "sample.extra") {
111 t.Errorf("a catalog with a key the page never reads was accepted, or the error does not name it: %v", err)
112 }
113
114 blank := complete(keyItself)
115 blank["copied"] = " "
116 _, err = www.Strings(catalogs(t, map[string]map[string]string{"en": blank}), "en")
117 if err == nil || !strings.Contains(err.Error(), "copied") {
118 t.Errorf("a catalog with an empty copied was accepted, or the error does not name it: %v", err)
119 }
120
121 if _, err := www.Strings(catalogs(t, nil), "en"); err == nil {
122 t.Error("a site source with no catalog at all was accepted")
123 }
124
125 if _, err := www.Strings(catalogs(t, map[string]map[string]string{"en": complete(keyItself)}), "en"); err != nil {
126 t.Errorf("the complete control catalog was refused: %v", err)
127 }
128}
129
130// TestPaulsWordsAreVerbatim: the headline, the lede and the install
131// line are Paul's words, byte for byte, in the English catalog.
132func TestPaulsWordsAreVerbatim(t *testing.T) {
133 en, err := www.Strings(realSite(), "en")
134 if err != nil {
135 t.Fatal(err)
136 }
137 for key, want := range map[string]string{
138 "headline": "Celebrate your new design system",
139 "lede": "Polished, accessible, multi-lingual, localised components for everyone.",
140 "install": "One stylesheet and done. JS optional. <25KiB gzipped.",
141 } {
142 if got := en[key]; got != want {
143 t.Errorf("%s is %q, want %q", key, got, want)
144 }
145 }
146}
147
148// TestThePlaceholdersSurviveTranslation: a {name} placeholder in an
149// English string is in its translation too. A Spanish catalog that
150// drops the English {n} is refused by key and placeholder; one that
151// keeps it passes. No real string holds a placeholder today, so the
152// fixture carries this test and the real catalogs merely pass.
153func TestThePlaceholdersSurviveTranslation(t *testing.T) {
154 en := complete(keyItself)
155 en["sample.next.body"] = "Reminders go out on Friday. {n} guests still need a reply."
156
157 dropped := complete(keyItself)
158 dropped["sample.next.body"] = "Los recordatorios salen el viernes. Tres invitados aún no han respondido."
159 _, err := www.Strings(catalogs(t, map[string]map[string]string{"en": en, "es": dropped}), "es")
160 if err == nil || !strings.Contains(err.Error(), "{n}") || !strings.Contains(err.Error(), "sample.next.body") {
161 t.Errorf("a Spanish catalog that drops {n} was accepted, or the error does not name the key and the placeholder: %v", err)
162 }
163
164 kept := complete(keyItself)
165 kept["sample.next.body"] = "Los recordatorios salen el viernes. {n} invitados aún no han respondido."
166 if _, err := www.Strings(catalogs(t, map[string]map[string]string{"en": en, "es": kept}), "es"); err != nil {
167 t.Errorf("a Spanish catalog that keeps {n} was refused: %v", err)
168 }
169
170 for _, lang := range www.Languages {
171 if _, err := www.Strings(realSite(), lang); err != nil {
172 t.Errorf("%s: %v", lang, err)
173 }
174 }
175}
176