home / skills / autumnsgrove / groveengine / javascript-testing

javascript-testing skill

/.claude/skills/javascript-testing

This skill helps you write and run JavaScript/TypeScript tests with Vitest or Jest, including mocks, component tests, and coverage.

npx playbooks add skill autumnsgrove/groveengine --skill javascript-testing

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
4.6 KB
---
name: javascript-testing
description: Write and run JavaScript/TypeScript tests using Vitest or Jest with mocking, component testing, and coverage. Use when writing JS/TS tests, testing Svelte/React components, or setting up test configuration.
---

# JavaScript/TypeScript Testing Skill

## When to Activate

Activate this skill when:
- Writing JavaScript or TypeScript tests
- Testing Svelte, React, or Vue components
- Setting up Vitest or Jest configuration
- Working with mocks, spies, or test utilities
- Running tests or checking coverage

## Framework Selection

| Use Case | Framework |
|----------|-----------|
| SvelteKit, Vite projects | **Vitest** (recommended) |
| Non-Vite projects, React Native | **Jest** |

## Quick Commands

### Vitest
```bash
npx vitest              # Watch mode
npx vitest run          # Single run (CI)
npx vitest run --coverage
npx vitest --ui         # Visual UI
```

### Jest
```bash
pnpm test
pnpm test --watch
pnpm test --coverage
```

## Test Structure: AAA Pattern

```typescript
import { describe, it, expect, beforeEach } from 'vitest';

describe('UserService', () => {
    let userService: UserService;

    beforeEach(() => {
        userService = new UserService();
    });

    it('should create a new user with valid data', () => {
        // Arrange
        const email = '[email protected]';
        const password = 'secure_pass123';

        // Act
        const result = userService.register(email, password);

        // Assert
        expect(result.success).toBe(true);
        expect(result.user.email).toBe(email);
    });
});
```

## Vitest Setup (SvelteKit)

```typescript
// vite.config.ts
import { defineConfig } from 'vitest/config';
import { sveltekit } from '@sveltejs/kit/vite';

export default defineConfig({
    plugins: [sveltekit()],
    test: {
        include: ['src/**/*.{test,spec}.{js,ts}'],
        globals: true,
        environment: 'jsdom',
        setupFiles: ['./src/tests/setup.ts'],
    }
});
```

## Mocking

### Vitest
```typescript
import { vi } from 'vitest';

vi.mock('./api', () => ({
    fetchUser: vi.fn()
}));

vi.mocked(fetchUser).mockResolvedValue({ id: 1, name: 'John' });
```

### Jest
```typescript
jest.mock('./api', () => ({
    fetchUser: jest.fn()
}));
```

## Component Testing (Svelte)

```typescript
import { render, screen, fireEvent } from '@testing-library/svelte';
import Counter from './Counter.svelte';

it('should increment count on click', async () => {
    render(Counter, { props: { initialCount: 0 } });

    const button = screen.getByRole('button', { name: /increment/i });
    await fireEvent.click(button);

    expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
```

## Common Assertions

```typescript
// Equality
expect(value).toBe(expected);           // Strict ===
expect(value).toEqual(expected);        // Deep equality

// Truthiness
expect(value).toBeTruthy();
expect(value).toBeNull();

// Arrays/Objects
expect(array).toContain(item);
expect(obj).toHaveProperty('key');

// Exceptions
expect(() => fn()).toThrow('error');

// Async
await expect(promise).resolves.toBe(value);
await expect(promise).rejects.toThrow();
```

## Query Priority (Testing Library)

1. `getByRole` - Accessible queries (best)
2. `getByLabelText` - Form fields
3. `getByPlaceholderText` - Inputs
4. `getByText` - Non-interactive elements
5. `getByTestId` - Last resort

## Directory Structure

```
src/
├── lib/
│   ├── components/
│   │   ├── Button.svelte
│   │   └── Button.test.ts
│   └── utils/
│       ├── format.ts
│       └── format.test.ts
└── tests/
    ├── setup.ts
    └── integration/
```

## SvelteKit Testing

### Load Functions
```typescript
import { load } from './+page.server';

it('should fetch posts', async () => {
    const mockFetch = vi.fn().mockResolvedValue({
        json: () => Promise.resolve([{ id: 1 }])
    });

    const result = await load({ fetch: mockFetch } as any);
    expect(result.posts).toHaveLength(1);
});
```

### Form Actions
```typescript
import { actions } from './+page.server';

it('should validate login', async () => {
    const formData = new FormData();
    formData.set('email', '[email protected]');

    const request = new Request('http://localhost', {
        method: 'POST',
        body: formData
    });

    const result = await actions.default({ request } as any);
    expect(result.success).toBe(true);
});
```

## Related Resources

See `AgentUsage/testing_javascript.md` for complete documentation including:
- Jest configuration
- Async testing patterns
- SvelteKit-specific patterns
- CI/CD integration

Overview

This skill helps you write and run JavaScript and TypeScript tests using Vitest or Jest, with built-in support for mocking, component testing, and coverage reporting. It targets web apps and Svelte/React components and includes patterns for load functions and form actions in SvelteKit. Use it to create reliable unit, integration, and component tests and to configure test runners for local development or CI.

How this skill works

The skill provides ready-to-use configurations and idiomatic examples for Vitest (recommended for Vite/SvelteKit projects) and Jest (for non-Vite projects or React Native). It demonstrates Arrange-Act-Assert test structure, Testing Library queries and priorities, mocking approaches (vi/jest), and component testing with @testing-library. It also shows commands for running tests locally, in watch mode, and in CI with coverage.

When to use it

  • Writing unit or integration tests in TypeScript or JavaScript
  • Testing Svelte, React, or Vue components and DOM interactions
  • Setting up Vitest or Jest configuration for a project
  • Creating mocks, spies, or stubs for external modules or network calls
  • Running test suites and collecting coverage for CI pipelines

Best practices

  • Prefer Vitest for Vite and SvelteKit projects; use Jest where Vitest isn’t available
  • Follow the AAA pattern: Arrange, Act, Assert for clear, maintainable tests
  • Favor accessible queries (getByRole, getByLabelText) over test ids when using Testing Library
  • Mock only external dependencies; keep unit tests focused and fast
  • Add a test setup file for shared globals and environment configuration (jsdom, setupFiles)

Example use cases

  • Unit test a service class with dependency mocks using vi.mock or jest.mock
  • Component test a Svelte button: render, fireEvent, and assert DOM changes
  • Test SvelteKit load functions by injecting a mocked fetch implementation
  • Validate form action logic by constructing Request with FormData and asserting result
  • Run npx vitest run --coverage or pnpm test --coverage in CI to gate code coverage

FAQ

Which runner should I pick for a SvelteKit project?

Use Vitest for SvelteKit and Vite projects because it integrates with the tooling and supports jsdom and fast runs.

How do I mock a network call in tests?

Mock the module that performs the fetch using vi.mock or jest.mock, then set the mock to resolve the desired value with vi.mocked(...).mockResolvedValue(...).