package chrome
import (
"bytes"
"html/template"
"net/http"
"net/http/httptest"
"net/url"
"os/exec"
"regexp"
"strings"
"testing"
"amadan.net/oficina/estilo.git/internal/tokencheck"
"amadan.net/oficina/estilo.git/menu"
"amadan.net/oficina/estilo.git/sky"
"github.com/carlosframework/rastrillo/ui"
)
func TestChromeUsesDefinedTokens(t *testing.T) {
missing, n := tokencheck.Undefined(CSS())
if n == 0 {
t.Fatal("chrome.css reads no rastrillo token; the check would pass vacuously")
}
if len(missing) > 0 {
t.Fatal("chrome.css reads undefined tokens:", missing)
}
}
// The bar's height is public contract and must be fixed, never a minimum:
// nothing inside it may grow it.
func TestBarHeightIsFixedAndPublic(t *testing.T) {
src := string(CSS())
for _, want := range []string{
"--estilo-bar-block-size: 3.25rem;",
"--estilo-z-bar: 45;",
"block-size: var(--estilo-bar-block-size);",
"flex-wrap: nowrap;",
} {
if !strings.Contains(src, want) {
t.Errorf("chrome.css lost %q", want)
}
}
// Narrow: the title field may shrink to nothing and the Rename button
// floats under it rather than taking room from Menu and the switcher.
// The browser proof is polish-audit/r2-chrome-check.mjs's reach checks.
narrow := src[strings.LastIndex(src, "@media (max-width: 799.98px)"):]
for _, want := range []string{"[estilo-bar-title-input] { min-inline-size: 0; }", "[estilo-bar-title]:focus-within [estilo-bar-title-submit] {\n position: absolute;"} {
if !strings.Contains(narrow, want) {
t.Errorf("the narrow title layout lost %q", want)
}
}
if regexp.MustCompile(`\[estilo-bar\]\s*\{[^}]*min-block-size`).MatchString(src) {
t.Error("the bar declares a min-block-size: it could grow")
}
}
func parse(t *testing.T) *template.Template {
t.Helper()
view := template.New("").Funcs(ui.Funcs())
view, err := view.ParseFS(ui.Templates(), "*.html")
if err != nil {
t.Fatal(err)
}
if view, err = view.ParseFS(menu.Templates(), "templates/*.html"); err != nil {
t.Fatal(err)
}
if view, err = view.ParseFS(Templates(), "templates/*.html"); err != nil {
t.Fatal(err)
}
return view
}
func render(t *testing.T, name string, data any) string {
t.Helper()
var out bytes.Buffer
if err := parse(t).ExecuteTemplate(&out, name, data); err != nil {
t.Fatal(err)
}
return out.String()
}
// One word per locale, used for every caller-supplied label, so a label
// the template dropped or hard-coded shows up as a missing string.
var locales = map[string]string{"en": "Account", "de": "Konto", "es": "Cuenta", "fr": "Compte", "it": "Account", "pt": "Conta", "nl": "Account", "pl": "Konto", "ar": "الحساب", "ja": "アカウント", "zh": "账户", "ko": "계정"}
func signedIn(label string) Bar {
return Bar{
App: App{Name: label + "-app", Slug: "docs", Home: "/", Icon: "/static/estilo/brand/docs.svg"},
ContextEdit: &TitleEdit{Action: "/d/abc/title", Name: "title", Value: label + "-title", Label: label + "-title-label", Submit: label + "-rename"},
Nav: []Link{{Href: "/", Label: label + "-nav", Current: true}},
NavLabel: label + "-navlabel",
Actions: []Action{
{Item: menu.Item{Href: "/d/abc/share", Label: label + "-share"}},
{Item: menu.Item{Action: "/d/new", Label: label + "-create"}, Primary: true},
},
Switcher: &Switcher{Label: label + "-apps", AllApps: menu.Item{Href: "https://oficina.example/", Label: label + "-allapps"}},
Account: &Account{
TriggerLabel: label + "-trigger", Initials: "P", Address: "paul@example.test",
Labels: AccountLabels{SignedInAs: label + "-signedinas", Appearance: label + "-appearance", Help: label + "-help"},
Items: []menu.Item{{Href: "/account/home", Label: label + "-connect"}},
Appearance: &AppearanceMenu{Action: "/appearance", Return: "/d/abc", Options: AppearanceOptions(Dark, label+"-light", label+"-dark", label+"-system")},
Help: []menu.Item{{Href: "/credits", Label: label + "-opensource"}},
SignOut: SignOut{Action: "/signout", Label: label + "-signout"},
},
Labels: BarLabels{Skip: label + "-skip", Menu: label + "-menu"},
}
}
func TestBarRendersCallerLabelsInEveryLocale(t *testing.T) {
for locale, label := range locales {
t.Run(locale, func(t *testing.T) {
html := render(t, "estilo-bar", signedIn(label))
esc := template.HTMLEscapeString
for _, want := range []string{
``, esc(label) + "-app",
`