Comprehensive guide to the test suite, testing strategies, and best practices for the MCP WordPress Server.
- Main Test Suite: 512/512 passed (100%) with Vitest
- Security Tests: 40/40 passed (100%)
- Performance Tests: 8/8 passed (100%)
- CI/CD Pipeline: Fully functional with Vitest integration
- Code Coverage: 96.17% line coverage maintained
tests/
βββ unit/ # Unit tests (17 tests)
β βββ security-utils.test.js
β βββ cache-manager.test.js
β βββ helper-functions.test.js
βββ integration/ # Integration tests (54 tests)
β βββ wordpress-api.test.js
β βββ multi-site.test.js
β βββ auth-methods.test.js
βββ security/ # Security tests (40 tests)
β βββ input-validation.test.js
β βββ auth-security.test.js
β βββ penetration.test.js
β βββ vulnerability.test.js
βββ performance/ # Performance tests (8 tests)
β βββ benchmarks.test.js
β βββ regression.test.js
β βββ load-testing.test.js
βββ cache/ # Cache tests (37 tests)
β βββ cache-functionality.test.js
β βββ cache-invalidation.test.js
β βββ cache-performance.test.js
βββ property/ # Property-based tests (12 tests)
β βββ data-structure.test.js
β βββ edge-cases.test.js
βββ config/ # Configuration tests (27 tests)
β βββ schema-validation.test.js
β βββ multi-site-config.test.js
β βββ environment-config.test.js
βββ contracts/ # Contract tests (mock)
β βββ pact-testing.test.js
β βββ api-contracts.test.js
βββ typescript-build.test.js # TypeScript build tests (21 tests)
βββ auth-headers-fix.test.js # Authentication header tests
βββ config-loading.test.js # Configuration loading tests
βββ tool-validation.test.js # Tool validation tests
βββ env-loading.test.js # Environment loading tests (7 tests)
βββ upload-timeout.test.js # Upload timeout tests (12 tests)
# Run all tests
npm test
# Run specific test suites
npm run test:unit # Unit tests only
npm run test:integration # Integration tests only
npm run test:security # Security tests only
npm run test:performance # Performance tests only
npm run test:cache # Cache tests only
npm run test:config # Configuration tests only
npm run test:property # Property-based tests only
# Development commands
npm run test:watch # Watch mode
npm run test:coverage # Generate coverage report
npm run test:fast # Quick validation# TypeScript and build tests
npm run test:typescript # TypeScript compilation tests
npm run test:tools # Tool functionality tests
npm run test:mcp # MCP protocol tests
# Multi-site and authentication
npm run test:multisite # Multi-site configuration tests
npm run test:auth # Authentication method tests
# Contract testing
npm run test:contracts # Mock contract tests
npm run test:contracts:live # Live WordPress contract tests
# Docker test environment
npm run test:with-env # Tests with Docker WordPress
./scripts/start-test-env.sh # Start test environment// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'node',
include: ['tests/**/*.test.js'],
coverage: {
include: ['src/**/*.ts'],
exclude: ['src/**/*.d.ts', 'src/**/*.test.ts'],
coverageThreshold: {
global: {
branches: 50,
functions: 50,
lines: 50,
statements: 50,
},
},
setupFilesAfterEnv: ["<rootDir>/tests/setup.js"],
testTimeout: 30000,
};// tests/setup.js
const { performance } = require("perf_hooks");
// Global test utilities
global.testUtils = {
createMockClient: () => ({
/* mock client */
}),
generateTestData: (schema) => ({
/* generated data */
}),
measurePerformance: (fn) => {
const start = performance.now();
const result = fn();
const duration = performance.now() - start;
return { result, duration };
},
};
// Setup test environment
beforeAll(() => {
process.env.NODE_ENV = "test";
process.env.DEBUG = "false";
});
afterAll(() => {
// Cleanup test environment
});Purpose: Test individual components in isolation
Coverage:
- Security utilities and helper functions
- Cache manager functionality
- Input validation logic
- Error handling mechanisms
Example:
// tests/unit/security-utils.test.js
describe("SecurityUtils", () => {
test("should sanitize input correctly", () => {
const input = '<script>alert("xss")</script>';
const sanitized = SecurityUtils.sanitizeInput(input);
expect(sanitized).not.toContain("<script>");
});
test("should validate email format", () => {
expect(SecurityUtils.isValidEmail("test@example.com")).toBe(true);
expect(SecurityUtils.isValidEmail("invalid-email")).toBe(false);
});
});Purpose: Test multi-component interactions with real WordPress instances
Coverage:
- WordPress API connectivity
- Multi-site configuration
- Authentication method validation
- End-to-end tool functionality
Example:
// tests/integration/wordpress-api.test.js
describe("WordPress API Integration", () => {
let client;
beforeAll(async () => {
client = new WordPressClient({
siteUrl: process.env.WORDPRESS_TEST_URL,
username: "admin",
appPassword: "test test test test test test",
});
});
test("should create and retrieve post", async () => {
const post = await client.posts.create({
title: "Test Post",
content: "Test content",
status: "publish",
});
expect(post.id).toBeDefined();
expect(post.title).toBe("Test Post");
const retrieved = await client.posts.get({ id: post.id });
expect(retrieved.title).toBe("Test Post");
});
});Purpose: Validate security measures and vulnerability protection
Coverage:
- Input validation and sanitization
- Authentication security
- Authorization checks
- XSS and SQL injection prevention
- Rate limiting and DoS protection
Example:
// tests/security/input-validation.test.js
describe("Input Validation Security", () => {
test("should reject malicious script injection", () => {
const maliciousInput = {
title: '<script>alert("xss")</script>',
content: '"><script>alert("xss")</script>',
};
expect(() => {
createPostSchema.parse(maliciousInput);
}).toThrow("Invalid input");
});
test("should prevent SQL injection in search", () => {
const sqlInjection = "'; DROP TABLE posts; --";
expect(() => {
searchSchema.parse({ query: sqlInjection });
}).toThrow("Invalid characters");
});
});Purpose: Ensure performance standards and detect regressions
Coverage:
- Response time benchmarks
- Memory usage monitoring
- Cache performance validation
- Load testing scenarios
Example:
// tests/performance/benchmarks.test.js
describe("Performance Benchmarks", () => {
test("should handle post creation under 500ms", async () => {
const start = performance.now();
await client.posts.create({
title: "Performance Test",
content: "Test content",
});
const duration = performance.now() - start;
expect(duration).toBeLessThan(500);
});
test("should maintain cache hit rate above 70%", async () => {
// Warm cache
await client.posts.list();
await client.posts.list();
const stats = await client.cache.getStats();
expect(stats.hitRate).toBeGreaterThan(0.7);
});
});Purpose: Validate caching functionality and performance
Coverage:
- Cache hit and miss scenarios
- Cache invalidation logic
- Multi-site cache isolation
- Cache performance optimization
Example:
// tests/cache/cache-functionality.test.js
describe("Cache Functionality", () => {
test("should cache GET requests", async () => {
const client = new CachedWordPressClient(config);
// First request - cache miss
const start1 = performance.now();
const posts1 = await client.posts.list();
const duration1 = performance.now() - start1;
// Second request - cache hit
const start2 = performance.now();
const posts2 = await client.posts.list();
const duration2 = performance.now() - start2;
expect(posts1).toEqual(posts2);
expect(duration2).toBeLessThan(duration1 * 0.1); // 90% faster
});
test("should invalidate cache on updates", async () => {
const client = new CachedWordPressClient(config);
// Cache posts list
await client.posts.list();
// Create new post
await client.posts.create({
title: "New Post",
content: "Content",
});
// List should be refreshed
const posts = await client.posts.list();
expect(posts.some((p) => p.title === "New Post")).toBe(true);
});
});Purpose: Test with generated data to find edge cases
Coverage:
- Data structure validation
- Edge case discovery
- Input boundary testing
- Randomized testing scenarios
Example:
// tests/property/data-structure.test.js
const fc = require("fast-check");
describe("Property-Based Testing", () => {
test("should handle any valid post data", () => {
fc.assert(
fc.property(
fc.record({
title: fc.string({ minLength: 1, maxLength: 200 }),
content: fc.string(),
status: fc.constantFrom("draft", "publish", "private"),
}),
async (postData) => {
const result = await client.posts.create(postData);
expect(result.title).toBe(postData.title);
expect(result.status).toBe(postData.status);
},
),
);
});
});Purpose: Validate configuration loading and validation
Coverage:
- Multi-site configuration validation
- Environment variable loading
- Schema validation with Zod
- Configuration error handling
Example:
// tests/config/schema-validation.test.js
describe("Configuration Schema Validation", () => {
test("should validate multi-site configuration", () => {
const validConfig = {
sites: [
{
id: "site1",
name: "Test Site",
config: {
WORDPRESS_SITE_URL: "https://example.com",
WORDPRESS_USERNAME: "admin",
WORDPRESS_APP_PASSWORD: "test test test test test test",
},
},
],
};
expect(() => {
multiSiteConfigSchema.parse(validConfig);
}).not.toThrow();
});
test("should reject invalid site URLs", () => {
const invalidConfig = {
sites: [
{
id: "site1",
name: "Test Site",
config: {
WORDPRESS_SITE_URL: "invalid-url",
WORDPRESS_USERNAME: "admin",
WORDPRESS_APP_PASSWORD: "password",
},
},
],
};
expect(() => {
multiSiteConfigSchema.parse(invalidConfig);
}).toThrow("Invalid URL");
});
});# Start complete test environment
./scripts/start-test-env.sh
# This creates:
# - WordPress instance on http://localhost:8081
# - MySQL database
# - Pre-configured admin user
# - Application password setup# docker-compose.test.yml
version: "3.8"
services:
wordpress:
image: wordpress:latest
ports:
- "8081:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
depends_on:
- db
volumes:
- ./tests/wordpress-config.php:/var/www/html/wp-config.php
db:
image: mysql:8.0
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
MYSQL_ROOT_PASSWORD: root
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:# Run tests with Docker environment
npm run test:with-env
# Run specific tests against Docker
WORDPRESS_TEST_URL=http://localhost:8081 npm test
# Clean up test environment
docker-compose -f docker-compose.test.yml down -v# Generate coverage report
npm run test:coverage
# Coverage report locations:
# - coverage/lcov-report/index.html (HTML report)
# - coverage/lcov.info (LCOV format)
# - coverage/coverage-final.json (JSON format)# Performance test reporting
npm run test:performance
# Generates:
# - Performance benchmarks
# - Regression detection
# - Memory usage analysis
# - Response time metrics# .github/workflows/ci.yml
name: CI/CD Pipeline
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run security tests
run: npm run test:security
- name: Run performance tests
run: npm run test:performance
- name: Upload coverage
uses: codecov/codecov-action@v3Pre-Commit Hooks:
- ESLint validation
- TypeScript type checking
- Quick test validation
- Security scanning
Pre-Push Hooks:
- Full test suite execution
- Security audit
- Performance regression tests
- Coverage threshold validation
// Standard test structure
describe("Component Name", () => {
// Setup
beforeAll(() => {
// One-time setup
});
beforeEach(() => {
// Per-test setup
});
// Test cases
describe("method name", () => {
test("should do something specific", () => {
// Arrange
const input = "test data";
// Act
const result = component.method(input);
// Assert
expect(result).toBe("expected output");
});
});
// Cleanup
afterEach(() => {
// Per-test cleanup
});
afterAll(() => {
// One-time cleanup
});
});- Descriptive Test Names: Use clear, specific test descriptions
- Arrange-Act-Assert Pattern: Structure tests consistently
- Mock External Dependencies: Isolate units under test
- Test Edge Cases: Include boundary conditions and error scenarios
- Performance Aware: Include performance assertions where relevant
- Security Focused: Test security-related functionality thoroughly
// tests/utils/mocks.js
export const mockWordPressClient = {
posts: {
create: vi.fn(),
update: vi.fn(),
delete: vi.fn(),
get: vi.fn(),
list: vi.fn(),
},
auth: {
authenticate: vi.fn(),
getAuthHeaders: vi.fn(),
},
};
export const mockConfig = {
siteUrl: "https://test.example.com",
username: "testuser",
appPassword: "test test test test test test",
};- Test Coverage: 95%+ maintained
- Test Execution Time: < 5 minutes for full suite
- Test Reliability: 100% pass rate in CI/CD
- Security Test Coverage: 100% of security features tested
- Performance Regression: < 20% performance degradation threshold
# Check test health
npm run test:health
# Outputs:
# - Test execution time trends
# - Coverage percentage by component
# - Flaky test detection
# - Performance regression alerts# Run tests with debug output
DEBUG=true npm test
# Debug specific test file
DEBUG=true npm test -- tests/integration/wordpress-api.test.js
# Debug with Node.js inspector (Vitest)
node --inspect-brk ./node_modules/.bin/vitest run --no-coverage// Debug utility functions
const debug = require("debug")("test:debug");
describe("Debug Example", () => {
test("should debug test execution", () => {
debug("Starting test execution");
const result = someFunction();
debug("Function result:", result);
expect(result).toBeDefined();
});
});- Architecture Guide - System design and patterns
- API Reference - Complete technical API documentation
- Security Guidelines - Security best practices
- Performance Guide - Performance optimization
Need help with testing? This comprehensive testing infrastructure ensures code quality, security, and performance. All tests are designed to be fast, reliable, and maintainable.