testing

$npx mdskill add cloudflare/sandbox-sdk/testing

Execute 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

SkillDescription
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)