npm install -D vitest @testing-library/react
npm install -D @testing-library/jest-dom
npm install -D supertest
// package.json
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest --coverage"
}
}
// __tests__/filters.test.js
import { describe, it, expect }
from 'vitest';
import { applyColorMatrix, SEPIA_MATRIX }
from '../src/filters';
describe('applyColorMatrix', () => {
it('applies sepia to white pixel',
() => {
const data = new Uint8ClampedArray(
[255, 255, 255, 255]);
const imageData = {
data, width: 1, height: 1 };
applyColorMatrix(
imageData, SEPIA_MATRIX);
// Sepia tints white → warm beige
expect(data[0]).toBeGreaterThan(200);
expect(data[2]).toBeLessThan(200);
});
it('preserves alpha channel', () => {
const data = new Uint8ClampedArray(
[100, 100, 100, 128]);
const imageData = {
data, width: 1, height: 1 };
applyColorMatrix(
imageData, SEPIA_MATRIX);
expect(data[3]).toBe(128);
});
});
describe('generateFilename', () => {
it('adds timestamp prefix', () => {
const name =
generateFilename('photo.jpg');
expect(name).toMatch(
/^\d{13}-photo\.jpg$/);
});
it('sanitizes special characters',
() => {
const name =
generateFilename(
'../hack/../../etc/passwd');
expect(name).not.toContain('..');
expect(name).not.toContain('/');
});
});
// __tests__/api/auth.test.js
import { describe, it, expect,
beforeAll, afterAll } from 'vitest';
import request from 'supertest';
import { app } from '../server/app';
describe('POST /api/v1/auth/register',
() => {
it('creates user with valid input',
async () => {
const res = await request(app)
.post('/api/v1/auth/register')
.send({
email: 'test@example.com',
password: 'SecurePass1',
name: 'Test User',
});
expect(res.status).toBe(201);
expect(res.body.token)
.toBeDefined();
expect(res.body.user.email)
.toBe('test@example.com');
});
it('rejects invalid email', async () => {
const res = await request(app)
.post('/api/v1/auth/register')
.send({
email: 'not-an-email',
password: 'SecurePass1',
name: 'Test',
});
expect(res.status).toBe(400);
expect(res.body.details[0].field)
.toBe('email');
});
it('rejects duplicate email',
async () => {
// Register once
await request(app)
.post('/api/v1/auth/register')
.send({
email: 'dupe@example.com',
password: 'SecurePass1',
name: 'First',
});
// Try again
const res = await request(app)
.post('/api/v1/auth/register')
.send({
email: 'dupe@example.com',
password: 'SecurePass1',
name: 'Second',
});
expect(res.status).toBe(409);
});
});
// __tests__/components/FilterPicker.test.jsx
import { render, screen, fireEvent }
from '@testing-library/react';
import { FilterPicker }
from '../src/components/FilterPicker';
describe('FilterPicker', () => {
it('renders all filter options', () => {
render(<FilterPicker
onSelect={() => {}} />);
expect(screen.getByText('Sepia'))
.toBeInTheDocument();
expect(screen.getByText('Grayscale'))
.toBeInTheDocument();
expect(screen.getByText('Sharpen'))
.toBeInTheDocument();
});
it('calls onSelect when clicked',
() => {
const handleSelect = vi.fn();
render(<FilterPicker
onSelect={handleSelect} />);
fireEvent.click(
screen.getByText('Sepia'));
expect(handleSelect)
.toHaveBeenCalledWith('sepia');
});
it('highlights active filter', () => {
render(<FilterPicker
active="sepia"
onSelect={() => {}} />);
const btn = screen.getByText('Sepia');
expect(btn.className)
.toContain('active');
});
});
git switch -c feature/PIXELCRAFT-073-testing
git add __tests__/ vitest.config.js
git commit -m "Add unit, integration, component tests (PIXELCRAFT-073)"
git push origin feature/PIXELCRAFT-073-testing
# PR → Review → Merge → Close ticket ✅
Tests are the only way to refactor with confidence.
Without tests, every change is a risk. With tests, you can restructure the entire codebase and know nothing broke — in seconds.
npm test → 42 tests pass in 1.3 seconds. Filters, API routes, React components — all verified automatically. Change any code → tests catch if you broke something. Deploy with confidence.