An embedded list's search form re-submits its sibling lists' state as hidden inputs. listSearchForm added them by ranging over a map, and a GET form submits its inputs in document order, so with two or more siblings the parameters of the URL the search pushes came out in a different order from one render to the next. They are now added in the sorted order of their keys, so the order is the same on every render. With one sibling, or none, the HTML is unchanged. TestListSearchFormCarriesSiblingInputsInSortedOrder renders the form 20 times with three siblings and checks each render for key order. It failed in 3 of 3 runs at the parent and passed in 3 of 3 at this commit. The new file internal/server/testdata/forms/per-request/list-search-three-siblings.html pins the three-sibling HTML as the other per-request files do, and the comment in forms_golden_test.go that explained why the list search was rendered with one sibling is removed. No existing golden file changes. No assertion of TestFormsHTML changed; it gains one case. How it was shown to change no other output: the names and results of ./internal/server (the whole package, on the test databases) are equal at the parent and at this commit apart from the two added lines, the new test and the new TestFormsHTML/per-request/list-search-three-siblings case, none failing. One break (the sorted keys walked backward) is caught by the new test. The demo-state walkthroughs give 16 pass and 6 skip at the parent and at this commit. Not probed: that a browser submits the inputs in document order. The HTML specification says it does, and no test here drives a browser's form submission.
41 lines
1.2 KiB
Go
41 lines
1.2 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// An embedded list's search form re-submits its sibling lists' state as
|
|
// hidden inputs. A GET form submits its inputs in document order, so the
|
|
// order of those inputs is the order of the parameters in the URL the
|
|
// search pushes; it is the keys' sorted order on every render.
|
|
func TestListSearchFormCarriesSiblingInputsInSortedOrder(t *testing.T) {
|
|
n := ListNav{BasePath: "/operator/orgs/x", Target: "#tc", ParamPrefix: "tc_", Q: "abc",
|
|
Extra: url.Values{"tab": {"grants"}, "ec_q": {"one"}, "ec_page": {"2"}}}
|
|
set := MemberSet(t)
|
|
want := []string{"ec_page", "ec_q", "tab"}
|
|
for i := 0; i < 20; i++ {
|
|
var buf bytes.Buffer
|
|
if err := set.ExecuteTemplate(&buf, "form", n.Form()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
html := buf.String()
|
|
last := -1
|
|
for _, k := range want {
|
|
at := strings.Index(html, `name="`+k+`"`)
|
|
if at < 0 {
|
|
t.Fatalf("render %d has no hidden input %q", i, k)
|
|
}
|
|
if at < last {
|
|
t.Fatalf("render %d: hidden input %q comes before an earlier key; want the order %v", i, k, want)
|
|
}
|
|
last = at
|
|
}
|
|
}
|
|
}
|