vitest.cloudflare.config.mts
Rama main · réplica de lectura del repositorio original.
import { cloudflareTest } from '@cloudflare/vitest-plugin'
import { config } from 'dotenv'
import type { ViteUserConfig } from 'vitest/config'
type UnhandledError = Parameters<
NonNullable<NonNullable<ViteUserConfig['test']>['onUnhandledError']>
>[0]
/**
* The connect-rpc failures the SDK wraps — they surface on the intermediate
* promises of the async-function chain too, so suites that assert on them with
* `expect(p).rejects` need them dropped.
*/
export function isConnectRpcRejection(
error: UnhandledError,
message: string
): boolean {
return error.name === 'ConnectError' || message.startsWith('ConnectError:')
}
export interface CloudflareVitestConfigOptions {
/** Globs excluded on top of `tests/runtimes/**`. */
exclude?: string[]
testTimeout?: number
maxWorkers?: number
/** Additional rejection shapes to drop, on top of the shared ones. */
isExpectedRejection?: (error: UnhandledError, message: string) => boolean
}
/**
* Runs a package's Node suite inside Cloudflare's workerd via
* vitest-plugin, against src — the same coverage as the bun and deno
* legs, but exercising the Workers runtime's fetch/streams implementations.
*/
export function createCloudflareVitestConfig({
exclude = [],
testTimeout = 30_000,
maxWorkers,
isExpectedRejection,
}: CloudflareVitestConfigOptions = {}): ViteUserConfig {
const env = config()
return {
plugins: [
// workerd resolves without the `node` condition, under which msw's
// `msw/node` entry has no export for its
// `@mswjs/interceptors/ClientRequest` import. vitest-pool-workers shipped
// this redirect to msw's fetch-based native entry until 0.21.3.
{
name: 'e2b:msw-native',
enforce: 'pre',
load(id) {
if (id.endsWith('msw/lib/node/index.mjs')) {
return 'export * from "../native/index.mjs"'
}
},
},
cloudflareTest({
miniflare: {
compatibilityDate: '2026-03-01',
// nodejs_compat is a hard requirement for the SDK on Workers. It also
// mirrors the bindings below into process.env (default since compat
// date 2025-04-01), which is how tests and the SDK read E2B_*.
compatibilityFlags: ['nodejs_compat'],
bindings: {
E2B_API_KEY:
process.env.E2B_API_KEY ?? env.parsed?.E2B_API_KEY ?? '',
E2B_DOMAIN: process.env.E2B_DOMAIN ?? env.parsed?.E2B_DOMAIN ?? '',
},
},
}),
],
test: {
name: 'cloudflare',
include: ['tests/**/*.test.ts'],
exclude: ['tests/runtimes/**', ...exclude],
globals: false,
testTimeout,
maxWorkers,
bail: 0,
// workerd reports a rejection as unhandled unless a handler is attached
// within the same microtask drain, and vitest never processes the
// rejectionhandled retraction, so rejections the tests DO handle (the
// `await expect(p).rejects` pattern, including the intermediate promises
// of the async-function chain) false-positive the run. Instead of
// dangerouslyIgnoreUnhandledErrors, drop only the rejection shapes these
// suites deliberately provoke; uncaught exceptions and any unknown
// rejection shape still fail the run.
onUnhandledError(error) {
if (error.type !== 'Unhandled Rejection') return
const message = String(error.message ?? '')
const expectedRejection =
// Aborted requests surface on intermediate promises too.
error.name === 'AbortError' ||
// workerd's teardown error for in-flight streams when a test kills
// the sandbox mid-request.
message === 'Network connection lost.' ||
isExpectedRejection?.(error, message) === true
if (expectedRejection) return false
},
},
}
}