Skip to content

Known issues

The Workers Vitest pool is currently in open beta. The following are issues Cloudflare is aware of and fixing:

Coverage

Native code coverage via V8 is not supported. You must use instrumented code coverage via Istanbul instead. Refer to the Vitest Coverage documentation for setup instructions.

Fake timers

Vitest's fake timers do not apply to KV, R2 and cache simulators. For example, you cannot expire a KV key by advancing fake time.

Dynamic import() statements with SELF and Durable Objects

Dynamic import() statements do not work inside export default { ... } handlers when writing integration tests with SELF, or inside Durable Object event handlers. You must import and call your handlers directly, or use static import statements in the global scope.

Durable Object alarms

Durable Object alarms are not reset between test runs and do not respect isolated storage. Ensure you delete or run all alarms with runDurableObjectAlarm() scheduled in each test before finishing the test.

Durable Objects and isolatedStorage

Using WebSockets with Durable Objects with the isolatedStorage flag turned on is not supported. You must set isolatedStorage: false in your vitest.config.ts file.

Returning non-primitive values from RPC methods

In order to return non-primitive values (objects or classes extending RpcTarget, for instance) from RPC methods, you must use the using keyword. Refer to https://developers.cloudflare.com/workers/runtime-apis/rpc/lifecycle#explicit-resource-management for more details. An example test is included in the workers-sdk repository.

Module resolution

If you encounter module resolution issues such as: Error: Cannot use require() to import an ES Module or Error: No such module, you can bundle these dependencies using the deps.optimizer option:

import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
deps: {
optimizer: {
ssr: {
enabled: true,
include: ["your-package-name"],
},
},
},
poolOptions: {
workers: {
// ...
},
},
},
});

You can find an example in the Recipes page.

Importing modules from global setup file

Although Vitest is set up to resolve packages for the workerd runtime, it runs your global setup file in the Node.js environment. This can cause issues when importing packages like Postgres.js, which exports a non-Node version for workerd. To work around this, you can create a wrapper that uses Vite's SSR module loader to import the global setup file under the correct conditions. Then, adjust your Vitest configuration to point to this wrapper. For example:

// File: global-setup-wrapper.ts
import { createServer } from "vite"
// Import the actual global setup file with the correct setup
const mod = await viteImport("./global-setup.ts")
export default mod.default;
// Helper to import the file with default node setup
async function viteImport(file: string) {
const server = await createServer({
root: import.meta.dirname,
configFile: false,
server: { middlewareMode: true, hmr: false, watch: null, ws: false },
optimizeDeps: { noDiscovery: true },
clearScreen: false,
});
const mod = await server.ssrLoadModule(file);
await server.close();
return mod;
}
// File: vitest.config.ts
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
// Replace the globalSetup with the wrapper file
globalSetup: ["./global-setup-wrapper.ts"],
poolOptions: {
workers: {
// ...
},
},
},
});