Validation & Testing
eziwiki includes powerful validation and testing tools to ensure your wiki is error-free.
Payload Validation
Automatic Validation
Payload configuration is automatically validated before every build:
npm run buildOutput:
š Validating payload configuration...
ā
Payload validation passed!Manual Validation
Validate without building:
npm run validate:payloadWhat Gets Validated
- Required fields:
title,description - Navigation structure: Valid hierarchy
- Color format: Hex colors (
#rrggbb) - File existence: All referenced Markdown files exist
- Path uniqueness: No duplicate paths
- JSON Schema: Full schema validation
Validation Errors
Common errors and fixes:
Missing Required Field
ā Payload validation failed:
⢠global.title is requiredFix:
global: {
title: 'My Wiki', // Add title
description: 'My description',
}Invalid Color Format
ā Payload validation failed:
⢠navigation[0].color must be a valid hex colorFix:
{
name: 'Section',
color: '#dbeafe', // Must be #rrggbb format
}Missing Content File
ā Payload validation failed:
⢠Content file not found: content/missing-page.mdFix:
# Create the missing file
touch content/missing-page.mdTesting
Run Tests
# Run all tests
npm run test
# Watch mode (for development)
npm run test:watchTest Structure
Tests are located in __tests__ directories:
lib/
āāā navigation/
ā āāā builder.ts
ā āāā __tests__/
ā āāā builder.test.tsExample Test
import { describe, it, expect } from 'vitest';
import { extractAllPaths } from '../builder';
describe('extractAllPaths', () => {
it('should extract all paths from navigation', () => {
const navigation = [
{ name: 'Home', path: 'intro' },
{
name: 'Guides',
children: [{ name: 'Quick Start', path: 'guides/quick-start' }],
},
];
const paths = extractAllPaths(navigation);
expect(paths).toEqual(['intro', 'guides/quick-start']);
});
});Writing Tests
Create a test file:
// lib/utils/__tests__/helper.test.ts
import { describe, it, expect } from 'vitest';
import { myFunction } from '../helper';
describe('myFunction', () => {
it('should do something', () => {
const result = myFunction('input');
expect(result).toBe('expected output');
});
it('should handle edge cases', () => {
expect(myFunction('')).toBe('');
expect(myFunction(null)).toBe(null);
});
});Type Checking
Run Type Check
npm run type-checkThis runs TypeScript compiler without emitting files, catching type errors:
src/components/Example.tsx:10:5 - error TS2322: Type 'string' is not assignable to type 'number'.
10 count: "invalid"
~~~~~Strict Mode
eziwiki uses strict TypeScript mode:
{
"compilerOptions": {
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
}
}Linting
Run Linter
npm run lintThis runs ESLint with auto-fix:
ā No ESLint warnings or errorsLinting Rules
Configured in .eslintrc.js:
module.exports = {
extends: ['next/core-web-vitals', 'plugin:@typescript-eslint/recommended', 'prettier'],
rules: {
'@typescript-eslint/no-unused-vars': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
},
};Formatting
Format Code
npm run formatThis runs Prettier on all files:
Checking formatting...
All matched files use Prettier code style!Format Configuration
Configured in .prettierrc:
{
"semi": true,
"trailingComma": "all",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2
}Pre-commit Checks
Recommended Workflow
Before committing:
# 1. Format code
npm run format
# 2. Run linter
npm run lint
# 3. Type check
npm run type-check
# 4. Run tests
npm run test
# 5. Validate payload
npm run validate:payloadGit Hooks
Set up pre-commit hooks with Husky:
npm install -D husky lint-staged
# Initialize husky
npx husky install
# Add pre-commit hook
npx husky add .husky/pre-commit "npm run lint && npm run type-check".husky/pre-commit:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm run lint
npm run type-check
npm run test
npm run validate:payloadCI/CD Integration
GitHub Actions
.github/workflows/test.yml:
name: Test
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm run type-check
- run: npm run test
- run: npm run validate:payload
- run: npm run buildShow URLs Script
View all hash-based URLs:
npm run show-urlsOutput:
š Hash-Based URLs
================================================================================
š intro
ā /2c8f9a1b
ā https://eziwiki.dev/2c8f9a1b
š getting-started/quick-start
ā /7d3e4f2a
ā https://eziwiki.dev/7d3e4f2a
š [HIDDEN] secret-page
ā /9f1a2b3c
ā https://eziwiki.dev/9f1a2b3c
================================================================================
Total pages: 15
Hidden pages: 1
š” Tip: Hidden pages are not shown in the sidebar but can be accessed via their hash URL.Useful for:
- Finding hidden page URLs
- Debugging navigation issues
- Sharing direct links
- Testing all pages
Best Practices
Validate Early
Run validation before committing:
npm run validate:payloadWrite Tests
Test critical functionality:
// Test navigation builder
// Test hash generation
// Test content parsing
// Test validation logicUse Type Safety
Leverage TypeScript:
ā
Good:
interface User {
name: string;
email: string;
}
function greet(user: User): string {
return `Hello, ${user.name}!`;
}
ā Bad:
function greet(user: any) {
return `Hello, ${user.name}!`;
}Keep Tests Fast
ā
Good - unit tests:
expect(add(1, 2)).toBe(3);
ā Bad - slow integration tests:
await fetch('https://api.example.com/test');Troubleshooting
Validation Fails
If validation fails:
- Read error messages carefully
- Check
payload/config.tsfor issues - Verify all Markdown files exist
- Check color format (
#rrggbb)
Tests Fail
If tests fail:
- Read test output
- Check for recent code changes
- Update tests if behavior changed
- Fix bugs if tests are correct
Type Errors
If type checking fails:
- Read error messages
- Add missing type annotations
- Fix type mismatches
- Use
anysparingly (last resort)