Wrangler は、Cloudflare Workers をプログラムから操作する API を提供します。
createTestHarness- 任意の Node.js テストランナーで、統合テスト用に 1 つ以上の Worker を起動します。experimental_generateTypes- Worker の設定から TypeScript の型定義を生成します。unstable_startWorker- Worker に対する統合テスト用サーバーを起動します。unstable_dev- Worker に対するエンドツーエンド(e2e)テストまたは統合テスト用サーバーを起動します。getPlatformProxy- Node.js プロセス内で Cloudflare Workers プラットフォームをエミュレートするためのプロキシと値を取得します。
createTestHarness() は、任意の Node.js テストランナーから、統合テスト用に 1 つ以上の Worker を起動します。Wrangler 設定ファイル、Vite が生成した設定ファイル、またはインラインの Wrangler 設定オブジェクトから、本番ビルドの出力を実行します。この API は Miniflare を包み、リクエストと scheduled イベントを送るメソッドを提供します。
セットアップ手順と例は、統合テストハーネス を参照してください。
import { createTestHarness } from "wrangler";
const server = createTestHarness(options);import { createTestHarness } from "wrangler";
const server = createTestHarness(options);-
optionsobjectoptional-
テストハーネスのオプションです。オプションなしで
createTestHarness()を呼ぶ場合は、server.listen()の前にserver.update(options)を呼んでください。-
rootstringoptional相対的な Worker 設定パスの解決に使うベースディレクトリです。既定は
process.cwd()です。 -
workersWorkerInput[]テストサーバーで実行する Worker です。最初の Worker がプライマリ Worker です。
-
-
各 WorkerInput は、Wrangler 設定ファイルから Worker を読み込めます。
const server = createTestHarness({
workers: [
{ configPath: "./wrangler.web.jsonc" },
{ configPath: "./wrangler.api.jsonc" },
],
});const server = createTestHarness({
workers: [
{ configPath: "./wrangler.web.jsonc" },
{ configPath: "./wrangler.api.jsonc" },
],
});設定ファイル入力は、次のフィールドをサポートします。
configPathstring | URL- Wrangler 設定ファイルへのパスです。相対パスは
rootから解決します。
- Wrangler 設定ファイルへのパスです。相対パスは
envstringoptional- 設定ファイルから読み込む Wrangler 環境です。
varsRecord<string, Json>optional- テスト専用の変数です。Wrangler 設定ファイルの変数を上書きします。
secretsRecord<string, string>optional- テスト専用のシークレットです。
.dev.varsと.envファイルから読み込んだ値を上書きします。
- テスト専用のシークレットです。
bindingOverridesRecord<string, string>optional- テスト専用のサービスバインディング上書きです。キーはこの Worker の環境内のバインディング名です。値はこのテストハーネス内の Worker 名です。
各 WorkerInput は、config でインラインの Wrangler 設定オブジェクトを渡すこともできます。
const server = createTestHarness({
workers: [
{
config: {
name: "api-worker",
main: "src/api.ts",
compatibility_date: "YYYY-MM-DD",
},
},
],
});const server = createTestHarness({
workers: [
{
config: {
name: "api-worker",
main: "src/api.ts",
compatibility_date: "YYYY-MM-DD",
},
},
],
});createTestHarness() は、次のメソッドを持つ TestHarness オブジェクトを返します。
listen()Promise<{ url: URL }>- サーバーを起動し、現在の URL を返します。サーバーを閉じるかリセットするまで、繰り返し呼んでも同じセッションを返します。
fetch(input, init)Promise<Response>- サーバー経由で fetch リクエストを送ります。相対 URL は現在のサーバー URL に対して解決します。絶対 URL は設定した Worker ルートに従い、該当しなければプライマリ Worker にフォールバックします。
getWorker(name?)WorkerHandle- Worker へ直接イベントを送るハンドルを返します。名前を指定しない場合は、プライマリ Worker を返します。
getLogs()WorkerdStructuredLog[]- 現在のサーバーセッション開始以降、または最後に
clearLogs()を呼んで以降に捕捉した Workers ランタイムログを返します。
- 現在のサーバーセッション開始以降、または最後に
clearLogs()void- 捕捉した Workers ランタイムログをクリアします。
debug()void- このテストサーバーの診断タイムライン(サーバーイベントと捕捉した Workers ランタイムログを含む)を出力します。テストランナーの失敗時やクリーンアップフックで役立ちます。
update(optionsOrUpdater)Promise<void>TestHarnessOptionsオブジェクト、または現在のオプションを受けて次のオプションを返す関数で、サーバー設定を更新します。サーバーがまだ起動していなければ、listen()が使うオプションを設定します。サーバーが稼働中なら、稼働中の Worker を再読み込みします。稼働中のサーバーで Worker の数を更新することはサポートしていません。
reset()Promise<void>- 現在のセッションが最初に起動したときのオプションへサーバーを戻します。ストレージは再作成され、リセット後にサーバー URL が変わることがあります。
close()Promise<void>- サーバーを停止し、すべてのランタイムリソースを解放します。
getWorker(name?) は、次のメソッドを持つ WorkerHandle オブジェクトを返します。
fetch(input, init)Promise<Response>- この Worker へ fetch イベントを直接送ります。
scheduled(options)Promise<{ outcome: "ok" | "canceled" | "exception"; noRetry: boolean }>- この Worker へ scheduled イベントを直接送ります。
getEnv()Promise<Env>- この Worker に設定された環境オブジェクト全体(変数、シークレット、バインディングを含む)を返します。
getExport()Promise<Service<Module['default']>>- RPC メソッドを含む、既定の Worker エクスポートを返します。
applyD1Migrations(bindingName)Promise<void>- まだ実行していないローカル D1 マイグレーションファイルを、この Worker の D1 バインディングへ適用します。
getDurableObjectStorage(classNameOrBindingName, options)Promise<DurableObjectStorageHandle>- Durable Object インスタンスの SQL ストレージアクセスを返します。
introspectWorkflow(bindingName)Promise<WorkflowIntrospector>- このメソッド呼び出し以降に作成された Workflow インスタンス向けの introspector を作成します。
introspectWorkflowInstance(bindingName, instanceId)Promise<WorkflowInstanceIntrospector>- 特定の Workflow インスタンス向けの introspector を作成します。
次の例は、Node.js 組み込みのテストランナーを使います。
import assert from "node:assert/strict";
import { after, afterEach, before, describe, test } from "node:test";
import { createTestHarness } from "wrangler";
const server = createTestHarness({
workers: [
{ configPath: "./wrangler.web.jsonc" },
{ configPath: "./wrangler.api.jsonc" },
],
});
const apiWorker = server.getWorker("api-worker");
describe("Worker", () => {
before(async () => {
await server.listen();
});
afterEach(async () => {
await server.reset();
});
after(async () => {
await server.close();
});
test("dispatches through configured routes", async () => {
const response = await server.fetch("http://example.com/users/123");
assert.equal(response.status, 200);
});
test("calls a specific Worker directly", async () => {
const response = await apiWorker.fetch(
"http://api.example.com/v1/users/123",
);
assert.equal(response.status, 200);
});
test("triggers a scheduled handler", async () => {
const result = await apiWorker.scheduled({
cron: "0 0 * * *",
scheduledTime: new Date(),
});
assert.equal(result.outcome, "ok");
});
});import assert from "node:assert/strict";
import { after, afterEach, before, describe, test } from "node:test";
import { createTestHarness } from "wrangler";
const server = createTestHarness({
workers: [
{ configPath: "./wrangler.web.jsonc" },
{ configPath: "./wrangler.api.jsonc" },
],
});
const apiWorker = server.getWorker("api-worker");
describe("Worker", () => {
before(async () => {
await server.listen();
});
afterEach(async () => {
await server.reset();
});
after(async () => {
await server.close();
});
test("dispatches through configured routes", async () => {
const response = await server.fetch("http://example.com/users/123");
assert.equal(response.status, 200);
});
test("calls a specific Worker directly", async () => {
const response = await apiWorker.fetch(
"http://api.example.com/v1/users/123",
);
assert.equal(response.status, 200);
});
test("triggers a scheduled handler", async () => {
const result = await apiWorker.scheduled({
cron: "0 0 * * *",
scheduledTime: new Date(),
});
assert.equal(result.outcome, "ok");
});
});Worker の設定から TypeScript の型定義を生成します。この API は wrangler types CLI コマンドと同じ中核ロジックを使うため、CLI とプログラム向け API の出力は揃います。
CLI コマンドと異なり、experimental_generateTypes はディスクへ自動書き込みしません。代わりに、生成した型コンテンツを構造化した文字列として返し、呼び出し側で扱います。
import { experimental_generateTypes } from "wrangler";
const result = await experimental_generateTypes(options);-
optionsobjectoptional-
wrangler typesCLI フラグに対応する、任意のオプションオブジェクトです。-
configstring | string[]使う Wrangler 設定ファイルへのパスです。複数設定の型解決では配列にできます。
-
envstring型を生成する Wrangler 環境の名前です。
-
envFilestring[]ローカルの変数とシークレットを推論するときに読み込む
.envファイルへのパスです。 -
envInterfacestring生成する環境インターフェースの名前です。既定は
Envです。 -
includeEnvboolean出力に環境とバインディングの型を含めるかどうかです。既定は
trueです。 -
includeRuntimeboolean出力にランタイム型を含めるかどうかです。既定は
trueです。 -
pathstring生成した型の宣言ファイルへのパスです。既定は
worker-configuration.d.tsです。 -
strictVarsboolean変数に対して厳密なリテラル型とユニオン型を生成するかどうかです。既定は
trueです。
-
-
experimental_generateTypes() は、次のフィールドを含むオブジェクトへ解決する Promise を返します。
-
contentstring- ヘッダーと、env 型およびランタイム型の両方を含む、生成したすべてのセクションをまとめた整形済み出力です。
-
envstring | null- 生成した環境とバインディングの型です。env 型を除外した場合は
nullです。
- 生成した環境とバインディングの型です。env 型を除外した場合は
-
pathstring- この生成実行に関連する、対象の宣言ファイルパスです。
-
runtimestring | null- 生成したランタイム型です。ランタイム型を除外した場合は
nullです。
- 生成したランタイム型です。ランタイム型を除外した場合は
experimental_generateTypes で型をプログラムから生成し、自分でディスクへ書くか、ほかのツールへ渡せます。
import { experimental_generateTypes } from "wrangler";
import * as fs from "node:fs";
const result = await experimental_generateTypes({
config: "wrangler.json",
includeRuntime: true,
includeEnv: true,
});
// Write the combined content to the path specified in options
fs.writeFileSync(result.path, result.content, "utf-8");ランタイム型なしで env 型だけを生成するには:
const result = await experimental_generateTypes({
includeRuntime: false,
});特定環境向けに、カスタムのインターフェース名で型を生成するには:
const result = await experimental_generateTypes({
env: "staging",
envInterface: "StagingEnv",
path: "./types/staging.d.ts",
});この API は Wrangler の開発サーバー内部を公開し、実行方法をカスタマイズできます。たとえば、unstable_startWorker() で Worker に対する統合テストを実行できます。次の例は node:test を使いますが、ほかのテストフレームワークにも当てはまります。
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();
});
});Worker のテスト用 HTTP サーバーを起動します。
呼び出すと、unstable_dev はアドレスやポートを知らなくても Worker を呼べる fetch() 関数と、HTTP サーバーを停止する stop() 関数を返します。
既定では、unstable_dev はローカルサーバーに対する統合テストを行います。プレビュー Worker に対する e2e テストを行う場合は、unstable_dev() を呼ぶときの options オブジェクトで local: false を渡します。e2e テストは統合テストより大幅に遅くなることがあります。
const worker = await unstable_dev(script, options);-
scriptstring- Worker スクリプトへのパスを含む文字列です。Worker プロジェクトのルートディレクトリからの相対パスです。
-
optionsobjectoptionalwrangler devの設定を含む、任意のオプションオブジェクトです。options内にexperimentalオブジェクトを入れると、disableExperimentalWarningなどの実験的機能にアクセスできます。disableExperimentalWarningをtrueにすると、unstable_プレフィックス付き API の利用に関する Wrangler の警告を無効にします。
unstable_dev() は、次のメソッドを含むオブジェクトを返します。
-
fetch()Promise<Response> -
stop()Promise<void>- 開発サーバーを停止します。
各テストスイートの開始時に、beforeAll() 関数で unstable_dev() を起動します。beforeAll() を使うとオーバーヘッドを抑えられます。開発サーバーの起動には数百ミリ秒かかり、テストごとに起動と停止を繰り返すとすぐに積み上がり、テストが遅くなります。
各テストケースでは await worker.fetch() を呼び、レスポンスが期待どおりかを確認します。
テストスイートの終わりでは、afterAll 関数で await worker.stop() を呼びます。
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!"`);
});
});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!"`);
});
});ほかの Worker を呼ぶ Worker をテストできます。次の例では、ほかの Worker を呼ぶ側を親 Worker、呼ばれる側を子 Worker とします。
子 Worker を先に停止すると、親 Worker は子 Worker の存在を知らず、テストは失敗します。
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!");
});
});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 関数は、(ローカル の workerd バインディングへの)プロキシと、Cloudflare Workers 固有の値のエミュレーションを含むオブジェクトを取得する方法を提供します。Node.js プロセス内でこれらをエミュレートできます。
プラットフォームプロキシを取得する一般的な用途は、Workers 向けアプリでありながら Workers ランタイム外で動く場合(たとえば Node.js で動くフレームワークのローカル開発サーバー)のバインディングのエミュレーションや、テスト(たとえば、コードが特定の種類のバインディングと正しくやり取りすることを確認する)です。
const platform = await getPlatformProxy(options);optionsobjectoptional- バインディングの設定を含む、任意のオプションオブジェクトです。
-
environmentstring使う環境です。
-
configPathstring使う設定ファイルへのパスです。
パスを指定しない場合の既定動作は、現在のディレクトリからファイルシステムを上へたどり、使う Wrangler 設定ファイル を探すことです。
注意: このフィールドは任意ですが、パスを指定する場合は、ファイルシステム上の有効なファイルを指す必要があります。
-
persistboolean |{ path: string }バインディングデータを永続化するかどうかと、その場所です。
trueまたはundefinedの場合、Wrangler と同じ場所が既定になり、Wrangler と呼び出し側でデータを共有できます。falseの場合、ファイルシステムへの書き込みも読み込みも行いません。注意:
wranglerの--persist-toオプションを使う場合、このオプションは内部でv3というサブディレクトリを追加しますが、getPlatformProxyのpersistは追加しません。たとえばwrangler dev --persist-to ./my-directoryを実行した場合、getPlatformProxyで同じ場所を再利用するにはpersist: { path: "./my-directory/v3" }を指定する必要があります。 -
remoteBindingsboolean optional (default: `true`)リモートバインディング を有効にするかどうかです。
-
- バインディングの設定を含む、任意のオプションオブジェクトです。
getPlatformProxy() は、次のフィールドを含むオブジェクトへ解決する Promise を返します。
-
envRecord<string, unknown>- 本番のバインディングと同じように使える、バインディングへのプロキシを含むオブジェクトです。モジュール形式の Worker に 2 番目の引数として渡される
envオブジェクトと同じ形です。これらはworkerd内で動くバインディング実装へのプロキシです。 - TypeScript のヒント:
getPlatformProxy<Env>()はジェネリック関数です。バインディングレコードの形を型引数として渡すと、unknownなしで適切な型を得られます。
- 本番のバインディングと同じように使える、バインディングへのプロキシを含むオブジェクトです。モジュール形式の Worker に 2 番目の引数として渡される
-
cfIncomingRequestCfProperties read-onlyRequestのcfプロパティのモックです。本番で見られるものに近いデータを含みます。
-
ctxobjectwaitUntilとpassThroughOnExceptionの何もしない実装を含むモックオブジェクトです。
-
cachesobject- Workers の
cachesランタイム API のエミュレーションです。 - 現時点では、すべてのキャッシュ操作は何もしません。より正確なエミュレーションは近日提供予定です。
- Workers の
-
dispose()() =>Promise<void>- 基盤の
workerdプロセスを終了します。 - プログラムがプラットフォームプロキシを必要としなくなったあとに呼んでください。開発サーバーのような長時間プロセスで、プロキシを無期限に使える場合は、この関数を呼ぶ必要はありません。
- 基盤の
getPlatformProxy 関数は、Wrangler 設定ファイル にあるバインディングを使います。たとえば、Wrangler 設定ファイルに 環境変数 の設定がある場合:
{
"vars": {
"MY_VARIABLE": "test"
}
}[vars]
MY_VARIABLE = "test"次のように getPlatformProxy をインポートして、バインディングへアクセスできます。
import { getPlatformProxy } from "wrangler";
const { env } = await getPlatformProxy();MY_VARIABLE バインディングの値にアクセスするには、コードに次を追加します。
console.log(`MY_VARIABLE = ${env.MY_VARIABLE}`);次の出力が印刷されます: MY_VARIABLE = test。
Wrangler 設定ファイル にある、サポート対象のバインディングはすべて env 経由で使えます。
getPlatformProxy がサポートするバインディングは次のとおりです。
-
-
getPlatformProxyで Durable Object バインディングを使う場合は、常にscript_nameを指定してください。たとえば、
getPlatformProxyが読む Wrangler 設定ファイルに、次のバインディングがあるとします。{ "durable_objects": { "bindings": [ { "name": "MyDurableObject", "class_name": "MyDurableObject", "script_name": "external-do-worker" } ] } }[[durable_objects.bindings]] name = "MyDurableObject" class_name = "MyDurableObject" script_name = "external-do-worker"Durable Object
"MyDurableObject"は、この例ではexternal-do-workerという別の Worker で宣言する必要があります。./external-do-worker/src/index.tsts export class MyDurableObject extends DurableObject { // Your DO code goes here } export default { fetch() { // Doesn't have to do anything, but a DO cannot be the default export return new Response("Hello, world!"); }, };その Worker にも、次のような Wrangler 設定ファイルが必要です。
{ "name": "external-do-worker", "main": "src/index.ts", "compatibility_date": "XXXX-XX-XX" }name = "external-do-worker" main = "src/index.ts" compatibility_date = "XXXX-XX-XX"Durable Object で RPC を使っていない場合は、フレームワークの開発サーバーと並行して、別の Wrangler 開発セッションを実行できます。
そうでない場合は、アプリをビルドし、同じ Wrangler 開発セッションで両方の Worker を実行できます。
Pages を使っている場合は、次を実行します。
npx wrangler pages dev -c path/to/pages/wrangler.jsonc -c path/to/external-do-worker/wrangler.jsoncyarn wrangler pages dev -c path/to/pages/wrangler.jsonc -c path/to/external-do-worker/wrangler.jsoncpnpm wrangler pages dev -c path/to/pages/wrangler.jsonc -c path/to/external-do-worker/wrangler.jsoncWorkers with Assets を使っている場合は、次を実行します。
npx wrangler dev -c path/to/workers-assets/wrangler.jsonc -c path/to/external-do-worker/wrangler.jsoncyarn wrangler dev -c path/to/workers-assets/wrangler.jsonc -c path/to/external-do-worker/wrangler.jsoncpnpm wrangler dev -c path/to/workers-assets/wrangler.jsonc -c path/to/external-do-worker/wrangler.jsonc
-