Testing Dial Annotations

Testing Guide
dial-cliv0.0.22

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

  1. Fork and Clone
git clone https://github.com/your-username/vuer-uikit.git
cd vuer-uikit/packages/vuer-uikit/dial-cli
  1. Install Dependencies
pnpm install
  1. 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

  1. Use Verbose Output
dial-cli --verbose TestComponent.tsx
# Check all generated files for debugging
  1. Inspect AST Add debug logging to see TypeScript AST:
console.log('AST Node:', node.kind, node.getText());
  1. 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