Files
ISA-Frontend/.claude/skills/test-migration-specialist/SKILL.md
Lorenz Hilpert 89b3d9aa60 Merged PR 2000: open tasks
Related work items: #5309
2025-11-06 10:01:41 +00:00

10 KiB

name, description
name description
test-migration-specialist This skill should be used when migrating Angular libraries from Jest + Spectator to Vitest + Angular Testing Utilities. It handles test configuration updates, test file refactoring, mock pattern conversion, and validation. Use this skill when the user requests test framework migration, specifically for the 40 remaining Jest-based libraries in the ISA-Frontend monorepo.

Test Migration Specialist

Overview

Automate the migration of Angular library tests from Jest + Spectator to Vitest + Angular Testing Utilities. This skill handles the complete migration workflow including configuration updates, test file refactoring, dependency management, and validation.

Current Migration Status: 40 libraries use Jest (65.6%), 21 libraries use Vitest (34.4%)

When to Use This Skill

Invoke this skill when:

  • User requests test migration for a specific library
  • User mentions "migrate tests" or "Jest to Vitest"
  • User wants to update test framework for a library
  • User references the 40 remaining libraries to migrate

Migration Workflow

Step 1: Pre-Migration Analysis

Before making any changes, analyze the current state:

  1. Read Testing Guidelines

    • Use docs-researcher agent to read docs/guidelines/testing.md
    • Understand migration patterns and best practices
    • Note JUnit and Cobertura configuration requirements
  2. Analyze Library Structure

    • Read libs/[path]/project.json to identify current test executor
    • Count test files using Glob: **/*.spec.ts
    • Scan for Spectator usage patterns using Grep: createComponentFactory|createServiceFactory|Spectator
    • Identify complex mocking scenarios (ng-mocks, jest.mock patterns)
  3. Determine Library Depth

    • Calculate directory levels from workspace root
    • This affects relative paths in vite.config.mts (../../../ vs ../../../../)

Step 2: Update Test Configuration

Update the library's test configuration to use Vitest:

  1. Update project.json Replace Jest executor with Vitest:

    {
      "test": {
        "executor": "@nx/vite:test",
        "options": {
          "configFile": "vite.config.mts"
        }
      }
    }
    
  2. Create vite.config.mts Create configuration with JUnit and Cobertura reporters:

    /// <reference types='vitest' />
    import { defineConfig } from 'vite';
    import angular from '@analogjs/vite-plugin-angular';
    import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
    import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin';
    
    export default
    // @ts-expect-error - Vitest reporter tuple types have complex inference issues
    defineConfig(() => ({
      root: __dirname,
      cacheDir: '../../../node_modules/.vite/libs/[path]',
      plugins: [angular(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])],
      test: {
        watch: false,
        globals: true,
        environment: 'jsdom',
        include: ['{src,tests}/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
        setupFiles: ['src/test-setup.ts'],
        reporters: [
          'default',
          ['junit', { outputFile: '../../../testresults/junit-[library-name].xml' }],
        ],
        coverage: {
          reportsDirectory: '../../../coverage/libs/[path]',
          provider: 'v8' as const,
          reporter: ['text', 'cobertura'],
        },
      },
    }));
    

    Critical: Adjust ../../../ depth based on library location

Step 3: Migrate Test Files

For each .spec.ts file, perform these conversions:

  1. Update Imports

    // REMOVE
    import { createComponentFactory, Spectator } from '@ngneat/spectator/jest';
    
    // ADD
    import { ComponentFixture, TestBed } from '@angular/core/testing';
    import { describe, it, expect, beforeEach } from 'vitest';
    
  2. Convert Component Tests

    // OLD (Spectator)
    const createComponent = createComponentFactory({
      component: MyComponent,
      imports: [CommonModule],
      mocks: [MyService]
    });
    
    let spectator: Spectator<MyComponent>;
    beforeEach(() => spectator = createComponent());
    
    it('should display title', () => {
      spectator.setInput('title', 'Test');
      expect(spectator.query('h1')).toHaveText('Test');
    });
    
    // NEW (Angular Testing Utilities)
    describe('MyComponent', () => {
      let fixture: ComponentFixture<MyComponent>;
      let component: MyComponent;
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          imports: [MyComponent, CommonModule],
          providers: [{ provide: MyService, useValue: mockService }]
        }).compileComponents();
    
        fixture = TestBed.createComponent(MyComponent);
        component = fixture.componentInstance;
      });
    
      it('should display title', () => {
        component.title = 'Test';
        fixture.detectChanges();
        expect(fixture.nativeElement.querySelector('h1').textContent).toContain('Test');
      });
    });
    
  3. Convert Service Tests

    // OLD (Spectator)
    const createService = createServiceFactory({
      service: MyService,
      mocks: [HttpClient]
    });
    
    // NEW (Angular Testing Utilities)
    describe('MyService', () => {
      let service: MyService;
      let httpMock: HttpTestingController;
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          imports: [HttpClientTestingModule],
          providers: [MyService]
        });
    
        service = TestBed.inject(MyService);
        httpMock = TestBed.inject(HttpTestingController);
      });
    
      afterEach(() => {
        httpMock.verify();
      });
    });
    
  4. Update Mock Patterns

    • Replace jest.fn()vi.fn()
    • Replace jest.spyOn()vi.spyOn()
    • Replace jest.mock()vi.mock()
    • For complex mocks, use ng-mocks library if needed
  5. Update Matchers

    • Replace Spectator matchers (toHaveText, toExist) with standard Jest/Vitest matchers
    • Use expect().toBeTruthy(), expect().toContain(), etc.

Step 4: Verify E2E Attributes

Check component templates for E2E testing attributes:

  1. Scan Templates Use Grep to find templates: **/*.html

  2. Validate Attributes Ensure interactive elements have:

    • data-what: Semantic description (e.g., "submit-button")
    • data-which: Unique identifier (e.g., "form-primary")
    • Dynamic data-* for list items: [attr.data-item-id]="item.id"
  3. Add Missing Attributes If missing, add them to components. See dev:add-e2e-attrs command or use that skill.

