test(web): add shell and navigation coverage
This commit is contained in:
parent
4da56d489d
commit
98144ab4ff
@ -58,7 +58,7 @@ Stack: Next.js 16 + React 19 + TypeScript
|
||||
- [ ] Performance pass
|
||||
- [ ] Accessibility pass
|
||||
- [ ] Token validation pass
|
||||
- [ ] Production build passes
|
||||
- [x] Production build passes
|
||||
- [ ] UX polish pass
|
||||
|
||||
# High-Collision Areas
|
||||
@ -108,6 +108,13 @@ Stack: Next.js 16 + React 19 + TypeScript
|
||||
- stronger focus-visible treatment for interactive controls
|
||||
- clearer active-nav semantics via `aria-current`
|
||||
- keyboard/accessibility guidance surfaced in navigation/settings
|
||||
- Added the first web UI test harness and coverage for:
|
||||
- shared `AppShell` skip-link/main landmark behavior
|
||||
- shared `Sidebar` primary-nav and active-page semantics
|
||||
- Verified `web/` with:
|
||||
- `npm test`
|
||||
- `npm run typecheck`
|
||||
- `npm run build`
|
||||
|
||||
# Open Questions
|
||||
|
||||
@ -139,8 +146,6 @@ Stack: Next.js 16 + React 19 + TypeScript
|
||||
- Extraction-backed task review flows
|
||||
- Backend-backed agent activity timeline, approval queue, proposal diff review, and audit filtering
|
||||
- Remaining dense/accessibility polish and performance hardening
|
||||
- Remaining verification:
|
||||
- run `npm test`
|
||||
|
||||
# Done When
|
||||
|
||||
|
||||
23
web/src/components/AppShell.test.tsx
Normal file
23
web/src/components/AppShell.test.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { AppShell } from "./AppShell";
|
||||
|
||||
vi.mock("@/components/Sidebar", () => ({
|
||||
Sidebar: () => <div data-testid="sidebar">Sidebar</div>,
|
||||
}));
|
||||
|
||||
describe("AppShell", () => {
|
||||
it("renders skip link, page title, actions, and main content landmark", () => {
|
||||
render(
|
||||
<AppShell title="Search" description="Find notes" actions={<button type="button">Run</button>}>
|
||||
<section>Results</section>
|
||||
</AppShell>
|
||||
);
|
||||
|
||||
expect(screen.getByRole("link", { name: "Skip to main content" })).toHaveAttribute("href", "#main-content");
|
||||
expect(screen.getByRole("heading", { level: 1, name: "Search" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("button", { name: "Run" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("main")).toHaveAttribute("id", "main-content");
|
||||
expect(screen.getByText("Results")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
30
web/src/components/Sidebar.test.tsx
Normal file
30
web/src/components/Sidebar.test.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
const usePathnameMock = vi.fn();
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
usePathname: () => usePathnameMock(),
|
||||
}));
|
||||
|
||||
vi.mock("next/link", () => ({
|
||||
default: ({ href, children, ...props }: React.ComponentProps<"a"> & { href: string }) => (
|
||||
<a href={href} {...props}>
|
||||
{children}
|
||||
</a>
|
||||
),
|
||||
}));
|
||||
|
||||
describe("Sidebar", () => {
|
||||
it("marks the active navigation item and exposes primary navigation landmarks", () => {
|
||||
usePathnameMock.mockReturnValue("/search");
|
||||
|
||||
render(<Sidebar />);
|
||||
|
||||
expect(screen.getByLabelText("Primary")).toBeInTheDocument();
|
||||
expect(screen.getByRole("navigation", { name: "Primary navigation" })).toBeInTheDocument();
|
||||
expect(screen.getByRole("link", { name: "Search" })).toHaveAttribute("aria-current", "page");
|
||||
expect(screen.getByText("Keyboard flow")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
1
web/src/test/setupTests.ts
Normal file
1
web/src/test/setupTests.ts
Normal file
@ -0,0 +1 @@
|
||||
import "@testing-library/jest-dom/vitest";
|
||||
15
web/vitest.config.ts
Normal file
15
web/vitest.config.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import path from "node:path";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
environment: "jsdom",
|
||||
setupFiles: ["./src/test/setupTests.ts"],
|
||||
globals: true,
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user