From cb31836fa8f521f369ebdf251e20bec491811aa2 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Thu, 16 Jan 2025 19:04:09 +0000 Subject: [PATCH 1/6] Add Miniflare + node:test tutorial --- src/content/docs/workers/testing/index.mdx | 16 +- .../testing/miniflare/writing-tests.mdx | 196 ++++++++++++++++++ .../local-development.mdx | 6 +- 3 files changed, 208 insertions(+), 10 deletions(-) create mode 100644 src/content/docs/workers/testing/miniflare/writing-tests.mdx rename src/content/docs/workers/{testing => wrangler}/local-development.mdx (95%) diff --git a/src/content/docs/workers/testing/index.mdx b/src/content/docs/workers/testing/index.mdx index 4ede7ed43eceb8..073cbd9ca75ab1 100644 --- a/src/content/docs/workers/testing/index.mdx +++ b/src/content/docs/workers/testing/index.mdx @@ -5,15 +5,19 @@ sidebar: order: 13 --- -import { DirectoryListing, Render } from "~/components"; +import { Render, LinkButton } from "~/components"; -Review the tools available for testing and debugging Workers. +The Workers platform has a variety of ways to test your applications, depending on your requirements. We recommend using the [Vitest integration](/workers/testing/vitest-integration), which allows for unit testing individual functions within your Worker. However, if you don't use Vitest, both [Miniflare's API](/workers/testing/miniflare/writing-tests) and the [`unstable_startWorker()`](/workers/testing/wrangler) API provide options for testing your Worker in any testing framework. + + + + Write your first test + - ## Testing comparison matrix -| Feature | Vitest Pool | `unstable_dev()` | Miniflare's API | +| Feature | [Vitest integration](/workers/testing/vitest-integration) | [`unstable_startWorker()`](/workers/testing/wrangler) | [Miniflare's API](/workers/testing/miniflare) | | ----------------------------------------- | ----------- | ---------------- | --------------- | | Unit testing | ✅ | ❌ | ❌ | | Integration testing | ✅ | ✅ | ✅ | @@ -21,12 +25,10 @@ Review the tools available for testing and debugging Workers. | Bindings directly in tests | ✅ | ❌ | ✅ | | Isolated per-test storage | ✅ | ❌ | ❌ | | Outbound request mocking | ✅ | ❌ | ✅ | -| Multiple Worker support | ✅ | 🚧[^1] | ✅ | +| Multiple Worker support | ✅ | ✅ | ✅ | | Direct access to Durable Objects | ✅ | ❌ | ❌ | | Run Durable Object alarms immediately | ✅ | ❌ | ❌ | | List Durable Objects | ✅ | ❌ | ❌ | | Testing service Workers | ❌ | ✅ | ✅ | -[^1]: Support for multiple Workers in [`unstable_dev()`](/workers/wrangler/api/#unstable_dev) relies on `wrangler dev`'s service registry which can be unreliable when running multiple tests in parallel. - diff --git a/src/content/docs/workers/testing/miniflare/writing-tests.mdx b/src/content/docs/workers/testing/miniflare/writing-tests.mdx new file mode 100644 index 00000000000000..5eaf2db7c39b09 --- /dev/null +++ b/src/content/docs/workers/testing/miniflare/writing-tests.mdx @@ -0,0 +1,196 @@ +--- +title: Writing tests +pcx_content_type: concept +sidebar: + order: 1 +head: [] +description: Write integration tests against Workers using Miniflare. +--- + +:::note +For most users, Cloudflare recommends using the Workers Vitest integration for testing Workers and [Pages Functions](/pages/functions/) projects. [Vitest](https://vitest.dev/) is a popular JavaScript testing framework featuring a very fast watch mode, Jest compatibility, and out-of-the-box support for TypeScript. +::: + +import { TabItem, Tabs, Details } from "~/components"; + +import { FileTree } from '@astrojs/starlight/components'; + +This guide will instruct you through setting up [Miniflare](/workers/testing/miniflare) for testing your Workers. Miniflare is a low-level API that allows you to fully control how your Workers are run and tested. + +To use Miniflare, make sure you've installed the latest version of Miniflare v3: + + + +```sh +npm install -D miniflare +``` + + + +```sh +yarn add -D miniflare +``` + + + +```sh +pnpm add -D miniflare +``` + + + +The rest of this guide demonstrates concepts with the [`node:test`](https://nodejs.org/api/test.html) testing framework, but any testing framework can be used. + +Miniflare is a low-level API that exposes a large variety of configuration options for running your Worker. In most cases, your tests will only need a subset of the available options, but you can refer to the [full API reference](/workers/testing/miniflare/get-started/#reference) to explore what's possible with Miniflare. + +Before writing a test, you'll need to create a Worker. Since Miniflare is a low-level API that emulates the Cloudflare platform primitives, your Worker will need to be written in JavaScript or you'll need to [integrate your own build pipeline](#custom-builds) into your testing setup. Here's an example JavaScript-only worker: + +```js title="src/index.js" +export default { + async fetch(request) { + return new Response(`Hello World`); + }, +}; +``` + +Next, you'll need to create an initial test file: + +```js {12,13,14,15,16,17,18,19} title="src/index.test.js" +import assert from "node:assert"; +import test, { after, before, describe } from "node:test"; +import { Miniflare } from "miniflare"; + +describe("worker", () => { + /** + * @type {Miniflare} + */ + let worker; + + before(async () => { + worker = new Miniflare({ + modules: [ + { + type: "ESModule", + path: "src/index.js", + }, + ], + }); + await worker.ready; + }); + + test("hello world", async () => { + assert.strictEqual( + await (await worker.dispatchFetch("http://example.com")).text(), + "Hello World" + ); + }); + + after(async () => { + await worker.dispose(); + }); +}); +``` + +You should be able to run the above test via `node --test` + +The highlighted lines of the test file above demonstrate how to set up Miniflare to run a JavaScript Worker. Once Miniflare has been set up, your individual tests can send requests to the running Worker and assert against the responses. This is the main limitation of using Miniflare for testing your Worker as compared to the [Vitest integration](/workers/testing/vitest-integration/)—all access to your Worker must be through the `dispatchFetch()` Miniflare API, and you cannot unit test individual functions from your Worker. + +
+ When using the [Vitest integration](/workers/testing/vitest-integration/), your entire test suite runs in [`workerd`](https://github.com/cloudflare/workerd), which is why it's possible to unit test individual functions. By contrast, when using a different testing framework to run run tests via Miniflare, only your Worker itself is running in [`workerd`](https://github.com/cloudflare/workerd)—your test files run in Node.js. This means that importing functions from your Worker into your test files might exhibit different behaviour than you'd see at runtime if the functions rely on `workerd`-specific behaviour. +
+ +## Interacting with Bindings + +The `dispatchFetch()` API from Miniflare allows you to send requests to your Worker and assert that the correct response is returned, but sometimes you need to interact directly with bindings in tests. For use cases like that, Miniflare provides the [`getBindings()`](/workers/testing/miniflare/get-started/#reference) API. For instance, to access an environment variable in your tests, adapt the test file `src/index.test.js` as follows: + +```diff lang="js" title="src/index.test.js" +... +describe("worker", () => { + ... + before(async () => { + worker = new Miniflare({ + ... ++ bindings: { ++ FOO: "Hello Bindings", ++ }, + }); + ... + }); + + test("text binding", async () => { + const bindings = await worker.getBindings(); + assert.strictEqual(bindings.FOO, "Hello Bindings"); + }); + ... +}); +``` + +You can also interact with local resources such as KV and R2, using the same API as you would from a Worker. For example, here's how you would interact with a KV namespace: + + +```diff lang="js" title="src/index.test.js" +... +describe("worker", () => { + ... + before(async () => { + worker = new Miniflare({ + ... ++ kvNamespaces: ["KV"], + }); + ... + }); + + test("kv binding", async () => { + const bindings = await worker.getBindings(); + await bindings.KV.put("key", "value"); + assert.strictEqual(await bindings.KV.get("key"), "value"); + }); + ... +}); +``` + +## More complex Workers + +The example given above shows how to test a simple Worker consisting of a single JavaScript file. However, most real-world Workers are more complex than that. Miniflare supports providing all constituent files of your Worker directly using the API: + +```js +new Miniflare({ + modules: [ + { + type: "ESModule", + path: "src/index.js", + }, + { + type: "ESModule", + path: "src/imported.js", + }, + ], +}); +``` + +This can be a bit cumbersome as your Worker grows. To help with thi, Miniflare can also crawl your module graph to automatically figure out which modules to include: + +```js +new Miniflare({ + scriptPath: "src/index-with-imports.js", + modules: true, + modulesRules: [{ type: "ESModule", include: ["**/*.js"] }], +}); +``` + +## Custom builds + +In many real-world cases, Workers are not written as plain JavaScript, but are instead written as multiple TypeScript files importing from npm packages etc... that are then bundled by a build tool. When testing your Worker via Miniflare directly you need to run this build tool before your tests. Exactly how this build is run will depend on the specific test framework you use, but for `node:test` it would likely be in a `setup()` hook. For example, if you use [Wrangler](/workers/wrangler/) to build and deploy your Worker, you could spawn a `wrangler build` command: + +```js +before(() => { + spawnSync("npx wrangler build -c wrangler-build.json", { + shell: true, + stdio: "pipe", + }); +}); +``` + + + + diff --git a/src/content/docs/workers/testing/local-development.mdx b/src/content/docs/workers/wrangler/local-development.mdx similarity index 95% rename from src/content/docs/workers/testing/local-development.mdx rename to src/content/docs/workers/wrangler/local-development.mdx index 0ad894cf04cab4..83f1bdd6f1fe5d 100644 --- a/src/content/docs/workers/testing/local-development.mdx +++ b/src/content/docs/workers/wrangler/local-development.mdx @@ -7,9 +7,9 @@ head: [] description: Develop your Workers locally via Wrangler. --- -Cloudflare Workers and most connected resources can be fully developed and tested locally - providing confidence that the applications you build locally will work the same way in production. This allows you to be more efficient and effective by providing a faster feedback loop and removing the need to test against remote resources. Local development runs against the same production runtime used by Cloudflare Workers, [workerd](https://github.com/cloudflare/workerd). +Cloudflare Workers and most connected resources can be fully developed and tested locally—providing confidence that the applications you build locally will work the same way in production. This allows you to be more efficient and effective by providing a faster feedback loop and removing the need to test against remote resources. Local development runs against the same production runtime used by Cloudflare Workers, [workerd](https://github.com/cloudflare/workerd). -In addition to testing Workers locally with [`wrangler dev`](/workers/wrangler/commands/#dev), the use of Miniflare allows you to test other Developer Platform products locally, such as [R2](/r2/), [KV](/kv/), [D1](/d1/), and [Durable Objects](/durable-objects/). +When devloping Workers locally with [`wrangler dev`](/workers/wrangler/commands/#dev), you can access local emulators of resources such as [R2](/r2/), [KV](/kv/), [D1](/d1/), and [Durable Objects](/durable-objects/). ## Start a local development server @@ -35,7 +35,7 @@ npx wrangler dev | ----------------------------------- | ------------------- | -------------------- | | AI | ✅[^1] | ✅ | | Assets | ✅ | ✅ | -| Analytics Engine | ❌ | ✅ | +| Analytics Engine | ✅ | ✅ | | Browser Rendering | ❌ | ✅ | | D1 | ✅ | ✅ | | Durable Objects | ✅ | ✅ | From b8951cbfbc343c2633f64e7d210e389d07fe7a9e Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Thu, 16 Jan 2025 19:09:36 +0000 Subject: [PATCH 2/6] move local --- .../docs/workers/{wrangler => testing}/local-development.mdx | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/content/docs/workers/{wrangler => testing}/local-development.mdx (100%) diff --git a/src/content/docs/workers/wrangler/local-development.mdx b/src/content/docs/workers/testing/local-development.mdx similarity index 100% rename from src/content/docs/workers/wrangler/local-development.mdx rename to src/content/docs/workers/testing/local-development.mdx From f67732d78cad480af9147a053d58f91cc131555b Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Thu, 16 Jan 2025 19:10:14 +0000 Subject: [PATCH 3/6] typo --- src/content/docs/workers/testing/local-development.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/workers/testing/local-development.mdx b/src/content/docs/workers/testing/local-development.mdx index 83f1bdd6f1fe5d..34ea1d143fcd69 100644 --- a/src/content/docs/workers/testing/local-development.mdx +++ b/src/content/docs/workers/testing/local-development.mdx @@ -9,7 +9,7 @@ description: Develop your Workers locally via Wrangler. Cloudflare Workers and most connected resources can be fully developed and tested locally—providing confidence that the applications you build locally will work the same way in production. This allows you to be more efficient and effective by providing a faster feedback loop and removing the need to test against remote resources. Local development runs against the same production runtime used by Cloudflare Workers, [workerd](https://github.com/cloudflare/workerd). -When devloping Workers locally with [`wrangler dev`](/workers/wrangler/commands/#dev), you can access local emulators of resources such as [R2](/r2/), [KV](/kv/), [D1](/d1/), and [Durable Objects](/durable-objects/). +When developing Workers locally with [`wrangler dev`](/workers/wrangler/commands/#dev), you can access local emulators of resources such as [R2](/r2/), [KV](/kv/), [D1](/d1/), and [Durable Objects](/durable-objects/). ## Start a local development server From cc968b46cb15b02cce4696f9afc53550af21e349 Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Thu, 16 Jan 2025 19:42:43 +0000 Subject: [PATCH 4/6] Add basic start worker docs --- src/content/docs/workers/testing/index.mdx | 4 +-- src/content/docs/workers/wrangler/api.mdx | 32 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/content/docs/workers/testing/index.mdx b/src/content/docs/workers/testing/index.mdx index 073cbd9ca75ab1..8cb1b88fa208ed 100644 --- a/src/content/docs/workers/testing/index.mdx +++ b/src/content/docs/workers/testing/index.mdx @@ -7,7 +7,7 @@ sidebar: import { Render, LinkButton } from "~/components"; -The Workers platform has a variety of ways to test your applications, depending on your requirements. We recommend using the [Vitest integration](/workers/testing/vitest-integration), which allows for unit testing individual functions within your Worker. However, if you don't use Vitest, both [Miniflare's API](/workers/testing/miniflare/writing-tests) and the [`unstable_startWorker()`](/workers/testing/wrangler) API provide options for testing your Worker in any testing framework. +The Workers platform has a variety of ways to test your applications, depending on your requirements. We recommend using the [Vitest integration](/workers/testing/vitest-integration), which allows for unit testing individual functions within your Worker. However, if you don't use Vitest, both [Miniflare's API](/workers/testing/miniflare/writing-tests) and the [`unstable_startWorker()`](/workers/wrangler/api/#unstable_startworker) API provide options for testing your Worker in any testing framework. @@ -17,7 +17,7 @@ The Workers platform has a variety of ways to test your applications, depending ## Testing comparison matrix -| Feature | [Vitest integration](/workers/testing/vitest-integration) | [`unstable_startWorker()`](/workers/testing/wrangler) | [Miniflare's API](/workers/testing/miniflare) | +| Feature | [Vitest integration](/workers/testing/vitest-integration) | [`unstable_startWorker()`](/workers/wrangler/api/#unstable_startworker) | [Miniflare's API](/workers/testing/miniflare) | | ----------------------------------------- | ----------- | ---------------- | --------------- | | Unit testing | ✅ | ❌ | ❌ | | Integration testing | ✅ | ✅ | ✅ | diff --git a/src/content/docs/workers/wrangler/api.mdx b/src/content/docs/workers/wrangler/api.mdx index d097174f06251f..c731e23b7b0d78 100644 --- a/src/content/docs/workers/wrangler/api.mdx +++ b/src/content/docs/workers/wrangler/api.mdx @@ -12,9 +12,41 @@ import { Render, TabItem, Tabs, Type, MetaInfo } from "~/components"; Wrangler offers APIs to programmatically interact with your Cloudflare Workers. +- [`unstable_startWorker`](#unstable_startworker) - Start a server for running integration tests against your Worker. - [`unstable_dev`](#unstable_dev) - Start a server for running either end-to-end (e2e) or integration tests against your Worker. - [`getPlatformProxy`](#getplatformproxy) - Get proxies and values for emulating the Cloudflare Workers platform in a Node.js process. +## `unstable_startWorker` + +This API exposes the internals of Wrangler's dev server, and allows you to customise how it runs. For example, you could use `unstable_startWorker()` to run integration tests against your Worker (the below example is with `node:test`, but this should work in any testing framework): + +```js +import assert from "node:assert"; +import test, { after, before, describe } from "node:test"; +import { unstable_startWorker } from "wrangler"; + +describe("worker", () => { + let worker; + + before(async () => { + worker = await unstable_startWorker({ config: "wrangler.json" }); + }); + + test("hello world", async () => { + assert.strictEqual( + await (await worker.fetch("http://example.com")).text(), + "Hello world" + ); + }); + + after(async () => { + await worker.dispose(); + }); +}); +``` + + + ## `unstable_dev` Start an HTTP server for testing your Worker. From 986b5e7e6ce136424df7f6015b89a8baa3aea03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Somhairle=20MacLe=C3=B2id?= Date: Tue, 21 Jan 2025 17:47:21 +0000 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: hyperlint-ai[bot] <154288675+hyperlint-ai[bot]@users.noreply.github.com> --- src/content/docs/workers/testing/miniflare/writing-tests.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/workers/testing/miniflare/writing-tests.mdx b/src/content/docs/workers/testing/miniflare/writing-tests.mdx index 5eaf2db7c39b09..5f11cd28a88376 100644 --- a/src/content/docs/workers/testing/miniflare/writing-tests.mdx +++ b/src/content/docs/workers/testing/miniflare/writing-tests.mdx @@ -43,7 +43,7 @@ The rest of this guide demonstrates concepts with the [`node:test`](https://node Miniflare is a low-level API that exposes a large variety of configuration options for running your Worker. In most cases, your tests will only need a subset of the available options, but you can refer to the [full API reference](/workers/testing/miniflare/get-started/#reference) to explore what's possible with Miniflare. -Before writing a test, you'll need to create a Worker. Since Miniflare is a low-level API that emulates the Cloudflare platform primitives, your Worker will need to be written in JavaScript or you'll need to [integrate your own build pipeline](#custom-builds) into your testing setup. Here's an example JavaScript-only worker: +Before writing a test, you'll need to create a Worker. Since Miniflare is a low-level API that emulates the Cloudflare platform primitives, your Worker will need to be written in JavaScript or you'll need to [integrate your own build pipeline](#custom-builds) into your testing setup. Here's an example JavaScript-only Worker: ```js title="src/index.js" export default { @@ -96,7 +96,7 @@ You should be able to run the above test via `node --test` The highlighted lines of the test file above demonstrate how to set up Miniflare to run a JavaScript Worker. Once Miniflare has been set up, your individual tests can send requests to the running Worker and assert against the responses. This is the main limitation of using Miniflare for testing your Worker as compared to the [Vitest integration](/workers/testing/vitest-integration/)—all access to your Worker must be through the `dispatchFetch()` Miniflare API, and you cannot unit test individual functions from your Worker.
- When using the [Vitest integration](/workers/testing/vitest-integration/), your entire test suite runs in [`workerd`](https://github.com/cloudflare/workerd), which is why it's possible to unit test individual functions. By contrast, when using a different testing framework to run run tests via Miniflare, only your Worker itself is running in [`workerd`](https://github.com/cloudflare/workerd)—your test files run in Node.js. This means that importing functions from your Worker into your test files might exhibit different behaviour than you'd see at runtime if the functions rely on `workerd`-specific behaviour. +When using the [Vitest integration](/workers/testing/vitest-integration/), your entire test suite runs in [`workerd`](https://github.com/cloudflare/workerd), which is why it's possible to unit test individual functions. By contrast, when using a different testing framework to run tests via Miniflare, only your Worker itself is running in [`workerd`](https://github.com/cloudflare/workerd)—your test files run in Node.js. This means that importing functions from your Worker into your test files might exhibit different behaviour than you'd see at runtime if the functions rely on `workerd`-specific behaviour.
## Interacting with Bindings From bf3abd8d9a20fe3cf3abbb77fbaadbf36ccde13c Mon Sep 17 00:00:00 2001 From: Samuel Macleod Date: Fri, 31 Jan 2025 17:36:38 +0000 Subject: [PATCH 6/6] address comments --- src/content/docs/workers/testing/index.mdx | 28 +++++++++---------- .../workers/testing/integration-testing.mdx | 25 ++++++++--------- .../testing/miniflare/writing-tests.mdx | 27 ++++++++++++------ src/content/docs/workers/wrangler/api.mdx | 8 ++---- 4 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/content/docs/workers/testing/index.mdx b/src/content/docs/workers/testing/index.mdx index 8cb1b88fa208ed..b5815dc45dc90c 100644 --- a/src/content/docs/workers/testing/index.mdx +++ b/src/content/docs/workers/testing/index.mdx @@ -9,26 +9,24 @@ import { Render, LinkButton } from "~/components"; The Workers platform has a variety of ways to test your applications, depending on your requirements. We recommend using the [Vitest integration](/workers/testing/vitest-integration), which allows for unit testing individual functions within your Worker. However, if you don't use Vitest, both [Miniflare's API](/workers/testing/miniflare/writing-tests) and the [`unstable_startWorker()`](/workers/wrangler/api/#unstable_startworker) API provide options for testing your Worker in any testing framework. - Write your first test - ## Testing comparison matrix -| Feature | [Vitest integration](/workers/testing/vitest-integration) | [`unstable_startWorker()`](/workers/wrangler/api/#unstable_startworker) | [Miniflare's API](/workers/testing/miniflare) | -| ----------------------------------------- | ----------- | ---------------- | --------------- | -| Unit testing | ✅ | ❌ | ❌ | -| Integration testing | ✅ | ✅ | ✅ | -| Loading Wrangler configuration files | ✅ | ✅ | ❌ | -| Bindings directly in tests | ✅ | ❌ | ✅ | -| Isolated per-test storage | ✅ | ❌ | ❌ | -| Outbound request mocking | ✅ | ❌ | ✅ | -| Multiple Worker support | ✅ | ✅ | ✅ | -| Direct access to Durable Objects | ✅ | ❌ | ❌ | -| Run Durable Object alarms immediately | ✅ | ❌ | ❌ | -| List Durable Objects | ✅ | ❌ | ❌ | -| Testing service Workers | ❌ | ✅ | ✅ | +| Feature | [Vitest integration](/workers/testing/vitest-integration) | [`unstable_startWorker()`](/workers/wrangler/api/#unstable_startworker) | [Miniflare's API](/workers/testing/miniflare) | +| ------------------------------------- | --------------------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------- | +| Unit testing | ✅ | ❌ | ❌ | +| Integration testing | ✅ | ✅ | ✅ | +| Loading Wrangler configuration files | ✅ | ✅ | ❌ | +| Use bindings directly in tests | ✅ | ❌ | ✅ | +| Isolated per-test storage | ✅ | ❌ | ❌ | +| Outbound request mocking | ✅ | ❌ | ✅ | +| Multiple Worker support | ✅ | ✅ | ✅ | +| Direct access to Durable Objects | ✅ | ❌ | ❌ | +| Run Durable Object alarms immediately | ✅ | ❌ | ❌ | +| List Durable Objects | ✅ | ❌ | ❌ | +| Testing service Workers | ❌ | ✅ | ✅ | diff --git a/src/content/docs/workers/testing/integration-testing.mdx b/src/content/docs/workers/testing/integration-testing.mdx index a23e47eed47fa7..adf58591055c6e 100644 --- a/src/content/docs/workers/testing/integration-testing.mdx +++ b/src/content/docs/workers/testing/integration-testing.mdx @@ -8,6 +8,7 @@ description: Test multiple units of your Worker working together. --- import { Render } from "~/components"; +import { LinkButton } from "@astrojs/starlight/components"; Integration tests test multiple units of your Worker together by sending HTTP requests to your Worker and asserting on the HTTP responses. As an example, consider the following Worker: @@ -84,32 +85,30 @@ This method is less recommended than `SELF` for integration tests because of its ::: -## Wrangler's `unstable_dev()` API +## [Wrangler's `unstable_startWorker()` API](/workers/wrangler/api/#unstable_startworker) -If you do not want to use Vitest and would like to write integration tests for a single Worker, consider using [Wrangler's `unstable_dev()` API](/workers/wrangler/api/#unstable_dev). `unstable_dev()` allows you to start an HTTP server similar to [`wrangler dev`](/workers/wrangler/commands/#dev) that you can send HTTP requests to. `unstable_dev()` will automatically load options from your Wrangler configuration file. Note that `unstable_dev()` is an experimental API subject to breaking changes. +:::caution +`unstable_startWorker()` is an experimental API subject to breaking changes. +::: + +If you do not want to use Vitest and would like to write integration tests for a single Worker, consider using [Wrangler's `unstable_startWorker()` API](/workers/wrangler/api/#unstable_startworker). This API exposes the internals of Wrangler's dev server, and allows you to customise how it runs. ```js import assert from "node:assert"; -import { unstable_dev } from "wrangler"; +import { unstable_startWorker } from "wrangler"; -const worker = await unstable_dev("./index.mjs"); +const worker = await unstable_startWorker({ config: "wrangler.json" }); try { const response = await worker.fetch("/?a=1&b=2"); assert.strictEqual(await response.text(), "3"); } finally { - await worker.stop(); + await worker.dispose(); } ``` -:::note - -If you have been using `unstable_dev()` for integration testing and want to migrate to Cloudflare's Vitest integration, refer to the [Migrate from `unstable_dev` migration guide](/workers/testing/vitest-integration/get-started/migrate-from-unstable-dev/) for more information. - -::: - -## Miniflare's API +## [Miniflare's API](/workers/testing/miniflare/writing-tests/) -If you would like to write integration tests for multiple Workers, need direct access to [bindings](/workers/runtime-apis/bindings/) outside your Worker in tests, or have another advanced use case, consider using [Miniflare's API](/workers/testing/miniflare) directly. Miniflare is the foundation for the other testing tools on this page, exposing a JavaScript API for the [`workerd` runtime](https://github.com/cloudflare/workerd) and local simulators for the other Developer Platform products. Unlike `unstable_dev()`, Miniflare does not automatically load options from your Wrangler configuration file. +If you would like to write integration tests for multiple Workers, need direct access to [bindings](/workers/runtime-apis/bindings/) outside your Worker in tests, or have another advanced use case, consider using [Miniflare's API](/workers/testing/miniflare) directly. Miniflare is the foundation for the other testing tools on this page, exposing a JavaScript API for the [`workerd` runtime](https://github.com/cloudflare/workerd) and local simulators for the other Developer Platform products. Unlike `unstable_startWorker()`, Miniflare does not automatically load options from your Wrangler configuration file. Refer to the [Writing Tests](/workers/testing/miniflare/writing-tests/) page for an example of how to use Miniflare together with `node:test`. ```js import assert from "node:assert"; diff --git a/src/content/docs/workers/testing/miniflare/writing-tests.mdx b/src/content/docs/workers/testing/miniflare/writing-tests.mdx index 5f11cd28a88376..bc6b281ca25a3f 100644 --- a/src/content/docs/workers/testing/miniflare/writing-tests.mdx +++ b/src/content/docs/workers/testing/miniflare/writing-tests.mdx @@ -13,7 +13,7 @@ For most users, Cloudflare recommends using the Workers Vitest integration for t import { TabItem, Tabs, Details } from "~/components"; -import { FileTree } from '@astrojs/starlight/components'; +import { FileTree } from "@astrojs/starlight/components"; This guide will instruct you through setting up [Miniflare](/workers/testing/miniflare) for testing your Workers. Miniflare is a low-level API that allows you to fully control how your Workers are run and tested. @@ -81,7 +81,7 @@ describe("worker", () => { test("hello world", async () => { assert.strictEqual( await (await worker.dispatchFetch("http://example.com")).text(), - "Hello World" + "Hello World", ); }); @@ -96,11 +96,25 @@ You should be able to run the above test via `node --test` The highlighted lines of the test file above demonstrate how to set up Miniflare to run a JavaScript Worker. Once Miniflare has been set up, your individual tests can send requests to the running Worker and assert against the responses. This is the main limitation of using Miniflare for testing your Worker as compared to the [Vitest integration](/workers/testing/vitest-integration/)—all access to your Worker must be through the `dispatchFetch()` Miniflare API, and you cannot unit test individual functions from your Worker.
-When using the [Vitest integration](/workers/testing/vitest-integration/), your entire test suite runs in [`workerd`](https://github.com/cloudflare/workerd), which is why it's possible to unit test individual functions. By contrast, when using a different testing framework to run tests via Miniflare, only your Worker itself is running in [`workerd`](https://github.com/cloudflare/workerd)—your test files run in Node.js. This means that importing functions from your Worker into your test files might exhibit different behaviour than you'd see at runtime if the functions rely on `workerd`-specific behaviour. + When using the [Vitest integration](/workers/testing/vitest-integration/), + your entire test suite runs in + [`workerd`](https://github.com/cloudflare/workerd), which is why it's possible + to unit test individual functions. By contrast, when using a different testing + framework to run tests via Miniflare, only your Worker itself is running in + [`workerd`](https://github.com/cloudflare/workerd)—your test files run in + Node.js. This means that importing functions from your Worker into your test + files might exhibit different behaviour than you'd see at runtime if the + functions rely on `workerd`-specific behaviour.
## Interacting with Bindings +:::caution + +Miniflare does not read [Wrangler's config file](/workers/wrangler/configuration), and so all bindings that your Worker uses need to be specified in the Miniflare API options. + +::: + The `dispatchFetch()` API from Miniflare allows you to send requests to your Worker and assert that the correct response is returned, but sometimes you need to interact directly with bindings in tests. For use cases like that, Miniflare provides the [`getBindings()`](/workers/testing/miniflare/get-started/#reference) API. For instance, to access an environment variable in your tests, adapt the test file `src/index.test.js` as follows: ```diff lang="js" title="src/index.test.js" @@ -127,7 +141,6 @@ describe("worker", () => { You can also interact with local resources such as KV and R2, using the same API as you would from a Worker. For example, here's how you would interact with a KV namespace: - ```diff lang="js" title="src/index.test.js" ... describe("worker", () => { @@ -168,7 +181,7 @@ new Miniflare({ }); ``` -This can be a bit cumbersome as your Worker grows. To help with thi, Miniflare can also crawl your module graph to automatically figure out which modules to include: +This can be a bit cumbersome as your Worker grows. To help with this, Miniflare can also crawl your module graph to automatically figure out which modules to include: ```js new Miniflare({ @@ -190,7 +203,3 @@ before(() => { }); }); ``` - - - - diff --git a/src/content/docs/workers/wrangler/api.mdx b/src/content/docs/workers/wrangler/api.mdx index c731e23b7b0d78..8d17e7ea152218 100644 --- a/src/content/docs/workers/wrangler/api.mdx +++ b/src/content/docs/workers/wrangler/api.mdx @@ -35,7 +35,7 @@ describe("worker", () => { test("hello world", async () => { assert.strictEqual( await (await worker.fetch("http://example.com")).text(), - "Hello world" + "Hello world", ); }); @@ -45,8 +45,6 @@ describe("worker", () => { }); ``` - - ## `unstable_dev` Start an HTTP server for testing your Worker. @@ -61,6 +59,8 @@ The `unstable_dev()` function has an `unstable_` prefix because the API is exper `unstable_dev()` has no known bugs and is safe to use. If you discover any bugs, open a [GitHub issue](https://github.com/cloudflare/workers-sdk/issues/new/choose). +If you have been using `unstable_dev()` for integration testing and want to migrate to Cloudflare's Vitest integration, refer to the [Migrate from `unstable_dev` migration guide](/workers/testing/vitest-integration/get-started/migrate-from-unstable-dev/) for more information. + ::: ### Constructor @@ -374,8 +374,6 @@ The bindings supported by `getPlatformProxy` are: For example, you might have the following file read by `getPlatformProxy`. - - ```toml