testing
skill✓Use when writing or running tests for this project. Covers unit vs E2E test decisions, test file locations, mock patterns, and project-specific testing conventions. (project)
apm::install
apm install @cloudflare/testingapm::skill.md
---
name: testing
description: Use when writing or running tests for this project. Covers unit vs E2E test decisions, test file locations, mock patterns, and project-specific testing conventions. (project)
---
# Testing in Sandbox SDK
This skill covers project-specific testing conventions. For TDD methodology, use the `superpowers:test-driven-development` skill.
## Two Test Suites
### Unit Tests
**When to use**: Testing isolated logic, client behavior, service methods, utilities.
**Location**:
- SDK: `packages/sandbox/tests/`
- Container: `packages/sandbox-container/tests/`
**Runtime**:
- SDK tests run in Workers runtime via `@cloudflare/vitest-pool-workers`
- Container tests run in Bun runtime
**Commands**:
```bash
npm test # All unit tests
npm test -w @cloudflare/sandbox # SDK tests only
npm test -w @repo/sandbox-container # Container tests only
```
**Mock patterns**:
- SDK tests use a mock container (no Docker needed)
- Container tests mock external dependencies (filesystem, processes)
- Use `createNoOpLogger()` from `@repo/shared` for logger mocks
**Known issue**: SDK unit tests may hang on exit due to vitest-pool-workers workerd shutdown. Tests still pass/fail correctly - the hang is cosmetic.
### E2E Tests
**When to use**: Testing full request flow, container integration, real Docker behavior.
**Location**: `tests/e2e/`
**Runtime**: Real Cloudflare Workers + Docker containers
**Commands**:
```bash
npm run test:e2e # All E2E tests (vitest + browser)
npm run test:e2e:vitest -- -- tests/e2e/process-lifecycle-workflow.test.ts # Single vitest file
npm run test:e2e:vitest -- -- tests/e2e/git-clone-workflow.test.ts -t 'test name' # Single vitest test
npm run test:e2e:browser # Browser tests only (Playwright)
```
**Note**: Use `test:e2e:vitest` when filtering tests. The `test:e2e` wrapper doesn't support argument passthrough.
**Key patterns**:
- All tests share ONE container for performance
- Use unique sessions for test isolation
- Tests run in parallel via thread pool
- Config: `vitest.e2e.config.ts` (root level)
**Writing E2E tests**:
```typescript
import { createTestSession } from './helpers';
describe('Feature X', () => {
let session: TestSession;
beforeEach(async () => {
session = await createTestSession(); // Gets unique session
});
it('should do something', async () => {
const result = await session.sandbox.exec('echo hello');
expect(result.stdout).toBe('hello\n');
});
});
```
## When to Use Which
| Scenario | Test Type |
| --------------------------------------- | --------- |
| Client method logic | Unit |
| Service business logic | Unit |
| Request/response handling | Unit |
| Full command execution flow | E2E |
| File operations with real filesystem | E2E |
| Process lifecycle (start, stop, signal) | E2E |
| Port exposure and preview URLs | E2E |
| Git operations | E2E |
## Test-Specific Conventions
**File naming**: `*.test.ts` for both unit and E2E tests
**Test structure**:
```typescript
describe('ComponentName', () => {
describe('methodName', () => {
it('should do X when Y', async () => {
// Arrange
// Act
// Assert
});
});
});
```
**Assertions**: Use vitest's `expect()` with clear, specific assertions
## Running Tests During Development
After making any meaningful code change:
1. `npm run check` - catch type errors first
2. `npm test` - verify unit tests pass
3. `npm run test:e2e` - if touching core functionality
**Build trust**: The monorepo build system handles dependencies automatically. E2E tests always run against latest built code - no manual rebuild needed.