package chrome import ( "html/template" "strings" "testing" "time" ) // The door's copy is the suite's one copy set (shared-chrome spec §9.2, // with Paul's 2026-10-01 ruling that the submit reads "Sign in"). Pinned // word for word: a change here is a copy decision, made on purpose, in one // place. func TestDoorCopyIsPinned(t *testing.T) { if LinkLifetime != 15*time.Minute { t.Fatalf("LinkLifetime = %v; the copy below says 15 minutes", LinkLifetime) } for _, c := range []struct{ name, got, want string }{ {"Heading", English.Heading, "Sign in"}, {"AddressLabel", English.AddressLabel, "Email address"}, {"Help", English.Help, "We’ll email you a link that signs you in. It works once and expires in 15 minutes."}, {"Submit", English.Submit, "Sign in"}, {"SentHeading", English.SentHeading, "Check your email"}, {"SentBody", English.SentBody, "If that address can sign in here, we’ve sent it a link. It works once and expires in 15 minutes."}, {"Again", English.Again, "Use a different address"}, {"SignedOutPage", English.SignedOutPage, "Signed out"}, {"SignedOutHeading", English.SignedOutHeading, "You’re signed out"}, {"SignedOutBody", English.signedOutBody("Calls"), "You’ve signed out of Calls on this device."}, {"SignIn", English.SignIn, "Sign in"}, } { if c.got != c.want { t.Errorf("%s = %q, want %q", c.name, c.got, c.want) } } for _, retired := range []string{"Email me a link", "Continue", "expires shortly", "on its way", "Back to sign in", "Send another link", "Use a different email address", "You are signed out", "Home"} { for _, s := range []string{English.Heading, English.Help, English.Submit, English.SentHeading, English.SentBody, English.Again, English.SignedOutHeading, English.signedOutBody("Docs"), English.SignIn} { if strings.Contains(s, retired) { t.Errorf("%q carries retired copy %q", s, retired) } } } } // Every door page's tab title is " · " (shared-chrome spec §10). func TestDoorTitles(t *testing.T) { for _, c := range []struct{ got, want string }{ {Title("Sign in", "Docs"), "Sign in · Docs"}, {Title("Sign in", ""), "Sign in"}, {Title("", "Docs"), "Docs"}, {SignIn{App: "Memoria"}.Title(), "Sign in · Memoria"}, {SignIn{App: "Memoria"}.Page(), "Sign in"}, {SignInNotice{App: "Calendar"}.Sent("/signin").Title(), "Check your email · Calendar"}, {SignInNotice{App: "Calendar"}.Sent("/signin").Page(), "Check your email"}, {SignInNotice{App: "Calls"}.SignedOut("/signin").Title(), "Signed out · Calls"}, {SignInNotice{App: "Calls"}.SignedOut("/signin").Page(), "Signed out"}, // A notice that is not one of the door's own is titled by its heading. {SignInNotice{App: "Sheets", Heading: "Continue signing in"}.Title(), "Continue signing in · Sheets"}, } { if c.got != c.want { t.Errorf("title %q, want %q", c.got, c.want) } } } // The templates draw the door's copy when the app supplies none: the app // passes its name, mark, sky and destinations, and nothing else. func TestTheDoorDrawsItsOwnCopy(t *testing.T) { html := render(t, "estilo-signin", SignIn{Icon: "/i.svg", App: "Calls", Action: "/signin"}) for _, want := range []string{ "

Sign in

", ">Email address", "We’ll email you a link that signs you in. It works once and expires in 15 minutes.", ``, } { if !strings.Contains(html, want) { t.Errorf("sign-in lacks %q:\n%s", want, html) } } if strings.Contains(html, "Email me a link") { t.Error("the door's submit must never read “Email me a link”") } html = render(t, "estilo-signin-sent", SignInNotice{Icon: "/i.svg", App: "Calls"}.Sent("/signin?return_to=%2Fm%2Fabc")) for _, want := range []string{ "

Check your email

", `

If that address can sign in here, we’ve sent it a link. It works once and expires in 15 minutes.

