Skip to main content
Version: v1 (Current)

Testing Guide for Gx ComponentKit

This document provides comprehensive information about testing the Gx ComponentKit component library.

Testing Stack

  • Test Runner: Vitest - Fast unit test framework for Vite projects
  • Vue Testing: @vue/test-utils - Official Vue.js testing utilities
  • DOM Environment: happy-dom - Lightweight DOM implementation
  • Coverage: c8 - Native V8 code coverage
  • Mocking: Built-in Vitest mocking capabilities

Available Scripts

# Run all tests
npm test

# Run tests in watch mode
npm run test:watch

# Run tests once (CI mode)
npm run test:run

# Run tests with coverage report
npm run test:coverage

# Run tests with UI interface
npm run test:ui

Test Structure

Directory Layout

src/
├── components/
│ ├── __tests__/
│ │ ├── GxModal.test.ts
│ │ ├── GxCountdown.test.ts
│ │ ├── GxThemeWrapper.test.ts
│ │ └── GxPageStart.test.ts
│ └── ...
├── composables/
│ ├── __tests__/
│ │ ├── useMedia.test.ts
│ │ └── useErrors.test.ts
│ └── ...
└── test/
├── setup.ts # Global test setup
├── test-utils.ts # Testing utilities
└── basic.test.ts # Basic functionality tests

Test Categories

1. Component Tests

Test Vue components in isolation with proper props, events, and rendering.

Example: GxThemeWrapper

import { mount } from '@vue/test-utils'
import GxThemeWrapper from '../GxThemeWrapper.vue'

describe('GxThemeWrapper', () => {
it('applies theme colors correctly', () => {
const wrapper = mount(GxThemeWrapper, {
props: {
theme: {
background_color: '#ffffff',
text_color: '#333333'
}
}
})

const element = wrapper.element as HTMLElement
expect(element.style.backgroundColor).toBe('#ffffff')
expect(element.style.color).toBe('#333333')
})
})

2. Composable Tests

Test Vue composables for state management and business logic.

Example: useErrors

import { useErrors } from '../useErrors'

describe('useErrors', () => {
it('manages error state correctly', () => {
const errors = useErrors()

errors.addError('Test error')
expect(errors.errorMessages.value).toEqual(['Test error'])
expect(errors.hasErrors.value).toBe(true)

errors.clearErrors()
expect(errors.hasErrors.value).toBe(false)
})
})

3. Integration Tests

Test component interactions and complex workflows.

4. Utility Tests

Test helper functions and utilities.

Testing Patterns

1. Component Testing Patterns

Basic Rendering

it('renders correctly', () => {
const wrapper = mount(Component)
expect(wrapper.exists()).toBe(true)
})

Props Testing

it('accepts and uses props correctly', () => {
const wrapper = mount(Component, {
props: { title: 'Test Title' }
})
expect(wrapper.text()).toContain('Test Title')
})

Event Testing

it('emits events correctly', async () => {
const wrapper = mount(Component)
await wrapper.find('button').trigger('click')
expect(wrapper.emitted('click')).toBeTruthy()
})

Slot Testing

it('renders slot content', () => {
const wrapper = mount(Component, {
slots: {
default: '<div class="test-content">Slot Content</div>'
}
})
expect(wrapper.find('.test-content').exists()).toBe(true)
})

2. Async Testing Patterns

Timer Testing

import { vi } from 'vitest'

beforeEach(() => {
vi.useFakeTimers()
})

afterEach(() => {
vi.useRealTimers()
})

it('handles timers correctly', async () => {
const wrapper = mount(CountdownComponent, {
props: { duration: 5 }
})

vi.advanceTimersByTime(1000)
await wrapper.vm.$nextTick()

expect(wrapper.text()).toContain('4')
})

Promise Testing

it('handles async operations', async () => {
const mockPromise = Promise.resolve('result')
const wrapper = mount(Component)

await wrapper.vm.asyncMethod()
expect(wrapper.vm.result).toBe('result')
})

