> ## Documentation Index
> Fetch the complete documentation index at: https://sunpeak.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Unit Testing

> Unit testing MCP App components and hooks with Vitest and happy-dom.

## Overview

<Note>
  Unit tests are for **sunpeak app framework projects** (created with `sunpeak new`). If you're using sunpeak as a standalone testing framework for an existing MCP server, use [E2E tests](/testing/e2e) instead, which test your server over the wire via the MCP protocol.
</Note>

Unit tests run your component and hook logic in isolation using Vitest with happy-dom. They're fast, don't require the inspector or a browser, and test tool handlers, React components, and data transformations directly.

<Tabs>
  <Tab title="pnpm">
    ```bash theme={null}
    pnpm test                    # Run unit + e2e tests
    pnpm test:unit               # Unit tests only
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={null}
    npm run test                    # Run unit + e2e tests
    npm run test:unit               # Unit tests only
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn test                    # Run unit + e2e tests
    yarn test:unit               # Unit tests only
    ```
  </Tab>
</Tabs>

## Setup

Unit tests live in `tests/unit/` (or any `*.test.ts` / `*.spec.ts` file matched by your Vitest config). For sunpeak framework projects, Vitest is pre-configured with happy-dom.

For standalone usage, add Vitest to your project:

<Tabs>
  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add -D vitest @vitest/coverage-v8
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={null}
    npm install -D vitest @vitest/coverage-v8
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add -D vitest @vitest/coverage-v8
    ```
  </Tab>
</Tabs>

```typescript theme={null}
// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    environment: 'happy-dom',
    include: ['tests/unit/**/*.{test,spec}.{ts,tsx}'],
  },
});
```

## Writing Unit Tests

Test component rendering, hook logic, and data transformations without the full inspector stack.

### Testing Components

```typescript theme={null}
import { render, screen } from '@testing-library/react';
import { test, expect } from 'vitest';
import { ReviewResource } from '../../src/resources/review/review';

test('renders review title', () => {
  // Mock the useToolData hook at the module level or via a provider
  render(<ReviewResource />);
  expect(screen.getByRole('heading')).toBeDefined();
});
```

### Testing Data Transformations

```typescript theme={null}
import { test, expect } from 'vitest';
import { formatAlbumData } from '../../src/resources/albums/utils';

test('formats album data correctly', () => {
  const raw = { title: 'Summer Slice', count: 12 };
  const result = formatAlbumData(raw);
  expect(result.displayTitle).toBe('Summer Slice (12 photos)');
});
```

### Testing Tool Handlers

Tool handlers are plain async functions, so you can test them directly:

```typescript theme={null}
import { test, expect } from 'vitest';
import handler from '../../src/tools/show-albums';

test('returns album data', async () => {
  const result = await handler({ category: 'travel' }, {} as any);
  expect(result.structuredContent).toBeDefined();
  expect(result.structuredContent.albums).toBeInstanceOf(Array);
});
```

## When to Use Unit Tests vs E2E Tests

| Use unit tests for                 | Use E2E tests for                            |
| ---------------------------------- | -------------------------------------------- |
| Data transformations and utilities | Visual rendering across hosts and themes     |
| Tool handler logic                 | Iframe communication and sandbox behavior    |
| Component logic in isolation       | Full tool call flow (call → render → assert) |
| Fast feedback during development   | Cross-host compatibility (ChatGPT vs Claude) |

Unit tests and E2E tests are complementary. Unit tests catch logic bugs fast. [E2E tests](/testing/e2e) catch rendering and integration issues across the full inspector stack.

## Additional Quality Tools

<AccordionGroup>
  <Accordion title="Linting (ESLint)">
    <Tabs>
      <Tab title="pnpm">
        ```bash theme={null}
        pnpm add -D eslint @typescript-eslint/eslint-plugin
        ```
      </Tab>

      <Tab title="npm">
        ```bash theme={null}
        npm install -D eslint @typescript-eslint/eslint-plugin
        ```
      </Tab>

      <Tab title="yarn">
        ```bash theme={null}
        yarn add -D eslint @typescript-eslint/eslint-plugin
        ```
      </Tab>
    </Tabs>

    Add `"lint": "eslint . --ext .ts,.tsx"` to package.json scripts.
  </Accordion>

  <Accordion title="Type Checking">
    TypeScript is already installed. Add to package.json scripts:

    ```json theme={null}
    "typecheck": "tsc --noEmit"
    ```
  </Accordion>

  <Accordion title="Formatting (Prettier)">
    <Tabs>
      <Tab title="pnpm">
        ```bash theme={null}
        pnpm add -D prettier
        ```
      </Tab>

      <Tab title="npm">
        ```bash theme={null}
        npm install -D prettier
        ```
      </Tab>

      <Tab title="yarn">
        ```bash theme={null}
        yarn add -D prettier
        ```
      </Tab>
    </Tabs>

    Add `"format": "prettier --write ."` to package.json scripts.
  </Accordion>
</AccordionGroup>

## Learn More

<Card horizontal title="Vitest Docs" icon="link" href="https://vitest.dev/">
  Learn more about Vitest for unit testing.
</Card>

<Card horizontal title="E2E Testing" icon="flask" href="/testing/e2e">
  Full-stack testing with the inspector and Playwright.
</Card>
