Cloudflare Docs
Workers
Edit this page
Give us feedback
Set theme to dark (⇧+D)

Wrangler API

Wrangler offers APIs to programmatically interact with your Cloudflare Workers.

  • unstable_dev - Start a server for running either end-to-end (e2e) or integration tests against your Worker.
  • getPlatformProxy - Get proxies and values for emulating the Cloudflare Workers platform in a Node.js process.

​​ unstable_dev

Start an HTTP server for testing your Worker.

Once called, unstable_dev will return a fetch() function for invoking your Worker without needing to know the address or port, as well as a stop() function to shut down the HTTP server.

By default, unstable_dev will perform integration tests against a local server. If you wish to perform an e2e test against a preview Worker, pass local: false in the options object when calling the unstable_dev() function. Note that e2e tests can be significantly slower than integration tests.

​​ Constructor

const worker = await unstable_dev(script, options)

​​ Parameters

  • script string

    • A string containing a path to your Worker script, relative to your Worker project’s root directory.
  • options object optional

    • Optional options object containing wrangler dev configuration settings.
    • Include an experimental object inside options to access experimental features such as disableExperimentalWarning.
      • Set disableExperimentalWarning to true to disable Wrangler’s warning about using unstable_ prefixed APIs.

​​ Return Type

unstable_dev() returns an object containing the following methods:

  • fetch() Promise<Response>

    • Send a request to your Worker. Returns a Promise that resolves with a Response object.
    • Refer to Fetch.
  • stop() Promise<void>

    • Shuts down the dev server.

​​ Usage

When initiating each test suite, use a beforeAll() function to start unstable_dev(). The beforeAll() function is used to minimize overhead: starting the dev server takes a few hundred milliseconds, starting and stopping for each individual test adds up quickly, slowing your tests down.

In each test case, call await worker.fetch(), and check that the response is what you expect.

To wrap up a test suite, call await worker.stop() in an afterAll function.

​​ Single Worker example

src/index.test.js
const { unstable_dev } = require("wrangler");
describe("Worker", () => {
let worker;
beforeAll(async () => {
worker = await unstable_dev("src/index.js", {
experimental: { disableExperimentalWarning: true },
});
});
afterAll(async () => {
await worker.stop();
});
it("should return Hello World", async () => {
const resp = await worker.fetch();
const text = await resp.text();
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
});
});
src/index.test.ts
import { unstable_dev } from "wrangler";
import type { UnstableDevWorker } from "wrangler";
describe("Worker", () => {
let worker: UnstableDevWorker;
beforeAll(async () => {
worker = await unstable_dev("src/index.ts", {
experimental: { disableExperimentalWarning: true },
});
});
afterAll(async () => {
await worker.stop();
});
it("should return Hello World", async () => {
const resp = await worker.fetch();
const text = await resp.text();
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
});
});

​​ Multi-Worker example

You can test Workers that call other Workers. In the below example, we refer to the Worker that calls other Workers as the parent Worker, and the Worker being called as a child Worker.

If you shut down the child Worker prematurely, the parent Worker will not know the child Worker exists and your tests will fail.

src/index.test.js
import { unstable_dev } from "wrangler";
describe("multi-worker testing", () => {
let childWorker;
let parentWorker;
beforeAll(async () => {
childWorker = await unstable_dev("src/child-worker.js", {
config: "src/child-wrangler.toml",
experimental: { disableExperimentalWarning: true },
});
parentWorker = await unstable_dev("src/parent-worker.js", {
config: "src/parent-wrangler.toml",
experimental: { disableExperimentalWarning: true },
});
});
afterAll(async () => {
await childWorker.stop();
await parentWorker.stop();
});
it("childWorker should return Hello World itself", async () => {
const resp = await childWorker.fetch();
const text = await resp.text();
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
});
it("parentWorker should return Hello World by invoking the child worker", async () => {
const resp = await parentWorker.fetch();
const parsedResp = await resp.text();
expect(parsedResp).toEqual("Parent worker sees: Hello World!");
});
});
src/index.test.ts
import { unstable_dev } from "wrangler";
import type { UnstableDevWorker } from "wrangler";
describe("multi-worker testing", () => {
let childWorker: UnstableDevWorker;
let parentWorker: UnstableDevWorker;
beforeAll(async () => {
childWorker = await unstable_dev("src/child-worker.js", {
config: "src/child-wrangler.toml",
experimental: { disableExperimentalWarning: true },
});
parentWorker = await unstable_dev("src/parent-worker.js", {
config: "src/parent-wrangler.toml",
experimental: { disableExperimentalWarning: true },
});
});
afterAll(async () => {
await childWorker.stop();
await parentWorker.stop();
});
it("childWorker should return Hello World itself", async () => {
const resp = await childWorker.fetch();
const text = await resp.text();
expect(text).toMatchInlineSnapshot(`"Hello World!"`);
});
it("parentWorker should return Hello World by invoking the child worker", async () => {
const resp = await parentWorker.fetch();
const parsedResp = await resp.text();
expect(parsedResp).toEqual("Parent worker sees: Hello World!");
});
});

