Skip to content
Back to skills

Typescript Testing

ASecurity

TypeScript testing patterns with Jest/Vitest including unit tests, integration tests, mocking strategies, and coverage. Use when writing TypeScript tests.

  • 8 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 1, 2026
ai-agentstypescriptreactexpresstestingapidatabase

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 1, 2026

npx -y skills add DmitriyYukhanov/claude-plugins --skill typescript-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Typescript Testing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Typescript Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dmitriyyukhanov-typescript-testing/badge)](https://www.skillsdirectory.com/skills/dmitriyyukhanov-typescript-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: typescript-testing
description: TypeScript testing patterns with Jest/Vitest including unit tests, integration tests, mocking strategies, and coverage. Use when writing TypeScript tests.
---

# TypeScript Testing Skill

You are a testing specialist for TypeScript projects.

## Testing Frameworks

### Framework Detection
- `jest.config.*` or `"jest"` in package.json → Jest
- `vitest.config.*` or `"vitest"` in package.json → Vitest
- `cypress.config.*` → Cypress (E2E)
- `playwright.config.*` → Playwright (E2E)
- If both Jest and Vitest are present, follow the scripts used by CI and existing test files in the target package

## Test Distribution

- **~75% Unit Tests**: Fast, isolated, fully mocked
- **~20% Integration Tests**: Module interactions, API contracts
- **~5% E2E Tests**: Full user flows (Cypress/Playwright)

## Unit Test Patterns

Examples below use Jest APIs. For Vitest, replace `jest` with `vi` and import helpers from `vitest`.

### Arrange-Act-Assert
```typescript
describe('UserService', () => {
  let sut: UserService;
  let mockRepository: jest.Mocked<IUserRepository>;

  beforeEach(() => {
    mockRepository = {
      findById: jest.fn(),
      save: jest.fn(),
    };
    sut = new UserService(mockRepository);
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('getUser', () => {
    it('should return user when found', async () => {
      // Arrange
      const expectedUser = { id: '1', name: 'Test' };
      mockRepository.findById.mockResolvedValue(expectedUser);

      // Act
      const result = await sut.getUser('1');

      // Assert
      expect(result).toEqual(expectedUser);
      expect(mockRepository.findById).toHaveBeenCalledWith('1');
    });

    it('should return null when user not found', async () => {
      // Arrange
      mockRepository.findById.mockResolvedValue(null);

      // Act
      const result = await sut.getUser('unknown');

      // Assert
      expect(result).toBeNull();
    });
  });
});
```

### Mocking Strategies

```typescript
// Mock modules
jest.mock('./database', () => ({
  getConnection: jest.fn().mockResolvedValue(mockConnection),
}));

// Mock implementations (include standard Response properties)
const mockData = { id: '1', name: 'Test' };
const mockFetch = jest.fn().mockImplementation((url: string) =>
  Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve(mockData) })
);

// Spy on methods
const spy = jest.spyOn(service, 'validate');
expect(spy).toHaveBeenCalledTimes(1);
```

## Integration Test Patterns

```typescript
describe('API Integration', () => {
  let app: Express;

  beforeAll(async () => {
    app = await createApp({ database: testDb });
  });

  afterAll(async () => {
    await testDb.close();
  });

  it('should create and retrieve user', async () => {
    const createResponse = await request(app)
      .post('/users')
      .send({ name: 'Test', email: 'test@example.com' })
      .expect(201);

    const getResponse = await request(app)
      .get(`/users/${createResponse.body.id}`)
      .expect(200);

    expect(getResponse.body.name).toBe('Test');
  });
});
```

## React Component Testing

```typescript
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

describe('Button', () => {
  it('should call onClick when clicked', async () => {
    const user = userEvent.setup();
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click me</Button>);

    await user.click(screen.getByText('Click me'));

    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('should be disabled when loading', () => {
    render(<Button isLoading>Submit</Button>);

    expect(screen.getByRole('button')).toBeDisabled();
  });
});
```

## Async Testing

```typescript
// Testing async functions
it('should handle async errors', async () => {
  mockApi.get.mockRejectedValue(new NetworkError('timeout'));

  await expect(service.fetchData('url')).rejects.toThrow(NetworkError);
});

// Testing timers (clean up in afterEach to prevent leaks on failure)
describe('debounce', () => {
  beforeEach(() => jest.useFakeTimers());
  afterEach(() => jest.useRealTimers());

  it('should debounce input', () => {
    const callback = jest.fn();

    debounce(callback, 300)('test');
    expect(callback).not.toHaveBeenCalled();

    jest.advanceTimersByTime(300);
    expect(callback).toHaveBeenCalledWith('test');
  });
});
```

## Vitest Equivalents

If using Vitest instead of Jest, the API is nearly identical:

| Jest | Vitest |
|------|--------|
| `jest.fn()` | `vi.fn()` |
| `jest.mock()` | `vi.mock()` |
| `jest.spyOn()` | `vi.spyOn()` |
| `jest.clearAllMocks()` | `vi.clearAllMocks()` |
| `jest.useFakeTimers()` | `vi.useFakeTimers()` |
| `jest.Mocked<T>` | `Mocked<T>` (from `vitest`) |

## Coverage Guidelines

- Enforce ≥80% coverage on critical business logic
- Don't chase 100% - focus on meaningful tests
- Never commit real `.env` files or API keys in tests
- Use test fixtures for complex data structures

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.