package web
import (
"strings"
"testing"
)
// A landing settles from somewhere else — a reviewer accepts on the
// record page, or CI goes green under an armed one — and the reader
// watching this list has no reason to reload. Until this, the list was
// the one landing surface with no live wiring at all: the record page
// and the timeline both followed the repository, and the queue did not,
// so an accepted landing sat in the list and in the nav badge until
// somebody pressed reload.
func TestTheLandingsListFollowsTheRepository(t *testing.T) {
var buf strings.Builder
err := noHooks.template(landingListPage).ExecuteTemplate(&buf, "content", pageData{
Repo: "alpha", Live: true, Nav: ticketNav{Repo: "alpha"},
})
if err != nil {
t.Fatal(err)
}
got := buf.String()
for _, want := range []string{
`data-signals="{tlRev: 0}"`,
`data-init="@get('/r/alpha/timeline.rev')"`,
`@get('/r/alpha/landing.frag')`,
`@get('/r/alpha/nav.frag?s=landing')`,
`<div id="l-list">`,
} {
if !strings.Contains(got, want) {
t.Errorf("FAIL: the live list is missing %s", want)
}
}
// data-init, never data-on:load — Datastar fires no load event, and
// the wrong spelling is inert rather than an error.
if strings.Contains(got, "data-on:load") {
t.Error("FAIL: uses an event Datastar never fires")
}
}
// The filter travels with the repaint. Without it a reader watching
// "Accepted" would have the list replaced with the open queue the
// moment anything in the repository moved.
func TestTheRepaintKeepsTheFilterThePageIsShowing(t *testing.T) {
var buf strings.Builder
if err := noHooks.template(landingListPage).ExecuteTemplate(&buf, "content", pageData{
Repo: "alpha", Live: true, Nav: ticketNav{Repo: "alpha", State: "accepted"},
}); err != nil {
t.Fatal(err)
}
if !strings.Contains(buf.String(), `landing.frag?state=accepted`) {
t.Error("FAIL: the repaint drops the state filter and would show the open queue instead")
}
}
// Without a notifier there is no revision stream to subscribe to, so
// the page carries no wiring — and is still a correct page.
func TestWithoutAStreamTheListIsPlain(t *testing.T) {
var buf strings.Builder
if err := noHooks.template(landingListPage).ExecuteTemplate(&buf, "content", pageData{
Repo: "alpha", Nav: ticketNav{Repo: "alpha"},
}); err != nil {
t.Fatal(err)
}
got := buf.String()
if strings.Contains(got, "data-init") || strings.Contains(got, "data-effect") {
t.Error("FAIL: a forge with no revision stream still subscribes to one")
}
// The listing itself is still there — the wiring is what is absent,
// not the content.
if !strings.Contains(got, `<div id="l-list">`) || !strings.Contains(got, "No branch is awaiting a decision") {
t.Error("FAIL: the plain page lost its listing")
}
}
// The fragment renders the same body the page does, wrapped in the
// element it replaces. Two renderings of one listing that could differ
// is the bug this shape exists to prevent.
func TestTheFragmentIsTheSameBodyThePageShows(t *testing.T) {
data := pageData{Repo: "alpha", Nav: ticketNav{Repo: "alpha"}}
var frag, page strings.Builder
if err := noHooks.template(landingListPage).ExecuteTemplate(&frag, "l-list-body", data); err != nil {
t.Fatal(err)
}
if err := noHooks.template(landingListPage).ExecuteTemplate(&page, "content", data); err != nil {
t.Fatal(err)
}
if !strings.Contains(page.String(), strings.TrimSpace(frag.String())) {
t.Error("FAIL: the fragment is not the body the page renders")
}
}