testing
Testing Skill
Instructions
When writing tests:
1. JavaScript Testing (Jest)
Setup:
// jest.config.js
module.exports = {
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
collectCoverageFrom: ['src/**/*.{js,jsx}'],
};
Unit Test Example:
// utils.test.js
import { formatPrice, validateEmail } from './utils';
describe('formatPrice', () => {
it('formats number as currency', () => {
expect(formatPrice(1000)).toBe('$1,000.00');
});
it('handles zero', () => {
expect(formatPrice(0)).toBe('$0.00');
});
it('handles negative numbers', () => {
expect(formatPrice(-50)).toBe('-$50.00');
});
});
describe('validateEmail', () => {
it('returns true for valid email', () => {
expect(validateEmail('user@example.com')).toBe(true);
});
it('returns false for invalid email', () => {
expect(validateEmail('invalid')).toBe(false);
expect(validateEmail('no@domain')).toBe(false);
});
});
Async Test:
describe('fetchUser', () => {
it('fetches user data', async () => {
const user = await fetchUser(1);
expect(user).toHaveProperty('name');
expect(user.id).toBe(1);
});
it('throws on invalid id', async () => {
await expect(fetchUser(-1)).rejects.toThrow('Invalid ID');
});
});
Mocking:
// Mock module
jest.mock('./api');
import { fetchData } from './api';
fetchData.mockResolvedValue({ data: 'mocked' });
// Mock function
const mockCallback = jest.fn();
mockCallback.mockReturnValue(42);
// Verify calls
expect(mockCallback).toHaveBeenCalled();
expect(mockCallback).toHaveBeenCalledWith('arg1', 'arg2');
expect(mockCallback).toHaveBeenCalledTimes(2);
2. React Testing (React Testing Library)
Component Test:
import { render, screen, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Button from './Button';
describe('Button', () => {
it('renders with label', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
});
it('calls onClick when clicked', async () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click</Button>);
await userEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
it('is disabled when loading', () => {
render(<Button loading>Submit</Button>);
expect(screen.getByRole('button')).toBeDisabled();
});
});
Form Test:
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import LoginForm from './LoginForm';
describe('LoginForm', () => {
it('submits form with valid data', async () => {
const onSubmit = jest.fn();
render(<LoginForm onSubmit={onSubmit} />);
await userEvent.type(screen.getByLabelText(/email/i), 'user@example.com');
await userEvent.type(screen.getByLabelText(/password/i), 'password123');
await userEvent.click(screen.getByRole('button', { name: /log in/i }));
await waitFor(() => {
expect(onSubmit).toHaveBeenCalledWith({
email: 'user@example.com',
password: 'password123',
});
});
});
it('shows error for invalid email', async () => {
render(<LoginForm onSubmit={jest.fn()} />);
await userEvent.type(screen.getByLabelText(/email/i), 'invalid');
await userEvent.click(screen.getByRole('button', { name: /log in/i }));
expect(await screen.findByText(/invalid email/i)).toBeInTheDocument();
});
});
3. PHP Testing (PHPUnit)
Setup:
<!-- phpunit.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="Unit">
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
</phpunit>
Unit Test:
<?php
// tests/Unit/HelperTest.php
use PHPUnit\Framework\TestCase;
class HelperTest extends TestCase
{
public function test_format_price_returns_formatted_string()
{
$result = format_price(1000);
$this->assertEquals('$1,000.00', $result);
}
public function test_sanitize_title_removes_special_chars()
{
$result = sanitize_title('Hello World!');
$this->assertEquals('hello-world', $result);
}
/**
* @dataProvider emailProvider
*/
public function test_validate_email($email, $expected)
{
$this->assertEquals($expected, validate_email($email));
}
public function emailProvider(): array
{
return [
['user@example.com', true],
['invalid', false],
['', false],
];
}
}
4. WordPress Testing
Setup:
<?php
// tests/bootstrap.php
$_tests_dir = getenv('WP_TESTS_DIR') ?: '/tmp/wordpress-tests-lib';
require_once $_tests_dir . '/includes/functions.php';
function _manually_load_plugin() {
require dirname(__DIR__) . '/plugin-name.php';
}
tests_add_filter('muplugins_loaded', '_manually_load_plugin');
require $_tests_dir . '/includes/bootstrap.php';
Plugin Test:
<?php
class PluginTest extends WP_UnitTestCase
{
public function test_plugin_is_activated()
{
$this->assertTrue(is_plugin_active('plugin-name/plugin-name.php'));
}
public function test_custom_post_type_is_registered()
{
$this->assertTrue(post_type_exists('portfolio'));
}
public function test_shortcode_renders_content()
{
$output = do_shortcode('[my_shortcode]');
$this->assertStringContainsString('expected-content', $output);
}
}
5. E2E Testing (Playwright)
// tests/e2e/login.spec.js
import { test, expect } from '@playwright/test';
test.describe('Login Flow', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/login');
});
test('successful login redirects to dashboard', async ({ page }) => {
await page.fill('[name="email"]', 'user@example.com');
await page.fill('[name="password"]', 'password123');
await page.click('button[type="submit"]');
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
});
test('invalid credentials show error', async ({ page }) => {
await page.fill('[name="email"]', 'wrong@example.com');
await page.fill('[name="password"]', 'wrongpassword');
await page.click('button[type="submit"]');
await expect(page.locator('.error')).toBeVisible();
await expect(page.locator('.error')).toContainText('Invalid credentials');
});
});
6. Test Structure
tests/
├── unit/ # Pure function tests
├── integration/ # Component interaction tests
├── e2e/ # Full user flow tests
├── fixtures/ # Test data
├── mocks/ # Mock implementations
└── helpers/ # Test utilities
7. Testing Best Practices
- Test behavior, not implementation
- One assertion per test (when practical)
- Use descriptive test names
- Arrange-Act-Assert pattern
- Don't test external libraries
- Keep tests fast and isolated
- Use factories for test data
- Mock external dependencies
- Aim for 80%+ coverage on critical paths
- Run tests in CI/CD
8. Common Matchers
// Jest/Vitest
expect(value).toBe(exact);
expect(value).toEqual(deepEqual);
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toContain(item);
expect(value).toHaveLength(3);
expect(value).toMatch(/regex/);
expect(fn).toThrow(Error);
expect(fn).toHaveBeenCalled();
More from vapvarun/claude-backup
php
Modern PHP development best practices including PHP 8.x features, OOP patterns, error handling, security, testing, and performance optimization. Use when writing PHP code, reviewing PHP projects, debugging PHP issues, or implementing PHP features outside of WordPress/Laravel specific contexts.
45email-marketing
Create email marketing campaigns including newsletters, drip sequences, promotional emails, and transactional emails. Use when writing email copy, designing email templates, or planning email automation.
14html-markup
Write semantic, accessible HTML5 markup following best practices for structure, SEO, and accessibility. Use when creating HTML templates, fixing markup issues, or building web page structures.
12landing-page
Create high-converting landing pages with persuasive copy, clear CTAs, social proof, and optimized structure. Use when building sales pages, product pages, lead capture pages, or conversion-focused pages.
12marketing
Create comprehensive marketing content for themes, plugins, and web products. Generates organized folder structure with product descriptions, feature highlights, social media posts, email campaigns, video scripts, sales materials, and brand assets. Use when creating promotional content, announcements, or sales copy.
11react-component
Create React components with TypeScript, following best practices for hooks, state management, accessibility, and testing. Use when building new UI components or refactoring existing ones.
11