Skip to content

Testing

Procella has two levels of testing: unit tests (320 tests across all packages) and E2E acceptance tests (89 tests exercising the full Pulumi CLI lifecycle).

Terminal window
bun run check
# or: bun test

Unit tests use Bun’s built-in test runner (bun:test) with describe, test, expect, beforeAll, and afterAll. They run without any external dependencies (no database, no Docker).

Key test suites across packages:

PackageCoverage
packages/authAuth service (dev + Descope mock)
packages/cryptoAES-256-GCM encryption, HKDF key derivation
packages/storageLocal + S3 blob storage
packages/stacksStack CRUD operations
packages/updatesUpdate lifecycle, GC worker
apps/serverHTTP handlers, middleware, route matching
apps/apitRPC procedures (stacks, updates, events)
Terminal window
# Run tests in a specific package
bun test --cwd packages/crypto
# Run tests matching a pattern
bun test --filter "encrypt"
Terminal window
bun run e2e

E2E tests exercise the full Pulumi CLI lifecycle against a real Procella server. They require:

  • PostgreSQL (started via docker compose up -d)
  • Pulumi CLI installed
  • PROCELLA_DATABASE_URL environment variable
FileCoverage
e2e/setup.tsTest infrastructure, server setup/teardown
e2e/login.test.tspulumi login validation
e2e/healthz.test.tsHealth endpoint
e2e/stacks.test.tsCreate, list, get, delete stacks
e2e/rename.test.tsStack rename operations
e2e/updates.test.tsFull update flow: create → start → checkpoint → events → complete
e2e/state.test.tsExport, import, versioned export
e2e/encryption.test.tsSecret encryption/decryption
e2e/cancel.test.tsUpdate cancellation + GC
e2e/examples.test.tsReal Pulumi YAML programs (pulumi-random, pulumi-command)

89 tests covering the full Pulumi CLI lifecycle, multi-tenant isolation, and edge cases.

The e2e/examples.test.ts file deploys real Pulumi YAML programs from the examples/ directory using:

  • pulumi-random — generates random resources (no cloud provider needed)
  • pulumi-command — runs local shell commands

This validates the complete update lifecycle end-to-end without requiring cloud provider credentials.

Terminal window
bun run check # Biome lint + typecheck + 320 unit tests
bun run e2e # 89 E2E acceptance tests
bun run check:all # check + e2e
import { describe, expect, test } from "bun:test";
describe("MyFeature", () => {
test("handles valid input", () => {
const result = myFeature("foo");
expect(result).toBe("bar");
});
test("rejects empty input", () => {
expect(() => myFeature("")).toThrow();
});
});

E2E tests use bun:test and interact with the server via HTTP or the Pulumi CLI:

import { describe, expect, test } from "bun:test";
import { pulumiCli, serverUrl } from "./helpers";
describe("MyE2EFeature", () => {
test("works end-to-end", async () => {
const result = await pulumiCli(["stack", "ls", "--json"]);
expect(result.exitCode).toBe(0);
});
});
Terminal window
# Run a specific test file
bun test e2e/stacks.test.ts
# Run tests matching a pattern
bun test --filter "stack lifecycle"