testing
$
npx mdskill add cloudflare/sandbox-sdk/testingExecute unit and E2E tests using project-specific conventions.
- Runs isolated logic checks and full integration flows.
- Integrates with Vitest, Bun, Docker, and Cloudflare Workers.
- Decides test scope by analyzing file locations and runtime requirements.
- Delivers test results via command-line output and status codes.
SKILL.md
.github/skills/testingView on GitHub ↗
---
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.
More from cloudflare/sandbox-sdk
- architectureUse when navigating the codebase for the first time, adding a new client method, adding a new container handler/service, or understanding how a request flows from Worker through the Sandbox DO into the container. Covers the three-layer architecture, client pattern, container runtime structure, and monorepo layout. (project)
- changesetsUse when creating a changeset, preparing a release, or bumping versions. Covers which packages to reference, how to write user-facing changeset descriptions, the release automation flow, and the npm/Docker version sync requirement. (project)
- coding-standardsUse when writing or reviewing TypeScript in this repo. Covers the no-`any` rule and where to put new types, the uppercase-acronym style guide, and the rules for code comments (no historical context). (project)
- examplesUse when working in the examples/ directory, running an example with wrangler dev, adding a new example, or answering questions about EXPOSE directives and the local Docker dev loop. (project)
- git-commitUse when creating git commits to ensure commit messages follow project standards. Applies the 7 rules for great commit messages with focus on conciseness and imperative mood.
- loggingUse when adding logs, debugging, or working with the Logger across the SDK and container runtime. Covers the constructor-injection pattern, child loggers, env-var configuration, and test mocking. (project)
- sandbox-bridgeUse when you need to exercise a real, running Sandbox deployment via HTTP — for example to validate SDK changes against a live container, reproduce a user-reported issue, or experiment with the API (including FUSE bucket mounts) without spinning up `wrangler dev`. Documents the Sandbox bridge worker reachable via `SANDBOX_WORKER_URL` + `SANDBOX_API_KEY` when the host injects them.
- session-executionUse when working on or reviewing session execution, command handling, shell state, FIFO-based streaming, or stdout/stderr separation. Relevant for session.ts, command handlers, exec/execStream, or anything involving shell process management. (project)