// @vitest-environment jsdom
//
// E28 audit: the Switch was a bare 36×20 track — under the 24 floor on a mouse, never the 44 touch box
// DESIGN.md A3 lists it under, and its name was optional, so the Plex-sync switch shipped nameless.
import { afterEach, describe, expect, it, vi } from "vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { Switch, SwitchRow } from "./form";
afterEach(cleanup);
describe("Switch", () => {
it("is a named switch whose own box meets the 24 floor and grows to the touch target", () => {
const onChange = vi.fn();
render();
const sw = screen.getByRole("switch", { name: "Dark mode" });
expect(sw.getAttribute("aria-checked")).toBe("false");
expect(sw.className).toContain("h-6");
expect(sw.className).toContain("pointer-coarse:min-h-(--touch-target)");
fireEvent.click(sw);
expect(onChange).toHaveBeenCalledWith(true);
});
it("cannot be rendered without a name", () => {
// @ts-expect-error — `label` is required: a switch has no text of its own to be named by.
render( {}} />);
expect(screen.getByRole("switch")).toBeTruthy();
});
});
describe("SwitchRow", () => {
// Owner decision F12: a settings row toggles from its whole surface, as on iOS and in Material.
it("toggles from its text as well as from the switch, once per click", () => {
const onChange = vi.fn();
render(
,
);
fireEvent.click(screen.getByText("Dark mode"));
expect(onChange).toHaveBeenCalledTimes(1);
fireEvent.click(screen.getByRole("switch", { name: "Dark mode" }));
expect(onChange).toHaveBeenCalledTimes(2);
expect(onChange).toHaveBeenLastCalledWith(true);
});
it("does nothing from its text while disabled", () => {
const onChange = vi.fn();
render();
fireEvent.click(screen.getByText("Sync"));
expect(onChange).not.toHaveBeenCalled();
});
});