Replace the entity slugs on organizations, workspaces, resource pools, and plan ladders with nullable `key` columns and add keys to products, prices, and entitlement sets. Rename `providers.slug` to `provider` and add partial unique indexes for system and org role names. Assign invoice numbers per billing account from a gapless transactional counter; Stripe's number moves to the invoice mapping as an external reference. Seeds, fixtures, and the operator lookup address rows by key, and the returning-login resync no longer blanks a display name when the IdP sends no `name` claim.
85 lines
3.5 KiB
Go
85 lines
3.5 KiB
Go
package server
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestOrgDetailTitledByOrganizationName covers plan-enrollment-administration
|
|
// ("The page is titled by the organization, not 'Enrollment'"): the h1 is the
|
|
// organization's own display name, the breadcrumb reads Organizations →
|
|
// {name}, and the word "Enrollment" appears nowhere in the title, breadcrumb,
|
|
// or (per docs/operator-ia.md's owning template) the sidebar.
|
|
func TestOrgDetailTitledByOrganizationName(t *testing.T) {
|
|
out := renderOrgEnrollment(t, onePoolFixture())
|
|
|
|
if !strings.Contains(out, `<h1 class="mb-0 h6">Test Org</h1>`) {
|
|
t.Errorf("expected the h1 to be the organization's own display name, got:\n%s", out)
|
|
}
|
|
if !strings.Contains(out, `<a href="/operator/organizations">Organizations</a> → Test Org`) {
|
|
t.Errorf("expected the breadcrumb Organizations → Test Org, got:\n%s", out)
|
|
}
|
|
if strings.Contains(out, "Enrollment") {
|
|
t.Errorf("the word Enrollment must not appear on the org detail page, got:\n%s", out)
|
|
}
|
|
}
|
|
|
|
// TestOrgDetailSectionHeadingsUseCanonicalVocabulary covers the same delta's
|
|
// canonical-heading requirement: billing, pools, plan and grants, members,
|
|
// with the audit list heading "Tier changes" (maintainer design round
|
|
// 2026-08-24 retired "Position history"; operators cannot decode
|
|
// "position"). Every heading renders OUTSIDE its box (h2, never a card
|
|
// title) per the same round's one-rule heading doctrine.
|
|
func TestOrgDetailSectionHeadingsUseCanonicalVocabulary(t *testing.T) {
|
|
data := onePoolFixture()
|
|
// The "Plan and grants" card only renders once a grant exists.
|
|
data.Grants = []GrantViewModel{
|
|
{GrantID: "g-1", ProductName: "Standard Plan", GrantReason: "manual", Status: "active", DeliveryState: "live"},
|
|
}
|
|
out := renderOrgEnrollment(t, data)
|
|
|
|
for _, want := range []string{
|
|
">Billing<",
|
|
">Pools<",
|
|
">Plan and grants<",
|
|
">Members<",
|
|
">Tier changes<",
|
|
} {
|
|
if !strings.Contains(out, want) {
|
|
t.Errorf("expected canonical section heading %q, got:\n%s", want, out)
|
|
}
|
|
}
|
|
for _, banned := range []string{"Resource Pools", "Transition History", "Position history"} {
|
|
if strings.Contains(out, banned) {
|
|
t.Errorf("retired heading %q must not render, got:\n%s", banned, out)
|
|
}
|
|
}
|
|
// Card titles may only name instances (the pool's own name); the two
|
|
// sections that used to title themselves inside their cards must not.
|
|
for _, banned := range []string{`card-title mb-0 h6">Billing`, `card-title h6 mb-0">Plan and grants`} {
|
|
if strings.Contains(out, banned) {
|
|
t.Errorf("section title rendered inside its card (%q); headings live outside the box, got:\n%s", banned, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestOrganizationsListManageLinkNotEnrollment covers the same delta's nav
|
|
// reference: the organizations list's row action into the detail page must
|
|
// not carry the retired "Enrollment" label.
|
|
func TestOrganizationsListManageLinkNotEnrollment(t *testing.T) {
|
|
body := renderOrganizationsPageBody(t, OrganizationsData{
|
|
Organizations: []OrganizationViewModel{
|
|
{OrgID: "org-1", Name: "Acme Co-op", OrgType: "team", Status: "active", OwnerName: "Jamie Rivera"},
|
|
},
|
|
})
|
|
if strings.Contains(body, "Enrollment") {
|
|
t.Errorf("organizations list must not offer an Enrollment-labeled action, got:\n%s", body)
|
|
}
|
|
if !strings.Contains(body, `href="/operator/organizations/org-1"`) {
|
|
t.Errorf("expected the row's action link to the org detail page, got:\n%s", body)
|
|
}
|
|
if !strings.Contains(body, "Manage") {
|
|
t.Errorf("expected the row's action link relabeled Manage, got:\n%s", body)
|
|
}
|
|
}
|