Automated Testing
Comprehensive automated testing for Docusaurus build scripts using Node.js built-in test runner.
Overview
The test suite validates the core functionality of three critical scripts:
- sync-tools.cjs - Tool documentation syncing and organization
- validate-mdx.cjs - MDX syntax validation
- check-links.cjs - Internal and external link checking
Features
- Zero Dependencies: Uses Node.js built-in test runner (no Jest, Mocha, etc.)
- Fast Execution: Tests run in seconds
- CI Integration: Automated testing via GitHub Actions
- Comprehensive Coverage: Tests parsing, validation, and file operations
- Clear Output: Structured test results with pass/fail indicators
Running Tests
Run All Tests
cd docusaurus
npm test
This runs all test files using the test runner script.
Run Individual Test Suites
# Test sync-tools.cjs
npm run test:sync
# Test validate-mdx.cjs
npm run test:validate
# Test check-links.cjs
npm run test:links
Run Tests with Node Directly
# Run a specific test file
node --test scripts/__tests__/sync-tools.test.cjs
# Run all tests in directory
node --test scripts/__tests__/*.test.cjs
Test Structure
Test Files Location
docusaurus/
├── scripts/
│ ├── __tests__/
│ │ ├── run-tests.cjs # Test runner
│ │ ├── sync-tools.test.cjs # sync-tools tests
│ │ ├── validate-mdx.test.cjs # validate-mdx tests
│ │ └── check-links.test.cjs # check-links tests
│ ├── sync-tools.cjs
│ ├── validate-mdx.cjs
│ └── check-links.cjs
Test Organization
Each test file uses Node's test and assert modules:
const { describe, it } = require('node:test');
const assert = require('node:assert');
describe('Feature', () => {
it('should do something', () => {
assert.strictEqual(1 + 1, 2);
});
});
Test Coverage
sync-tools.cjs Tests
Tests for tool documentation syncing:
- Frontmatter Parsing: YAML frontmatter extraction
- MDX Safety: Email escaping, file:// link handling
- Category Organization: Slug generation, title conversion
- Title Extraction: H1 heading extraction
- H1 Stripping: Leading heading removal
- Cost Calculation: Annual cost calculation logic
validate-mdx.cjs Tests
Tests for MDX syntax validation:
- Code Block Detection: Fenced code block identification
- JSX Expression Detection: Curly brace expression detection
- Valid Tag Detection: HTML/JSX tag recognition
- Pattern Detection: Email, numbers, special characters
- File Type Handling: .md vs .mdx differentiation
- Line Number Calculation: Error position tracking
check-links.cjs Tests
Tests for link checking:
- Link Extraction: Markdown, MDX, and HTML links
- Link Classification: External vs internal links
- Internal Link Validation: Path resolution
- URL Parsing: Valid URL detection
- File Extension Handling: .md/.mdx extensions
- Results Tracking: Error and warning accumulation
Example Test
Here's a complete test example:
const { describe, it } = require('node:test');
const assert = require('node:assert');
describe('Category Slugification', () => {
it('should convert category to slug correctly', () => {
const categoryToSlug = (category) => {
if (!category) return 'uncategorized';
return category.toLowerCase().replace(/_/g, '-');
};
assert.strictEqual(categoryToSlug('WEBSITE'), 'website');
assert.strictEqual(categoryToSlug('MARKETING_TOOL'), 'marketing-tool');
assert.strictEqual(categoryToSlug('SELF_HOSTING'), 'self-hosting');
assert.strictEqual(categoryToSlug(null), 'uncategorized');
});
});
GitHub Actions CI
Tests run automatically on push and pull requests via GitHub Actions.
Workflow File
.github/workflows/test-docusaurus-scripts.yml
name: Test Docusaurus Scripts
on:
push:
branches: [main]
paths:
- 'docusaurus/scripts/**'
- 'tools/**'
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x, 22.x]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
working-directory: ./docusaurus
- run: npm test
working-directory: ./docusaurus
Workflow Features
- Multi-Node Testing: Tests on Node 20 and 22
- Automatic Triggering: Runs on script changes
- Build Verification: Runs sync and validation scripts
- Artifact Upload: Saves test results for review
Writing New Tests
1. Create Test File
Create a new file in scripts/__tests__/:
#!/usr/bin/env node
const { describe, it } = require('node:test');
const assert = require('node:assert');
describe('My Feature', () => {
it('should work correctly', () => {
// Your test here
assert.strictEqual(1 + 1, 2);
});
});
if (require.main === module) {
console.log('Running my tests...\n');
}
2. Add to Test Runner
Edit scripts/__tests__/run-tests.cjs:
const TEST_FILES = [
'sync-tools.test.cjs',
'validate-mdx.test.cjs',
'check-links.test.cjs',
'my-new-test.cjs', // Add your test
];
3. Add npm Script (Optional)
Edit package.json:
{
"scripts": {
"test:mynew": "node --test ./scripts/__tests__/my-new-test.cjs"
}
}
4. Run Your Test
npm run test:mynew
Best Practices
Test Organization
- One file per script: Keep tests focused
- Descriptive names: Use clear test descriptions
- Group related tests: Use
describeblocks - Test edge cases: Include error conditions
Assertions
Use appropriate assertion methods:
// Equality
assert.strictEqual(actual, expected);
assert.deepStrictEqual(actualObject, expectedObject);
// Truthiness
assert.ok(value);
assert.strictEqual(value, true);
// Exceptions
assert.throws(() => { throw new Error(); });
assert.doesNotThrow(() => { /* safe code */ });
Test Independence
- No shared state: Each test should be independent
- Clean up: Remove test fixtures after tests
- Mock carefully: Avoid complex mocking (keep it simple)
Troubleshooting
Test Failures
Issue: Tests fail locally but pass in CI
Solution: Ensure you're using the same Node version as CI (20.x or 22.x)
node --version
nvm use 20 # or nvm use 22
Issue: Import errors in tests
Solution: Use CommonJS (require) not ES modules (import)
// ✅ Correct
const { describe, it } = require('node:test');
// ❌ Incorrect
import { describe, it } from 'node:test';
Issue: Tests hang or timeout
Solution: Ensure async operations complete
// Use async/await properly
it('async test', async () => {
const result = await someAsyncFunction();
assert.ok(result);
});
Continuous Integration
Local Pre-Commit Testing
Run tests before committing:
cd docusaurus
npm test && npm run check-links
Pre-Push Hook
Add to .git/hooks/pre-push:
#!/bin/bash
cd docusaurus
npm test
if [ $? -ne 0 ]; then
echo "Tests failed. Push aborted."
exit 1
fi
Make executable:
chmod +x .git/hooks/pre-push
Performance
Test Execution Time
Typical test run times:
- sync-tools tests: ~100ms
- validate-mdx tests: ~150ms
- check-links tests: ~200ms
- Total: ~450ms
Optimization Tips
- Keep tests focused and small
- Avoid slow operations (file I/O, network)
- Use fixtures for complex data
- Run tests in parallel when possible
Related Documentation
- Tool Categorization System - Tool syncing and organization
- Link Checker - Link checking documentation
- Documentation Verification - Automated verification tracking
Future Enhancements
- Add code coverage reporting
- Create integration tests for full build process
- Add performance benchmarks
- Test Docusaurus build output
- Add visual regression testing
Last Updated: 2026-01-06
Test Framework: Node.js built-in test runner
Node Version: 20.x, 22.x
Status: Active