Testing --- Jest & Playwright
⏱ 18 min read read
Setup Jest + Testing Library:
npm install -D jest jest-environment-jsdom @testing-library/react
@testing-library/jest-dom @types/jest
npx jest --init
// jest.config.ts
import type { Config } from 'jest';
const config: Config = {
testEnvironment: 'jsdom',
setupFilesAfterFramework: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: { '^@/(.*)$': '<rootDir>/$1' },
};
export default config;
// jest.setup.ts
import '@testing-library/jest-dom';
Unit Testing Components:
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from '@/components/Counter';
describe('Counter', () => {
it('renders initial count of 0', () => {
render(<Counter />);
expect(screen.getByText('Count: 0')).toBeInTheDocument();
});
it('increments on button click', () => {
render(<Counter />);
fireEvent.click(screen.getByRole('button', { name: /\+1/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
});
Playwright --- End-to-End Testing:
npm init playwright@latest
// tests/home.spec.ts
import { test, expect } from '@playwright/test';
test('homepage loads and shows title', async ({ page }) => {
await page.goto('http://localhost:3000');
await expect(page).toHaveTitle(/My App/);
await expect(page.getByRole('heading', { name: 'Hello'
})).toBeVisible();
});
test('can add a student', async ({ page }) => {
await page.goto('/students');
await page.getByPlaceholder('Name').fill('Alice');
await page.getByPlaceholder('Grade').fill('92');
await page.getByRole('button', { name: 'Add' }).click();
await expect(page.getByText('Alice: 92')).toBeVisible();
});
Jest + Testing Library = unit tests for pure functions and React
components.
Playwright = browser-based E2E tests (Chrome, Firefox, Safari).
Testing Library philosophy: test behaviour, not implementation.
Query priority: getByRole > getByLabelText > getByText >
getByTestId.
Run: npm test (Jest) | npx playwright test (E2E)
npm install -D jest jest-environment-jsdom @testing-library/react
@testing-library/jest-dom @types/jest
npx jest --init
// jest.config.ts
import type { Config } from 'jest';
const config: Config = {
testEnvironment: 'jsdom',
setupFilesAfterFramework: ['<rootDir>/jest.setup.ts'],
moduleNameMapper: { '^@/(.*)$': '<rootDir>/$1' },
};
export default config;
// jest.setup.ts
import '@testing-library/jest-dom';
Unit Testing Components:
import { render, screen, fireEvent } from '@testing-library/react';
import Counter from '@/components/Counter';
describe('Counter', () => {
it('renders initial count of 0', () => {
render(<Counter />);
expect(screen.getByText('Count: 0')).toBeInTheDocument();
});
it('increments on button click', () => {
render(<Counter />);
fireEvent.click(screen.getByRole('button', { name: /\+1/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
});
Playwright --- End-to-End Testing:
npm init playwright@latest
// tests/home.spec.ts
import { test, expect } from '@playwright/test';
test('homepage loads and shows title', async ({ page }) => {
await page.goto('http://localhost:3000');
await expect(page).toHaveTitle(/My App/);
await expect(page.getByRole('heading', { name: 'Hello'
})).toBeVisible();
});
test('can add a student', async ({ page }) => {
await page.goto('/students');
await page.getByPlaceholder('Name').fill('Alice');
await page.getByPlaceholder('Grade').fill('92');
await page.getByRole('button', { name: 'Add' }).click();
await expect(page.getByText('Alice: 92')).toBeVisible();
});
Jest + Testing Library = unit tests for pure functions and React
components.
Playwright = browser-based E2E tests (Chrome, Firefox, Safari).
Testing Library philosophy: test behaviour, not implementation.
Query priority: getByRole > getByLabelText > getByText >
getByTestId.
Run: npm test (Jest) | npx playwright test (E2E)
Log in to track your progress and earn badges as you complete lessons.
Log In to Track Progress