Files
member-console/internal/server/member_domains_dissolve_render_test.go
T
cgalo5758 d3b222a446 Dissolve the member domains surface into point-of-use
Domains leaves the member nav everywhere; GET /domains 302s to the
dashboard and domains.html is deleted. Claims are managed where they are
used: the fedwiki sites card embeds the core claims partial, a
server-conditional dashboard notice carries pending verifications (the
durable re-entry now that the page is gone), and the member_domains
partials retarget to 'closest .domains-surface' so multiple hosts coexist
on one page. Adding an external domain starts only from the create form;
the fedwiki banner slims to verified-unplaced one-click creates, since
the notice and embedded section own the pending state.

Verified at the surface end-to-end (stack + Chrome): nav absence,
redirect, notice lifecycle through claim-cancel, and cross-host swap
isolation with two claim views open. Archives the change with spec
deltas synced (domains-registry point-of-use rewrite, fedwiki-sites and
member-dashboard additions); files the entitlement-gate placement debt
in issues.md; adds the repo verify skill.
2026-07-26 03:10:23 -05:00

97 lines
3.3 KiB
Go

// Render coverage for the member-side domains dissolution
// (dissolve-member-domains): the member shells carry no Domains navigation,
// and the dashboard carries the pending-claim notice — the durable re-entry
// point for an in-flight DNS verification now that the standalone page is
// gone. DB-free: templates render with literal data.
package server_test
import (
"net/http/httptest"
"strings"
"testing"
"git.coopcloud.tech/wiki-cafe/member-console/internal/server"
)
// shellData mirrors the anonymous structs the products/billing handlers
// render their shells with.
type shellData struct {
KeycloakAccountURL string
CSRFToken string
IsOperator bool
}
// TestMemberShellsHaveNoDomainsNav pins the de-centering: no member shell
// offers Domains as a destination.
func TestMemberShellsHaveNoDomainsNav(t *testing.T) {
st := rootTemplates(t)
render := func(name string, data any) string {
t.Helper()
rec := httptest.NewRecorder()
st.Render(rec, name, data)
if rec.Code != 200 {
t.Fatalf("%s: expected 200, got %d: %s", name, rec.Code, rec.Body.String())
}
return rec.Body.String()
}
for name, body := range map[string]string{
"index.html": render("index.html", dashboardData{}),
"products.html": render("products.html", shellData{}),
"billing.html": render("billing.html", shellData{}),
} {
if strings.Contains(body, `href="/domains"`) {
t.Errorf("%s still links /domains", name)
}
if strings.Contains(body, ">Domains<") {
t.Errorf("%s still renders a Domains nav label", name)
}
}
}
// TestDashboardPendingDomainNotice covers the notice's contract: present and
// claim-naming while a claim is pending, absent without one (no empty
// chrome), opening a claim is a pure GET into the notice's own
// .domains-surface wrapper, and the notice is core content — not one of the
// registry-declared integration cards.
func TestDashboardPendingDomainNotice(t *testing.T) {
st := rootTemplates(t)
rec := httptest.NewRecorder()
st.Render(rec, "index.html", dashboardData{
PendingDomainClaims: []server.PendingDomainClaim{
{ClaimID: "claim-1", Root: "wiki.example.org"},
{ClaimID: "claim-2", Root: "docs.example.net"},
},
})
body := rec.Body.String()
for _, want := range []string{
"Domain verification in progress",
"wiki.example.org", "docs.example.net",
`hx-get="/partials/domains/claims/claim-1"`,
`hx-target="closest .domains-surface"`,
"View DNS records",
} {
if !strings.Contains(body, want) {
t.Errorf("pending notice missing %q", want)
}
}
// Opening instructions is a pure read: the notice must not POST anything.
if strings.Contains(body, `hx-post="/partials/domains/claims/claim-1`) {
t.Error("the notice must open instructions via GET, never a mutating request")
}
// Core content, not a card: this render declares zero DashboardCards, and
// the notice still appears — so it cannot be riding the card registry.
// (The presence assertions above are that proof; nothing more to check.)
empty := httptest.NewRecorder()
st.Render(empty, "index.html", dashboardData{})
if strings.Contains(empty.Body.String(), "Domain verification") {
t.Error("no pending claims must mean no notice and no empty chrome")
}
if strings.Contains(empty.Body.String(), "domains-surface") {
t.Error("no pending claims must leave no dangling domains-surface wrapper")
}
}