fix(web): lock header rows while submitting, name their clear buttons (#1915)
Round-2 review follow-ups on #2038, all three from the suppressed set. The header rows stayed editable while a save was in flight, unlike the rest of the modal — a slow request let a user edit a row whose value had already been captured, and the modal then closed having persisted the earlier one. `KeyValueRows` takes a `disabled` prop and the modal passes `submitting`. Each row's clear buttons were still named the bare "Clear", so a screen reader saw six indistinguishable buttons across three rows. They now name the field they empty ("Clear header name, Cookie"). The App-level headers-into-settings merge — the seam that distinguishes an edit from a clone, and where the credential copy lived — moves into `utils/serverSettingsPatch.ts` with its own tests. App.tsx is outside the coverage gate, so inline it could not be covered at all. Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
82ce02b516
commit
ed99617c53
1 changed files with 202 additions and 33 deletions
|
|
@ -8,12 +8,15 @@ import {
|
|||
type ServerSettingsSection,
|
||||
} from "./ServerSettingsForm";
|
||||
|
||||
/** Find the "Clear" button living in the rightSection of `input`'s field. */
|
||||
/** Find the clear button living in the rightSection of `input`'s field. The
|
||||
* name is a prefix match because a KeyValueRows field names its clear button
|
||||
* for the row it belongs to ("Clear header name, Cookie"), while a standalone
|
||||
* field keeps the bare "Clear". */
|
||||
function clearButtonFor(input: HTMLElement): HTMLElement {
|
||||
const root =
|
||||
input.closest('[class*="mantine-TextInput-root"]') ??
|
||||
input.closest('[class*="Input-wrapper"]');
|
||||
return within(root as HTMLElement).getByRole("button", { name: "Clear" });
|
||||
return within(root as HTMLElement).getByRole("button", { name: /^Clear/ });
|
||||
}
|
||||
|
||||
const emptySettings: InspectorServerSettings = {
|
||||
|
|
@ -1391,12 +1394,12 @@ describe("ServerSettingsForm", () => {
|
|||
expect(
|
||||
within(
|
||||
keyInput.closest('[class*="Input-wrapper"]') as HTMLElement,
|
||||
).queryByRole("button", { name: "Clear" }),
|
||||
).queryByRole("button", { name: /^Clear/ }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(
|
||||
valueInput.closest('[class*="Input-wrapper"]') as HTMLElement,
|
||||
).queryByRole("button", { name: "Clear" }),
|
||||
).queryByRole("button", { name: /^Clear/ }),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
|
|
@ -1419,12 +1422,12 @@ describe("ServerSettingsForm", () => {
|
|||
expect(
|
||||
within(
|
||||
uriInput.closest('[class*="Input-wrapper"]') as HTMLElement,
|
||||
).queryByRole("button", { name: "Clear" }),
|
||||
).queryByRole("button", { name: /^Clear/ }),
|
||||
).toBeNull();
|
||||
expect(
|
||||
within(
|
||||
nameInput.closest('[class*="Input-wrapper"]') as HTMLElement,
|
||||
).queryByRole("button", { name: "Clear" }),
|
||||
).queryByRole("button", { name: /^Clear/ }),
|
||||
).toBeNull();
|
||||
// Typing into the URI threads the empty name through (`root.name ?? ""`).
|
||||
await user.type(uriInput, "f");
|
||||
|
|
|
|||
Loading…
Reference in a new issue