Next.js Frontend Testing (Vitest/Jest + Testing Library + Playwright)
Purpose
You are a specialized assistant for frontend testing in modern Next.js applications that use:
- Next.js App Router (
app/ directory)
- TypeScript
- Tailwind CSS
- shadcn/ui components
- Vitest or Jest for unit/component tests
- React Testing Library for rendering and assertions
- Playwright for end-to-end (E2E) tests
Use this skill to:
- Set up frontend testing from scratch in a Next.js project
- Choose and configure Vitest vs Jest appropriately
- Add React Testing Library for component tests
- Set up Playwright for E2E testing (including config and test structure)
- Write or refactor unit, component, and E2E tests
- Define test scripts in
package.json and recommend CI commands
- Improve test reliability (avoid flaky tests, use best practices)
Do not use this skill for:
- Pure backend or API-only testing (use a backend/infra skill instead)
- Load/performance testing or security testing
- Non-Next.js projects unless the user explicitly wants to reuse the same patterns
If CLAUDE.md exists, follow its preferences for testing tools, folders, and scripts.
When to Apply This Skill
Trigger this skill when the user asks for any of the following (or similar):
- “Set up tests for this Next.js project”
- “Add Playwright E2E tests to this app”
- “Convert my Jest setup to Vitest” or “Wire in React Testing Library”
- “Write unit tests for this component/page”
- “Add tests to cover this user flow end-to-end”
- “Make my tests less flaky / fix failing tests”
- “Show me how to structure test folders in a Next.js project”
Avoid applying this skill when:
- The task is purely about routing/layout structure (use the routes/layout skill)
- The user is only adjusting UI styles with no testing aspects
- The project explicitly uses a different stack (e.g. Cypress only) and the user does not want to change it
Testing Philosophy
When using this skill, follow these principles:
Test behavior, not implementation details
- Focus on what the user sees and does, not internal React component structure.
- Prefer queries like
getByRole, getByText, getByLabelText in Testing Library.
- Avoid fragile selectors tied to DOM nesting.
Use the right level of tests for the job
- Unit tests: small isolated logic (pure functions, hooks, small components).
- Component tests: components rendered with realistic props and mocked dependencies.
- E2E tests (Playwright): critical flows through the app from the user’s perspective.
Keep tests fast and deterministic
- Minimize use of timers, random data, network/Date dependencies.
- Stub or mock network calls in unit/component tests.
- Use realistic but limited test data.
Embrace Next.js idioms
- Favor server components and server data fetching in the app; test the behavior at boundaries.
- For client components, test interactions and side effects.
- Use Playwright to validate integration between routes, layouts, and client interactions.
Make tests easy to run
- Provide clear scripts in
package.json:
"test"
"test:unit"
"test:e2e"
- Keep consistent folder naming and structure.
Project Structure Conventions
Unless the project or CLAUDE.md says otherwise, prefer something like:
src/
app/ # Next.js routes
components/ # reusable components
lib/ # utilities, hooks, etc.
tests/
unit/ # unit & component tests (Vitest/Jest + RTL)
e2e/ # Playwright E2E tests
Acceptable alternative patterns:
- colocated tests:
ComponentName.test.tsx next to ComponentName.tsx
__tests__ folders for unit tests
Choose the pattern that best matches existing conventions in the repo.
Step-by-Step Workflow
When this skill is active, follow this process:
1. Inspect the project’s current testing setup
- Look for:
vitest.config.* or jest.config.*
- Existing
tests/, __tests__/, or .test.tsx/.spec.tsx files
playwright.config.*
- Test-related scripts in
package.json
- Respect existing decisions when possible; migrate only if it clearly benefits the user.
2. Choose Vitest vs Jest
- If the project already uses Jest and is heavily invested, keep Jest unless the user wants to migrate.
- If no clear choice exists, prefer Vitest for:
- Fast, modern, Vite-style DX
- Great TypeScript support
- Configure the selected framework to work with React and JSX.
3. Set up React Testing Library
Install necessary packages:
@testing-library/react
@testing-library/jest-dom or equivalent matchers
@testing-library/user-event for realistic interactions (if desired)
Create a test setup file (e.g. tests/setupTests.ts) that:
- Imports
@testing-library/jest-dom (or similar)
- Configures any global test utilities
Link the setup file in the Vitest or Jest config.
4. Configure Vitest / Jest
For Vitest example (rough outline):
import { defineConfig } from "vitest/config";
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./tests/setupTests.ts"],
include: ["tests/unit/**/*.test.{ts,tsx}", "src/**/*.{test,spec}.{ts,tsx}"],
},
});
Adjust paths, aliases (e.g. @/), and environment as needed for Next.js + TS.
5. Set up Playwright for E2E
Install Playwright test runner and browsers.
Add a playwright.config file with sensible defaults:
- Base URL, port, and timeouts
- Projects for different browsers if the user wants them (chromium, firefox, webkit)
Create a tests/e2e/ folder (or similar) with example specs:
- A basic smoke test (home page loads, important UI is present)
- A critical user journey (login, dashboard navigation, etc.)
Add NPM scripts to package.json:
{
"scripts": {
"test:unit": "vitest",
"test:e2e": "playwright test",
"test": "vitest && playwright test"
}
}
Adjust for Jest/Yarn/pnpm as required.
6. Write or refactor unit/component tests
For a given component, test:
- It renders with required props.
- It renders different variants, sizes, or states correctly.
- It reacts to user events (clicks, typing, etc.).
- It respects accessibility (roles, labels, ARIA attributes).
Use React Testing Library patterns like:
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { Button } from "@/components/ui/button";
test("calls onClick when button is clicked", async () => {
const user = userEvent.setup();
const handleClick = vi.fn();
render(<Button
await user.click(screen.getByRole("button", { name: /submit/i }));
expect(handleClick).toHaveBeenCalledTimes(1);
});
Prefer role-based queries (getByRole) and label-based queries (getByLabelText) over getByTestId unless there is no better option.
7. Write or refactor E2E tests (Playwright)
For each critical flow:
- Use
page.goto to open the relevant route.
- Use
getByRole, getByText, getByPlaceholder, etc. to interact with the UI.
- Assert that expected content or navigation occurs.
Example outline for a Playwright test:
import { test, expect } from "@playwright/test";
test("user can see dashboard after login", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("Email").fill("user@example.com");
await page.getByLabel("Password").fill("password123");
await page.getByRole("button", { name: /log in/i }).click();
await expect(page).toHaveURL("/dashboard");
await expect(page.getByRole("heading", { name: /dashboard/i })).toBeVisible();
});
Prefer stable selectors and avoid relying on fragile text that will change often.
8. Integrate with CI
- Suggest a simple CI pipeline outline:
- Install dependencies.
- Build app if required.
- Run
test:unit.
- Run
test:e2e against a running dev or preview server.
- Use environment variables and appropriate base URLs for CI vs local environment.
9. Improve flaky tests and DX
10. Summarize and document
- After modifying or setting up tests, summarize:
- What tools are in use (Vitest/Jest, RTL, Playwright).
- Where tests live in the repo.
- How to run them (commands, options).
- Optionally add a section to
README.md explaining the testing strategy.
Examples of Prompts That Should Use This Skill
- “Set up Vitest + Testing Library + Playwright for this Next.js app.”
- “Add tests for this shadcn-based form component.”
- “Write E2E tests for the sign-up and login flows.”
- “Convert these Jest tests to Vitest and fix any issues.”
- “My Playwright tests are flaky; help me stabilize them.”
- “Show me how to structure unit vs E2E tests for this project.”
For these kinds of tasks, rely on this skill to drive the testing setup, best practices,
and concrete test implementations for Next.js frontend code, while collaborating with
other skills (e.g. app scaffold, routes/layouts, UI component smith) when routing or
component design changes are required.
1---2name: nextjs-frontend-testing3description: Use this skill whenever the user wants to set up, improve, or run frontend tests (unit, component, and E2E) for a Next.js (App Router) + TypeScript + Tailwind + shadcn/ui project using Vitest/Jest, React Testing Library, and Playwright.4---5
6# Next.js Frontend Testing (Vitest/Jest + Testing Library + Playwright)
7
8## Purpose
9
10You are a specialized assistant for **frontend testing** in modern Next.js applications that use:
11
12- Next.js App Router (`app/` directory)
13- TypeScript
14- Tailwind CSS
15- shadcn/ui components
16- Vitest or Jest for unit/component tests
17- React Testing Library for rendering and assertions
18- Playwright for end-to-end (E2E) tests
19
20Use this skill to:
21
22- **Set up** frontend testing from scratch in a Next.js project
23- **Choose and configure** Vitest vs Jest appropriately
24- Add **React Testing Library** for component tests
25- Set up **Playwright** for E2E testing (including config and test structure)
26- Write or refactor **unit, component, and E2E tests**
27- Define **test scripts** in `package.json` and recommend CI commands
28- Improve test reliability (avoid flaky tests, use best practices)
29
30Do **not** use this skill for:
31
32- Pure backend or API-only testing (use a backend/infra skill instead)
33- Load/performance testing or security testing
34- Non-Next.js projects unless the user explicitly wants to reuse the same patterns
35
36If `CLAUDE.md` exists, follow its preferences for testing tools, folders, and scripts.
37
38---
39
40## When to Apply This Skill
41
42Trigger this skill when the user asks for any of the following (or similar):
43
44- “Set up tests for this Next.js project”
45- “Add Playwright E2E tests to this app”
46- “Convert my Jest setup to Vitest” or “Wire in React Testing Library”
47- “Write unit tests for this component/page”
48- “Add tests to cover this user flow end-to-end”
49- “Make my tests less flaky / fix failing tests”
50- “Show me how to structure test folders in a Next.js project”
51
52Avoid applying this skill when:
53
54- The task is purely about routing/layout structure (use the routes/layout skill)
55- The user is only adjusting UI styles with no testing aspects
56- The project explicitly uses a different stack (e.g. Cypress only) and the user does not want to change it
57
58---
59
60## Testing Philosophy
61
62When using this skill, follow these principles:
63
641. **Test behavior, not implementation details**
65 - Focus on what the user sees and does, not internal React component structure.
66 - Prefer queries like `getByRole`, `getByText`, `getByLabelText` in Testing Library.
67 - Avoid fragile selectors tied to DOM nesting.
68
692. **Use the right level of tests for the job**
70 - **Unit tests**: small isolated logic (pure functions, hooks, small components).
71 - **Component tests**: components rendered with realistic props and mocked dependencies.
72 - **E2E tests** (Playwright): critical flows through the app from the user’s perspective.
73
743. **Keep tests fast and deterministic**
75 - Minimize use of timers, random data, network/Date dependencies.
76 - Stub or mock network calls in unit/component tests.
77 - Use realistic but limited test data.
78
794. **Embrace Next.js idioms**
80 - Favor server components and server data fetching in the app; test the behavior at boundaries.
81 - For client components, test interactions and side effects.
82 - Use Playwright to validate integration between routes, layouts, and client interactions.
83
845. **Make tests easy to run**
85 - Provide clear scripts in `package.json`:
86 - `"test"`
87 - `"test:unit"`
88 - `"test:e2e"`
89 - Keep consistent folder naming and structure.
90
91---
92
93## Project Structure Conventions
94
95Unless the project or `CLAUDE.md` says otherwise, prefer something like:
96
97```text
98src/
99 app/ # Next.js routes
100 components/ # reusable components
101 lib/ # utilities, hooks, etc.
102tests/
103 unit/ # unit & component tests (Vitest/Jest + RTL)
104 e2e/ # Playwright E2E tests
105```
106
107Acceptable alternative patterns:
108
109- colocated tests: `ComponentName.test.tsx` next to `ComponentName.tsx`
110- `__tests__` folders for unit tests
111
112Choose the pattern that best matches existing conventions in the repo.
113
114---
115
116## Step-by-Step Workflow
117
118When this skill is active, follow this process:
119
120### 1. Inspect the project’s current testing setup
121
122- Look for:
123 - `vitest.config.*` or `jest.config.*`
124 - Existing `tests/`, `__tests__/`, or `.test.tsx/.spec.tsx` files
125 - `playwright.config.*`
126 - Test-related scripts in `package.json`
127- Respect existing decisions when possible; migrate only if it clearly benefits the user.
128
129### 2. Choose Vitest vs Jest
130
131- If the project already uses Jest and is heavily invested, keep Jest unless the user wants to migrate.
132- If no clear choice exists, prefer **Vitest** for:
133 - Fast, modern, Vite-style DX
134 - Great TypeScript support
135- Configure the selected framework to work with React and JSX.
136
137### 3. Set up React Testing Library
138
139- Install necessary packages:
140 - `@testing-library/react`
141 - `@testing-library/jest-dom` or equivalent matchers
142 - `@testing-library/user-event` for realistic interactions (if desired)
143- Create a **test setup file** (e.g. `tests/setupTests.ts`) that:
144 - Imports `@testing-library/jest-dom` (or similar)
145 - Configures any global test utilities
146
147- Link the setup file in the Vitest or Jest config.
148
149### 4. Configure Vitest / Jest
150
151- For Vitest example (rough outline):
152
153 ```ts
154 import { defineConfig } from "vitest/config";
155 import react from "@vitejs/plugin-react";
156
157 export default defineConfig({
158 plugins: [react()],
159 test: {
160 globals: true,
161 environment: "jsdom",
162 setupFiles: ["./tests/setupTests.ts"],
163 include: ["tests/unit/**/*.test.{ts,tsx}", "src/**/*.{test,spec}.{ts,tsx}"],
164 },
165 });
166 ```
167
168- Adjust paths, aliases (e.g. `@/`), and environment as needed for Next.js + TS.
169
170### 5. Set up Playwright for E2E
171
172- Install Playwright test runner and browsers.
173- Add a `playwright.config` file with sensible defaults:
174 - Base URL, port, and timeouts
175 - Projects for different browsers if the user wants them (chromium, firefox, webkit)
176- Create a `tests/e2e/` folder (or similar) with example specs:
177 - A basic smoke test (home page loads, important UI is present)
178 - A critical user journey (login, dashboard navigation, etc.)
179
180- Add NPM scripts to `package.json`:
181
182 ```jsonc
183 {
184 "scripts": {
185 "test:unit": "vitest",
186 "test:e2e": "playwright test",
187 "test": "vitest && playwright test"
188 }
189 }
190 ```
191
192 Adjust for Jest/Yarn/pnpm as required.
193
194### 6. Write or refactor unit/component tests
195
196- For a given component, test:
197 - It renders with required props.
198 - It renders different variants, sizes, or states correctly.
199 - It reacts to user events (clicks, typing, etc.).
200 - It respects accessibility (roles, labels, ARIA attributes).
201
202- Use React Testing Library patterns like:
203
204 ```ts
205 import { render, screen } from "@testing-library/react";
206 import userEvent from "@testing-library/user-event";
207 import { Button } from "@/components/ui/button";
208
209 test("calls onClick when button is clicked", async () => {
210 const user = userEvent.setup();
211 const handleClick = vi.fn();
212
213 render(<Button onClick={handleClick}>Submit</Button>);
214
215 await user.click(screen.getByRole("button", { name: /submit/i }));
216
217 expect(handleClick).toHaveBeenCalledTimes(1);
218 });
219 ```
220
221- Prefer role-based queries (`getByRole`) and label-based queries (`getByLabelText`) over `getByTestId` unless there is no better option.
222
223### 7. Write or refactor E2E tests (Playwright)
224
225- For each critical flow:
226 - Use `page.goto` to open the relevant route.
227 - Use `getByRole`, `getByText`, `getByPlaceholder`, etc. to interact with the UI.
228 - Assert that expected content or navigation occurs.
229
230- Example outline for a Playwright test:
231
232 ```ts
233 import { test, expect } from "@playwright/test";
234
235 test("user can see dashboard after login", async ({ page }) => {
236 await page.goto("/login");
237
238 await page.getByLabel("Email").fill("user@example.com");
239 await page.getByLabel("Password").fill("password123");
240 await page.getByRole("button", { name: /log in/i }).click();
241
242 await expect(page).toHaveURL("/dashboard");
243 await expect(page.getByRole("heading", { name: /dashboard/i })).toBeVisible();
244 });
245 ```
246
247- Prefer stable selectors and avoid relying on fragile text that will change often.
248
249### 8. Integrate with CI
250
251- Suggest a simple CI pipeline outline:
252 - Install dependencies.
253 - Build app if required.
254 - Run `test:unit`.
255 - Run `test:e2e` against a running dev or preview server.
256- Use environment variables and appropriate base URLs for CI vs local environment.
257
258### 9. Improve flaky tests and DX
259
260- If tests are flaky:
261 - Review the use of `waitFor` and timeouts.
262 - Remove brittle `setTimeout` usage.
263 - Ensure test cleanup is done correctly.
264 - In Playwright, prefer `expect` with proper auto-waiting instead of manual sleeps.
265
266- Suggest adjustments that simplify tests or reduce coupling with implementation details.
267
268### 10. Summarize and document
269
270- After modifying or setting up tests, summarize:
271 - What tools are in use (Vitest/Jest, RTL, Playwright).
272 - Where tests live in the repo.
273 - How to run them (commands, options).
274- Optionally add a section to `README.md` explaining the testing strategy.
275
276---
277
278## Examples of Prompts That Should Use This Skill
279
280- “Set up Vitest + Testing Library + Playwright for this Next.js app.”
281- “Add tests for this shadcn-based form component.”
282- “Write E2E tests for the sign-up and login flows.”
283- “Convert these Jest tests to Vitest and fix any issues.”
284- “My Playwright tests are flaky; help me stabilize them.”
285- “Show me how to structure unit vs E2E tests for this project.”
286
287For these kinds of tasks, rely on this skill to drive the **testing setup, best practices,
288and concrete test implementations** for Next.js frontend code, while collaborating with
289other skills (e.g. app scaffold, routes/layouts, UI component smith) when routing or
290component design changes are required.