`, `Use a different address`, } { if !strings.Contains(html, want) { t.Errorf("sent lacks %q:\n%s", want, html) } } html = render(t, "estilo-signed-out", SignInNotice{Icon: "/i.svg", App: "Calls"}.SignedOut("/signin")) for _, want := range []string{ "

You’re signed out

", "

You’ve signed out of Calls on this device.

", `Sign in`, } { if !strings.Contains(html, want) { t.Errorf("signed-out lacks %q:\n%s", want, html) } } } // The sign-in email names the app and says the true lifetime, the same // words as the door (shared-chrome spec §9.2). func TestSignInEmail(t *testing.T) { subject, body := SignInEmail("Docs", "https://docs.example/auth/verify?token=x") if subject != "Sign in to Docs" { t.Errorf("subject %q", subject) } want := "Here’s your link to sign in to Docs:\n\nhttps://docs.example/auth/verify?token=x\n\nIt works once and expires in 15 minutes. If you didn’t ask for it, you can ignore this email." if body != want { t.Errorf("body %q\nwant %q", body, want) } if got := EmailBody("Docs")("L"); !strings.Contains(got, "\n\nL\n\n") { t.Errorf("EmailBody does not place the link: %q", got) } } // A locale other than English replaces every word through Copy. func TestDoorCopyIsReplaceablePerLocale(t *testing.T) { for locale, label := range locales { t.Run(locale, func(t *testing.T) { esc := template.HTMLEscapeString c := &DoorCopy{Heading: label + "-h", AddressLabel: label + "-addr", Help: label + "-help", Submit: label + "-submit", SentHeading: label + "-sent", SentBody: label + "-sentbody", Again: label + "-again", SignedOutPage: label + "-outpage", SignedOutHeading: label + "-out", SignedOutBody: label + " {app}-outbody", SignIn: label + "-in"} html := render(t, "estilo-signin", SignIn{Icon: "/i.svg", App: "Docs", Copy: c, Action: "/signin"}) for _, want := range []string{"

" + esc(label) + "-h

", esc(label) + "-addr", esc(label) + "-help", esc(label) + "-submit"} { if !strings.Contains(html, want) { t.Fatalf("missing %q in %s", want, html) } } n := SignInNotice{Icon: "/i.svg", App: "Docs", Copy: c} if h := render(t, "estilo-signin-sent", n.Sent("/signin")); !strings.Contains(h, esc(label)+"-sentbody") || !strings.Contains(h, esc(label)+"-again") { t.Fatal("sent", h) } if h := render(t, "estilo-signed-out", n.SignedOut("/signin")); !strings.Contains(h, esc(label)+" Docs-outbody") || !strings.Contains(h, esc(label)+"-in") { t.Fatal("signed out", h) } if got := n.SignedOut("/signin").Title(); got != label+"-outpage · Docs" { t.Fatalf("title %q", got) } }) } } // The copy's slots are tokens, {app} and {link}, not Printf verbs: a // translation that drops the slot, moves it, or carries a literal "%" // renders as written rather than as "%!(EXTRA …)" (Fable on estilo #19, // finding 4). func TestDoorCopyFillsTokensNotFormats(t *testing.T) { c := English c.SignedOutBody = "100% done: {app} is signed out here." if got := (SignInNotice{App: "Docs", Copy: &c}).SignedOut("/signin").Body; got != "100% done: Docs is signed out here." { t.Errorf("signed-out body %q", got) } c.SignedOutBody = "Signed out." if got := (SignInNotice{App: "Docs", Copy: &c}).SignedOut("/signin").Body; got != "Signed out." { t.Errorf("a body without {app} rendered %q", got) } // With no app, the suite is named, as the hub's own page does. if got := (SignInNotice{}).SignedOut("/signin").Body; got != "You’ve signed out of Oficina on this device." { t.Errorf("no-app signed-out body %q", got) } // The link is substituted once: a link that happens to carry "{app}" // is not rewritten. if _, body := English.SignInEmail("Docs", "https://x.example/?q={app}"); !strings.Contains(body, "\n\nhttps://x.example/?q={app}\n\n") { t.Errorf("the link was rewritten: %q", body) } } // The email is part of the copy set: a locale's subject and body are what // a locale's email says (Fable on estilo #19, finding 3), and the package // helpers are English's. func TestSignInEmailReadsTheCopy(t *testing.T) { c := English c.EmailSubject = "Entra en {app}" c.EmailBody = "{app}: {link} (100%)" subject, body := c.SignInEmail("Docs", "L") if subject != "Entra en Docs" || body != "Docs: L (100%)" { t.Errorf("locale email = %q, %q", subject, body) } if got := c.MailSubject("Docs"); got != "Entra en Docs" { t.Errorf("MailSubject %q", got) } if got := c.MailBody("Docs")("L"); got != "Docs: L (100%)" { t.Errorf("MailBody %q", got) } s, b := SignInEmail("Docs", "L") if es, eb := English.SignInEmail("Docs", "L"); s != es || b != eb || EmailSubject("Docs") != es || EmailBody("Docs")("L") != eb { t.Error("the package helpers are not English's email") } }