package render import ( "strings" "testing" "time" "khosra/internal/content" ) func TestChromeTextIsLocalisedAndNeverEmpty(t *testing.T) { cases := []struct{ lang, key, want string }{ {"en", "newer", "Newer"}, {"bn", "newer", "নতুন"}, {"fr", "newer", "Newer"}, // unknown language falls back to the default locale {"bn", "nope", "nope"}, // unknown phrase returns its key rather than nothing } for _, c := range cases { if got := text(c.lang, c.key); got != c.want { t.Errorf("text(%q, %q) = %q, want %q", c.lang, c.key, got, c.want) } } if got := text("bn", "page-of", numerals("bn", 2), numerals("bn", 11)); got != "পৃষ্ঠা ২ / ১১" { t.Errorf("page-of in Bengali = %q", got) } if got := text("en", "page-of", "2", "11"); got != "Page 2 of 11" { t.Errorf("page-of in English = %q", got) } } func TestEveryPhraseCarriesEveryLanguage(t *testing.T) { // A phrase missing a language falls back silently, so nothing else would catch a half-translated table. for key, forms := range chrome { for lang := range months { if forms[lang] == "" { t.Errorf("phrase %q has no %s form", key, lang) } } } for lang, names := range months { if len(names) != 12 { t.Errorf("%s has %d month names, want 12", lang, len(names)) } } if len(digits["bn"]) != 10 { t.Errorf("Bengali digits = %d, want 10", len(digits["bn"])) } } func TestDatesReadInTheirOwnScript(t *testing.T) { when := time.Date(2026, time.March, 8, 0, 0, 0, 0, time.UTC) if got := day(content.DefaultLang, when); got != "8 March 2026" { t.Errorf("English date = %q", got) } if got := day("bn", when); got != "৮ মার্চ ২০২৬" { t.Errorf("Bengali date = %q, want Bengali digits and month", got) } if got := day("en", time.Time{}); got != "" { t.Errorf("an undated bundle should render nothing, got %q", got) } } func TestTypographerSmoothsProseAndLeavesCodeAlone(t *testing.T) { r, err := New(nil, nil) if err != nil { t.Fatal(err) } b, err := content.Parse("posts/x.md", []byte( "---\ntitle: X\n---\nShe said \"wait\" -- then left... `\"raw\" -- code`\n")) if err != nil { t.Fatal(err) } out, err := r.Bundle(b, "en", nil, nil) if err != nil { t.Fatal(err) } got := string(out) for _, want := range []string{"“wait”", "–", "…"} { if !strings.Contains(got, want) { t.Errorf("prose missing %s:\n%s", want, got) } } if !strings.Contains(got, `"raw" -- code`) { t.Errorf("a code span must survive untouched:\n%s", got) } } func TestMachineReadableOutputStaysASCII(t *testing.T) { r, err := New(nil, nil) if err != nil { t.Fatal(err) } b, err := content.Parse("posts/x.bn.md", []byte("---\ntitle: এক\ndate: 2026-03-08\n---\n")) if err != nil { t.Fatal(err) } out, err := r.Listing("posts", "bn", []content.Bundle{b}, 1) if err != nil { t.Fatal(err) } got := string(out) if !strings.Contains(got, `datetime="2026-03-08"`) { t.Errorf("datetime must stay ASCII for parsers (ADR-0034):\n%s", got) } if !strings.Contains(got, "৮ মার্চ ২০২৬") { t.Errorf("the visible date should read in Bengali:\n%s", got) } }