3. Mocking Patterns

API Mocking

import { vi } from 'vitest'

const mockApi = {
getData: vi.fn().mockResolvedValue({ data: 'test' })
}

vi.mock('@/api', () => ({
default: mockApi
}))

Browser API Mocking

// Mock getUserMedia for camera tests
Object.defineProperty(navigator, 'mediaDevices', {
writable: true,
value: {
getUserMedia: vi.fn().mockResolvedValue(mockStream)
}
})

Test Utilities

Custom Mount Helper

// src/test/test-utils.ts
export function mountWithProps(
component: Component,
additionalProps: Record<string, any> = {},
options: Record<string, any> = {}
) {
const defaultProps = {
theme: mockTheme,
pluginVars: mockPluginVars,
// ... other common props
}

return mount(component, {
props: { ...defaultProps, ...additionalProps },
...options,
})
}

Mock Data

export const mockTheme = {
background_color: '#ffffff',
text_color: '#333333',
primary_color: '#007bff',
}

export const mockPluginVars = {
primary_color: '#007bff',
projectId: 123,
apiBaseUrl: 'https://api.test.com',
}

Coverage Requirements

Target Coverage Levels

  • Statements: 90%+
  • Branches: 85%+
  • Functions: 90%+
  • Lines: 90%+

Coverage Reports

# Generate coverage report
npm run test:coverage

# View HTML coverage report
open coverage/index.html

Coverage Configuration

Coverage is configured in vitest.config.ts:

export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
exclude: [
'node_modules/',
'src/test/',
'**/*.d.ts',
'dist/',
],
thresholds: {
statements: 90,
branches: 85,
functions: 90,
lines: 90
}
},
},
})

Best Practices

1. Test Organization

  • Group related tests using describe blocks
  • Use descriptive test names that explain the expected behavior
  • Follow the AAA pattern: Arrange, Act, Assert

2. Test Independence

  • Each test should be independent and not rely on other tests
  • Use beforeEach and afterEach for setup and cleanup
  • Reset mocks between tests

3. Mock Strategy

  • Mock external dependencies (APIs, browser APIs)
  • Don't mock the code you're testing
  • Use realistic mock data

4. Async Testing

  • Always await async operations
  • Use fake timers for time-dependent tests
  • Handle promise rejections properly

5. Component Testing

  • Test behavior, not implementation details
  • Focus on user interactions and expected outcomes
  • Test edge cases and error conditions

Debugging Tests

Running Specific Tests

# Run specific test file
npm run test:run src/components/__tests__/GxModal.test.ts

# Run tests matching pattern
npm run test:run -- --grep "modal"

# Run tests in specific directory
npm run test:run src/components/__tests__/

Debug Mode

# Run tests with debug output
npm run test:run -- --reporter=verbose

# Run tests in watch mode for development
npm run test:watch

VS Code Integration

Add to .vscode/settings.json:

{
"vitest.enable": true,
"vitest.commandLine": "npm run test"
}

Continuous Integration

GitHub Actions Example

name: Tests
on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '18'
- run: npm ci
- run: npm run test:coverage
- uses: codecov/codecov-action@v3

Common Issues and Solutions

1. Component Not Rendering

Problem: Component wrapper is empty Solution: Check if all required props are provided

2. Async Test Failures

Problem: Tests fail intermittently Solution: Ensure proper awaiting of async operations

3. Mock Not Working

Problem: Mock functions not being called Solution: Verify mock is set up before component mount

4. Timer Tests Failing

Problem: Timer-based tests are flaky Solution: Use vi.useFakeTimers() and vi.advanceTimersByTime()

Contributing

When adding new components or features:

  1. Write tests alongside your code
  2. Aim for high test coverage
  3. Include both happy path and edge case tests
  4. Update this documentation if adding new testing patterns
  5. Run the full test suite before submitting PRs

Resources