admin: enable toggles become rac switches
the upstream, blocklist source, and safe search enable controls mutate the row the moment they move, so they now carry the switch role via a shared drawn rac switch with a 44px hit area, a focus-visible ring, and naming modes made exclusive by a discriminated union. safe search supersedes its one-commit-old checkbox form, and the file-authority guard now names the switch role instead of relying on the bare input selector.
This commit is contained in:
@@ -46,7 +46,7 @@ test("another group can be renamed and deleted, and carries its safe-search stat
|
||||
await screen.findByRole("heading", { name: "kids", level: 2 });
|
||||
|
||||
expect((screen.getByRole("button", { name: "Rename group" }) as HTMLButtonElement).disabled).toBe(false);
|
||||
expect((screen.getByRole("checkbox", { name: "Safe search" }) as HTMLInputElement).checked).toBe(true);
|
||||
expect((screen.getByRole("switch", { name: "Safe search" }) as HTMLInputElement).checked).toBe(true);
|
||||
|
||||
fireEvent.click(screen.getByRole("button", { name: "Delete group" }));
|
||||
const dialog = await screen.findByRole("alertdialog");
|
||||
@@ -60,7 +60,7 @@ test("toggling safe search resends the whole group row", async () => {
|
||||
await openProtection(2);
|
||||
await screen.findByRole("heading", { name: "kids", level: 2 });
|
||||
|
||||
fireEvent.click(screen.getByRole("checkbox", { name: "Safe search" }));
|
||||
fireEvent.click(screen.getByRole("switch", { name: "Safe search" }));
|
||||
|
||||
await waitFor(() => expect(writes("PUT")).toHaveLength(1));
|
||||
expect(writes("PUT")[0]).toMatchObject({
|
||||
@@ -98,8 +98,10 @@ test("the source checkboxes form one named group, and each carries its own state
|
||||
const group = await screen.findByRole("group", { name: "Assigned sources" });
|
||||
const ads = within(group).getByRole("checkbox", { name: "Ads" }) as HTMLInputElement;
|
||||
expect(ads.checked).toBe(false);
|
||||
// Safe search is the group's own field, not one of its sources.
|
||||
expect(within(group).queryByRole("checkbox", { name: "Safe search" })).toBeNull();
|
||||
// Safe search is the group's own field, not one of its sources, and it is a
|
||||
// switch rather than a checkbox because it applies the moment it moves.
|
||||
expect(within(group).queryByRole("switch")).toBeNull();
|
||||
expect(screen.getByRole("switch", { name: "Safe search" })).toBeTruthy();
|
||||
|
||||
fireEvent.click(ads);
|
||||
await waitFor(() => expect(ads.checked).toBe(true));
|
||||
@@ -235,11 +237,33 @@ test("the Sources tab lists the catalogue with both skipped columns and their no
|
||||
expect(
|
||||
screen.getByText(/Skipped unsupported lines are syntax nxdns cannot translate into a DNS decision/),
|
||||
).toBeTruthy();
|
||||
expect((screen.getByLabelText("Ads enabled") as HTMLInputElement).checked).toBe(true);
|
||||
expect((screen.getByLabelText("Trackers enabled") as HTMLInputElement).checked).toBe(false);
|
||||
// Switches, not checkboxes: the row applies the moment it moves, and the role
|
||||
// is what tells a screen reader so.
|
||||
expect((screen.getByRole("switch", { name: "Ads enabled" }) as HTMLInputElement).checked).toBe(true);
|
||||
expect((screen.getByRole("switch", { name: "Trackers enabled" }) as HTMLInputElement).checked).toBe(false);
|
||||
expect(screen.getByRole("heading", { name: "Add source" })).toBeTruthy();
|
||||
});
|
||||
|
||||
test("a source switch resends the whole row immediately, with no Save step", async () => {
|
||||
calls = stubApi(DATABASE);
|
||||
await renderPage("/configuration/protection?tab=sources", "Protection");
|
||||
|
||||
fireEvent.click(await screen.findByRole("switch", { name: "Trackers enabled" }));
|
||||
|
||||
// No Save button stands between the switch and the write: one click, one PUT.
|
||||
await waitFor(() => expect(writes("PUT")).toHaveLength(1));
|
||||
expect(writes("PUT")[0]).toMatchObject({
|
||||
url: "/api/blocklists/2",
|
||||
// The whole row goes back, not a patch of the one field that moved.
|
||||
body: {
|
||||
url: "https://example.com/trackers.txt",
|
||||
name: "Trackers",
|
||||
enabled: true,
|
||||
is_suggested: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("Update now says it started, and says nothing once it succeeds", async () => {
|
||||
let release: ((response: Response) => void) | null = null;
|
||||
calls = stubApi(DATABASE, {
|
||||
|
||||
Reference in New Issue
Block a user