Step 5: Run Tests and Validate

Execute tests to verify migration:

  1. Run Tests

    npx nx test [library-name] --skip-nx-cache
    
  2. Run with Coverage

    npx nx test [library-name] --coverage.enabled=true --skip-nx-cache
    
  3. Verify Output Files Check that CI/CD integration files are created:

    • JUnit XML: testresults/junit-[library-name].xml
    • Cobertura XML: coverage/libs/[path]/cobertura-coverage.xml
  4. Address Failures If tests fail:

    • Review test conversion (common issues: missing fixture.detectChanges(), incorrect selectors)
    • Check mock configurations
    • Verify imports are correct
    • Ensure async tests use proper patterns

Step 6: Clean Up

Remove legacy configurations:

  1. Remove Jest Files

    • Delete jest.config.ts or jest.config.js if present
    • Remove Jest-specific setup files
  2. Update Dependencies

    • Note if Spectator can be removed (check if other libs still use it)
    • Note if Jest can be removed (check if other libs still use it)
    • Don't actually remove from package.json unless all libs migrated
  3. Update Documentation Update library README.md with new test commands:

    ## Testing
    
    This library uses Vitest + Angular Testing Utilities.
    
    ```bash
    # Run tests
    npx nx test [library-name] --skip-nx-cache
    
    # Run with coverage
    npx nx test [library-name] --coverage.enabled=true --skip-nx-cache
    
    
    

Step 7: Generate Migration Report

Provide comprehensive migration summary:

Test Migration Complete
=======================

Library: [library-name]
Framework: Jest + Spectator → Vitest + Angular Testing Utilities

📊 Migration Statistics
-----------------------
Test files migrated: XX
Component tests: XX
Service tests: XX
Total test cases: XX

✅ Test Results
---------------
Passing: XX/XX (100%)
Coverage: XX%

📝 Configuration
----------------
- project.json: ✅ Updated to @nx/vite:test
- vite.config.mts: ✅ Created with JUnit + Cobertura
- E2E attributes: ✅ Validated

📁 CI/CD Integration
--------------------
- JUnit XML: ✅ testresults/junit-[name].xml
- Cobertura XML: ✅ coverage/libs/[path]/cobertura-coverage.xml

🧹 Cleanup
----------
- Jest config removed: ✅
- README updated: ✅

💡 Next Steps
-------------
1. Verify tests in CI/CD pipeline
2. Monitor for any edge cases
3. Consider migrating related libraries

📚 Remaining Libraries
----------------------
Jest libraries remaining: XX/40
Progress: XX% complete

Error Handling

Common Migration Issues

Issue 1: Tests fail after migration

  • Check fixture.detectChanges() is called after setting inputs
  • Verify async tests use async/await properly
  • Check component imports are correct (standalone components)

Issue 2: Mocks not working

  • Verify vi.fn() syntax is correct
  • Check providers array in TestBed configuration
  • For complex mocks, consider using ng-mocks

Issue 3: Coverage files not generated

  • Verify path depth in vite.config.mts matches library location
  • Check reporters array includes 'cobertura'
  • Ensure provider: 'v8' is set

Issue 4: Type errors in vite.config.mts

  • Add // @ts-expect-error comment before defineConfig()
  • This is expected due to Vitest reporter type complexity

References

Use docs-researcher agent to access:

  • docs/guidelines/testing.md - Comprehensive migration guide with examples
  • CLAUDE.md - Testing Framework section for project conventions

Key Documentation Sections:

  • Vitest Configuration with JUnit and Cobertura
  • Angular Testing Utilities examples
  • Migration patterns and best practices
  • E2E attribute requirements