mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 06:14:59 +00:00
Add AST-based migration framework for converting TypeScript tests to JSON: New files: - scripts/migrate-tests/converter.ts (350+ lines) * AST parser for .test.ts files * Extracts describe/it/expect blocks * Maps 30+ Jest/Vitest matchers to JSON types * Returns structured ConversionResult - scripts/migrate-tests/migrator.ts (250+ lines) * Batch discovery and migration orchestrator * Glob-based .test.ts file discovery * Automatic output directory creation * Dry-run mode for safe preview * Pretty-printed progress reporting * Package name mapping (frontends → packages) - scripts/migrate-tests/validator.ts (300+ lines) * JSON schema validation using AJV * Semantic checks (unique IDs, assertions) * Unused import warnings * Directory-wide validation support * Structured ValidationResult output - scripts/migrate-tests/index.ts * Unified export module - scripts/migrate-tests/README.md * Comprehensive usage guide * Conversion process documentation * Matcher mapping reference * Workflow recommendations * Troubleshooting guide Features: * 80/20 conversion (handles ~80% of tests cleanly) * Fallback for complex tests requiring manual adjustment * Dry-run mode to preview changes * Verbose logging for troubleshooting * Validates against tests_schema.json Matcher Support: * Basic: equals, deepEquals, notEquals, truthy, falsy * Numeric: greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual * Type: null, notNull, undefined, notUndefined, instanceOf * Collection: contains, matches, hasProperty, hasLength * DOM: toBeVisible, toBeInTheDocument, toHaveTextContent, toHaveAttribute, toHaveClass, toBeDisabled, toBeEnabled, toHaveValue * Control: throws, notThrows, custom This completes Phase 3 Task 4 of the JSON interpreter everywhere implementation. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
383 lines
9.4 KiB
Markdown
383 lines
9.4 KiB
Markdown
# Test Migration Toolkit
|
|
|
|
Tools for migrating TypeScript test files (.test.ts) to declarative JSON format for the MetaBuilder unified test runner.
|
|
|
|
## Overview
|
|
|
|
The toolkit consists of three main components:
|
|
|
|
1. **Converter** - Parses TypeScript test files and converts them to JSON
|
|
2. **Migrator** - Batch discovers and migrates all test files
|
|
3. **Validator** - Validates JSON test files against the schema
|
|
|
|
## Architecture
|
|
|
|
```
|
|
TypeScript .test.ts files
|
|
↓
|
|
[Converter] ← Uses TypeScript AST to parse test structure
|
|
↓
|
|
JSON test definitions
|
|
↓
|
|
[Validator] ← Ensures JSON conforms to schema
|
|
↓
|
|
/packages/*/unit-tests/tests.json
|
|
↓
|
|
[Unified Test Runner] ← Discovers and executes
|
|
```
|
|
|
|
## Usage
|
|
|
|
### 1. Dry-Run Migration (Safe Preview)
|
|
|
|
```bash
|
|
# Preview what would be converted
|
|
npm --prefix scripts/migrate-tests run migrate -- --dry-run --verbose
|
|
|
|
# Or directly:
|
|
npx ts-node scripts/migrate-tests/migrator.ts --dry-run --verbose
|
|
```
|
|
|
|
### 2. Actual Migration
|
|
|
|
```bash
|
|
# Migrate all discovered .test.ts files
|
|
npm --prefix scripts/migrate-tests run migrate
|
|
|
|
# Or directly:
|
|
npx ts-node scripts/migrate-tests/migrator.ts
|
|
```
|
|
|
|
### 3. Validate Converted Tests
|
|
|
|
```bash
|
|
# Validate all JSON test files in packages
|
|
npm --prefix scripts/migrate-tests run validate
|
|
|
|
# Or directly:
|
|
npx ts-node scripts/migrate-tests/validator.ts packages
|
|
|
|
# Validate specific directory:
|
|
npx ts-node scripts/migrate-tests/validator.ts packages/my_package
|
|
```
|
|
|
|
## How It Works
|
|
|
|
### Conversion Process
|
|
|
|
The converter uses TypeScript's AST (Abstract Syntax Tree) to understand test structure:
|
|
|
|
1. **Parse imports** - Extract all import statements into `imports` array
|
|
2. **Extract test suites** - Find all `describe()` blocks
|
|
3. **Parse tests** - Extract `it()` blocks within suites
|
|
4. **Parse assertions** - Extract `expect()` calls and map matchers to JSON types
|
|
5. **Build JSON** - Construct JSON test definition with $schema, package, imports, testSuites
|
|
|
|
### Matcher Mapping
|
|
|
|
The converter maps 30+ Vitest/Jest matchers to JSON assertion types:
|
|
|
|
| TypeScript Matcher | JSON Type | Example |
|
|
|-------------------|-----------|---------|
|
|
| `toBe()` | `equals` | Strict equality |
|
|
| `toEqual()` | `deepEquals` | Deep object equality |
|
|
| `toBeGreaterThan()` | `greaterThan` | Numeric comparison |
|
|
| `toContain()` | `contains` | String/array contains |
|
|
| `toThrow()` | `throws` | Exception handling |
|
|
| `toBeVisible()` | `toBeVisible` | DOM assertion |
|
|
| `toHaveClass()` | `toHaveClass` | DOM assertion |
|
|
| ... and 24 more | ... | ... |
|
|
|
|
### Package Name Mapping
|
|
|
|
Tests are placed in the appropriate package directory:
|
|
|
|
- `frontends/nextjs/*.test.ts` → `packages/nextjs_frontend/unit-tests/tests.json`
|
|
- `frontends/cli/*.test.ts` → `packages/cli_frontend/unit-tests/tests.json`
|
|
- `frontends/qt6/*.test.ts` → `packages/qt6_frontend/unit-tests/tests.json`
|
|
- Others → `packages/[extracted_name]/unit-tests/tests.json`
|
|
|
|
## JSON Test Format
|
|
|
|
### Basic Structure
|
|
|
|
```json
|
|
{
|
|
"$schema": "https://metabuilder.dev/schemas/tests.schema.json",
|
|
"schemaVersion": "2.0.0",
|
|
"package": "my_package",
|
|
"imports": [
|
|
{ "from": "@/lib/utils", "items": ["validateEmail"] }
|
|
],
|
|
"testSuites": [
|
|
{
|
|
"id": "suite_validate",
|
|
"name": "Email Validation",
|
|
"tests": [
|
|
{
|
|
"id": "test_valid_email",
|
|
"name": "should accept valid email",
|
|
"arrange": {
|
|
"fixtures": { "email": "user@example.com" }
|
|
},
|
|
"act": {
|
|
"type": "function_call",
|
|
"target": "validateEmail",
|
|
"input": "$arrange.fixtures.email"
|
|
},
|
|
"assert": {
|
|
"expectations": [
|
|
{
|
|
"type": "truthy",
|
|
"actual": "result",
|
|
"message": "Should return true for valid email"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### Supported Actions (Act Phase)
|
|
|
|
- `function_call` - Call an imported function
|
|
- `render` - Render React component (requires React Testing Library)
|
|
- `click` - Simulate click event
|
|
- `fill` - Fill form input
|
|
- `select` - Select dropdown option
|
|
- `hover` - Hover over element
|
|
- `focus` - Focus on element
|
|
- `blur` - Blur from element
|
|
- `waitFor` - Wait for condition
|
|
|
|
### Supported Assertions
|
|
|
|
**Basic**: equals, deepEquals, notEquals, truthy, falsy
|
|
|
|
**Numeric**: greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual
|
|
|
|
**Type**: null, notNull, undefined, notUndefined, instanceOf
|
|
|
|
**Collection**: contains, matches, hasProperty, hasLength
|
|
|
|
**DOM**: toBeVisible, toBeInTheDocument, toHaveTextContent, toHaveAttribute, toHaveClass, toBeDisabled, toBeEnabled, toHaveValue
|
|
|
|
**Control**: throws, notThrows, custom
|
|
|
|
## Configuration
|
|
|
|
### Converter Options
|
|
|
|
```typescript
|
|
interface ConversionResult {
|
|
success: boolean;
|
|
jsonContent?: any; // The generated JSON
|
|
warnings: string[]; // Non-fatal issues
|
|
errors: string[]; // Fatal errors
|
|
}
|
|
```
|
|
|
|
### Migrator Options
|
|
|
|
```typescript
|
|
interface MigrationConfig {
|
|
dryRun?: boolean; // Preview only, don't write
|
|
verbose?: boolean; // Detailed logging
|
|
pattern?: string; // Glob pattern (default: 'frontends/**/*.test.ts')
|
|
targetDir?: string; // Output directory (default: 'packages')
|
|
}
|
|
```
|
|
|
|
### CLI Flags
|
|
|
|
```bash
|
|
# Dry run (preview)
|
|
--dry-run
|
|
|
|
# Verbose logging
|
|
--verbose
|
|
|
|
# Custom glob pattern
|
|
--pattern 'src/**/*.test.ts'
|
|
|
|
# Custom target directory
|
|
--target-dir 'my-packages'
|
|
```
|
|
|
|
## Limitations & Fallbacks
|
|
|
|
### Known Limitations
|
|
|
|
1. **Complex Mocking** - Tests with advanced mock setup (spies, call tracking) may not convert perfectly
|
|
2. **Custom Hooks** - Tests with custom React hooks require manual adjustment
|
|
3. **Snapshots** - Snapshot tests require manual conversion
|
|
4. **Dynamic Imports** - Dynamic require() calls may not be captured
|
|
5. **Conditional Logic** - Complex conditional test logic may be simplified
|
|
|
|
### Handling Lossy Conversion
|
|
|
|
For tests that don't convert perfectly:
|
|
|
|
1. Run converter with `--verbose` to see warnings
|
|
2. Review warnings in output
|
|
3. Manually adjust the generated JSON as needed
|
|
4. Validate with validator tool
|
|
|
|
The 80/20 rule applies: ~80% of tests convert cleanly, ~20% need manual adjustment.
|
|
|
|
## Workflow
|
|
|
|
### Recommended Workflow
|
|
|
|
1. **Backup** - Commit current state before migration
|
|
```bash
|
|
git add .
|
|
git commit -m "backup: before test migration"
|
|
```
|
|
|
|
2. **Dry Run** - Preview what will happen
|
|
```bash
|
|
npx ts-node scripts/migrate-tests/migrator.ts --dry-run --verbose
|
|
```
|
|
|
|
3. **Migrate** - Run actual migration
|
|
```bash
|
|
npx ts-node scripts/migrate-tests/migrator.ts --verbose
|
|
```
|
|
|
|
4. **Validate** - Ensure JSON is valid
|
|
```bash
|
|
npx ts-node scripts/migrate-tests/validator.ts packages
|
|
```
|
|
|
|
5. **Test** - Run unified test runner
|
|
```bash
|
|
npm run test:unified
|
|
```
|
|
|
|
6. **Commit** - Save migration results
|
|
```bash
|
|
git add packages/*/unit-tests/
|
|
git commit -m "feat: migrate TypeScript tests to JSON format"
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Example 1: Simple Function Test
|
|
|
|
**TypeScript:**
|
|
```typescript
|
|
describe('Email Validation', () => {
|
|
it('should accept valid email', () => {
|
|
const result = validateEmail('user@example.com');
|
|
expect(result).toBe(true);
|
|
});
|
|
});
|
|
```
|
|
|
|
**JSON (Converted):**
|
|
```json
|
|
{
|
|
"testSuites": [{
|
|
"name": "Email Validation",
|
|
"tests": [{
|
|
"name": "should accept valid email",
|
|
"act": {
|
|
"type": "function_call",
|
|
"target": "validateEmail",
|
|
"input": "user@example.com"
|
|
},
|
|
"assert": {
|
|
"expectations": [{
|
|
"type": "equals",
|
|
"expected": true
|
|
}]
|
|
}
|
|
}]
|
|
}]
|
|
}
|
|
```
|
|
|
|
### Example 2: Test with Fixtures
|
|
|
|
**TypeScript:**
|
|
```typescript
|
|
it('should validate email from fixture', () => {
|
|
const email = 'test@example.com';
|
|
const result = validateEmail(email);
|
|
expect(result).toBe(true);
|
|
});
|
|
```
|
|
|
|
**JSON (Converted):**
|
|
```json
|
|
{
|
|
"arrange": {
|
|
"fixtures": { "email": "test@example.com" }
|
|
},
|
|
"act": {
|
|
"type": "function_call",
|
|
"target": "validateEmail",
|
|
"input": "$arrange.fixtures.email"
|
|
},
|
|
"assert": {
|
|
"expectations": [{
|
|
"type": "equals",
|
|
"expected": true
|
|
}]
|
|
}
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Issue: "Schema not found"
|
|
**Solution**: Ensure `schemas/package-schemas/tests_schema.json` exists
|
|
|
|
### Issue: "No test files found"
|
|
**Solution**: Check glob pattern matches your test files
|
|
```bash
|
|
# Verify pattern:
|
|
npx ts-node scripts/migrate-tests/migrator.ts --verbose
|
|
```
|
|
|
|
### Issue: "Package directory not created"
|
|
**Solution**: Ensure output directory exists and is writable
|
|
```bash
|
|
mkdir -p packages/my_package/unit-tests
|
|
```
|
|
|
|
### Issue: "Validation errors after conversion"
|
|
**Solution**: Review warnings and adjust JSON manually as needed
|
|
|
|
## Files
|
|
|
|
- `converter.ts` - Main conversion logic (350+ lines)
|
|
- `migrator.ts` - Batch migration orchestration (250+ lines)
|
|
- `validator.ts` - JSON validation against schema (300+ lines)
|
|
- `index.ts` - Export module
|
|
- `README.md` - This file
|
|
|
|
## Integration with Unified Test Runner
|
|
|
|
After migration, tests are automatically discovered by the unified test runner:
|
|
|
|
```typescript
|
|
import { UnifiedTestRunner } from '@/e2e/test-runner';
|
|
|
|
const runner = new UnifiedTestRunner();
|
|
const tests = await runner.discoverTests();
|
|
// Discovers: unit tests from packages/*/unit-tests/tests.json
|
|
```
|
|
|
|
## Next Steps
|
|
|
|
1. Run migration on existing TypeScript tests
|
|
2. Validate all converted JSON
|
|
3. Run unified test runner to execute tests
|
|
4. Document any manual adjustments needed
|
|
5. Update testing guidelines to use JSON format for new tests
|