package web // v0.48.0 edit-a — the standalone customer edit page merged into the customer page's Edit tab // (config_form_body embedded; Block/Delete relocated to a danger zone) plus the redirect-anchor // contract of the surrounding POST actions. Groups A + B of the task's test plan. import ( "io" "log" "net/http" "net/http/httptest" "net/url" "strings" "testing" "gitea.dooplex.hu/admin/felhom-hub/internal/hetznerapi" "gitea.dooplex.hu/admin/felhom-hub/internal/offsite" "gitea.dooplex.hu/admin/felhom-hub/internal/store" ) // editPanel slices the rendered customer page down to the Edit tab's panel (from its opening div // to the next panel) so containment assertions are panel-scoped, not page-scoped. func editPanel(t *testing.T, html string) string { t.Helper() start := strings.Index(html, `tab-panel" data-tab="edit"`) if start < 0 { t.Fatal("Edit tab panel missing") } end := strings.Index(html[start:], `tab-panel" data-tab="backup"`) if end < 0 { t.Fatal("Backup panel (the Edit panel's terminator) missing") } return html[start : start+end] } // Group A — the Edit tab renders the full mutation surface and the header is cleaned. func TestCustomerEditTab_RendersMutationSurface(t *testing.T) { s, st := newTestServer(t) if err := st.SaveCustomerConfig(&store.CustomerConfig{ CustomerID: "c1", CustomerName: "Acme", Domain: "acme.hu", Email: "a@acme.hu", RetrievalPassword: "pw", APIKey: "k", Status: "active", ConfigJSON: `{"infrastructure":{"cf_tunnel_token":"stored-tunnel-token"}}`, }); err != nil { t.Fatal(err) } if err := st.SaveReport("c1", []byte(tabsTestReportJSON)); err != nil { t.Fatal(err) } html := renderCustomerPage(t, s, "c1") panel := editPanel(t, html) // The panel carries the config form + the three sibling cards. for _, want := range []string{ `action="/configs/c1/edit"`, // the embedded config form "Controller Update", "Geo-korlátozás", "Danger zone", `action="/customers/c1/block"`, `action="/configs/c1/delete"`, `name="_csrf"`, // CSRF field inside the form } { if !strings.Contains(panel, want) { t.Errorf("Edit panel missing %q", want) } } // Stored override values populate the embedded form (values come from Config/ConfigJSON). if !strings.Contains(panel, `value="stored-tunnel-token"`) { t.Error("embedded form does not render the stored cf_tunnel_token override") } // The named trap: the floor/geo/danger forms must be SIBLINGS after , never nested // inside the config
no other