package web
import (
"net/http/httptest"
"strings"
"testing"
)
func deferURL(target string) string {
return deferredDiffURL("alpha", "abc123", httptest.NewRequest("GET", target, nil))
}
// The bare check-in page defers: everything above the diff is cheap,
// and the diff is two store subprocesses the reader should not wait
// through before seeing the check-in at all.
func TestTheBareCheckinPageDefersItsDiff(t *testing.T) {
got := deferURL("/r/alpha/checkin/abc123")
if got == "" {
t.Fatal("FAIL: the bare page did not defer")
}
if !strings.Contains(got, "/diff.frag?whole=1") {
t.Errorf("FAIL: deferred to %q, want the whole-body fragment", got)
}
}
// A request carrying any diff-shaping parameter is a deep link somebody
// may have shared. Deferring one would defer exactly what its address
// asked for, and — for a no-script reader following the unified/split
// links — would break the page outright.
func TestADeepLinkedDiffIsNeverDeferred(t *testing.T) {
for _, target := range []string{
"/r/alpha/checkin/abc123?view=split",
"/r/alpha/checkin/abc123?file=main.go",
"/r/alpha/checkin/abc123?after=200",
"/r/alpha/checkin/abc123?prev=0",
"/r/alpha/checkin/abc123?branch=1",
"/r/alpha/checkin/abc123?from=deadbeef",
} {
if got := deferURL(target); got != "" {
t.Errorf("FAIL: %s deferred to %q, want inline", target, got)
}
}
}
// nojs=1 is the address the no-script fallback reloads into. If that
// deferred too, a reader without script would bounce for ever.
func TestTheNoScriptEscapeAlwaysRendersInline(t *testing.T) {
if got := deferURL("/r/alpha/checkin/abc123?nojs=1"); got != "" {
t.Errorf("FAIL: nojs=1 deferred to %q — a no-script reader would reload for ever", got)
}
}
// The deferred frame must carry both halves: the fetch for a scripted
// reader, and the escape for one without script. Either alone is a
// page that is permanently missing its diff for somebody.
func TestTheDeferredFrameCarriesBothPaths(t *testing.T) {
var buf strings.Builder
err := diffPage.ExecuteTemplate(&buf, "diff-body", pageData{
Repo: "alpha", DiffDeferURL: "/r/alpha/checkin/abc123/diff.frag?whole=1",
})
if err != nil {
t.Fatal(err)
}
got := buf.String()
if !strings.Contains(got, `data-init="@get(`) {
t.Error("FAIL: the frame does not fetch the diff for a scripted reader")
}
if !strings.Contains(got, `<noscript><meta http-equiv="refresh" content="0; url=?nojs=1">`) {
t.Error("FAIL: the frame has no no-script escape")
}
// It patches the same element it lives in, so the placeholder is
// replaced rather than accumulating above the diff.
if !strings.Contains(got, `id="diffbody"`) {
t.Error("FAIL: the deferred frame lost the target element")
}
// data-init, not data-on:load. Datastar has no "load" event — the
// bundle contains no such handler — so data-on:load binds a DOM
// load event that never fires on a <p> or a <div>, and the fetch
// silently never happens.
if strings.Contains(got, "data-on:load") {
t.Error("FAIL: the fetch uses an event Datastar never fires")
}
}
// And the inline path must be untouched by the deferral: a page that
// already has its diff renders it, with no placeholder and no escape.
func TestTheInlineFrameStillRendersTheDiff(t *testing.T) {
var buf strings.Builder
err := diffPage.ExecuteTemplate(&buf, "diff-body", pageData{
Repo: "alpha",
Diff: diffDetail{Repo: "alpha", To: "abc123", Note: "nothing changed"},
})
if err != nil {
t.Fatal(err)
}
got := buf.String()
if strings.Contains(got, "data-init") || strings.Contains(got, "nojs=1") {
t.Error("FAIL: an inline diff still carries the deferral scaffolding")
}
if !strings.Contains(got, "nothing changed") {
t.Error("FAIL: the inline diff did not render")
}
}
// Datastar has no "load" event. The bundle registers an "init" plugin
// and nothing named load, so data-on:load binds a DOM load event —
// which never fires on a div or a paragraph, leaving the fetch silently
// undone. This caught a landing card whose live stream had never
// started.
func TestNothingWaitsOnADatastarLoadEvent(t *testing.T) {
if strings.Contains(styleSource, "data-on:load") {
t.Error("FAIL: a data-on:load fetch is back; Datastar never fires it — use data-init")
}
}