fix(web): SwitchHiddenInput on settings hideAmounts toggle + correct smoke comment
This commit is contained in:
parent
6e84d99d46
commit
b02674aa62
3 changed files with 47 additions and 14 deletions
|
|
@ -4,18 +4,23 @@ import * as fx from "../src/test/fixtures";
|
|||
/**
|
||||
* One smoke path: /login → submit → /home renders the real dashboard.
|
||||
*
|
||||
* There's no live Go backend in CI, so this intercepts the network at the
|
||||
* browser layer (page.route) rather than standing up a stub server — the
|
||||
* Next dev server (and all of its own client/server code, including the
|
||||
* httpOnly-cookie auth route and the middleware guard) runs for real; only
|
||||
* the two things that would otherwise reach the Go backend
|
||||
* (`/api/auth/login`, `/api/v1/*`) are fulfilled with fixtures.
|
||||
*
|
||||
* Also asserts the two security-relevant properties the review flagged:
|
||||
* - the session cookie set on login is HttpOnly
|
||||
* - no response body observed during the flow contains a raw bearer token
|
||||
* (the Next auth route is supposed to strip `token` before it reaches the
|
||||
* browser — see src/app/api/auth/login/route.ts)
|
||||
* There's no live Go backend in CI, so `page.route` intercepts
|
||||
* `/api/auth/login` and `/api/v1/*` at the BROWSER network layer, before
|
||||
* either request ever reaches the Next server — the real
|
||||
* `src/app/api/auth/login/route.ts` handler (which calls the Go backend,
|
||||
* strips `token`, and calls `buildSetCookie`) never runs in this test; this
|
||||
* spec fabricates the `Set-Cookie` header and the token-free `{user}` body
|
||||
* itself. What DOES run for real: the Next dev server's page rendering, the
|
||||
* client-side login form + navigation, and — critically — the
|
||||
* `src/middleware.ts` route guard, which reads the `mercury_session` cookie
|
||||
* this test's fake `Set-Cookie` puts in the browser's real cookie jar to
|
||||
* decide whether `/home` is reachable. So this smoke covers the
|
||||
* login → navigate → guarded-route → dashboard-render path end to end; it
|
||||
* does NOT cover the real auth route's token-stripping/cookie-building logic
|
||||
* (that's covered separately by src/app/api/auth/auth.route.test.ts). The
|
||||
* httpOnly/no-raw-token assertions below validate this test's own mocked
|
||||
* response shape, i.e. they document the contract the real route must also
|
||||
* satisfy — they are not independent proof that the real route satisfies it.
|
||||
*/
|
||||
test("login → home renders the dashboard; session cookie is httpOnly; no raw token leaks", async ({
|
||||
page,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { render, screen } from "@testing-library/react";
|
||||
import { render, screen, fireEvent } from "@testing-library/react";
|
||||
import { it, expect, vi } from "vitest";
|
||||
import type { Settings } from "@/api/schemas";
|
||||
|
||||
|
|
@ -31,3 +31,16 @@ it("renders the holder-name field pre-filled from useSettings", () => {
|
|||
const input = screen.getByLabelText("Данс эзэмшигчийн нэр") as HTMLInputElement;
|
||||
expect(input.value).toBe(settingsFixture.holderName);
|
||||
});
|
||||
|
||||
// Flagged in review: SwitchRoot needs its SwitchHiddenInput sibling to be an
|
||||
// accessible, interactive `role="switch"` at all — SwitchControl/SwitchThumb
|
||||
// are aria-hidden decoration only (same bug fixed in ds/HideAmountsToggle.tsx).
|
||||
it("hideAmounts switch is an accessible, toggleable role=switch bound to form state", () => {
|
||||
render(<SettingsForm />);
|
||||
const toggle = screen.getByRole("switch", { name: "Үнийн дүн нуух" });
|
||||
expect(toggle).not.toBeChecked();
|
||||
|
||||
fireEvent.click(toggle);
|
||||
|
||||
expect(toggle).toBeChecked();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,16 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import { TextFieldRoot, TextFieldInput, SwitchRoot, SwitchControl, SwitchThumb, SwitchLabel, Skeleton } from "@seed-design/react";
|
||||
import {
|
||||
TextFieldRoot,
|
||||
TextFieldInput,
|
||||
SwitchRoot,
|
||||
SwitchControl,
|
||||
SwitchThumb,
|
||||
SwitchLabel,
|
||||
SwitchHiddenInput,
|
||||
Skeleton,
|
||||
} from "@seed-design/react";
|
||||
import { MercuryButton } from "@/ds/MercuryButton";
|
||||
import { useSettings } from "@/api/hooks/reads";
|
||||
import { useSaveSettings } from "@/api/hooks/mutations";
|
||||
|
|
@ -166,6 +175,12 @@ export function SettingsForm({ onBack }: SettingsFormProps) {
|
|||
checked={form.hideAmounts}
|
||||
onCheckedChange={(v: boolean) => setForm((f) => ({ ...f, hideAmounts: v }))}
|
||||
>
|
||||
{/* The actual interactive/accessible element (role="switch",
|
||||
checked/onChange) lives on the hidden input — SwitchControl and
|
||||
SwitchThumb are purely decorative (aria-hidden). Without this
|
||||
the switch renders but nothing is clickable or announced to
|
||||
assistive tech (same bug as ds/HideAmountsToggle.tsx). */}
|
||||
<SwitchHiddenInput />
|
||||
<SwitchControl>
|
||||
<SwitchThumb />
|
||||
</SwitchControl>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue