Zum Inhalt springen

testing-web

Type Skill
Plugin awl-testing · v0.0.27
Invoke /awl-testing:testing-web
Tools Read, Write, Edit, Bash, Glob, Grep
Source plugins/awl-testing/skills/testing-web/SKILL.md

Writes and debugs JavaScript/TypeScript tests using Jest, Vitest, Testing Library, and Playwright. Use when “write jest tests”, “vitest test”, “react testing library”, “playwright test”, “test typescript”, “test javascript”, “component test”, “e2e test web”, “mock api”, “test react component”, “test vue component”, “test node.js”, “fix jest test”, “debug vitest”, “accessibility test”, “a11y”, “axe”, “sveltekit e2e”.

Trigger phrases: write jest tests · vitest test · react testing library · playwright test · test typescript · test javascript · component test · e2e test web · mock api · test react component · test vue component · test node.js · fix jest test · debug vitest · accessibility test · a11y · axe · sveltekit e2e

describe('UserService', () => {
it('should return user when ID exists', async () => {
// Arrange
const mockUser = { id: 1, name: 'Alice' };
vi.spyOn(api, 'fetchUser').mockResolvedValue(mockUser);
// Act
const user = await userService.getUser(1);
// Assert
expect(user).toEqual(mockUser);
});
});

Run tests:

Terminal-Fenster
npm test
npm run test:watch
npx playwright test
Task This Skill Helps With
Unit tests Functions, services, utilities
Component tests React, Vue, Svelte components
E2E tests Full user flows with Playwright
Test failures Debugging red tests, fixing assertions
Mocking APIs, modules, timers

Suites: describe('ComponentName' | 'functionName')

Tests: it('should <behavior> when <condition>')

Examples:

  • it('should render button with correct text')
  • it('should return false when email is invalid')
  • it('should call onClick handler when clicked')
describe('validateEmail', () => {
it('should return true for valid email', () => {
expect(validateEmail('test@example.com')).toBe(true);
});
it('should return false for invalid email', () => {
expect(validateEmail('invalid')).toBe(false);
});
});
import { render, screen, fireEvent } from '@testing-library/react';
describe('Button', () => {
it('should call onClick when clicked', () => {
const handleClick = vi.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByRole('button', { name: /click me/i }));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
import { test, expect } from '@playwright/test';
test('user can login', async ({ page }) => {
await page.goto('/login');
await page.fill('input[name="email"]', 'user@example.com');
await page.fill('input[name="password"]', 'password123');
await page.click('button[type="submit"]');
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
});
it('should fetch data', async () => {
const data = await fetchData();
expect(data).toEqual({ id: 1 });
});
it('should reject with error', async () => {
await expect(fetchInvalidData()).rejects.toThrow('Not found');
});
const mockFn = vi.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ id: 1 });
mockFn.mockRejectedValue(new Error('Failed'));
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
// Vitest
vi.mock('./api', () => ({
fetchUser: vi.fn(),
}));
// Jest
jest.mock('./api', () => ({
fetchUser: jest.fn(),
}));
it('should debounce calls', () => {
vi.useFakeTimers();
const callback = vi.fn();
const debounced = debounce(callback, 1000);
debounced();
debounced();
expect(callback).not.toHaveBeenCalled();
vi.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalledTimes(1);
vi.useRealTimers();
});
describe('Database tests', () => {
let db: Database;
beforeEach(async () => {
db = await createTestDatabase();
});
afterEach(async () => {
await db.close();
});
});
expect(value).toBe(expected);
expect(value).toEqual(expected); // Deep equality
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeDefined();
expect(array).toContain(item);
expect(array).toHaveLength(3);
expect(fn).toHaveBeenCalled();
expect(fn).toHaveBeenCalledWith(arg);
screen.getByRole('button', { name: /submit/i });
screen.getByLabelText(/email/i);
screen.getByText(/welcome/i);
screen.getByTestId('user-card');
await screen.findByText(/loaded/i); // Async
Terminal-Fenster
# Check pattern matches
npm test -- --listTests
# Vitest
npx vitest --reporter=verbose
// BAD: Import before mock
import { api } from './api';
vi.mock('./api');
// GOOD: Mock hoisted automatically in Vitest
vi.mock('./api');
import { api } from './api';
// Increase timeout
it('slow test', async () => { ... }, 10000);
// Or globally in config
test: { timeout: 10000 }
// BAD: Query immediately after render
render(<AsyncComponent />);
expect(screen.getByText('data')).toBeInTheDocument();
// GOOD: Wait for element
render(<AsyncComponent />);
expect(await screen.findByText('data')).toBeInTheDocument();
// Wrap state updates
await act(async () => {
fireEvent.click(button);
});
  1. AAA Pattern - Arrange-Act-Assert structure
  2. Test behavior - Not implementation details
  3. Accessibility queries - getByRole, getByLabelText first
  4. userEvent over fireEvent - More realistic interactions
  5. Independent tests - No shared state between tests
  6. Mock boundaries - APIs, databases, not internal modules
  7. Fast tests - Unit tests in milliseconds
Terminal-Fenster
# Vitest
npm test # Run once
npm run test:watch # Watch mode
npm run test:coverage # Coverage
# Jest
npm test -- --watch
npm test -- --coverage
# Playwright
npx playwright test
npx playwright test --ui # UI mode
npx playwright show-report

For advanced patterns and complete examples:

  • FRONTEND.md - Component testing, E2E, mocking strategies
  • BACKEND.md - Node.js API testing, database patterns
  • EXAMPLES.md - Complete working examples
  • AWL_PLAYWRIGHT.md - @awl/playwright-a11y and @awl/playwright-sveltekit; read when the project is a SvelteKit app or needs accessibility checks in e2e