# Typescript Component Testing

> TypeScript Component Testing Skill

- Skill: `agentient/typescript-component-testing` (Agent Skill)
- Install (CLI): `npx skillmds@latest add agentient/typescript-component-testing`
- Raw SKILL.md: https://api.skillmd.com/api/skills/agentient/typescript-component-testing/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: Agentient (https://skillmd.com/u/agentient)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/agentient/typescript-component-testing

---

# TypeScript Component Testing Skill

## Metadata (Tier 1)

**Keywords**: jest, vitest, testing-library, react, component test, render

**File Patterns**: *.test.tsx, *.spec.ts, *.test.js

**Modes**: testing_frontend

---

## Instructions (Tier 2)

### React Testing Library Philosophy

**Core Principle**: Test from user's perspective, not implementation

### Query Priority
1. `getByRole` (accessible roles)
2. `getByLabelText` (form elements)
3. `getByPlaceholderText`
4. `getByText`
5. `getByTestId` (last resort)

### Basic Test Pattern

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

test('submits login form', async () => {
  const handleSubmit = jest.fn();
  render(<LoginForm onSubmit={handleSubmit} />);

  await userEvent.type(screen.getByLabelText(/email/i), 'user@example.com');
  await userEvent.type(screen.getByLabelText(/password/i), 'password123');
  await userEvent.click(screen.getByRole('button', { name: /log in/i }));

  expect(handleSubmit).toHaveBeenCalledWith({
    email: 'user@example.com',
    password: 'password123'
  });
});
```

### Async Testing

```typescript
test('loads and displays data', async () => {
  render(<UserProfile userId="123" />);

  // Wait for data to load
  expect(await screen.findByText('John Doe')).toBeInTheDocument();
});

// Or with waitFor
await waitFor(() => {
  expect(screen.getByText('John Doe')).toBeInTheDocument();
});
```

### User Interactions (userEvent)

```typescript
// ✅ Preferred: userEvent (realistic)
await userEvent.click(button);
await userEvent.type(input, 'text');
await userEvent.selectOptions(select, ['option1']);

// ❌ Avoid: fireEvent (low-level)
fireEvent.click(button);
```

### Anti-Patterns

❌ Testing implementation details (state, methods)
❌ Using container.querySelector
❌ Not waiting for async updates
❌ Manually wrapping in act()

