Files
member-console/test/e2e/operator-walkthroughs/error_contract_test.go
T
cgalo5758 88db730fcc Add dual licensing and SPDX headers
Introduce a commercial license option alongside AGPL-3.0-only, require a
CLA for contributors, and document the terms in COMMERCIAL.md and
NOTICE. Add a script to stamp SPDX headers on Go files and apply it
across the tree.
2026-09-06 02:29:42 -05:00

67 lines
2.5 KiB
Go

// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
// walkthrough: error-contract (cross-cutting)
// covers: bullet 4 — forced 5xx response triggers the error toast, no UI
// bleed (no orphan partial, no half-swap).
//
// Uses rod's request hijacking to inject a 500 response for a specific
// known POST without modifying the app. Verifies that
// internal/embeds/static/error-handler.js fires its showErrorToast funnel.
package operatorwalkthroughs_test
import (
"strings"
"testing"
"time"
"github.com/go-rod/rod"
"github.com/go-rod/rod/lib/proto"
)
func TestErrorContractWalkthrough(t *testing.T) {
base := baseURL(t)
browser := newBrowser(t)
page := browser.MustPage()
loginAsOperator(t, page, base, "/operator/entitlement-sets")
t.Logf("hijacking POST /partials/operator/entitlement-sets → 500")
router := page.HijackRequests()
defer router.MustStop()
router.MustAdd("*/partials/operator/entitlement-sets", func(ctx *rod.Hijack) {
if string(ctx.Request.Method()) != "POST" {
ctx.ContinueRequest(&proto.FetchContinueRequest{})
return
}
ctx.Response.SetHeader("Content-Type", "text/html")
ctx.Response.Payload().ResponseCode = 500
ctx.Response.SetBody("internal server error")
})
go router.Run()
// design D20 (round 4): the create form lives on its own page, reached
// from the list's filled "New entitlement set" link.
t.Logf("phase 0: follow the New entitlement set link to the create page")
page.Timeout(10 * time.Second).MustElement(`a[href="/operator/entitlement-sets/new"]`).MustClick()
page.Timeout(10 * time.Second).MustElement(`form[data-form="operator.entitlement-set"]`)
t.Logf("submit valid entitlement set form → hijacked 500 → expect error toast")
page.MustElement(`form[data-form="operator.entitlement-set"] input[name="name"]`).MustInput("e2e-error-contract")
page.MustElement(`form[data-form="operator.entitlement-set"] button[type=submit]`).MustClick()
// error-handler.js calls showErrorToast() for 5xx; #errorToast.show
// should appear.
page.Timeout(10 * time.Second).MustElement(`#errorToast.show`)
// No UI bleed: the form should still be intact (not half-swapped).
if _, err := page.Element(`form[data-form="operator.entitlement-set"]`); err != nil {
t.Errorf("UI bleed: the entitlement-set create form vanished after 5xx (should be preserved)")
}
errText := strings.TrimSpace(page.MustElement(`#errorToast`).MustText())
if errText == "" {
t.Errorf("error toast text is empty")
}
}