​​ getPlatformProxy

The getPlatformProxy function provides a way to obtain an object containing proxies (to local workerd bindings) and emulations of Cloudflare Workers specific values, allowing the emulation of such in a Node.js process.

One general use case for getting a platform proxy is for emulating bindings in applications targeting Workers, but running outside the Workers runtime (for example, framework local development servers running in Node.js), or for testing purposes (for example, ensuring code properly interacts with a type of binding).

​​ Syntax

const platform = await getPlatformProxy(options);

​​ Parameters

  • options object optional

    • Optional options object containing preferences for the bindings:

      • environment string

        The environment to use.

      • configPath string

        The path to the configuration object to use (default wrangler.toml).

      • experimentalJsonConfig boolean

        If true, allows the utility to read a JSON config file (for example, wrangler.json).

      • persist boolean | { path: string }

        Indicates if and where to persist the bindings data. If true or undefined, defaults to the same location used by Wrangler, so data can be shared between it and the caller. If false, no data is persisted to or read from the filesystem.

        Note: If you use wrangler’s --persist-to option, note that this option adds a sub directory called v3 under the hood while getPlatformProxy’s persist does not. For example, if you run wrangler dev --persist-to ./my-directory, to reuse the same location using getPlatformProxy, you will have to specify: persist: "./my-directory/v3".

​​ Return Type

getPlatformProxy() returns a Promise resolving to an object containing the following fields.

  • env Record<string, unknown>

    • Object containing proxies to bindings that can be used in the same way as production bindings. This matches the shape of the env object passed as the second argument to modules-format workers. These proxy to binding implementations run inside workerd.
    • Typescript Tip: getPlatformProxy<Env>() is a generic function. You can pass the shape of the bindings record as a type argument to get proper types without unknown values.
  • cf IncomingRequestCfProperties read-only

    • Mock of the Request’s cf property, containing data similar to what you would see in production.
  • ctx object

  • caches object

    • Emulation of the Workers caches runtime API.
    • For the time being, all cache operations do nothing. A more accurate emulation will be made available soon.
  • dispose() () => Promise<void>

    • Terminates the underlying workerd process.
    • Call this after the platform proxy is no longer required by the program. If you are running a long running process (such as a dev server) that can indefinitely make use of the proxy, you do not need to call this function.

​​ Usage

The getPlatformProxy function uses bindings found in wrangler.toml. For example, if you have an environment variable configuration set up in wrangler.toml:

[vars]
MY_VARIABLE = "test"

You can access the bindings by importing getPlatformProxy like this:

import { getPlatformProxy } from "wrangler";
const { env } = await getPlatformProxy();

To access the value of the MY_VARIABLE binding add the following to your code:

console.log(`MY_VARIABLE = ${env.MY_VARIABLE}`);

This will print the following output: MY_VARIABLE = test.

​​ Supported bindings

All supported bindings found in your wrangler.toml are available to you via env.

The bindings supported by getPlatformProxy are:

  • Environment variables

  • Service bindings

  • KV namespace bindings

  • Durable Object bindings

    • To use a Durable Object binding with getPlatformProxy, always specify a script_name and have the target Worker run in a separate terminal via wrangler dev.

      For example, you might have the following file read by getPlatformProxy.

      wrangler.toml
      [[durable_objects.bindings]]
      name = "MyDurableObject"
      class_name = "MyDurableObject"
      script_name = "my-worker"

      In order for this binding to be successfully proxied by getPlatformProxy, a worker named my-worker with a Durable Object declaration using the same class_name of "MyDurableObject" must be run separately via wrangler dev.

  • R2 bucket bindings

  • Queue bindings

  • D1 database bindings

  • Workers AI bindings

    • To use the AI binding with getPlatformProxy, you need to set the CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN environment variables to your Cloudflare account ID and a Workers AI enabled API token respectively.