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 options object containing
wrangler dev
configuration settings. - Include an
experimental
object insideoptions
to access experimental features such asdisableExperimentalWarning
.- Set
disableExperimentalWarning
totrue
to disable Wrangler’s warning about usingunstable_
prefixed APIs.
- Set
- Optional options object containing
Return Type
unstable_dev()
returns an object containing the following methods:
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.jsconst { 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.tsimport { 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.jsimport { 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.tsimport { 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 options object containing preferences for the bindings:
environment
string
The environment to use.
configPath
string
The path to the config file to use.
If no path is specified the default behavior is to search from the current directory up the filesystem for a
wrangler.toml
to use.Note: this field is optional but if a path is specified it must point to a valid file on the filesystem.
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
orundefined
, defaults to the same location used by Wrangler, so data can be shared between it and the caller. Iffalse
, 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 calledv3
under the hood whilegetPlatformProxy
’spersist
does not. For example, if you runwrangler dev --persist-to ./my-directory
, to reuse the same location usinggetPlatformProxy
, 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 insideworkerd
. - 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 withoutunknown
values.
- Object containing proxies to bindings that can be used in the same way as production bindings. This matches the shape of the
cf
IncomingRequestCfProperties
- Mock of the
Request
’scf
property, containing data similar to what you would see in production.
- Mock of the
ctx
object
- Mock object containing implementations of the
waitUntil
andpassThroughOnException
functions that do nothing.
- Mock object containing implementations of the
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.
- Emulation of the Workers
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.
- Terminates the underlying
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:
To use a Durable Object binding with
getPlatformProxy
, always specify ascript_name
and have the target Worker run in a separate terminal viawrangler 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 namedmy-worker
with a Durable Object declaration using the sameclass_name
of"MyDurableObject"
must be run separately viawrangler dev
.