Implement the ux-first-run change: a state-derived setup checklist on /operator/setup with a landing region that recedes once required steps are done, and empty states that distinguish blocked from empty across operator and member surfaces. Also add production deployment and environment reference docs, plus a config-key completeness test.
80 lines
2.7 KiB
Go
80 lines
2.7 KiB
Go
package server_test
|
|
|
|
// DB-backed handler tests for the grants list's empty-state gate
|
|
// (ux-first-run 3.3): naming "no product has been published yet" when
|
|
// blocked, versus pointing at the per-organization issue flow once at
|
|
// least one product has been published but no grant has been issued.
|
|
//
|
|
// DB-backed via TEST_DATABASE_URL (shared testDB helper). Reuses
|
|
// cleanCatalogTables and gateGet (operator_product_create_gate_test.go) and
|
|
// otcHarness/newOtcHarness (operator_org_type_change_test.go), all in this
|
|
// same package.
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.coopcloud.tech/wiki-cafe/member-console/internal/billing"
|
|
"git.coopcloud.tech/wiki-cafe/member-console/internal/entitlements"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func TestGrantsPage_BlockedWhenNoPublishedProduct(t *testing.T) {
|
|
database := testDB(t)
|
|
cleanCatalogTables(t, database)
|
|
h := newOtcHarness(t, database, "grants-gate-blocked")
|
|
|
|
code, body := gateGet(t, h.ctx, h.handler.GetGrantsPage)
|
|
if code != http.StatusOK {
|
|
t.Fatalf("status = %d, body: %s", code, body)
|
|
}
|
|
if !strings.Contains(body, "no product has been published yet") {
|
|
t.Errorf("expected the blocked explanation naming the missing prerequisite, got:\n%s", body)
|
|
}
|
|
if !strings.Contains(body, `href="/operator/products"`) {
|
|
t.Errorf("expected a link to Products, got:\n%s", body)
|
|
}
|
|
}
|
|
|
|
func TestGrantsPage_EmptyPointsAtIssueFlowWhenProductPublished(t *testing.T) {
|
|
database := testDB(t)
|
|
cleanCatalogTables(t, database)
|
|
ctx := context.Background()
|
|
eq := entitlements.New(database)
|
|
bq := billing.New(database)
|
|
|
|
es, err := eq.CreateEntitlementSet(ctx, entitlements.CreateEntitlementSetParams{
|
|
Name: "grants-gate-set",
|
|
IsActive: true,
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("create entitlement set: %v", err)
|
|
}
|
|
if _, err := bq.CreateProduct(ctx, billing.CreateProductParams{
|
|
Name: "Grants Gate Product",
|
|
IsActive: true,
|
|
IsPublic: true,
|
|
EntitlementSetID: uuid.NullUUID{UUID: uuid.MustParse(es.SetID), Valid: true},
|
|
LifecycleStatus: "published",
|
|
}); err != nil {
|
|
t.Fatalf("create product: %v", err)
|
|
}
|
|
|
|
h := newOtcHarness(t, database, "grants-gate-unblocked")
|
|
code, body := gateGet(t, h.ctx, h.handler.GetGrantsPage)
|
|
if code != http.StatusOK {
|
|
t.Fatalf("status = %d, body: %s", code, body)
|
|
}
|
|
if strings.Contains(body, "no product has been published yet") {
|
|
t.Errorf("must not render the blocked explanation once a product is published, got:\n%s", body)
|
|
}
|
|
if !strings.Contains(body, "issued from each organization's detail page") {
|
|
t.Errorf("expected the empty state to point at the issue flow, got:\n%s", body)
|
|
}
|
|
if !strings.Contains(body, "No grants found.") {
|
|
t.Errorf("expected the base empty-state line to still render, got:\n%s", body)
|
|
}
|
|
}
|