Files
wehub-resource-sync 70bf21e064
Deploy (to testing) and Test Playground Preview Worker / Deploy Playground Preview Worker (testing) (push) Has been skipped
Deploy Workers Shared Staging / Deploy Workers Shared Staging (push) Failing after 0s
Prerelease / build (push) Has been skipped
Handle Changesets / Handle Changesets (push) Has been cancelled
Semgrep OSS scan / semgrep-oss (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:11 +08:00

385 lines
12 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import path from "path";
import { D1Database, R2Bucket } from "@cloudflare/workers-types";
import { toMatchImageSnapshot } from "jest-image-snapshot";
import { beforeEach, describe, it, MockInstance, vi } from "vitest";
import { getPlatformProxy } from "./shared";
import type {
Fetcher,
Hyperdrive,
ImagesBinding,
KVNamespace,
Workflow,
} from "@cloudflare/workers-types";
type Env = {
MY_VAR: string;
MY_VAR_A: string;
MY_JSON_VAR: Object;
MY_DEV_VAR: string;
MY_KV: KVNamespace;
MY_KV_PROD: KVNamespace;
MY_BUCKET: R2Bucket;
MY_D1: D1Database;
MY_HYPERDRIVE: Hyperdrive;
ASSETS: Fetcher;
IMAGES: ImagesBinding;
MY_WORKFLOW_INTERNAL: Workflow;
MY_WORKFLOW_EXTERNAL: Workflow;
};
const wranglerConfigFilePath = path.join(__dirname, "..", "wrangler.jsonc");
describe("getPlatformProxy - env", () => {
let warn = {} as MockInstance<typeof console.warn>;
beforeEach(() => {
// Hide stdout messages from the test logs
vi.spyOn(console, "log").mockImplementation(() => {});
vi.spyOn(console, "error").mockImplementation(() => {});
warn = vi.spyOn(console, "warn").mockImplementation(() => {});
warn.mockClear();
});
describe("var bindings", () => {
it("correctly obtains var bindings from both wrangler config and .dev.vars", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { MY_VAR, MY_JSON_VAR, MY_DEV_VAR } = env;
expect(MY_VAR).toEqual("my-var-value");
expect(MY_JSON_VAR).toEqual({
test: true,
});
expect(MY_DEV_VAR).toEqual("my-dev-var-value");
} finally {
await dispose();
}
});
it("correctly makes vars from .dev.vars override the ones in wrangler config", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { MY_VAR_A } = env;
expect(MY_VAR_A).not.toEqual("my-var-a"); // if this fails, the value was read from wrangler config not .dev.vars
expect(MY_VAR_A).toEqual("my-dev-var-a");
} finally {
await dispose();
}
});
it("correctly makes vars from .dev.vars not override bindings of the same name from wrangler config", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { MY_KV } = env;
expect(MY_KV).not.toEqual("my-dev-kv");
["get", "delete", "list", "put", "getWithMetadata"].every(
(methodName) =>
expect(
typeof (MY_KV as unknown as Record<string, unknown>)[methodName]
).toBe("function")
);
} finally {
await dispose();
}
});
it("correctly reads a toml from a custom path alongside with its .dev.vars", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: path.join(
__dirname,
"..",
"custom-toml",
"path",
"test.toml"
),
});
try {
const { MY_VAR, MY_JSON_VAR, MY_DEV_VAR } = env;
expect(MY_VAR).toEqual("my-var-value-from-a-custom-toml");
expect(MY_JSON_VAR).toEqual({
test: true,
customToml: true,
});
expect(MY_DEV_VAR).toEqual("my-dev-var-value-from-a-custom-location");
} finally {
await dispose();
}
});
});
it("correctly reads a json config file", async ({ expect }) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: path.join(__dirname, "..", "wrangler.json"),
});
try {
const { MY_VAR, MY_JSON_VAR } = env;
expect(MY_VAR).toEqual("my-var-value-from-a-json-config-file");
expect(MY_JSON_VAR).toEqual({
test: true,
fromJson: true,
});
} finally {
await dispose();
}
});
it("correctly obtains functioning ASSETS bindings", async ({ expect }) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
const res = await env.ASSETS.fetch("https://0.0.0.0/test.txt");
const text = await res.text();
expect(text).toEqual("this is a test text file!\n");
await dispose();
});
it("correctly obtains functioning KV bindings", async ({ expect }) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
const { MY_KV } = env;
let numOfKeys = (await MY_KV.list()).keys.length;
expect(numOfKeys).toBe(0);
await MY_KV.put("my-key", "my-value");
numOfKeys = (await MY_KV.list()).keys.length;
expect(numOfKeys).toBe(1);
const value = await MY_KV.get("my-key");
expect(value).toBe("my-value");
await dispose();
});
it("correctly obtains functioning R2 bindings", async ({ expect }) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { MY_BUCKET } = env;
let numOfObjects = (await MY_BUCKET.list()).objects.length;
expect(numOfObjects).toBe(0);
await MY_BUCKET.put("my-object", "my-value");
numOfObjects = (await MY_BUCKET.list()).objects.length;
expect(numOfObjects).toBe(1);
const value = await MY_BUCKET.get("my-object");
expect(await value?.text()).toBe("my-value");
} finally {
await dispose();
}
});
it("correctly obtains functioning D1 bindings", async ({ expect }) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { MY_D1 } = env;
await MY_D1.exec(
`CREATE TABLE IF NOT EXISTS users ( id integer PRIMARY KEY AUTOINCREMENT, name text NOT NULL )`
);
const stmt = MY_D1.prepare("insert into users (name) values (?1)");
await MY_D1.batch([
stmt.bind("userA"),
stmt.bind("userB"),
stmt.bind("userC"),
]);
const { results } = await MY_D1.prepare(
"SELECT name FROM users LIMIT 5"
).all();
expect(results).toEqual([
{ name: "userA" },
{ name: "userB" },
{ name: "userC" },
]);
} finally {
await dispose();
}
});
it("correctly obtains functioning Image bindings", async ({ expect }) => {
expect.extend({ toMatchImageSnapshot });
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { IMAGES } = env;
const streams = (
await fetch("https://playground.devprod.cloudflare.dev/flares.png")
).body!.tee();
// @ts-expect-error The stream types aren't matching up properly?
expect(await IMAGES.info(streams[0])).toMatchInlineSnapshot(`
{
"fileSize": 96549,
"format": "image/png",
"height": 1145,
"width": 2048,
}
`);
// @ts-expect-error The stream types aren't matching up properly?
const response = await env.IMAGES.input(streams[1])
.transform({ rotate: 90 })
.transform({ width: 128, height: 100 })
.transform({ blur: 20 })
.output({ format: "image/png" });
expect(
Buffer.from(await response.response().arrayBuffer())
).toMatchImageSnapshot();
} finally {
await dispose();
}
});
// Important: the hyperdrive values are passthrough ones since the workerd specific hyperdrive values only make sense inside
// workerd itself and would simply not work in a node.js process
it("correctly obtains passthrough Hyperdrive bindings", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
const { MY_HYPERDRIVE } = env;
expect(MY_HYPERDRIVE.connectionString).toEqual(
"postgres://user:pass@127.0.0.1:1234/db"
);
expect(MY_HYPERDRIVE.database).toEqual("db");
expect(MY_HYPERDRIVE.host).toEqual("127.0.0.1");
expect(MY_HYPERDRIVE.user).toEqual("user");
expect(MY_HYPERDRIVE.password).toEqual("pass");
expect(MY_HYPERDRIVE.port).toEqual(1234);
} finally {
await dispose();
}
});
describe("DO warnings", () => {
it("warns about internal DOs and doesn't crash", async ({ expect }) => {
await getPlatformProxy<Env>({
configPath: path.join(__dirname, "..", "wrangler_internal_do.jsonc"),
});
expect(warn.mock.calls[0][0].replaceAll(/[\r\n]+/g, "\n"))
.toMatchInlineSnapshot(`
"▲ [WARNING]  You have defined bindings to the following internal Durable Objects:
- {"class_name":"MyDurableObject","name":"MY_DURABLE_OBJECT"}
These will not work in local development, but they should work in production.
If you want to develop these locally, you can define your DO in a separate Worker, with a separate configuration file.
For detailed instructions, refer to the Durable Objects section here: https://developers.cloudflare.com/workers/wrangler/api#supported-bindings
"
`);
});
it("doesn't warn about external DOs and doesn't crash", async ({
expect,
}) => {
await getPlatformProxy<Env>({
configPath: path.join(__dirname, "..", "wrangler_external_do.jsonc"),
});
expect(warn).not.toHaveBeenCalled();
});
it("warns only about internal Workflows, not cross-script ones, and doesn't crash", async ({
expect,
}) => {
await getPlatformProxy<Env>({
configPath: path.join(__dirname, "..", "wrangler_workflow.jsonc"),
});
// Only MY_WORKFLOW_INTERNAL (no script_name) is unsupported in
// getPlatformProxy(); MY_WORKFLOW_EXTERNAL (script_name set) is
// passed through to miniflare, which routes it via the dev-registry
// proxy to the named worker.
expect(warn).toHaveBeenCalledTimes(1);
expect(warn.mock.calls[0][0].replaceAll(/[\r\n]+/g, "\n"))
.toMatchInlineSnapshot(`
"▲ [WARNING] You have defined bindings to the following Workflows without a script_name:
- {"binding":"MY_WORKFLOW_INTERNAL","name":"my-workflow-internal","class_name":"MyWorkflowInternal"}
These are not available in local development, so you will not be able to bind to them when testing locally, but they should work in production.
"
`);
});
});
describe("with a target environment", () => {
it("should provide bindings targeting a specified environment and also inherit top-level ones", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
environment: "production",
});
try {
expect(env.MY_VAR).not.toBe("my-var-value");
expect(env.MY_VAR).toBe("my-PRODUCTION-var-value");
expect(env.MY_JSON_VAR).toEqual({ test: true, production: true });
expect(env.MY_KV).toBeTruthy();
expect(env.MY_KV_PROD).toBeTruthy();
} finally {
await dispose();
}
});
it("should not provide bindings targeting an environment when none was specified", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
});
try {
expect(env.MY_VAR).not.toBe("my-PRODUCTION-var-value");
expect(env.MY_VAR).toBe("my-var-value");
expect(env.MY_JSON_VAR).toEqual({ test: true });
expect(env.MY_KV).toBeTruthy();
expect(env.MY_KV_PROD).toBeFalsy();
} finally {
await dispose();
}
});
it("should provide secrets targeting a specified environment", async ({
expect,
}) => {
const { env, dispose } = await getPlatformProxy<Env>({
configPath: wranglerConfigFilePath,
environment: "production",
});
try {
const { MY_DEV_VAR } = env;
expect(MY_DEV_VAR).not.toEqual("my-dev-var-value");
expect(MY_DEV_VAR).toEqual("my-PRODUCTION-dev-var-value");
} finally {
await dispose();
}
});
it("should error if a non-existent environment is provided", async ({
expect,
}) => {
await expect(
getPlatformProxy({
configPath: wranglerConfigFilePath,
environment: "non-existent-environment",
})
).rejects.toThrow(
/No environment found in configuration with name "non-existent-environment"/
);
});
});
});