package markup
import (
"html/template"
"regexp"
"strings"
"testing"
)
func cardOf(t *testing.T, d EmailDoc) string {
t.Helper()
if d.Body == "" {
d.Body = "<p>hi</p>"
}
got, ok := EmailDocument(d)
if !ok {
t.Fatal("EmailDocument fell back")
}
return got
}
var cardDoc = EmailDoc{
Title: "t", Name: "alpha", Mark: IdenticonMark("alpha"), Surface: "chat",
Context: "<strong>jva</strong> mentioned you", Meta: "now",
Open: "Open the message", OpenURL: "https://forge.example/r/alpha/chat/7",
Why: "because", SettingsURL: "https://forge.example/me#notifications",
HomeURL: "https://forge.example", HomeName: "forge.example",
}
func TestEmailDocumentIsOneTableCard(t *testing.T) {
got := cardOf(t, cardDoc)
if n := strings.Count(got, `class="q-card"`); n != 1 {
t.Errorf("%d cards", n)
}
for _, want := range []string{`max-width:600px`, `role="presentation"`, `class="q-page"`, `class="q-btn"`, `<!doctype html>`} {
if !strings.Contains(got, want) {
t.Errorf("missing %s", want)
}
}
for _, banned := range []string{"<div style=\"display:flex", "display:grid", "<img", "<script", "<svg"} {
if strings.Contains(got, banned) {
t.Errorf("carries %s", banned)
}
}
}
func TestEmailDocumentLoadsOnlyTheFontSheet(t *testing.T) {
got := cardOf(t, cardDoc)
for _, m := range regexp.MustCompile(`(?:src|href)="([^"]*)"`).FindAllStringSubmatch(got, -1) {
u := m[1]
if !strings.HasPrefix(u, "https://") {
t.Errorf("non-absolute %q", u)
}
}
links := regexp.MustCompile(`<link [^>]*>`).FindAllString(got, -1)
if len(links) != 1 || !strings.Contains(links[0], `href="https://fonts.googleapis.com/`) {
t.Errorf("links: %v", links)
}
if strings.Contains(got, "@import") || strings.Contains(got, "url(") {
t.Error("remote resource in the stylesheet")
}
}
func TestEmailDocumentReplyHintOnlyWhenAsked(t *testing.T) {
if got := cardOf(t, cardDoc); strings.Contains(got, "reply to this email") {
t.Error("reply hint without ReplyIn")
}
d := cardDoc
d.ReplyIn = "answer in chat"
if got := cardOf(t, d); !strings.Contains(got, "reply to this email") {
t.Error("no reply hint with ReplyIn")
}
}
func TestEmailDocumentHasDarkBlockAndPlexFirst(t *testing.T) {
got := cardOf(t, cardDoc)
if !strings.Contains(got, "@media (prefers-color-scheme: dark)") {
t.Error("no dark block")
}
if !strings.Contains(got, "font-family:'IBM Plex Sans',") {
t.Error("Plex Sans is not first")
}
}
func TestEmailDocumentEscapesAndCaps(t *testing.T) {
d := cardDoc
d.Name = "<b>x</b>"
if got := cardOf(t, d); strings.Contains(got, "<b>x</b>") {
t.Error("repo not escaped")
}
d.Body = template.HTML("<p>" + strings.Repeat("word ", EmailHTMLMax/4) + "</p>")
if _, ok := EmailDocument(d); ok {
t.Error("oversized document kept")
}
}