Skip to content
quarry Artifact [cf88083cfc]
Login

Artifact [cf88083cfc]

Artifact cf88083cfc052d22b2344b45d2608b5ea4d83df82f6354cb42ae3fc761453d86:


package web

import (
	"strings"
	"testing"
)

func aTeamSettingsPage(stream string) pageData {
	td := &teamDetail{
		Team:      teamRow{Name: "grove", Title: "Grove"},
		CanManage: true,
		Repos:     []teamRepo{{Repo: "alpha", Added: "2026-09-01T00:00:00Z"}},
		Offered: []teamOfferRow{{Repo: "beta", OfferedBy: "lou",
			Offered: "2026-09-15T00:00:00Z", Expires: "2026-09-22T00:00:00Z"}},
		MayRemove: []string{"alpha"},
	}
	data := teamSettingsData(td, noHooks.marks == nil, false, nil)
	data.TeamStream = stream
	return data
}

// The roster a changed team sends is the roster the page draws,
// rendered by the same template. Two views of one team cannot drift.
func TestAChangedTeamSendsItsRoster(t *testing.T) {
	data := aTeamSettingsPage("")
	got := teamRosterPart(&noHooks, data)
	for _, want := range []string{
		"event: datastar-patch-elements",
		"data: selector #t-repos",
		// Inner, because the wrapper carries the id the patch targets.
		"data: mode inner",
		"alpha",
		"beta",
	} {
		if !strings.Contains(got, want) {
			t.Errorf("FAIL: the patch is missing %q", want)
		} else {
			t.Logf("ok: the patch carries %q", want)
		}
	}
	// It is comparable, which is what lets the stream stay quiet when
	// nothing moved.
	if teamRosterPart(&noHooks, data) != got {
		t.Error("FAIL: the same team renders differently twice")
	}
	// And the page renders that same fragment rather than a second
	// copy of the roster.
	var page strings.Builder
	if err := noHooks.template(teamSettingsPage).ExecuteTemplate(&page, "content", data); err != nil {
		t.Fatal(err)
	}
	var frag strings.Builder
	if err := noHooks.template(teamSettingsPage).ExecuteTemplate(&frag, "team-repos", data); err != nil {
		t.Fatal(err)
	}
	if !strings.Contains(page.String(), frag.String()) {
		t.Error("FAIL: the page does not render the same roster fragment")
	} else {
		t.Log("ok: page and stream render one template")
	}
}

// The page opens its stream from a wrapper, and says nothing when
// there is no stream to open.
func TestATeamOpensItsStreamFromAWrapper(t *testing.T) {
	var page strings.Builder
	if err := noHooks.template(teamSettingsPage).ExecuteTemplate(&page,
		"content", aTeamSettingsPage("/t/grove/settings.sse")); err != nil {
		t.Fatal(err)
	}
	got := page.String()
	if !strings.Contains(got, `data-init="@get('/t/grove/settings.sse')"`) {
		t.Fatal("FAIL: the team settings page does not open its stream")
	}
	// Outside the patched region, not on it: a patch morphs its target
	// and would take the attribute — and the connection — with it.
	init := strings.Index(got, "data-init=")
	target := strings.Index(got, `id="t-repos"`)
	if target < 0 || init > target {
		t.Errorf("FAIL: data-init is not outside #t-repos (init %d, target %d)", init, target)
	} else {
		t.Log("ok: data-init sits outside the patched element")
	}

	var quiet strings.Builder
	if err := noHooks.template(teamSettingsPage).ExecuteTemplate(&quiet, "content", aTeamSettingsPage("")); err != nil {
		t.Fatal(err)
	}
	if strings.Contains(quiet.String(), "data-init=") {
		t.Error("FAIL: the page opens a stream it was given no address for")
	} else {
		t.Log("ok: no stream, no data-init")
	}
}

// The forms stay OUT of the patched region. A patch morphs what it
// lands on, so streaming the name, the description or the image picker
// would take the letters out from under somebody part-way through
// typing them — to tell them about a repository.
func TestTheTeamsFormsAreNotStreamed(t *testing.T) {
	var frag strings.Builder
	if err := noHooks.template(teamSettingsPage).ExecuteTemplate(&frag,
		"team-repos", aTeamSettingsPage("")); err != nil {
		t.Fatal(err)
	}
	got := frag.String()
	for _, hook := range []string{`id="t-title"`, `id="t-descr"`, `data-hook="avatar-edit"`} {
		if strings.Contains(got, hook) {
			t.Errorf("FAIL: %s is inside the patched region", hook)
		} else {
			t.Logf("ok: %s is not streamed", hook)
		}
	}
	// The roster itself is in there, or the region is the wrong one.
	if !strings.Contains(got, "alpha") {
		t.Error("FAIL: the roster is not in the patched region")
	}
}