Testing Dial Annotations
This guide covers testing strategies for Dial annotations, running the dial-cli test suite, and contributing to dial-cli development.
Testing Your Dial Annotations
1. Validate Generated Schemas
After annotating your components, validate the generated schemas:
# Generate with verbose output for inspection
dial-cli --verbose MyComponent.tsx
# Check the generated files
cat metadata/schema.dial | jq '.'
2. Common Validation Checks
Check Property Types
Ensure properties have the correct dtype:
{
"name": "position",
"dtype": "vector3", // Should match your annotation
"value": [0, 0, 0]
}
Verify Constraints
Check min/max/step values are applied:
{
"name": "opacity",
"dtype": "number",
"min": 0,
"max": 1,
"step": 0.01
}
Validate Grouping
Ensure properties are correctly grouped:
{
"name": "rotation",
"dtype": "euler",
"tags": {
"grouping": "transform"
}
}
3. Test Type Inheritance
When using interface inheritance or type intersections:
# Generate schema for inherited types
dial-cli --verbose ExtendedComponent.tsx
# Verify all parent properties are included
jq '.[] | select(.component == "ExtendedComponent") | .schemas[].name' \
metadata/schema.dial
4. Automated Testing
Create a test script to validate your schemas:
// test-dial-schemas.js
const fs = require('fs');
const schema = require('./metadata/schema.dial');
describe('Dial Schemas', () => {
test('should have required properties', () => {
const component = schema.find(c => c.component === 'MyComponent');
expect(component).toBeDefined();
const propNames = component.schemas.map(s => s.name);
expect(propNames).toContain('position');
expect(propNames).toContain('rotation');
expect(propNames).toContain('scale');
});
test('should have correct types', () => {
const component = schema.find(c => c.component === 'MyComponent');
const position = component.schemas.find(s => s.name === 'position');
expect(position.dtype).toBe('vector3');
expect(position.value).toHaveLength(3);
});
test('should inherit group configurations', () => {
const component = schema.find(c => c.component === 'AnimatedBox');
const duration = component.schemas.find(s => s.name === 'duration');
expect(duration.tags?.noWrap).toBe(true);
});
});
Running Dial CLI Tests
The dial-cli package includes a comprehensive test suite for validation.
Prerequisites
# Navigate to dial-cli directory
cd packages/vuer-uikit/dial-cli
# Install dependencies
pnpm install
# Build the CLI
pnpm build
Running Tests
# Run all tests
pnpm test
# Run tests in watch mode for development
pnpm test:watch
# Run tests with coverage
pnpm test:coverage
Test Output
Successful test run shows:
PASS spec/inheritance.test.ts
dial-cli inheritance tests
Interface Inheritance
✓ should resolve properties from extended interfaces
✓ should handle deep inheritance chains
Type Inheritance
✓ should resolve properties from type intersections
✓ should handle utility types (Pick, Omit, Partial)
Mixed Inheritance
✓ should handle interface extending type
✓ should handle type intersecting interface
Group configurations
✓ should inherit group-level @dial-no-wrap
dial-cli remove functionality
✓ should remove specific component metadata
✓ should remove all metadata files
Test Suites: 1 passed, 1 total
Tests: 9 passed, 9 total
Contributing to Dial CLI
Development Setup
- Fork and Clone
git clone https://github.com/your-username/vuer-uikit.git
cd vuer-uikit/packages/vuer-uikit/dial-cli
- Install Dependencies
pnpm install
- Start Development Mode
pnpm dev
# This watches for changes and rebuilds automatically
Writing New Tests
Tests are located in the spec/ directory:
spec/
├── inheritance.test.ts # Main test suite
├── fixtures/ # Test TypeScript files
│ ├── InterfaceInheritance.tsx
│ ├── TypeInheritance.tsx
│ └── MixedInheritance.tsx
└── outputs/ # Expected outputs for comparison
Adding a Test Case
// spec/inheritance.test.ts
test('should handle new feature', () => {
const fixture = join(FIXTURES_DIR, 'NewFeature.tsx');
// Generate schema
execSync(`node "${DIAL_CLI}" --verbose --output "${OUTPUT_DIR}" "${fixture}"`);
// Read and validate
const schemaPath = join(OUTPUT_DIR, 'schema.dial');
const schemas = JSON.parse(readFileSync(schemaPath, 'utf-8'));
// Assertions
expect(schemas).toBeDefined();
expect(schemas[0].component).toBe('NewFeature');
});
Creating Test Fixtures
// spec/fixtures/NewFeature.tsx
import React from 'react';
/**
* Test component for new feature
* @dial config @dial-new-feature
*/
interface NewFeatureProps {
/**
* Test property
* @dial config
* @dial-dtype string
* @dial-new-annotation value
*/
testProp: string;
}
export const NewFeature: React.FC<NewFeatureProps> = ({ testProp }) => {
return <div>{testProp}</div>;
};
Running Tests During Development
# Run specific test file
pnpm test inheritance.test.ts
# Run tests matching pattern
pnpm test -- --testNamePattern="type intersection"
# Run with debugging
NODE_OPTIONS="--inspect" pnpm test
Debugging Tips
- Use Verbose Output
dial-cli --verbose TestComponent.tsx
# Check all generated files for debugging
- Inspect AST Add debug logging to see TypeScript AST:
console.log('AST Node:', node.kind, node.getText());
- Test Individual Components
# Test a specific fixture
node dist/dial-cli.js --verbose spec/fixtures/TypeInheritance.tsx
Common Issues and Solutions
Issue: Properties Not Appearing in Schema
Cause: Missing @dial annotation
Solution: Ensure property has at least one @dial tag
// Won't appear in schema
/** Just a comment */
prop: string;
// Will appear in schema
/** @dial control */
prop: string;
Issue: Type Inheritance Not Working
Cause: Types not properly exported or resolved Solution: Ensure all types are exported and accessible
// Export types for proper resolution
export type BaseType = { ... };
export interface ExtendedInterface extends BaseType { ... }
Issue: Group Configuration Not Applied
Cause: Group-level annotations at wrong position Solution: Place group annotations in interface/type JSDoc
/**
* @dial transform @dial-no-wrap // Correct position
*/
interface Props {
// Properties here inherit the configuration
}
Next Steps
- Review Type Inheritance patterns
- Check CLI Reference for all options
- See Examples for real-world usage
- Read Troubleshooting for common issues