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
10783 lines
322 KiB
TypeScript
10783 lines
322 KiB
TypeScript
import path from "node:path";
|
||
import TOML from "smol-toml";
|
||
import { assert, describe, it, test, vi } from "vitest";
|
||
import { normalizeAndValidateConfig } from "../../../src/config/validation";
|
||
import { normalizeString } from "../../../src/test-helpers";
|
||
import type {
|
||
Config,
|
||
ConfigFields,
|
||
RawConfig,
|
||
RawDevConfig,
|
||
RawEnvironment,
|
||
} from "../../../src/config";
|
||
import type { RedirectedRawConfig } from "../../../src/config/config";
|
||
import type { DurableObjectExport } from "../../../src/config/environment";
|
||
|
||
describe("normalizeAndValidateConfig()", () => {
|
||
it("should use defaults for empty configuration", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{},
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: undefined,
|
||
}
|
||
);
|
||
|
||
expect(config).toEqual({
|
||
account_id: undefined,
|
||
build: {
|
||
command: undefined,
|
||
cwd: undefined,
|
||
watch_dir: "./src",
|
||
},
|
||
compatibility_date: undefined,
|
||
compatibility_flags: [],
|
||
configPath: undefined,
|
||
d1_databases: [],
|
||
vectorize: [],
|
||
ai_search_namespaces: [],
|
||
ai_search: [],
|
||
agent_memory: [],
|
||
hyperdrive: [],
|
||
dev: {
|
||
ip: process.platform === "win32" ? "127.0.0.1" : "localhost",
|
||
local_protocol: "http",
|
||
port: undefined, // the default of 8787 is set at runtime
|
||
upstream_protocol: "http",
|
||
host: undefined,
|
||
enable_containers: true,
|
||
inspector_port: undefined,
|
||
inspector_ip: undefined,
|
||
container_engine: undefined,
|
||
generate_types: false,
|
||
},
|
||
containers: undefined,
|
||
cloudchamber: {},
|
||
durable_objects: {
|
||
bindings: [],
|
||
},
|
||
jsx_factory: "React.createElement",
|
||
jsx_fragment: "React.Fragment",
|
||
tsconfig: undefined,
|
||
kv_namespaces: [],
|
||
send_email: [],
|
||
logfwdr: {
|
||
bindings: [],
|
||
},
|
||
send_metrics: undefined,
|
||
dependencies_instrumentation: undefined,
|
||
main: undefined,
|
||
migrations: [],
|
||
exports: {},
|
||
name: undefined,
|
||
queues: {
|
||
consumers: [],
|
||
producers: [],
|
||
},
|
||
r2_buckets: [],
|
||
secrets_store_secrets: [],
|
||
artifacts: [],
|
||
unsafe_hello_world: [],
|
||
flagship: [],
|
||
ratelimits: [],
|
||
vpc_services: [],
|
||
vpc_networks: [],
|
||
services: [],
|
||
analytics_engine_datasets: [],
|
||
route: undefined,
|
||
routes: undefined,
|
||
rules: [],
|
||
site: undefined,
|
||
text_blobs: undefined,
|
||
browser: undefined,
|
||
ai: undefined,
|
||
websearch: undefined,
|
||
version_metadata: undefined,
|
||
triggers: {
|
||
crons: undefined,
|
||
},
|
||
unsafe: {
|
||
bindings: undefined,
|
||
metadata: undefined,
|
||
},
|
||
dispatch_namespaces: [],
|
||
mtls_certificates: [],
|
||
vars: {},
|
||
define: {},
|
||
definedEnvironments: [],
|
||
targetEnvironment: undefined,
|
||
wasm_modules: undefined,
|
||
data_blobs: undefined,
|
||
workers_dev: undefined,
|
||
preview_urls: undefined,
|
||
python_modules: { exclude: ["**/*.pyc"] },
|
||
no_bundle: undefined,
|
||
minify: undefined,
|
||
first_party_worker: undefined,
|
||
keep_vars: undefined,
|
||
logpush: undefined,
|
||
upload_source_maps: undefined,
|
||
placement: undefined,
|
||
worker_loaders: [],
|
||
tail_consumers: undefined,
|
||
streaming_tail_consumers: undefined,
|
||
pipelines: [],
|
||
workflows: [],
|
||
userConfigPath: undefined,
|
||
topLevelName: undefined,
|
||
alias: undefined,
|
||
find_additional_modules: undefined,
|
||
preserve_file_names: undefined,
|
||
base_dir: undefined,
|
||
limits: undefined,
|
||
keep_names: undefined,
|
||
assets: undefined,
|
||
observability: undefined,
|
||
cache: undefined,
|
||
compliance_region: undefined,
|
||
images: undefined,
|
||
media: undefined,
|
||
stream: undefined,
|
||
previews: undefined,
|
||
} satisfies Config);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
describe("top-level non-environment configuration", () => {
|
||
it("should override config defaults with provided values", ({ expect }) => {
|
||
const expectedConfig: Partial<ConfigFields<RawDevConfig>> = {
|
||
send_metrics: false,
|
||
dev: {
|
||
ip: "255.255.255.255",
|
||
port: 9999,
|
||
local_protocol: "https",
|
||
upstream_protocol: "http",
|
||
enable_containers: false,
|
||
generate_types: false,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid top level fields", ({ expect }) => {
|
||
const expectedConfig = {
|
||
send_metrics: "BAD",
|
||
dependencies_instrumentation: "NOPE" as unknown,
|
||
keep_vars: "NEVER",
|
||
dev: {
|
||
ip: 222,
|
||
port: "FOO",
|
||
local_protocol: "wss",
|
||
upstream_protocol: "ws",
|
||
enable_containers: true,
|
||
generate_types: false,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
...expectedConfig,
|
||
main: undefined,
|
||
})
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "send_metrics" to be of type boolean but got "BAD".
|
||
- Expected "dependencies_instrumentation" to be of type object but got "NOPE".
|
||
- Expected "keep_vars" to be of type boolean but got "NEVER".
|
||
- Expected "dev.ip" to be of type string but got 222.
|
||
- Expected "dev.port" to be of type number but got "FOO".
|
||
- Expected "dev.local_protocol" field to be one of ["http","https"] but got "wss".
|
||
- Expected "dev.upstream_protocol" field to be one of ["http","https"] but got "ws"."
|
||
`);
|
||
});
|
||
|
||
it("should error if the deprecated `legacy_env` field is present", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ legacy_env: true } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The "legacy_env" field is no longer supported, so please remove it from your configuration file.
|
||
Service environments have been removed, and each environment is now deployed as its own Worker named "<name>-<environment>". This matches the behaviour of "legacy_env = true", which was the default, so removing the field will not change how your Worker is deployed.
|
||
Refer to https://developers.cloudflare.com/workers/wrangler/environments/ for more information."
|
||
`);
|
||
});
|
||
|
||
it("should warn on and remove unexpected top level fields", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig = {
|
||
unexpected: {
|
||
subkey: "some-value",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect("unexpected" in config).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in top-level field: "unexpected""
|
||
`);
|
||
});
|
||
|
||
it("should report a deprecation warning if `miniflare` appears at the top level", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig = {
|
||
miniflare: {
|
||
host: "localhost",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect("miniflare" in config).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in top-level field: "miniflare""
|
||
`);
|
||
});
|
||
|
||
it("should normalise a blank route value to be undefined", ({ expect }) => {
|
||
const expectedConfig = {
|
||
route: "",
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.route).toBeUndefined();
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The "route" field in your configuration is an empty string and will be ignored.
|
||
Please remove the "route" field from your configuration."
|
||
`);
|
||
});
|
||
|
||
it("should normalise a blank account_id value to be undefined", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig = {
|
||
account_id: "",
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.account_id).toBeUndefined();
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The "account_id" field in your configuration is an empty string and will be ignored.
|
||
Please remove the "account_id" field from your configuration."
|
||
`);
|
||
});
|
||
|
||
describe("compatibility_date", () => {
|
||
it("should allow valid values", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
compatibility_date: "2024-10-01",
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error for en-dashes", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
compatibility_date: "2024–10–01", // en-dash
|
||
};
|
||
|
||
const result = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: undefined,
|
||
}
|
||
);
|
||
|
||
expect(result.config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(result.diagnostics.hasWarnings()).toBe(false);
|
||
expect(result.diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(normalizeString(result.diagnostics.renderErrors()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "compatibility_date" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—)."
|
||
`);
|
||
});
|
||
|
||
it("should error for em-dashes", ({ expect }) => {
|
||
const expectedConfig = {
|
||
compatibility_date: "2024—10—01", // em-dash
|
||
};
|
||
|
||
const result = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: undefined,
|
||
}
|
||
);
|
||
|
||
expect(result.config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(result.diagnostics.hasWarnings()).toBe(false);
|
||
expect(result.diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(normalizeString(result.diagnostics.renderErrors()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "compatibility_date" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—)."
|
||
`);
|
||
});
|
||
|
||
it("should error for invalid date values", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
compatibility_date: "abc",
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(normalizeString(diagnostics.renderErrors()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "compatibility_date" field should be a valid ISO-8601 date (YYYY-MM-DD), but got "abc"."
|
||
`);
|
||
});
|
||
|
||
it("should error for dates that are both invalid and include en/em dashes", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig = {
|
||
compatibility_date: "2024—100—01", // invalid date + em-dash
|
||
};
|
||
|
||
const result = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: undefined,
|
||
}
|
||
);
|
||
|
||
expect(result.config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(result.diagnostics.hasWarnings()).toBe(false);
|
||
expect(result.diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(normalizeString(result.diagnostics.renderErrors()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "compatibility_date" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—).
|
||
- "compatibility_date" field should be a valid ISO-8601 date (YYYY-MM-DD), but got "2024—100—01"."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[site]", () => {
|
||
it("should override `site` config defaults with provided values", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
site: {
|
||
bucket: "BUCKET",
|
||
"entry-point": "my-site",
|
||
exclude: ["EXCLUDE_1", "EXCLUDE_2"],
|
||
include: ["INCLUDE_1", "INCLUDE_2"],
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
|
||
expect(normalizeString(diagnostics.renderWarnings()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- [1mDeprecation[0m: "site.entry-point":
|
||
Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
|
||
\`\`\`
|
||
main = "my-site/index.js"
|
||
\`\`\`"
|
||
`);
|
||
});
|
||
|
||
it("should error if `site` config is missing `bucket`", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
// @ts-expect-error we're intentionally passing an invalid configuration here
|
||
site: {
|
||
"entry-point": "workers-site",
|
||
include: ["INCLUDE_1", "INCLUDE_2"],
|
||
exclude: ["EXCLUDE_1", "EXCLUDE_2"],
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(normalizeString(diagnostics.renderWarnings()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- [1mDeprecation[0m: "site.entry-point":
|
||
Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
|
||
\`\`\`
|
||
main = "workers-site/index.js"
|
||
\`\`\`"
|
||
`);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "site.bucket" is a required field."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid `site` values", ({ expect }) => {
|
||
const expectedConfig = {
|
||
site: {
|
||
bucket: "BUCKET",
|
||
"entry-point": 111,
|
||
include: [222, 333],
|
||
exclude: [444, 555],
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "sites.include.[0]" to be of type string but got 222.
|
||
- Expected "sites.include.[1]" to be of type string but got 333.
|
||
- Expected "sites.exclude.[0]" to be of type string but got 444.
|
||
- Expected "sites.exclude.[1]" to be of type string but got 555.
|
||
- Expected "site.entry-point" to be of type string but got 111."
|
||
`);
|
||
|
||
expect(normalizeString(diagnostics.renderWarnings()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- [1mDeprecation[0m: "site.entry-point":
|
||
Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
|
||
\`\`\`
|
||
main = "111/index.js"
|
||
\`\`\`"
|
||
`);
|
||
});
|
||
|
||
it("should log a deprecation warning if entry-point is defined", async ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
site: {
|
||
bucket: "some/path",
|
||
"entry-point": "some/other/script.js",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.site).toMatchInlineSnapshot(`
|
||
{
|
||
"bucket": "some/path",
|
||
"entry-point": "some/other/script.js",
|
||
"exclude": [],
|
||
"include": [],
|
||
}
|
||
`);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
|
||
expect(normalizeString(diagnostics.renderWarnings()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- [1mDeprecation[0m: "site.entry-point":
|
||
Delete the \`site.entry-point\` field, then add the top level \`main\` field to your configuration file:
|
||
\`\`\`
|
||
main = "some/other/script.js"
|
||
\`\`\`"
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[alias]", () => {
|
||
it("errors with a non-object", ({ expect }) => {
|
||
const { config: _config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
alias: "some silly string",
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected alias to be an object, but got string"
|
||
`);
|
||
});
|
||
|
||
it("errors with non string values", ({ expect }) => {
|
||
const { config: _config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
alias: {
|
||
"some-module": 123,
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected alias["some-module"] to be a string, but got number"
|
||
`);
|
||
});
|
||
|
||
it("returns the alias config when valid", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
alias: {
|
||
"some-module": "./path/to/some-module",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
|
||
expect(config.alias).toMatchInlineSnapshot(`
|
||
{
|
||
"some-module": "./path/to/some-module",
|
||
}
|
||
`);
|
||
});
|
||
});
|
||
|
||
it("should map `wasm_module` paths from relative to the config path to relative to the cwd", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
wasm_modules: {
|
||
MODULE_1: "path/to/module_1.mjs",
|
||
MODULE_2: "module_2.mjs",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
wasm_modules: {
|
||
MODULE_1: path.normalize("project/path/to/module_1.mjs"),
|
||
MODULE_2: path.normalize("project/module_2.mjs"),
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should warn on unexpected fields on `triggers`", async ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
triggers: {
|
||
crons: ["1 * * * *"],
|
||
// @ts-expect-error we're purposely adding a field
|
||
// that doesn't belong here
|
||
someOtherfield: 123,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
triggers: {
|
||
crons: ["1 * * * *"],
|
||
someOtherfield: 123,
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
|
||
expect(normalizePath(diagnostics.renderWarnings()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing project/wrangler.toml configuration:
|
||
- Unexpected fields found in triggers field: "someOtherfield""
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid `wasm_modules` paths", ({ expect }) => {
|
||
const expectedConfig = {
|
||
wasm_modules: {
|
||
MODULE_1: 111,
|
||
MODULE_2: 222,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
wasm_modules: {},
|
||
})
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
|
||
"Processing project/wrangler.toml configuration:
|
||
- Expected "wasm_modules['MODULE_1']" to be of type string but got 111.
|
||
- Expected "wasm_modules['MODULE_2']" to be of type string but got 222."
|
||
`);
|
||
});
|
||
|
||
it("should map `text_blobs` paths from relative to the config path to relative to the cwd", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
text_blobs: {
|
||
BLOB_1: "path/to/text1.txt",
|
||
BLOB_2: "text2.md",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
text_blobs: {
|
||
BLOB_1: path.normalize("project/path/to/text1.txt"),
|
||
BLOB_2: path.normalize("project/text2.md"),
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid `text_blob` paths", ({ expect }) => {
|
||
const expectedConfig = {
|
||
text_blobs: {
|
||
MODULE_1: 111,
|
||
MODULE_2: 222,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
text_blobs: {},
|
||
})
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
|
||
"Processing project/wrangler.toml configuration:
|
||
- Expected "text_blobs['MODULE_1']" to be of type string but got 111.
|
||
- Expected "text_blobs['MODULE_2']" to be of type string but got 222."
|
||
`);
|
||
});
|
||
|
||
it("should map `data_blobs` paths from relative to the config path to relative to the cwd", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
data_blobs: {
|
||
BLOB_1: "path/to/data1.bin",
|
||
BLOB_2: "data2.bin",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
data_blobs: {
|
||
BLOB_1: path.normalize("project/path/to/data1.bin"),
|
||
BLOB_2: path.normalize("project/data2.bin"),
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid `data_blob` paths", ({ expect }) => {
|
||
const expectedConfig = {
|
||
data_blobs: {
|
||
MODULE_1: 111,
|
||
MODULE_2: 222,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
data_blobs: {},
|
||
})
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(normalizePath(diagnostics.renderErrors())).toMatchInlineSnapshot(`
|
||
"Processing project/wrangler.toml configuration:
|
||
- Expected "data_blobs['MODULE_1']" to be of type string but got 111.
|
||
- Expected "data_blobs['MODULE_2']" to be of type string but got 222."
|
||
`);
|
||
});
|
||
|
||
it("should resolve tsconfig relative to wrangler.toml", async ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
tsconfig: "path/to/some-tsconfig.json",
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
tsconfig: path.normalize("project/path/to/some-tsconfig.json"),
|
||
})
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should warn on unsafe binding metadata usage", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
unsafe: {
|
||
bindings: [
|
||
{
|
||
type: "metadata",
|
||
name: "METADATA",
|
||
},
|
||
],
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
unsafe: {
|
||
bindings: [
|
||
{
|
||
type: "metadata",
|
||
name: "METADATA",
|
||
},
|
||
],
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
|
||
expect(normalizeString(diagnostics.renderWarnings()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing project/wrangler.toml configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time.
|
||
- "unsafe.bindings[0]": {"type":"metadata","name":"METADATA"}
|
||
- The deployment object in the metadata binding is now deprecated. Please switch using the version_metadata binding for access to version specific fields: https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata"
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("top-level environment configuration", () => {
|
||
it("should override config defaults with provided values", ({ expect }) => {
|
||
const main = "src/index.ts";
|
||
const resolvedMain = path.resolve(process.cwd(), main);
|
||
|
||
const expectedConfig: RawEnvironment = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
routes: [
|
||
"ROUTE_1",
|
||
"ROUTE_2",
|
||
{ pattern: "ROUTE3", zone_id: "ZONE_ID_3" },
|
||
"ROUTE_4",
|
||
],
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
tsconfig: "path/to/tsconfig",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
main,
|
||
build: {
|
||
command: "COMMAND",
|
||
cwd: "CWD",
|
||
watch_dir: "WATCH_DIR",
|
||
},
|
||
define: {
|
||
DEF1: "DEFINE_1",
|
||
DEF2: "DEFINE_2",
|
||
},
|
||
vars: {
|
||
VAR1: "VALUE_1",
|
||
VAR2: "VALUE_2",
|
||
},
|
||
cloudchamber: {},
|
||
durable_objects: {
|
||
bindings: [
|
||
{ name: "DO_BINDING_1", class_name: "CLASS1" },
|
||
{
|
||
name: "DO_BINDING_2",
|
||
class_name: "CLASS2",
|
||
script_name: "SCRIPT2",
|
||
},
|
||
{
|
||
name: "DO_BINDING_3",
|
||
class_name: "CLASS3",
|
||
script_name: "SCRIPT3",
|
||
environment: "ENV3",
|
||
},
|
||
],
|
||
},
|
||
kv_namespaces: [
|
||
{ binding: "KV_BINDING_1", id: "KV_ID_1" },
|
||
{
|
||
binding: "KV_BINDING_2",
|
||
id: "KV_ID_2",
|
||
preview_id: "KV_PREVIEW_1",
|
||
},
|
||
],
|
||
send_email: [
|
||
{ name: "SEB_TARGET", destination_address: "teste@example.com" },
|
||
{ name: "SEB_UNRESTRICTED" },
|
||
{
|
||
name: "SEB_ALLOWLIST",
|
||
allowed_destination_addresses: [
|
||
"email1@example.com",
|
||
"email2@example.com",
|
||
],
|
||
},
|
||
],
|
||
r2_buckets: [
|
||
{ binding: "R2_BINDING_1", bucket_name: "r2-bucket-1" },
|
||
{
|
||
binding: "R2_BINDING_2",
|
||
bucket_name: "r2-bucket-2",
|
||
preview_bucket_name: "r2-preview-2",
|
||
},
|
||
],
|
||
services: [
|
||
{
|
||
binding: "SERVICE_BINDING_1",
|
||
service: "SERVICE_TYPE_1",
|
||
environment: "SERVICE_BINDING_ENVIRONMENT_1",
|
||
entrypoint: "SERVICE_BINDING_ENVIRONMENT_1",
|
||
},
|
||
],
|
||
analytics_engine_datasets: [
|
||
{
|
||
binding: "AE_BINDING_1",
|
||
dataset: "DATASET_1",
|
||
},
|
||
{
|
||
binding: "AE_BINDING_2",
|
||
},
|
||
],
|
||
unsafe: {
|
||
bindings: [
|
||
{ name: "UNSAFE_BINDING_1", type: "UNSAFE_TYPE_1" },
|
||
{
|
||
name: "UNSAFE_BINDING_2",
|
||
type: "UNSAFE_TYPE_2",
|
||
extra: "UNSAFE_EXTRA_1",
|
||
},
|
||
],
|
||
metadata: undefined,
|
||
},
|
||
no_bundle: true,
|
||
minify: true,
|
||
first_party_worker: true,
|
||
logpush: true,
|
||
upload_source_maps: true,
|
||
placement: {
|
||
mode: "smart",
|
||
},
|
||
observability: {
|
||
enabled: true,
|
||
head_sampling_rate: 1,
|
||
logs: {
|
||
enabled: true,
|
||
head_sampling_rate: 1,
|
||
invocation_logs: true,
|
||
destinations: ["test"],
|
||
persist: true,
|
||
},
|
||
traces: {
|
||
enabled: true,
|
||
head_sampling_rate: 1,
|
||
destinations: ["test"],
|
||
persist: true,
|
||
},
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"wrangler.toml",
|
||
"wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
assert(config.tsconfig);
|
||
expect({ ...config, tsconfig: normalizePath(config.tsconfig) }).toEqual(
|
||
expect.objectContaining({
|
||
...expectedConfig,
|
||
main: resolvedMain,
|
||
topLevelName: expectedConfig.name,
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler.toml configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time.
|
||
- In your wrangler.toml file, you have configured \`durable_objects\` exported by this Worker (CLASS1), but no live \`exports\` entry for them. This may not work as expected until you add a live \`durable-object\` entry to \`exports\` for each. Add the following configuration:
|
||
|
||
\`\`\`
|
||
[exports.CLASS1]
|
||
type = "durable-object"
|
||
storage = "sqlite"
|
||
|
||
\`\`\`"
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid environment values", ({ expect }) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
name: 111,
|
||
account_id: 222,
|
||
compatibility_date: 333,
|
||
compatibility_flags: [444, 555],
|
||
workers_dev: "BAD",
|
||
routes: [
|
||
666,
|
||
777,
|
||
// this one's valid, but we add it here to make sure
|
||
// it doesn't get included in the error message
|
||
"example.com/*",
|
||
{ pattern: 123, zone_id: "zone_id_1" },
|
||
{ pattern: "route_2", zone_id: 123 },
|
||
{ pattern: "route_2", zone_name: 123 },
|
||
{ pattern: "route_3" },
|
||
{ zone_id: "zone_id_4" },
|
||
{ zone_name: "zone_name_4" },
|
||
{ pattern: undefined },
|
||
{ pattern: "route_5", zone_id: "zone_id_5", some_other_key: 123 },
|
||
{ pattern: "route_5", zone_name: "zone_name_5", some_other_key: 123 },
|
||
// this one's valid too
|
||
{ pattern: "route_6", zone_id: "zone_id_6" },
|
||
// as well as this one
|
||
{ pattern: "route_6", zone_name: "zone_name_6" },
|
||
],
|
||
route: 888,
|
||
jsx_factory: 999,
|
||
jsx_fragment: 1000,
|
||
tsconfig: true,
|
||
triggers: { crons: [1111, 1222] },
|
||
main: 1333,
|
||
build: {
|
||
command: 1444,
|
||
cwd: 1555,
|
||
watch_dir: 1666,
|
||
},
|
||
define: {
|
||
DEF1: 1777,
|
||
},
|
||
no_bundle: "INVALID",
|
||
minify: "INVALID",
|
||
first_party_worker: "INVALID",
|
||
logpush: "INVALID",
|
||
upload_source_maps: "INVALID",
|
||
placement: {
|
||
mode: "INVALID",
|
||
},
|
||
observability: {
|
||
enabled: "INVALID",
|
||
head_sampling_rate: "INVALID",
|
||
logs: {
|
||
enabled: "INVALID",
|
||
head_sampling_rate: "INVALID",
|
||
destinations: "INVALID",
|
||
persist: "INVALID",
|
||
invocation_logs: "INVALID",
|
||
},
|
||
traces: {
|
||
enabled: "INVALID",
|
||
head_sampling_rate: "INVALID",
|
||
destinations: "INVALID",
|
||
persist: "INVALID",
|
||
},
|
||
},
|
||
} as unknown as RawEnvironment;
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "route" to be either a string, or an object with shape { pattern, custom_domain, zone_id | zone_name, enabled, previews_enabled }, but got 888.
|
||
- Expected "account_id" to be of type string but got 222.
|
||
- Expected "routes" to be an array of either strings or objects with the shape { pattern, custom_domain, zone_id | zone_name, enabled, previews_enabled }, but these weren't valid: [
|
||
666,
|
||
777,
|
||
{
|
||
"pattern": 123,
|
||
"zone_id": "zone_id_1"
|
||
},
|
||
{
|
||
"pattern": "route_2",
|
||
"zone_id": 123
|
||
},
|
||
{
|
||
"pattern": "route_2",
|
||
"zone_name": 123
|
||
},
|
||
{
|
||
"pattern": "route_3"
|
||
},
|
||
{
|
||
"zone_id": "zone_id_4"
|
||
},
|
||
{
|
||
"zone_name": "zone_name_4"
|
||
},
|
||
{},
|
||
{
|
||
"pattern": "route_5",
|
||
"zone_id": "zone_id_5",
|
||
"some_other_key": 123
|
||
},
|
||
{
|
||
"pattern": "route_5",
|
||
"zone_name": "zone_name_5",
|
||
"some_other_key": 123
|
||
}
|
||
].
|
||
- Expected exactly one of the following fields ["routes","route"].
|
||
- Expected "workers_dev" to be of type boolean but got "BAD".
|
||
- Expected "build.command" to be of type string but got 1444.
|
||
- Expected "build.cwd" to be of type string but got 1555.
|
||
- Expected "build.watch_dir" to be of type string but got 1666.
|
||
- Expected "compatibility_date" to be of type string but got 333.
|
||
- Expected "compatibility_flags" to be of type string array but got [444,555].
|
||
- Expected "jsx_factory" to be of type string but got 999.
|
||
- Expected "jsx_fragment" to be of type string but got 1000.
|
||
- Expected "tsconfig" to be of type string but got true.
|
||
- Expected "name" to be of type string, alphanumeric and lowercase with dashes only but got 111.
|
||
- Expected "main" to be of type string but got 1333.
|
||
- Expected "placement.mode" field to be one of ["off","smart","targeted"] but got "INVALID".
|
||
- The field "define.DEF1" should be a string but got 1777.
|
||
- Expected "no_bundle" to be of type boolean but got "INVALID".
|
||
- Expected "minify" to be of type boolean but got "INVALID".
|
||
- Expected "first_party_worker" to be of type boolean but got "INVALID".
|
||
- Expected "logpush" to be of type boolean but got "INVALID".
|
||
- Expected "upload_source_maps" to be of type boolean but got "INVALID".
|
||
- Expected "observability.enabled" to be of type boolean but got "INVALID".
|
||
- Expected "observability.logs.enabled" to be of type boolean but got "INVALID".
|
||
- Expected "observability.traces.enabled" to be of type boolean but got "INVALID".
|
||
- Expected "observability.head_sampling_rate" to be of type number but got "INVALID".
|
||
- Expected "observability.logs.enabled" to be of type boolean but got "INVALID".
|
||
- Expected "observability.logs.head_sampling_rate" to be of type number but got "INVALID".
|
||
- Expected "observability.logs.invocation_logs" to be of type boolean but got "INVALID".
|
||
- Expected "logs.destinations" to be an array of strings but got "INVALID"
|
||
- Expected "observability.logs.persist" to be of type boolean but got "INVALID".
|
||
- Expected "observability.traces.enabled" to be of type boolean but got "INVALID".
|
||
- Expected "observability.traces.head_sampling_rate" to be of type number but got "INVALID".
|
||
- Expected "traces.destinations" to be an array of strings but got "INVALID"
|
||
- Expected "observability.traces.persist" to be of type boolean but got "INVALID"."
|
||
`);
|
||
});
|
||
|
||
describe("name", () => {
|
||
it("should error on invalid `name` value with spaces", ({ expect }) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
name: "this has spaces",
|
||
} as unknown as RawEnvironment;
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "name" to be of type string, alphanumeric and lowercase with dashes only but got "this has spaces"."
|
||
`);
|
||
});
|
||
|
||
it("should be valid `name` with underscores", ({ expect }) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
name: "enterprise_nx_01",
|
||
} as unknown as RawEnvironment;
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid `name` value with special characters", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
name: "Thy'lek-Shran",
|
||
} as unknown as RawEnvironment;
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "name" to be of type string, alphanumeric and lowercase with dashes only but got "Thy'lek-Shran"."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid `name` value with only special characters", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
name: "!@#$%^&*(()",
|
||
} as unknown as RawEnvironment;
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "name" to be of type string, alphanumeric and lowercase with dashes only but got "!@#$%^&*(()"."
|
||
`);
|
||
});
|
||
|
||
it("should accept any Worker name if the dispatch-namespace flag is used", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "example.com",
|
||
main: "index.js",
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined, "dispatch-namespace": "test-namespace" }
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe("[build]", () => {
|
||
it("should default custom build watch directories to src", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
build: {
|
||
command: "execute some --build",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.build).toEqual(
|
||
expect.objectContaining({
|
||
command: "execute some --build",
|
||
watch_dir: "./src",
|
||
})
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should resolve custom build watch directories relative to wrangler.toml", async ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
build: {
|
||
command: "execute some --build",
|
||
watch_dir: "some/path",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.build).toEqual(
|
||
expect.objectContaining({
|
||
command: "execute some --build",
|
||
watch_dir: path.normalize("project/some/path"),
|
||
})
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should allow watch_dir to be an array of paths", ({ expect }) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
build: {
|
||
command: "execute some --build",
|
||
watch_dir: ["some/path/a", "some/path/b", "some/path/c"],
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.build).toEqual(
|
||
expect.objectContaining({
|
||
command: "execute some --build",
|
||
watch_dir: [
|
||
path.normalize("project/some/path/a"),
|
||
path.normalize("project/some/path/b"),
|
||
path.normalize("project/some/path/c"),
|
||
],
|
||
})
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error when the watch_dir array isn't an array of strings", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
build: {
|
||
command: "execute some --build",
|
||
watch_dir: [
|
||
"some/path/a",
|
||
"some/path/b",
|
||
// @ts-expect-error intentionally bad "paths"
|
||
123,
|
||
"some/path/c",
|
||
// @ts-expect-error intentionally bad "paths"
|
||
false,
|
||
],
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
"project/wrangler.toml",
|
||
"project/wrangler.toml",
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.build).toEqual(
|
||
expect.objectContaining({
|
||
command: "execute some --build",
|
||
watch_dir: [
|
||
path.normalize("project/some/path/a"),
|
||
path.normalize("project/some/path/b"),
|
||
path.normalize("project/123"),
|
||
path.normalize("project/some/path/c"),
|
||
path.normalize("project/false"),
|
||
],
|
||
})
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(normalizePath(diagnostics.renderErrors()))
|
||
.toMatchInlineSnapshot(`
|
||
"Processing project/wrangler.toml configuration:
|
||
- Expected "build.watch_dir.[2]" to be of type string but got 123.
|
||
- Expected "build.watch_dir.[4]" to be of type string but got false."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[durable_objects]", () => {
|
||
it("should error if durable_objects is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is not defined", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects" is missing the required "bindings" property."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is an object", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: { bindings: {} } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects.bindings" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is a string", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: { bindings: "BAD" } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects.bindings" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is a number", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: { bindings: 999 } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects.bindings" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ durable_objects: { bindings: null } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "durable_objects.bindings" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
durable_objects: {
|
||
bindings: [
|
||
{},
|
||
{ name: "MISSING_CLASS" },
|
||
{ name: 1555, class_name: 1666 },
|
||
{
|
||
name: 1777,
|
||
class_name: 1888,
|
||
script_name: 1999,
|
||
},
|
||
{
|
||
name: "SOMENAME",
|
||
class_name: "SomeClass",
|
||
environment: "staging",
|
||
},
|
||
{
|
||
name: 1778,
|
||
class_name: 1889,
|
||
script_name: 1992,
|
||
environment: 2111,
|
||
},
|
||
{
|
||
name: 1772,
|
||
class_name: 1883,
|
||
environment: 2112,
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "durable_objects.bindings[0]": {}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
|
||
- "durable_objects.bindings[1]": {"name":"MISSING_CLASS"}
|
||
- binding should have a string "class_name" field.
|
||
|
||
- "durable_objects.bindings[2]": {"name":1555,"class_name":1666}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
|
||
- "durable_objects.bindings[3]": {"name":1777,"class_name":1888,"script_name":1999}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
- the field "script_name", when present, should be a string.
|
||
|
||
- "durable_objects.bindings[4]": {"name":"SOMENAME","class_name":"SomeClass","environment":"staging"}
|
||
- binding should have a "script_name" field if "environment" is present.
|
||
|
||
- "durable_objects.bindings[5]": {"name":1778,"class_name":1889,"script_name":1992,"environment":2111}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
- the field "script_name", when present, should be a string.
|
||
- the field "environment", when present, should be a string.
|
||
|
||
- "durable_objects.bindings[6]": {"name":1772,"class_name":1883,"environment":2112}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
- the field "environment", when present, should be a string.
|
||
- binding should have a "script_name" field if "environment" is present."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[migrations]", () => {
|
||
it("should override `migrations` config defaults with provided values", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
migrations: [
|
||
{
|
||
tag: "TAG",
|
||
new_classes: ["CLASS_1", "CLASS_2"],
|
||
new_sqlite_classes: ["CLASS_1", "CLASS_2"],
|
||
renamed_classes: [
|
||
{
|
||
from: "FROM_CLASS",
|
||
to: "TO_CLASS",
|
||
},
|
||
],
|
||
deleted_classes: ["CLASS_3", "CLASS_4"],
|
||
},
|
||
],
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid `migrations` values", ({ expect }) => {
|
||
const expectedConfig = {
|
||
migrations: [
|
||
{
|
||
tag: 111,
|
||
new_classes: [222, 333],
|
||
new_sqlite_classes: [222, 333],
|
||
renamed_classes: [
|
||
{
|
||
from: 444,
|
||
to: 555,
|
||
},
|
||
],
|
||
deleted_classes: [666, 777],
|
||
},
|
||
],
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "migrations[0].tag" to be of type string but got 111.
|
||
- Expected "migrations[0].new_classes.[0]" to be of type string but got 222.
|
||
- Expected "migrations[0].new_classes.[1]" to be of type string but got 333.
|
||
- Expected "migrations[0].new_sqlite_classes.[0]" to be of type string but got 222.
|
||
- Expected "migrations[0].new_sqlite_classes.[1]" to be of type string but got 333.
|
||
- Expected "migrations[0].renamed_classes" to be an array of "{from: string, to: string}" objects but got [{"from":444,"to":555}].
|
||
- Expected "migrations[0].deleted_classes.[0]" to be of type string but got 666.
|
||
- Expected "migrations[0].deleted_classes.[1]" to be of type string but got 777."
|
||
`);
|
||
});
|
||
|
||
it("should warn/error on unexpected fields on `migrations`", async ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig = {
|
||
migrations: [
|
||
{
|
||
tag: "TAG",
|
||
new_classes: ["CLASS_1", "CLASS_2"],
|
||
renamed_classes: [
|
||
{
|
||
from: "FROM_CLASS",
|
||
to: "TO_CLASS",
|
||
},
|
||
{
|
||
a: "something",
|
||
b: "someone",
|
||
},
|
||
],
|
||
deleted_classes: ["CLASS_3", "CLASS_4"],
|
||
new_sqlite_classes: ["CLASS_5", "CLASS_6"],
|
||
transferred_classes: [
|
||
{
|
||
from: "FROM_CLASS",
|
||
from_script: "FROM_SCRIPT",
|
||
to: "TO_CLASS",
|
||
},
|
||
{
|
||
from: "FROM_CLASS",
|
||
to: "TO_CLASS",
|
||
},
|
||
],
|
||
unrecognized_field: "FOO",
|
||
},
|
||
],
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in migrations field: "unrecognized_field""
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "migrations[0].renamed_classes" to be an array of "{from: string, to: string}" objects but got [{"from":"FROM_CLASS","to":"TO_CLASS"},{"a":"something","b":"someone"}].
|
||
- Expected "migrations[0].transferred_classes" to be an array of "{from: string, from_script: string, to: string}" objects but got [{"from":"FROM_CLASS","from_script":"FROM_SCRIPT","to":"TO_CLASS"},{"from":"FROM_CLASS","to":"TO_CLASS"}]."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[exports]", () => {
|
||
it("accepts a live durable-object entry with sqlite storage and no explicit state", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
exports: {
|
||
MyDO: { type: "durable-object", storage: "sqlite" },
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it('accepts a live durable-object entry with an explicit state of "created"', ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
exports: {
|
||
MyDO: {
|
||
type: "durable-object",
|
||
state: "created",
|
||
storage: "sqlite",
|
||
},
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("accepts all tombstone states and expecting-transfer alongside a live entry", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
exports: {
|
||
NewName: { type: "durable-object", storage: "sqlite" },
|
||
OldGone: { type: "durable-object", state: "deleted" },
|
||
OldName: {
|
||
type: "durable-object",
|
||
state: "renamed",
|
||
renamed_to: "NewName",
|
||
},
|
||
Movee: {
|
||
type: "durable-object",
|
||
state: "transferred",
|
||
transferred_to: "target-worker",
|
||
},
|
||
Incoming: {
|
||
type: "durable-object",
|
||
state: "expecting-transfer",
|
||
storage: "sqlite",
|
||
transfer_from: "source-worker",
|
||
},
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("accepts worker entries with cache config", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
exports: {
|
||
default: { type: "worker", cache: { enabled: false } },
|
||
Admin: { type: "worker", cache: { enabled: true } },
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("accepts mixed Durable Object and worker entries", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
exports: {
|
||
Counter: { type: "durable-object", storage: "sqlite" },
|
||
Admin: { type: "worker", cache: { enabled: true } },
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("errors when worker cache enabled is not a boolean", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Admin: {
|
||
type: "worker",
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally invalid shape under test
|
||
cache: { enabled: "true" } as any,
|
||
},
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'Expected "exports.Admin.cache.enabled" to be of type boolean'
|
||
);
|
||
});
|
||
|
||
it("warns when worker entries include unexpected fields", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Admin: {
|
||
type: "worker",
|
||
storage: "sqlite",
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toContain(
|
||
'Unexpected fields found in exports.Admin field: "storage"'
|
||
);
|
||
});
|
||
|
||
it("errors when storage is missing on a live entry", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally invalid shape under test
|
||
MyDO: { type: "durable-object" } as any,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'"exports.MyDO.storage" is required for state "created"'
|
||
);
|
||
});
|
||
|
||
it("errors when storage uses an unknown value", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally invalid shape under test
|
||
MyDO: { type: "durable-object", storage: "kv" } as any,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain('"exports.MyDO.storage"');
|
||
});
|
||
|
||
it("errors when renamed_to equals the source class name", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Same: {
|
||
type: "durable-object",
|
||
state: "renamed",
|
||
renamed_to: "Same",
|
||
},
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
"cannot equal the source class name"
|
||
);
|
||
});
|
||
|
||
it("errors when a deleted tombstone carries forbidden fields", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Bad: {
|
||
type: "durable-object",
|
||
state: "deleted",
|
||
storage: "sqlite",
|
||
} as DurableObjectExport,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'"exports.Bad.storage" is forbidden on state "deleted"'
|
||
);
|
||
});
|
||
|
||
it("errors when a transferred tombstone omits transferred_to", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Movee: {
|
||
type: "durable-object",
|
||
state: "transferred",
|
||
} as DurableObjectExport,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'"exports.Movee.transferred_to" is required'
|
||
);
|
||
});
|
||
|
||
it("errors when an expecting-transfer entry omits transfer_from", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Incoming: {
|
||
type: "durable-object",
|
||
state: "expecting-transfer",
|
||
storage: "sqlite",
|
||
} as DurableObjectExport,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'"exports.Incoming.transfer_from" is required'
|
||
);
|
||
});
|
||
|
||
it("errors when an expecting-transfer entry omits storage", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
Incoming: {
|
||
type: "durable-object",
|
||
state: "expecting-transfer",
|
||
transfer_from: "source-worker",
|
||
} as DurableObjectExport,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'"exports.Incoming.storage" is required for state "expecting-transfer"'
|
||
);
|
||
});
|
||
|
||
it("errors when transfer_from is set on a live `created` entry", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
MyDO: {
|
||
type: "durable-object",
|
||
storage: "sqlite",
|
||
transfer_from: "source-worker",
|
||
} as DurableObjectExport,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "exports.MyDO.transfer_from" is forbidden on state "created".
|
||
- Allowed properties are: type, state, and storage."
|
||
`);
|
||
});
|
||
|
||
it("errors when the type is unknown", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally invalid shape under test
|
||
Weird: { type: "container" } as any,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "exports.Weird.type" must be "durable-object" or "worker", but got "container"."
|
||
`);
|
||
});
|
||
|
||
it("errors when the state is unknown", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
exports: {
|
||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- intentionally invalid shape under test
|
||
Weird: { type: "durable-object", state: "rebooted" } as any,
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "exports.Weird.state" must be one of "created", "deleted", "renamed", "transferred", or "expecting-transfer" but got "rebooted"."
|
||
`);
|
||
});
|
||
|
||
it("errors when `migrations` and `exports` are both non-empty", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
migrations: [{ tag: "v1", new_sqlite_classes: ["MyDO"] }],
|
||
exports: {
|
||
MyDO: { type: "durable-object", storage: "sqlite" },
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- \`migrations\` and \`exports\` are mutually exclusive. Choose one or the other to declare your Durable Object lifecycle, but not both."
|
||
`);
|
||
});
|
||
|
||
it("does not warn about missing migrations when exports covers the bound class", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
durable_objects: {
|
||
bindings: [{ name: "DO", class_name: "MyDO" }],
|
||
},
|
||
exports: {
|
||
MyDO: { type: "durable-object", storage: "sqlite" },
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("warns and suggests an `exports` entry when the only entry for a bound class is a tombstone", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
durable_objects: {
|
||
bindings: [{ name: "DO", class_name: "MyDO" }],
|
||
},
|
||
exports: {
|
||
MyDO: { type: "durable-object", state: "deleted" },
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
const rendered = diagnostics.renderWarnings();
|
||
expect(rendered).toContain("no live `exports` entry for them");
|
||
expect(rendered).toContain('"type": "durable-object"');
|
||
expect(rendered).toContain('"storage": "sqlite"');
|
||
expect(rendered).not.toContain("new_sqlite_classes");
|
||
});
|
||
|
||
it("warns and suggests an `exports` entry when `exports` is in use but the bound class is missing", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
durable_objects: {
|
||
bindings: [{ name: "DO", class_name: "MyDO" }],
|
||
},
|
||
exports: {
|
||
// User is already on the `exports` path (unrelated
|
||
// tombstone present) but forgot to add a live entry
|
||
// for `MyDO`.
|
||
OldGone: { type: "durable-object", state: "deleted" },
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
const rendered = diagnostics.renderWarnings();
|
||
expect(rendered).toContain("no live `exports` entry for them");
|
||
expect(rendered).toContain('"MyDO"');
|
||
expect(rendered).not.toContain("new_sqlite_classes");
|
||
});
|
||
|
||
it("warns and suggests an `exports` entry when neither lifecycle is declared", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
durable_objects: {
|
||
bindings: [{ name: "DO", class_name: "MyDO" }],
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
const rendered = diagnostics.renderWarnings();
|
||
expect(rendered).toContain("no live `exports` entry for them");
|
||
expect(rendered).toContain('"type": "durable-object"');
|
||
expect(rendered).toContain('"storage": "sqlite"');
|
||
expect(rendered).not.toContain("new_sqlite_classes");
|
||
});
|
||
});
|
||
|
||
describe("[assets]", () => {
|
||
it("should override `assets` config defaults with provided values", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
assets: {
|
||
directory: "public/",
|
||
binding: "ASSETS",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid `assets` values", ({ expect }) => {
|
||
const expectedConfig = {
|
||
assets: {
|
||
binding: 2,
|
||
notAField: "boop",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in assets field: "notAField""
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "assets.binding" to be of type string but got 2."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid `assets` config values", ({ expect }) => {
|
||
const expectedConfig = {
|
||
assets: {
|
||
directory: "./public",
|
||
html_handling: "foo",
|
||
not_found_handling: "bar",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "assets.html_handling" field to be one of ["auto-trailing-slash","force-trailing-slash","drop-trailing-slash","none"] but got "foo".
|
||
- Expected "assets.not_found_handling" field to be one of ["single-page-application","404-page","none"] but got "bar"."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid `assets` config values", ({ expect }) => {
|
||
const expectedConfig: RawConfig = {
|
||
assets: {
|
||
directory: "./public",
|
||
html_handling: "drop-trailing-slash",
|
||
not_found_handling: "404-page",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid additional fields", ({ expect }) => {
|
||
const expectedConfig = {
|
||
assets: {
|
||
directory: "./public",
|
||
invalid_field_1: "this is invalid",
|
||
invalid_field_2: "this is invalid too",
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in assets field: "invalid_field_1","invalid_field_2""
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBeFalsy();
|
||
});
|
||
});
|
||
|
||
describe("[browser]", () => {
|
||
it("should error if browser is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ browser: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "browser" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if browser is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ browser: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "browser" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if browser is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ browser: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "browser" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if browser is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ browser: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "browser" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[websearch]", () => {
|
||
it("should accept a valid websearch binding", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ websearch: { binding: "WEBSEARCH" } } as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error if websearch is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ websearch: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "websearch" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if websearch has no binding name", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ websearch: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- binding should have a string "binding" field."
|
||
`);
|
||
});
|
||
});
|
||
|
||
// Vectorize
|
||
describe("[vectorize]", () => {
|
||
it("should error if vectorize is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ vectorize: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "vectorize" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if vectorize bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vectorize: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, index_name: 2111 },
|
||
{
|
||
binding: "BINDING_2",
|
||
index_name: "ID_2",
|
||
},
|
||
{ binding: "VALID", index_name: "" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "vectorize[0]" bindings should have a string "binding" field but got {}.
|
||
- "vectorize[0]" bindings must have an "index_name" field but got {}.
|
||
- "vectorize[1]" bindings must have an "index_name" field but got {"binding":"VALID"}.
|
||
- "vectorize[2]" bindings should have a string "binding" field but got {"binding":2000,"index_name":2111}.
|
||
- "vectorize[2]" bindings must have an "index_name" field but got {"binding":2000,"index_name":2111}."
|
||
`);
|
||
});
|
||
|
||
it("should error if vectorize is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ vectorize: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "vectorize" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if vectorize is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ vectorize: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "vectorize" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if vectorize is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ vectorize: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "vectorize" should be an array but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[ai_search_namespaces]", () => {
|
||
it("should error if ai_search_namespaces is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ ai_search_namespaces: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ai_search_namespaces" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if ai_search_namespaces bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ai_search_namespaces: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, namespace: 2111 },
|
||
{
|
||
binding: "BINDING_2",
|
||
namespace: "production",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "ai_search_namespaces[0]" bindings should have a string "binding" field but got {}.
|
||
- "ai_search_namespaces[0]" bindings must have a "namespace" field but got {}.
|
||
- "ai_search_namespaces[1]" bindings must have a "namespace" field but got {"binding":"VALID"}.
|
||
- "ai_search_namespaces[2]" bindings should have a string "binding" field but got {"binding":2000,"namespace":2111}.
|
||
- "ai_search_namespaces[2]" bindings must have a "namespace" field but got {"binding":2000,"namespace":2111}."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid ai_search_namespaces bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ai_search_namespaces: [
|
||
{
|
||
binding: "AI_SEARCH",
|
||
namespace: "production",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error on additional properties", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ai_search_namespaces: [
|
||
{
|
||
binding: "AI_SEARCH",
|
||
namespace: "production",
|
||
extra_field: "unexpected",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toContain("extra_field");
|
||
});
|
||
});
|
||
|
||
describe("[ai_search]", () => {
|
||
it("should error if ai_search is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ ai_search: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ai_search" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if ai_search bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ai_search: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, instance_name: 2111 },
|
||
{
|
||
binding: "BINDING_2",
|
||
instance_name: "cloudflare-blog",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "ai_search[0]" bindings should have a string "binding" field but got {}.
|
||
- "ai_search[0]" bindings must have an "instance_name" field but got {}.
|
||
- "ai_search[1]" bindings must have an "instance_name" field but got {"binding":"VALID"}.
|
||
- "ai_search[2]" bindings should have a string "binding" field but got {"binding":2000,"instance_name":2111}.
|
||
- "ai_search[2]" bindings must have an "instance_name" field but got {"binding":2000,"instance_name":2111}."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid ai_search bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ai_search: [
|
||
{
|
||
binding: "BLOG_SEARCH",
|
||
instance_name: "cloudflare-blog",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error on additional properties", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ai_search: [
|
||
{
|
||
binding: "BLOG_SEARCH",
|
||
instance_name: "cloudflare-blog",
|
||
extra_field: "unexpected",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toContain("extra_field");
|
||
});
|
||
});
|
||
|
||
describe("[agent_memory]", () => {
|
||
it("should error if agent_memory is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ agent_memory: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "agent_memory" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if agent_memory is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ agent_memory: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "agent_memory" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if agent_memory is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ agent_memory: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "agent_memory" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if agent_memory is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ agent_memory: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "agent_memory" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if agent_memory bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
agent_memory: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, namespace: 2111 },
|
||
{
|
||
binding: "BINDING_2",
|
||
namespace: "my-namespace",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "agent_memory[0]" bindings should have a string "binding" field but got {}.
|
||
- "agent_memory[0]" bindings must have a "namespace" field but got {}.
|
||
- "agent_memory[1]" bindings must have a "namespace" field but got {"binding":"VALID"}.
|
||
- "agent_memory[2]" bindings should have a string "binding" field but got {"binding":2000,"namespace":2111}.
|
||
- "agent_memory[2]" bindings must have a "namespace" field but got {"binding":2000,"namespace":2111}."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid agent_memory bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
agent_memory: [
|
||
{
|
||
binding: "MEMORY",
|
||
namespace: "my-namespace",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error on additional properties", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
agent_memory: [
|
||
{
|
||
binding: "MEMORY",
|
||
namespace: "my-namespace",
|
||
extra_field: "unexpected",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toContain("extra_field");
|
||
});
|
||
});
|
||
|
||
// AI
|
||
describe("[ai]", () => {
|
||
it("should error if ai is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ ai: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ai" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if ai is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ ai: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ai" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if ai is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ ai: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ai" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if ai is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ ai: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ai" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
// Images
|
||
describe("[images]", () => {
|
||
it("should error if images is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ images: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "images" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if images is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ images: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "images" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if images is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ images: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "images" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if ai is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ images: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "images" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
// Media
|
||
describe("[media]", () => {
|
||
it("should error if media is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ media: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "media" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if media is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ media: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "media" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if media is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ media: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "media" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if media is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ media: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "media" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
// Stream
|
||
describe("[stream]", () => {
|
||
it("should error if stream is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ stream: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "stream" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if stream is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ stream: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "stream" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if stream is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ stream: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "stream" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if stream is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ stream: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "stream" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
// Worker Version Metadata
|
||
describe("[version_metadata]", () => {
|
||
it("should error if version_metadata is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ version_metadata: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "version_metadata" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if version_metadata is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ version_metadata: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "version_metadata" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if version_metadata is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ version_metadata: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "version_metadata" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if version_metadata is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ version_metadata: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "version_metadata" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[cloudchamber]", () => {
|
||
it("should error if cloudchamber is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ cloudchamber: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cloudchamber" should be an object, but got null"
|
||
`);
|
||
});
|
||
|
||
it("should error if cloudchamber is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ cloudchamber: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cloudchamber" should be an object, but got []"
|
||
`);
|
||
});
|
||
|
||
it("should error if cloudchamber is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ cloudchamber: "test" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cloudchamber" should be an object, but got "test""
|
||
`);
|
||
});
|
||
|
||
it("should error if cloudchamber is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ cloudchamber: 22 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cloudchamber" should be an object, but got 22"
|
||
`);
|
||
});
|
||
|
||
it("should error if cloudchamber bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cloudchamber: {
|
||
image: 123, // should be a string
|
||
location: 123, // should be a string
|
||
vcpu: "invalid", // should be a number
|
||
memory: 123, // should be a string
|
||
ipv4: "invalid", // should be a boolean
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cloudchamber" bindings should, optionally, have a string "memory" field but got {"image":123,"location":123,"vcpu":"invalid","memory":123,"ipv4":"invalid"}.
|
||
- "cloudchamber" bindings should, optionally, have a string "image" field but got {"image":123,"location":123,"vcpu":"invalid","memory":123,"ipv4":"invalid"}.
|
||
- "cloudchamber" bindings should, optionally, have a string "location" field but got {"image":123,"location":123,"vcpu":"invalid","memory":123,"ipv4":"invalid"}.
|
||
- "cloudchamber" bindings should, optionally, have a boolean "ipv4" field but got {"image":123,"location":123,"vcpu":"invalid","memory":123,"ipv4":"invalid"}.
|
||
- "cloudchamber" bindings should, optionally, have a number "vcpu" field but got {"image":123,"location":123,"vcpu":"invalid","memory":123,"ipv4":"invalid"}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[containers]", () => {
|
||
it("should error if containers is not an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ containers: "test" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers" field should be an array, but got "test""
|
||
`);
|
||
});
|
||
|
||
it("should error if containers is an object that is not an array", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ containers: { something: "here" } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers" field should be an array, but got {"something":"here"}"
|
||
`);
|
||
});
|
||
|
||
it("should error if containers is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ containers: "test" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers" field should be an array, but got "test""
|
||
`);
|
||
});
|
||
|
||
it("should error if containers is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ containers: 22 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers" field should be an array, but got 22"
|
||
`);
|
||
});
|
||
|
||
it("should error if no containers name and no worker name are provided", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
containers: [
|
||
{
|
||
image: "registry.cloudflare.com/something:hello",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers.class_name" is a required field.
|
||
- Must have either a top level "name" and "containers.class_name" field defined, or have field "containers.name" defined."
|
||
`);
|
||
});
|
||
|
||
it("should provide a name if no container name is provided and worker name exists", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics, config } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker-name",
|
||
containers: [
|
||
{
|
||
image: "registry.cloudflare.com/something:hello",
|
||
class_name: "test-class",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(config.containers).toEqual([
|
||
{
|
||
class_name: "test-class",
|
||
name: "test-worker-name-test-class",
|
||
image: "registry.cloudflare.com/something:hello",
|
||
image_build_context: undefined,
|
||
},
|
||
]);
|
||
if (config.containers) {
|
||
expect(config.containers[0].name).toEqual(
|
||
"test-worker-name-test-class"
|
||
);
|
||
}
|
||
});
|
||
|
||
it("should error for invalid container app fields", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
image: "something",
|
||
class_name: "test-class",
|
||
rollout_kind: "invalid",
|
||
instance_type: "invalid",
|
||
max_instances: "invalid",
|
||
image_build_context: 123,
|
||
image_vars: "invalid",
|
||
scheduling_policy: "invalid",
|
||
unknown_field: "value",
|
||
rollout_active_grace_period: "60s",
|
||
rollout_step_percentage: "invalid",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in containers field: "unknown_field""
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "containers.image_build_context" to be of type string but got 123.
|
||
- The image "something" does not appear to be a valid path to a Dockerfile, or a valid image registry path:
|
||
If this is an image registry path, it needs to include at least a tag ':' (e.g: docker.io/httpd:1)
|
||
- "containers.rollout_step_percentage" must be a number or array of numbers, but got "invalid"
|
||
- Expected "containers.rollout_kind" field to be one of ["full_auto","full_manual","none"] but got "invalid".
|
||
- "containers.rollout_active_grace_period" field should be a positive number but got "60s"
|
||
- Expected "containers.max_instances" to be of type number but got "invalid".
|
||
- Expected "containers.image_vars" to be of type object but got "invalid".
|
||
- Expected "containers.scheduling_policy" field to be one of ["regional","moon","default"] but got "invalid".
|
||
- Expected "containers.instance_type" field to be one of ["lite","basic","standard-1","standard-2","standard-3","standard-4","dev","standard"] but got "invalid"."
|
||
`);
|
||
});
|
||
|
||
it("should error if rollout_active_grace_period and rollout_step_percentage are out of range", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
image: "blah",
|
||
class_name: "test-class",
|
||
rollout_active_grace_period: -1,
|
||
rollout_step_percentage: 9,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The image "blah" does not appear to be a valid path to a Dockerfile, or a valid image registry path:
|
||
If this is an image registry path, it needs to include at least a tag ':' (e.g: docker.io/httpd:1)
|
||
- "containers.rollout_step_percentage" must be one of [5, 10, 20, 25, 50, 100], but got 9
|
||
- "containers.rollout_active_grace_period" field should be a positive number but got "-1""
|
||
`);
|
||
});
|
||
|
||
it("should warn for deprecated container fields", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "test-class",
|
||
instances: 10,
|
||
configuration: {
|
||
image: "config-image",
|
||
},
|
||
durable_objects: {
|
||
namespace_id: "test-namespace",
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers.configuration" is deprecated. Use top level "containers" fields instead. "configuration.image" should be "image", limits should be set via "instance_type".
|
||
- "containers.instances" is deprecated. Use "containers.max_instances" instead.
|
||
- "containers.durable_objects" is deprecated. Use the "class_name" field instead."
|
||
`);
|
||
});
|
||
|
||
it("should error for invalid containers.configuration fields", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "test-class",
|
||
configuration: {
|
||
image: "config-image",
|
||
secrets: [],
|
||
labels: [],
|
||
disk: { size: "2GB" },
|
||
memory: "256MB",
|
||
vcpu: 0.5,
|
||
memory_mib: 256,
|
||
invalid_field: "should not be here",
|
||
another_invalid: 123,
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers.configuration" is deprecated. Use top level "containers" fields instead. "configuration.image" should be "image", limits should be set via "instance_type".
|
||
- Unexpected fields found in containers.configuration field: "memory","invalid_field","another_invalid""
|
||
`);
|
||
});
|
||
|
||
it.for([{ value: 25 }, { value: [20, 50, 100] }])(
|
||
"should accept rollout_step_percentage set to $value",
|
||
(value, { expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "test-class",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
rollout_step_percentage: value.value,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
}
|
||
);
|
||
|
||
it("should error for invalid rollout_step_percentage number values", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "test-class",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
rollout_step_percentage: 15,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers.rollout_step_percentage" must be one of [5, 10, 20, 25, 50, 100], but got 15"
|
||
`);
|
||
});
|
||
|
||
it("should error for rollout_step_percentage array with invalid items", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "test-class",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
rollout_step_percentage: [20, 30, 1, 101],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers.rollout_step_percentage" array elements must be in ascending order, but got "20,30,1,101"
|
||
- The final step in "containers.rollout_step_percentage" must be 100, but got "101"
|
||
- "containers.rollout_step_percentage" array elements must be between 10 and 100, but got "1, 101""
|
||
`);
|
||
});
|
||
|
||
it("should error when rollout_step_percentage has more steps than max_instances", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
name: "test-container",
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
max_instances: 2,
|
||
rollout_step_percentage: [10, 50, 75, 100],
|
||
},
|
||
],
|
||
durable_objects: {
|
||
bindings: [
|
||
{
|
||
name: "TEST_DO",
|
||
class_name: "TestClass",
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "containers.rollout_step_percentage" cannot have more steps (4) than "max_instances" (2)"
|
||
`);
|
||
});
|
||
|
||
it("should warn when dev instance type is used", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
name: "test-container",
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
instance_type: "dev",
|
||
},
|
||
],
|
||
durable_objects: {
|
||
bindings: [
|
||
{
|
||
name: "TEST_DO",
|
||
class_name: "TestClass",
|
||
},
|
||
],
|
||
},
|
||
migrations: [
|
||
{
|
||
tag: "v1",
|
||
new_sqlite_classes: ["TestClass"],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The "dev" instance_type has been renamed to "lite" and will be removed in a subsequent version. Please update your configuration to use "lite" instead."
|
||
`);
|
||
});
|
||
|
||
it("should error when both constraints.tier and constraints.tiers are set", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
constraints: {
|
||
tier: 1,
|
||
tiers: [1, 2],
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "constraints.tier" has been deprecated in favor of "constraints.tiers". Please update your configuration to use "constraints.tiers" instead."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- containers.constraints.tier and containers.constraints.tiers cannot both be set"
|
||
`);
|
||
});
|
||
|
||
it("should error when constraints.tiers is not an array of numbers", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
constraints: {
|
||
tiers: ["a", "b"],
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "containers.constraints.tiers.[0]" to be of type number but got "a".
|
||
- Expected "containers.constraints.tiers.[1]" to be of type number but got "b"."
|
||
`);
|
||
});
|
||
|
||
it("should allow valid constraints.tiers array of numbers", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
constraints: {
|
||
tiers: [1, 2, 3],
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error when constraints.jurisdiction is invalid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
constraints: {
|
||
jurisdiction: "invalid",
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- containers.constraints.jurisdiction must be one of: "eu", "fedramp""
|
||
`);
|
||
});
|
||
|
||
it("should error when constraints.regions contains invalid region", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
constraints: {
|
||
regions: ["INVALID", "ENAM"],
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- containers.constraints.regions contains invalid region "INVALID". Valid regions are: ENAM, WNAM, EEUR, WEUR, APAC, SAM, ME, OC, AFR"
|
||
`);
|
||
});
|
||
|
||
it("should allow valid constraints.regions and constraints.jurisdiction", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
name: "test-worker",
|
||
containers: [
|
||
{
|
||
class_name: "TestClass",
|
||
image: "registry.cloudflare.com/test:latest",
|
||
constraints: {
|
||
regions: ["ENAM", "WNAM"],
|
||
jurisdiction: "fedramp",
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe("[kv_namespaces]", () => {
|
||
it("should error if kv_namespaces is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ kv_namespaces: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "kv_namespaces" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ kv_namespaces: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "kv_namespaces" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ kv_namespaces: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "kv_namespaces" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ kv_namespaces: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "kv_namespaces" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
kv_namespaces: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, id: 2111 },
|
||
{
|
||
binding: "KV_BINDING_2",
|
||
id: "KV_ID_2",
|
||
preview_id: 2222,
|
||
},
|
||
{ binding: "VALID", id: "" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "kv_namespaces[0]" bindings should have a string "binding" field but got {}.
|
||
- "kv_namespaces[2]" bindings should have a string "binding" field but got {"binding":2000,"id":2111}.
|
||
- "kv_namespaces[2]" bindings should have a string "id" field but got {"binding":2000,"id":2111}.
|
||
- "kv_namespaces[3]" bindings should, optionally, have a string "preview_id" field but got {"binding":"KV_BINDING_2","id":"KV_ID_2","preview_id":2222}.
|
||
- "kv_namespaces[4]" bindings should have a string "id" field but got {"binding":"VALID","id":""}."
|
||
`);
|
||
});
|
||
|
||
it("should allow the id field to be omitted (resource provisioning)", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
kv_namespaces: [{ binding: "VALID" }],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
});
|
||
|
||
it("should error if send_email.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
send_email: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ name: "SEB", destination_address: 123 },
|
||
{
|
||
name: "SEB2",
|
||
allowed_destination_addresses: 123,
|
||
},
|
||
{
|
||
name: "SEB3",
|
||
destination_address: "email@example.com",
|
||
allowed_destination_addresses: ["email@example.com"],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "send_email[0]" bindings should have a string "name" field but got {}.
|
||
- "send_email[1]" bindings should have a string "name" field but got {"binding":"VALID"}.
|
||
- "send_email[2]" bindings should, optionally, have a string "destination_address" field but got {"name":"SEB","destination_address":123}.
|
||
- "send_email[3]" bindings should, optionally, have a []string "allowed_destination_addresses" field but got {"name":"SEB2","allowed_destination_addresses":123}.
|
||
- "send_email[4]" bindings should have either a "destination_address" or "allowed_destination_addresses" field, but not both."
|
||
`);
|
||
});
|
||
|
||
describe("[d1_databases]", () => {
|
||
it("should error if d1_databases is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ d1_databases: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "d1_databases" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if d1_databases is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ d1_databases: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "d1_databases" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if d1_databases is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ d1_databases: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "d1_databases" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if d1_databases is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ d1_databases: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "d1_databases" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if d1_databases.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, id: 2111 },
|
||
{
|
||
binding: "D1_BINDING_2",
|
||
id: "my-db",
|
||
preview_id: 2222,
|
||
},
|
||
{ binding: "VALID", id: "" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in d1_databases[2] field: "id"
|
||
- Unexpected fields found in d1_databases[3] field: "id","preview_id"
|
||
- Unexpected fields found in d1_databases[4] field: "id""
|
||
`);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "d1_databases[0]" bindings should have a string "binding" field but got {}.
|
||
- "d1_databases[2]" bindings should have a string "binding" field but got {"binding":2000,"id":2111}."
|
||
`);
|
||
});
|
||
|
||
it("should allow the database_id field to be omitted (resource provisioning)", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [{ binding: "VALID" }],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if D1 database database_name has incorrect type", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [
|
||
{
|
||
binding: "DB",
|
||
database_name: true,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "d1_databases[0]" bindings should, optionally, have a string "database_name" field but got {"binding":"DB","database_name":true}."
|
||
`);
|
||
});
|
||
|
||
it("should error if D1 database migrations_dir has incorrect type", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [
|
||
{
|
||
binding: "DB",
|
||
migrations_dir: 123,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "d1_databases[0]" bindings should, optionally, have a string "migrations_dir" field but got {"binding":"DB","migrations_dir":123}."
|
||
`);
|
||
});
|
||
|
||
it("should error if D1 database migrations_table has incorrect type", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [
|
||
{
|
||
binding: "DB",
|
||
migrations_table: {},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "d1_databases[0]" bindings should, optionally, have a string "migrations_table" field but got {"binding":"DB","migrations_table":{}}."
|
||
`);
|
||
});
|
||
|
||
it("should error if D1 database database_internal_env has incorrect type", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [
|
||
{
|
||
binding: "DB",
|
||
database_internal_env: false,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "d1_databases[0]" bindings should, optionally, have a string "database_internal_env" field but got {"binding":"DB","database_internal_env":false}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[hyperdrive]", () => {
|
||
it("should error if hyperdrive is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ hyperdrive: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "hyperdrive" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if hyperdrive is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ hyperdrive: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "hyperdrive" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if hyperdrive is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ hyperdrive: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "hyperdrive" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if hyperdrive is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ hyperdrive: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "hyperdrive" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
hyperdrive: [
|
||
{ binding: "VALID", id: "343cd4f1d58c42fbb5bd082592fd7143" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error if hyperdrive.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
hyperdrive: [
|
||
{},
|
||
{ binding: "VALID", id: "343cd4f1d58c42fbb5bd082592fd7143" },
|
||
{ binding: 2000, project: 2111 },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in hyperdrive[2] field: "project""
|
||
`);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "hyperdrive[0]" bindings should have a string "binding" field but got {}.
|
||
- "hyperdrive[0]" bindings must have a "id" field but got {}.
|
||
- "hyperdrive[2]" bindings should have a string "binding" field but got {"binding":2000,"project":2111}.
|
||
- "hyperdrive[2]" bindings must have a "id" field but got {"binding":2000,"project":2111}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[queues]", () => {
|
||
it("should error if queues is not an object", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{ queues: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.not.objectContaining({ queues: expect.anything })
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "queues" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if queues producer bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
queues: {
|
||
invalidField: "madeupValue",
|
||
producers: [
|
||
{},
|
||
{ binding: "QUEUE_BINDING_1" },
|
||
{ binding: 2333, queue: 2444 },
|
||
{ binding: "QUEUE_BINDING_3", queue: "" },
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.not.objectContaining({
|
||
queues: { producers: expect.anything },
|
||
})
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in queues field: "invalidField""
|
||
`);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "queues.producers[0]" bindings should have a string "binding" field but got {}.
|
||
- "queues.producers[0]" bindings should have a string "queue" field but got {}.
|
||
- "queues.producers[1]" bindings should have a string "queue" field but got {"binding":"QUEUE_BINDING_1"}.
|
||
- "queues.producers[2]" bindings should have a string "binding" field but got {"binding":2333,"queue":2444}.
|
||
- "queues.producers[2]" bindings should have a string "queue" field but got {"binding":2333,"queue":2444}.
|
||
- "queues.producers[3]" bindings should have a string "queue" field but got {"binding":"QUEUE_BINDING_3","queue":""}."
|
||
`);
|
||
});
|
||
|
||
it("should error if queues consumer type is not 'worker'", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
queues: {
|
||
consumers: [
|
||
{ queue: "myQueue", type: "http_pull" },
|
||
{ queue: "myQueue2", type: "r2_bucket" },
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "queues.consumers[0].type" has an invalid value "http_pull". Only "worker" consumers can be configured in your Wrangler configuration.
|
||
- "queues.consumers[1].type" has an invalid value "r2_bucket". Only "worker" consumers can be configured in your Wrangler configuration."
|
||
`);
|
||
});
|
||
|
||
it("should allow queues consumer type 'worker' explicitly", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
queues: {
|
||
consumers: [{ queue: "myQueue", type: "worker" }],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if queues consumers are not valid", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
queues: {
|
||
invalidField: "madeupValue",
|
||
consumers: [
|
||
{},
|
||
{ queue: 22 },
|
||
{ queue: "myQueue", invalidField: "madeupValue" },
|
||
{
|
||
queue: "myQueue",
|
||
max_batch_size: "3",
|
||
max_batch_timeout: null,
|
||
max_retries: "hello",
|
||
dead_letter_queue: 5,
|
||
max_concurrency: "hello",
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.not.objectContaining({
|
||
queues: { producers: expect.anything },
|
||
})
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in queues field: "invalidField"
|
||
- Unexpected fields found in queues.consumers[2] field: "invalidField""
|
||
`);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "queues.consumers[0]" should have a string "queue" field but got {}.
|
||
- "queues.consumers[1]" should have a string "queue" field but got {"queue":22}.
|
||
- "queues.consumers[3]" should, optionally, have a number "max_batch_size" field but got {"queue":"myQueue","max_batch_size":"3","max_batch_timeout":null,"max_retries":"hello","dead_letter_queue":5,"max_concurrency":"hello"}.
|
||
- "queues.consumers[3]" should, optionally, have a number "max_batch_timeout" field but got {"queue":"myQueue","max_batch_size":"3","max_batch_timeout":null,"max_retries":"hello","dead_letter_queue":5,"max_concurrency":"hello"}.
|
||
- "queues.consumers[3]" should, optionally, have a number "max_retries" field but got {"queue":"myQueue","max_batch_size":"3","max_batch_timeout":null,"max_retries":"hello","dead_letter_queue":5,"max_concurrency":"hello"}.
|
||
- "queues.consumers[3]" should, optionally, have a string "dead_letter_queue" field but got {"queue":"myQueue","max_batch_size":"3","max_batch_timeout":null,"max_retries":"hello","dead_letter_queue":5,"max_concurrency":"hello"}.
|
||
- "queues.consumers[3]" should, optionally, have a number "max_concurrency" field but got {"queue":"myQueue","max_batch_size":"3","max_batch_timeout":null,"max_retries":"hello","dead_letter_queue":5,"max_concurrency":"hello"}."
|
||
`);
|
||
});
|
||
|
||
it("should warn if delivery_delay is set on a queue producer", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
queues: {
|
||
producers: [
|
||
{ binding: "QUEUE_BINDING_1", queue: "queue1" },
|
||
{
|
||
binding: "QUEUE_BINDING_2",
|
||
queue: "queue2",
|
||
delivery_delay: 60,
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.queues.producers).toHaveLength(2);
|
||
expect(config.queues.producers?.[1]).toMatchObject({
|
||
delivery_delay: 60,
|
||
});
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The "delivery_delay" field in "queues.producers[1]" is deprecated and has no effect. Queue-level settings should be configured using "wrangler queues update" instead. This setting will be removed in a future version."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[r2_buckets]", () => {
|
||
it("should error if r2_buckets is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ r2_buckets: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "r2_buckets" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ r2_buckets: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "r2_buckets" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ r2_buckets: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "r2_buckets" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ r2_buckets: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "r2_buckets" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
r2_buckets: [
|
||
{},
|
||
{ binding: "R2_BINDING_1" },
|
||
{ binding: 2333, bucket_name: 2444 },
|
||
{
|
||
binding: "R2_BINDING_2",
|
||
bucket_name: "r2-bucket-2",
|
||
preview_bucket_name: 2555,
|
||
},
|
||
{ binding: "R2_BINDING_3", bucket_name: "INVALID-NAME" },
|
||
{
|
||
binding: "R2_BINDING_4",
|
||
bucket_name: "bucket",
|
||
preview_bucket_name: "INVALID-NAME",
|
||
},
|
||
{ binding: "R2_BINDING_5", bucket_name: "" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "r2_buckets[0]" bindings should have a string "binding" field but got {}.
|
||
- "r2_buckets[2]" bindings should have a string "binding" field but got {"binding":2333,"bucket_name":2444}.
|
||
- "r2_buckets[2]" bindings should have a string "bucket_name" field but got {"binding":2333,"bucket_name":2444}.
|
||
- "r2_buckets[3]" bindings should, optionally, have a string "preview_bucket_name" field but got {"binding":"R2_BINDING_2","bucket_name":"r2-bucket-2","preview_bucket_name":2555}.
|
||
- r2_buckets[4].bucket_name="INVALID-NAME" is invalid. Bucket names must begin and end with an alphanumeric character, only contain lowercase letters, numbers, and hyphens, and be between 3 and 63 characters long.
|
||
- r2_buckets[5].preview_bucket_name= "INVALID-NAME" is invalid. Bucket names must begin and end with an alphanumeric character, only contain lowercase letters, numbers, and hyphens, and be between 3 and 63 characters long.
|
||
- "r2_buckets[6]" bindings should have a string "bucket_name" field but got {"binding":"R2_BINDING_5","bucket_name":""}."
|
||
`);
|
||
});
|
||
|
||
it("should allow the bucket_name field to be omitted (resource provisioning)", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
d1_databases: [{ binding: "VALID" }],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe("[services]", () => {
|
||
it("should error if services is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ services: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "services" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if services is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ services: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "services" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if services is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ services: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "services" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if services is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ services: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "services" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if services bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
services: [
|
||
{},
|
||
{ binding: "SERVICE_BINDING_1" },
|
||
{ binding: 123, service: 456 },
|
||
{ binding: 123, service: 456, environment: 789 },
|
||
{ binding: "SERVICE_BINDING_1", service: 456, environment: 789 },
|
||
{
|
||
binding: 123,
|
||
service: "SERVICE_BINDING_SERVICE_1",
|
||
environment: 789,
|
||
},
|
||
{
|
||
binding: 123,
|
||
service: 456,
|
||
environment: "SERVICE_BINDING_ENVIRONMENT_1",
|
||
},
|
||
{
|
||
binding: "SERVICE_BINDING_1",
|
||
service: "SERVICE_BINDING_SERVICE_1",
|
||
environment: "SERVICE_BINDING_ENVIRONMENT_1",
|
||
entrypoint: 123,
|
||
},
|
||
{
|
||
binding: "SERVICE_BINDING_1",
|
||
service: "SERVICE_BINDING_SERVICE_1",
|
||
entrypoint: 123,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "services[0]" bindings should have a string "binding" field but got {}.
|
||
- "services[0]" bindings should have a string "service" field but got {}.
|
||
- "services[1]" bindings should have a string "service" field but got {"binding":"SERVICE_BINDING_1"}.
|
||
- "services[2]" bindings should have a string "binding" field but got {"binding":123,"service":456}.
|
||
- "services[2]" bindings should have a string "service" field but got {"binding":123,"service":456}.
|
||
- "services[3]" bindings should have a string "binding" field but got {"binding":123,"service":456,"environment":789}.
|
||
- "services[3]" bindings should have a string "service" field but got {"binding":123,"service":456,"environment":789}.
|
||
- "services[3]" bindings should have a string "environment" field but got {"binding":123,"service":456,"environment":789}.
|
||
- "services[4]" bindings should have a string "service" field but got {"binding":"SERVICE_BINDING_1","service":456,"environment":789}.
|
||
- "services[4]" bindings should have a string "environment" field but got {"binding":"SERVICE_BINDING_1","service":456,"environment":789}.
|
||
- "services[5]" bindings should have a string "binding" field but got {"binding":123,"service":"SERVICE_BINDING_SERVICE_1","environment":789}.
|
||
- "services[5]" bindings should have a string "environment" field but got {"binding":123,"service":"SERVICE_BINDING_SERVICE_1","environment":789}.
|
||
- "services[6]" bindings should have a string "binding" field but got {"binding":123,"service":456,"environment":"SERVICE_BINDING_ENVIRONMENT_1"}.
|
||
- "services[6]" bindings should have a string "service" field but got {"binding":123,"service":456,"environment":"SERVICE_BINDING_ENVIRONMENT_1"}.
|
||
- "services[7]" bindings should have a string "entrypoint" field but got {"binding":"SERVICE_BINDING_1","service":"SERVICE_BINDING_SERVICE_1","environment":"SERVICE_BINDING_ENVIRONMENT_1","entrypoint":123}.
|
||
- "services[8]" bindings should have a string "entrypoint" field but got {"binding":"SERVICE_BINDING_1","service":"SERVICE_BINDING_SERVICE_1","entrypoint":123}."
|
||
`);
|
||
});
|
||
|
||
it("should accept a valid `dev` local-plugin configuration", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
services: [
|
||
{
|
||
binding: "ENTITLEMENTS",
|
||
service: "edge-entitlements",
|
||
dev: {
|
||
plugin: {
|
||
package: "@cloudflare/workers-toolbox-plugins",
|
||
name: "entitlements",
|
||
},
|
||
options: { entitlements: [], mapping: {} },
|
||
},
|
||
},
|
||
{
|
||
binding: "ENTITLEMENTS_NO_OPTS",
|
||
service: "edge-entitlements",
|
||
dev: {
|
||
plugin: {
|
||
package: "@cloudflare/workers-toolbox-plugins",
|
||
name: "entitlements",
|
||
},
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on a malformed service binding `dev` field", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
services: [
|
||
{
|
||
binding: "BAD_DEV_NOT_OBJECT",
|
||
service: "svc",
|
||
dev: "nope",
|
||
},
|
||
{
|
||
binding: "BAD_DEV_MISSING_PLUGIN",
|
||
service: "svc",
|
||
dev: {},
|
||
},
|
||
{
|
||
binding: "BAD_DEV_PLUGIN_WRONG_SHAPE",
|
||
service: "svc",
|
||
dev: { plugin: { package: 1, name: 2 } },
|
||
},
|
||
{
|
||
binding: "BAD_DEV_OPTIONS_NOT_OBJECT",
|
||
service: "svc",
|
||
dev: {
|
||
plugin: { package: "p", name: "n" },
|
||
options: "should-be-object",
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "services[0]" bindings should have an object "dev" field but got "nope".
|
||
- "services[1].dev" should have an object "plugin" field but got undefined.
|
||
- "services[2].dev.plugin" should have a string "package" field but got 1.
|
||
- "services[2].dev.plugin" should have a string "name" field but got 2.
|
||
- "services[3].dev.options" should be an object but got "should-be-object"."
|
||
`);
|
||
});
|
||
|
||
it("should warn when both `dev` and `remote: true` are set", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
services: [
|
||
{
|
||
binding: "SERVICE",
|
||
service: "svc",
|
||
remote: true,
|
||
dev: {
|
||
plugin: { package: "p", name: "n" },
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "services[0]" binding has both "dev" and "remote" set; "remote" is ignored when "dev" is present and the binding is routed through the local Miniflare plugin."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[analytics_engine_datasets]", () => {
|
||
it("should error if analytics_engine_datasets is an object", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ analytics_engine_datasets: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "analytics_engine_datasets" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets is a string", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ analytics_engine_datasets: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "analytics_engine_datasets" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets is a number", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ analytics_engine_datasets: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "analytics_engine_datasets" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ analytics_engine_datasets: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "analytics_engine_datasets" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
analytics_engine_datasets: [
|
||
{},
|
||
{ binding: 2333, dataset: 2444 },
|
||
{
|
||
binding: "AE_BINDING_2",
|
||
dataset: 2555,
|
||
},
|
||
{ binding: "AE_BINDING_1", dataset: "" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "analytics_engine_datasets[0]" bindings should have a string "binding" field but got {}.
|
||
- "analytics_engine_datasets[1]" bindings should have a string "binding" field but got {"binding":2333,"dataset":2444}.
|
||
- "analytics_engine_datasets[1]" bindings should, optionally, have a string "dataset" field but got {"binding":2333,"dataset":2444}.
|
||
- "analytics_engine_datasets[2]" bindings should, optionally, have a string "dataset" field but got {"binding":"AE_BINDING_2","dataset":2555}.
|
||
- "analytics_engine_datasets[3]" bindings should, optionally, have a string "dataset" field but got {"binding":"AE_BINDING_1","dataset":""}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[dispatch_namespaces]", () => {
|
||
it("should error if dispatch_namespaces is not an array", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
dispatch_namespaces: "just a string",
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "dispatch_namespaces" should be an array but got "just a string"."
|
||
`);
|
||
});
|
||
|
||
it("should error on non valid dispatch_namespaces", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
dispatch_namespaces: [
|
||
"a string",
|
||
123,
|
||
{
|
||
binding: 123,
|
||
namespace: 456,
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_1",
|
||
namespace: 456,
|
||
},
|
||
// this one is valid
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_1",
|
||
namespace: "DISPATCH_NAMESPACE_BINDING_NAMESPACE_1",
|
||
},
|
||
{
|
||
binding: 123,
|
||
namespace: "DISPATCH_NAMESPACE_BINDING_SERVICE_1",
|
||
},
|
||
{
|
||
binding: 123,
|
||
service: 456,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "dispatch_namespaces[0]" binding should be objects, but got "a string"
|
||
- "dispatch_namespaces[1]" binding should be objects, but got 123
|
||
- "dispatch_namespaces[2]" should have a string "binding" field but got {"binding":123,"namespace":456}.
|
||
- "dispatch_namespaces[2]" should have a string "namespace" field but got {"binding":123,"namespace":456}.
|
||
- "dispatch_namespaces[3]" should have a string "namespace" field but got {"binding":"DISPATCH_NAMESPACE_BINDING_1","namespace":456}.
|
||
- "dispatch_namespaces[5]" should have a string "binding" field but got {"binding":123,"namespace":"DISPATCH_NAMESPACE_BINDING_SERVICE_1"}.
|
||
- "dispatch_namespaces[6]" should have a string "binding" field but got {"binding":123,"service":456}.
|
||
- "dispatch_namespaces[6]" should have a string "namespace" field but got {"binding":123,"service":456}."
|
||
`);
|
||
});
|
||
|
||
test("should error on invalid outbounds for a namespace", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
dispatch_namespaces: [
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_1",
|
||
namespace: "NAMESPACE",
|
||
outbound: "a string",
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_2",
|
||
namespace: "NAMESPACE",
|
||
outbound: [{ not: "valid" }],
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_3",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: 123,
|
||
},
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_4",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: "outbound",
|
||
environment: { bad: "env" },
|
||
},
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_5",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
environment: "production",
|
||
},
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_6",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: "outbound",
|
||
parameters: "bad",
|
||
},
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_7",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: "outbound",
|
||
parameters: false,
|
||
},
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_8",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: "outbound",
|
||
parameters: [true, { not: "good" }],
|
||
},
|
||
},
|
||
// these are correct
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_9",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: "outbound",
|
||
parameters: ["finally", "real", "params"],
|
||
},
|
||
},
|
||
{
|
||
binding: "DISPATCH_NAMESPACE_BINDING_10",
|
||
namespace: "NAMESPACE",
|
||
outbound: {
|
||
service: "outbound",
|
||
environment: "production",
|
||
parameters: ["some", "more", "params"],
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "dispatch_namespaces[0].outbound" should be an object, but got "a string"
|
||
- "dispatch_namespaces[0]" has an invalid outbound definition.
|
||
- "dispatch_namespaces[1].outbound.service" is a required field.
|
||
- "dispatch_namespaces[1]" has an invalid outbound definition.
|
||
- Expected "dispatch_namespaces[2].outbound.service" to be of type string but got 123.
|
||
- "dispatch_namespaces[2]" has an invalid outbound definition.
|
||
- Expected "dispatch_namespaces[3].outbound.environment" to be of type string but got {"bad":"env"}.
|
||
- "dispatch_namespaces[3]" has an invalid outbound definition.
|
||
- "dispatch_namespaces[4].outbound.service" is a required field.
|
||
- "dispatch_namespaces[4]" has an invalid outbound definition.
|
||
- Expected "dispatch_namespaces[5].outbound.parameters" to be an array of strings but got "bad"
|
||
- "dispatch_namespaces[5]" has an invalid outbound definition.
|
||
- Expected "dispatch_namespaces[6].outbound.parameters" to be an array of strings but got false
|
||
- "dispatch_namespaces[6]" has an invalid outbound definition.
|
||
- Expected "dispatch_namespaces[7].outbound.parameters.[0]" to be of type string but got true.
|
||
- Expected "dispatch_namespaces[7].outbound.parameters.[1]" to be of type string but got {"not":"good"}.
|
||
- "dispatch_namespaces[7]" has an invalid outbound definition."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[mtls_certificates]", () => {
|
||
it("should error if mtls_certificates is not an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
mtls_certificates: "just a string",
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "mtls_certificates" should be an array but got "just a string"."
|
||
`);
|
||
});
|
||
|
||
it("should error on non valid mtls_certificates", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
mtls_certificates: [
|
||
"a string",
|
||
123,
|
||
false,
|
||
{
|
||
binding: 123,
|
||
namespace: 123,
|
||
},
|
||
{
|
||
binding: "CERT_ONE",
|
||
id: "1234",
|
||
},
|
||
{
|
||
binding: "CERT_TWO",
|
||
certificate_id: 1234,
|
||
},
|
||
// this one is valid
|
||
{
|
||
binding: "CERT_THREE",
|
||
certificate_id: "1234",
|
||
},
|
||
{
|
||
binding: true,
|
||
service: "1234",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in mtls_certificates[3] field: "namespace"
|
||
- Unexpected fields found in mtls_certificates[4] field: "id"
|
||
- Unexpected fields found in mtls_certificates[7] field: "service""
|
||
`);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "mtls_certificates" bindings should be objects, but got "a string"
|
||
- "mtls_certificates" bindings should be objects, but got 123
|
||
- "mtls_certificates" bindings should be objects, but got false
|
||
- "mtls_certificates[3]" bindings should have a string "binding" field but got {"binding":123,"namespace":123}.
|
||
- "mtls_certificates[3]" bindings should have a string "certificate_id" field but got {"binding":123,"namespace":123}.
|
||
- "mtls_certificates[4]" bindings should have a string "certificate_id" field but got {"binding":"CERT_ONE","id":"1234"}.
|
||
- "mtls_certificates[5]" bindings should have a string "certificate_id" field but got {"binding":"CERT_TWO","certificate_id":1234}.
|
||
- "mtls_certificates[7]" bindings should have a string "binding" field but got {"binding":true,"service":"1234"}.
|
||
- "mtls_certificates[7]" bindings should have a string "certificate_id" field but got {"binding":true,"service":"1234"}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[pipelines]", () => {
|
||
it("should error if pipelines is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ pipelines: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "pipelines" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if pipelines is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ pipelines: "BAD" },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "pipelines" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if pipelines is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ pipelines: 999 },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "pipelines" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if pipelines is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ pipelines: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "pipelines" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings with stream field", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
pipelines: [
|
||
{
|
||
binding: "VALID",
|
||
stream: "343cd4f1d58c42fbb5bd082592fd7143",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should accept deprecated pipeline field with warning", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
pipelines: [
|
||
{
|
||
binding: "VALID",
|
||
pipeline: "343cd4f1d58c42fbb5bd082592fd7143",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The "pipeline" field in "pipelines[0]" bindings is deprecated. Use "stream" instead."
|
||
`);
|
||
});
|
||
|
||
it("should error if pipelines.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
pipelines: [
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
stream: "343cd4f1d58c42fbb5bd082592fd7143",
|
||
},
|
||
{ binding: 2000, project: 2111 },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in pipelines[2] field: "project""
|
||
`);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "pipelines[0]" bindings must have a string "binding" field but got {}.
|
||
- "pipelines[0]" bindings must have a string "stream" field but got {}.
|
||
- "pipelines[2]" bindings must have a string "binding" field but got {"binding":2000,"project":2111}.
|
||
- "pipelines[2]" bindings must have a string "stream" field but got {"binding":2000,"project":2111}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[secrets_store_secrets]", () => {
|
||
it("should error if secrets_store_secrets is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ secrets_store_secrets: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "secrets_store_secrets" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if secrets_store_secrets is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ secrets_store_secrets: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "secrets_store_secrets" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
secrets_store_secrets: [
|
||
{
|
||
binding: "VALID",
|
||
store_id: "store_id",
|
||
secret_name: "secret_name",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if secrets_store_secrets.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
secrets_store_secrets: [
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
store_id: "store_id",
|
||
secret_name: "secret_name",
|
||
},
|
||
{
|
||
binding: null,
|
||
invalid: true,
|
||
store_id: 123,
|
||
secret_name: null,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in secrets_store_secrets[2] field: "invalid""
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "secrets_store_secrets[0]" bindings must have a string "binding" field but got {}.
|
||
- "secrets_store_secrets[0]" bindings must have a string "store_id" field but got {}.
|
||
- "secrets_store_secrets[0]" bindings must have a string "secret_name" field but got {}.
|
||
- "secrets_store_secrets[2]" bindings must have a string "binding" field but got {"binding":null,"invalid":true,"store_id":123,"secret_name":null}.
|
||
- "secrets_store_secrets[2]" bindings must have a string "store_id" field but got {"binding":null,"invalid":true,"store_id":123,"secret_name":null}.
|
||
- "secrets_store_secrets[2]" bindings must have a string "secret_name" field but got {"binding":null,"invalid":true,"store_id":123,"secret_name":null}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[artifacts]", () => {
|
||
it("should error if artifacts is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ artifacts: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "artifacts" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if artifacts is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ artifacts: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "artifacts" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
artifacts: [
|
||
{
|
||
binding: "MY_ARTIFACTS",
|
||
namespace: "default",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept valid bindings with remote set to true", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
artifacts: [
|
||
{
|
||
binding: "MY_ARTIFACTS",
|
||
namespace: "default",
|
||
remote: true,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if remote is not a boolean", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
artifacts: [
|
||
{
|
||
binding: "MY_ARTIFACTS",
|
||
namespace: "default",
|
||
remote: "yes",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "artifacts[0]" should, optionally, have a boolean "remote" field but got {"binding":"MY_ARTIFACTS","namespace":"default","remote":"yes"}."
|
||
`);
|
||
});
|
||
|
||
it("should error if artifacts bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
artifacts: [
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
namespace: "default",
|
||
},
|
||
{
|
||
binding: null,
|
||
invalid: true,
|
||
namespace: 123,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in artifacts[2] field: "invalid""
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "artifacts[0]" bindings must have a string "binding" field but got {}.
|
||
- "artifacts[0]" bindings must have a string "namespace" field but got {}.
|
||
- "artifacts[2]" bindings must have a string "binding" field but got {"binding":null,"invalid":true,"namespace":123}.
|
||
- "artifacts[2]" bindings must have a string "namespace" field but got {"binding":null,"invalid":true,"namespace":123}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[worker_loaders]", () => {
|
||
it("should error if worker_loaders is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ worker_loaders: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "worker_loaders" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if worker_loaders is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ worker_loaders: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "worker_loaders" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
worker_loaders: [
|
||
{
|
||
binding: "VALID",
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if worker_loaders bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
worker_loaders: [
|
||
// @ts-expect-error Test if empty object is caught
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
},
|
||
{
|
||
// @ts-expect-error Test if binding is not a string
|
||
binding: null,
|
||
invalid: true,
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in worker_loaders[2] field: "invalid""
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "worker_loaders[0]" bindings must have a string "binding" field but got {}.
|
||
- "worker_loaders[2]" bindings must have a string "binding" field but got {"binding":null,"invalid":true}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[unsafe_hello_world]", () => {
|
||
it("should error if unsafe_hello_world is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ unsafe_hello_world: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe_hello_world" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe_hello_world is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ unsafe_hello_world: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe_hello_world" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
unsafe_hello_world: [
|
||
{
|
||
binding: "VALID",
|
||
enable_timer: true,
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if hello_world.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
unsafe_hello_world: [
|
||
// @ts-expect-error Test if empty object is caught
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
// @ts-expect-error Test if enable_timer is not a boolean
|
||
enable_timer: "yes",
|
||
},
|
||
{
|
||
// @ts-expect-error Test if binding is not a string
|
||
binding: null,
|
||
invalid: true,
|
||
enable_timer: false,
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in unsafe_hello_world[2] field: "invalid""
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe_hello_world[0]" bindings must have a string "binding" field but got {}.
|
||
- "unsafe_hello_world[1]" bindings must have a boolean "enable_timer" field but got {"binding":"VALID","enable_timer":"yes"}.
|
||
- "unsafe_hello_world[2]" bindings must have a string "binding" field but got {"binding":null,"invalid":true,"enable_timer":false}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[flagship]", () => {
|
||
it("should error if flagship is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ flagship: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "flagship" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if flagship is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ flagship: "bad" },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "flagship" should be an array but got "bad"."
|
||
`);
|
||
});
|
||
|
||
it("should error if flagship is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ flagship: 999 },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "flagship" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if flagship is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ flagship: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "flagship" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid flagship bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
flagship: [
|
||
{
|
||
binding: "FLAGS",
|
||
app_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error if flagship bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
flagship: [
|
||
// @ts-expect-error purposely using an invalid value
|
||
{},
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ binding: "VALID" },
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ binding: 2000, app_id: 2111 },
|
||
{
|
||
binding: "BINDING_2",
|
||
app_id: "valid-app-id",
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "flagship[0]" bindings must have a string "binding" field but got {}.
|
||
- "flagship[0]" bindings must have a string "app_id" field but got {}.
|
||
- "flagship[1]" bindings must have a string "app_id" field but got {"binding":"VALID"}.
|
||
- "flagship[2]" bindings must have a string "binding" field but got {"binding":2000,"app_id":2111}.
|
||
- "flagship[2]" bindings must have a string "app_id" field but got {"binding":2000,"app_id":2111}."
|
||
`);
|
||
});
|
||
|
||
it("should warn on unexpected fields", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
flagship: [
|
||
{
|
||
binding: "FLAGS",
|
||
app_id: "valid-app-id",
|
||
// @ts-expect-error purposely using an invalid field
|
||
unknown_field: true,
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in flagship[0] field: "unknown_field""
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[workflows]", () => {
|
||
it("should error if workflows is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ workflows: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "workflows" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if workflows is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ workflows: "BAD" },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "workflows" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if workflows is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ workflows: 999 },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "workflows" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if workflows is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ workflows: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "workflows" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid workflow bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should accept valid workflow bindings with optional fields", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
script_name: "my-script",
|
||
remote: true,
|
||
limits: { steps: 100 },
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should accept valid workflow bindings with schedules as a string", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: "*/5 * * * *",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should accept valid workflow bindings with schedules as an array of strings", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: ["*/5 * * * *", "0 9 * * 1"],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error if workflow bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{},
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
},
|
||
{ binding: 2000, name: 2111, class_name: 3000 },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings should have a string "binding" field but got {}.
|
||
- "workflows[0]" bindings should have a string "name" field but got {}.
|
||
- "workflows[0]" bindings should have a string "class_name" field but got {}.
|
||
- "workflows[2]" bindings should have a string "binding" field but got {"binding":2000,"name":2111,"class_name":3000}.
|
||
- "workflows[2]" bindings should have a string "name" field but got {"binding":2000,"name":2111,"class_name":3000}.
|
||
- "workflows[2]" bindings should have a string "class_name" field but got {"binding":2000,"name":2111,"class_name":3000}."
|
||
`);
|
||
});
|
||
|
||
it("should error if workflow name has invalid format", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "invalid name with spaces",
|
||
class_name: "MyWorkflow",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" binding "name" field is invalid. Workflow names must be 1-64 characters long, start with a letter, number, or underscore, and may only contain letters, numbers, underscores, or hyphens."
|
||
`);
|
||
});
|
||
|
||
it("should error if optional fields have wrong types", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
script_name: 123,
|
||
remote: "yes",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings should, optionally, have a string "script_name" field but got {"binding":"MY_WORKFLOW","name":"my-workflow","class_name":"MyWorkflow","script_name":123,"remote":"yes"}.
|
||
- "workflows[0]" bindings should, optionally, have a boolean "remote" field but got {"binding":"MY_WORKFLOW","name":"my-workflow","class_name":"MyWorkflow","script_name":123,"remote":"yes"}."
|
||
`);
|
||
});
|
||
|
||
it("should error if schedules has wrong type", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: 123,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings should, optionally, have a string or array of strings "schedules" field but got {"binding":"MY_WORKFLOW","name":"my-workflow","class_name":"MyWorkflow","schedules":123}."
|
||
`);
|
||
});
|
||
|
||
it("should error if schedules is an empty string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: "",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings "schedules" field must not be an empty string."
|
||
`);
|
||
});
|
||
|
||
it("should error if schedules is an empty array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: [],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings "schedules" field must not be an empty array."
|
||
`);
|
||
});
|
||
|
||
it("should error if schedules is an array containing non-strings", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: ["*/5 * * * *", 123],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings should, optionally, have a string or array of strings "schedules" field but got {"binding":"MY_WORKFLOW","name":"my-workflow","class_name":"MyWorkflow","schedules":["*/5 * * * *",123]}."
|
||
`);
|
||
});
|
||
|
||
it("should error if schedules is an array containing empty strings", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
schedules: ["*/5 * * * *", ""],
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings "schedules" field must not contain empty strings."
|
||
`);
|
||
});
|
||
|
||
it("should error if limits is not an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
limits: "bad",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings should, optionally, have an object "limits" field but got {"binding":"MY_WORKFLOW","name":"my-workflow","class_name":"MyWorkflow","limits":"bad"}."
|
||
`);
|
||
});
|
||
|
||
it("should error if limits.steps is not a positive integer", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
limits: { steps: -1 },
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" bindings "limits.steps" field must be a positive integer but got -1."
|
||
`);
|
||
});
|
||
|
||
it("should warn if limits.steps exceeds 25000", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
limits: { steps: 30000 },
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows[0]" has a step limit of 30000, which exceeds the production maximum of 25,000. This configuration may not work when deployed."
|
||
`);
|
||
});
|
||
|
||
it("should warn on unexpected fields", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "MY_WORKFLOW",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow",
|
||
unknown_field: true,
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in workflows[0] field: "unknown_field""
|
||
`);
|
||
});
|
||
|
||
it("should error on duplicate workflow names", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
workflows: [
|
||
{
|
||
binding: "WORKFLOW_1",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow1",
|
||
},
|
||
{
|
||
binding: "WORKFLOW_2",
|
||
name: "my-workflow",
|
||
class_name: "MyWorkflow2",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "workflows" bindings must have unique "name" values; duplicate(s) found: "my-workflow""
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[logfwdr]", () => {
|
||
it("should error if logfwdr is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr.bindings is not defined", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: {} } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr" is missing the required "bindings" property."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr.bindings is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: { bindings: {} } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr.bindings" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr.bindings is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: { bindings: "BAD" } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr.bindings" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr.bindings is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: { bindings: 999 } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr.bindings" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr.bindings is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ logfwdr: { bindings: null } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "logfwdr.bindings" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid logfwdr bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
logfwdr: {
|
||
bindings: [
|
||
{
|
||
name: "httplogs",
|
||
destination: "httplogs",
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error if logfwdr.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
logfwdr: {
|
||
bindings: [
|
||
{},
|
||
{ name: "VALID", destination: "valid-dest" },
|
||
{ name: 123, destination: 456 },
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "logfwdr.bindings[0]": {}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "destination" field.
|
||
|
||
- "logfwdr.bindings[2]": {"name":123,"destination":456}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "destination" field."
|
||
`);
|
||
});
|
||
|
||
it("should error if logfwdr has deprecated schema property", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
logfwdr: {
|
||
bindings: [
|
||
{
|
||
name: "httplogs",
|
||
destination: "httplogs",
|
||
},
|
||
],
|
||
schema: "some-schema",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "logfwdr" binding "schema" property has been replaced with the "unsafe.capnp" object, which expects a "base_path" and an array of "source_schemas" to compile, or a "compiled_schema" property."
|
||
`);
|
||
});
|
||
|
||
it("should warn on unexpected fields in logfwdr bindings", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
logfwdr: {
|
||
bindings: [
|
||
{
|
||
name: "httplogs",
|
||
destination: "httplogs",
|
||
unknown_field: true,
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "logfwdr.bindings[0]": {"name":"httplogs","destination":"httplogs","unknown_field":true}
|
||
- Unexpected fields found in logfwdr.bindings[0] field: "unknown_field""
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[ratelimit]", () => {
|
||
it("should error if ratelimit is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ ratelimits: {} },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ratelimits" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if ratelimit is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid value
|
||
{ ratelimits: null },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "ratelimits" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ratelimits: [
|
||
{
|
||
name: "RATE_LIMITER",
|
||
namespace_id: "1001",
|
||
simple: {
|
||
limit: 5,
|
||
period: 60,
|
||
},
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if ratelimit bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
ratelimits: [
|
||
// @ts-expect-error Test if empty object is caught
|
||
{},
|
||
// @ts-expect-error Test if simple is missing
|
||
{
|
||
name: "VALID",
|
||
namespace_id: "1001",
|
||
},
|
||
{
|
||
// @ts-expect-error Test if name is not a string
|
||
name: null,
|
||
// @ts-expect-error Test if namespace_id is not a string
|
||
namespace_id: 123,
|
||
simple: {
|
||
// @ts-expect-error Test if limit is not a number
|
||
limit: "not a number",
|
||
// @ts-expect-error Test if period is invalid
|
||
period: 90,
|
||
},
|
||
invalid: true,
|
||
},
|
||
{
|
||
name: "MISSING_PERIOD",
|
||
namespace_id: "1002",
|
||
// @ts-expect-error Test if period is missing
|
||
simple: {
|
||
limit: 10,
|
||
},
|
||
},
|
||
],
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in ratelimits[2] field: "invalid""
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "ratelimits[0]" bindings must have a string "name" field but got {}.
|
||
- "ratelimits[0]" bindings must have a string "namespace_id" field but got {}.
|
||
- "ratelimits[0]" bindings must have a "simple" configuration object but got {}.
|
||
- "ratelimits[1]" bindings must have a "simple" configuration object but got {"name":"VALID","namespace_id":"1001"}.
|
||
- "ratelimits[2]" bindings must have a string "name" field but got {"name":null,"namespace_id":123,"simple":{"limit":"not a number","period":90},"invalid":true}.
|
||
- "ratelimits[2]" bindings must have a string "namespace_id" field but got {"name":null,"namespace_id":123,"simple":{"limit":"not a number","period":90},"invalid":true}.
|
||
- "ratelimits[2]" bindings "simple.limit" must be a number but got {"limit":"not a number","period":90}.
|
||
- "ratelimits[2]" bindings "simple.period" must be either 10 or 60 but got 90.
|
||
- "ratelimits[3]" bindings "simple.period" is required and must be a number but got {"limit":10}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[vpc_services]", () => {
|
||
it("should accept valid bindings", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vpc_services: [
|
||
{
|
||
binding: "MYAPI",
|
||
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
|
||
},
|
||
{
|
||
binding: "DATABASE",
|
||
service_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
|
||
},
|
||
],
|
||
} as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.vpc_services).toEqual([
|
||
{
|
||
binding: "MYAPI",
|
||
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
|
||
},
|
||
{
|
||
binding: "DATABASE",
|
||
service_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
|
||
},
|
||
]);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if vpc_services bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vpc_services: [
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
|
||
},
|
||
{ binding: null, service_id: 123, invalid: true },
|
||
{ binding: "MISSING_SERVICE_ID" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "vpc_services[0]" bindings should have a string "binding" field but got {}.
|
||
- "vpc_services[0]" bindings must have a "service_id" field but got {}.
|
||
- "vpc_services[2]" bindings should have a string "binding" field but got {"binding":null,"service_id":123,"invalid":true}.
|
||
- "vpc_services[2]" bindings must have a "service_id" field but got {"binding":null,"service_id":123,"invalid":true}.
|
||
- "vpc_services[3]" bindings must have a "service_id" field but got {"binding":"MISSING_SERVICE_ID"}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[vpc_networks]", () => {
|
||
it("should accept valid bindings with tunnel_id", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vpc_networks: [
|
||
{
|
||
binding: "MY_NETWORK",
|
||
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
|
||
},
|
||
{
|
||
binding: "MY_OTHER_NETWORK",
|
||
tunnel_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
|
||
},
|
||
],
|
||
} as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.vpc_networks).toEqual([
|
||
{
|
||
binding: "MY_NETWORK",
|
||
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
|
||
},
|
||
{
|
||
binding: "MY_OTHER_NETWORK",
|
||
tunnel_id: "0299295b-b3ac-7760-8246-bca40877b3e0",
|
||
},
|
||
]);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept valid bindings with network_id", ({ expect }) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vpc_networks: [
|
||
{
|
||
binding: "MY_MESH_NETWORK",
|
||
network_id: "some-network-id",
|
||
},
|
||
],
|
||
} as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.vpc_networks).toEqual([
|
||
{
|
||
binding: "MY_MESH_NETWORK",
|
||
network_id: "some-network-id",
|
||
},
|
||
]);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if both tunnel_id and network_id are provided", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vpc_networks: [
|
||
{
|
||
binding: "MY_NETWORK",
|
||
tunnel_id: "aaa",
|
||
network_id: "some-network-id",
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "vpc_networks[0]" bindings must have either a "tunnel_id" or "network_id", but not both."
|
||
`);
|
||
});
|
||
|
||
it("should error if vpc_networks bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vpc_networks: [
|
||
{},
|
||
{
|
||
binding: "VALID",
|
||
tunnel_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
|
||
},
|
||
{ binding: null, tunnel_id: 123, invalid: true },
|
||
{ binding: "MISSING_ID" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "vpc_networks[0]" bindings should have a string "binding" field but got {}.
|
||
- "vpc_networks[0]" bindings must have either a "tunnel_id" or "network_id" field but got {}.
|
||
- "vpc_networks[2]" bindings should have a string "binding" field but got {"binding":null,"tunnel_id":123,"invalid":true}.
|
||
- "vpc_networks[2]" bindings must have a string "tunnel_id" field but got {"binding":null,"tunnel_id":123,"invalid":true}.
|
||
- "vpc_networks[3]" bindings must have either a "tunnel_id" or "network_id" field but got {"binding":"MISSING_ID"}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[unsafe.bindings]", () => {
|
||
it("should error if unsafe is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: [] } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: "BAD" } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: 999 } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: null } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should not error if unsafe is an empty object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: {} } satisfies RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe contains unexpected properties", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
unsafe: {
|
||
invalid: true,
|
||
},
|
||
} as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time.
|
||
- Unexpected fields found in unsafe field: "invalid""
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { bindings: {} } } as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.bindings" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { bindings: "BAD" } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.bindings" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { bindings: 999 } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.bindings" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { bindings: null } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.bindings" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
unsafe: {
|
||
bindings: [
|
||
{},
|
||
{ name: "UNSAFE_BINDING_1" },
|
||
{ name: 2666, type: 2777 },
|
||
{
|
||
name: "UNSAFE_BINDING_2",
|
||
type: "UNSAFE_TYPE_2",
|
||
extra: 2888,
|
||
},
|
||
],
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "unsafe.bindings[0]": {}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "type" field.
|
||
|
||
- "unsafe.bindings[1]": {"name":"UNSAFE_BINDING_1"}
|
||
- binding should have a string "type" field.
|
||
|
||
- "unsafe.bindings[2]": {"name":2666,"type":2777}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "type" field."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { metadata: [] } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.metadata" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { metadata: "BAD" } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.metadata" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { metadata: 999 } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.metadata" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { metadata: null } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "unsafe.metadata" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should not provide an unsafe warning when the environment variable is specified", ({
|
||
expect,
|
||
}) => {
|
||
vi.stubEnv("WRANGLER_DISABLE_EXPERIMENTAL_WARNING", "1");
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ unsafe: { bindings: [] } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
});
|
||
|
||
it("should accept unsafe fields under containers", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
containers: [
|
||
{
|
||
name: "test-container",
|
||
class_name: "TestContainer",
|
||
image: "registry.cloudflare.com/test:image",
|
||
unsafe: {
|
||
custom_field: "value",
|
||
},
|
||
},
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
});
|
||
|
||
describe("[placement]", () => {
|
||
it(`should error if placement hint is set with placement mode "off"`, ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ placement: { mode: "off", hint: "wnam" } },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "placement.hint" can only be set when "placement.mode" is "smart""
|
||
`);
|
||
});
|
||
|
||
it(`should not error if placement hint is set with placement mode "smart"`, ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ placement: { mode: "smart", hint: "wnam" } },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it(`should error if placement hint object is set with placement mode "targeted"`, ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
placement: { mode: "targeted", hint: "wnam" },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "placement.mode" field to be one of ["off","smart"] but got "targeted".
|
||
- "placement.hint" can only be set when "placement.mode" is "smart""
|
||
`);
|
||
});
|
||
|
||
it(`should not error if hostname field is set with placement mode "targeted"`, ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ placement: { hostname: "example.com" } },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it(`should not error if host field is set with placement mode "targeted"`, ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ placement: { host: "example.com:5432" } },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it(`should not error if host field is set with placement mode "targeted"`, ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ placement: { region: "aws:us-east-1" } },
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it(`should error if placement has an invalid field`, ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ placement: { shoeSize: 13 } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
});
|
||
});
|
||
|
||
describe("route & routes fields", () => {
|
||
it("should error if both route and routes are specified", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
route: "route1",
|
||
routes: ["route2", "route3"],
|
||
};
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected exactly one of the following fields ["routes","route"]."
|
||
`);
|
||
});
|
||
});
|
||
});
|
||
|
||
describe("named environments", () => {
|
||
it("should use --env CLI arg to select the active environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
name: "my-worker",
|
||
env: {
|
||
dev: {
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
},
|
||
prod: {
|
||
kv_namespaces: [{ binding: "KV", id: "yyyy-yyyy-yyyy-yyyy" }],
|
||
},
|
||
},
|
||
};
|
||
const { config: configDev } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "dev" }
|
||
);
|
||
expect(configDev).toEqual(
|
||
expect.objectContaining({
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
})
|
||
);
|
||
|
||
const { config: configProd } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "prod" }
|
||
);
|
||
expect(configProd).toEqual(
|
||
expect.objectContaining({
|
||
kv_namespaces: [{ binding: "KV", id: "yyyy-yyyy-yyyy-yyyy" }],
|
||
})
|
||
);
|
||
});
|
||
|
||
it("should use CLOUDFLARE_ENV environment variable to select the active environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
name: "my-worker",
|
||
env: {
|
||
dev: {
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
},
|
||
prod: {
|
||
kv_namespaces: [{ binding: "KV", id: "yyyy-yyyy-yyyy-yyyy" }],
|
||
},
|
||
},
|
||
};
|
||
vi.stubEnv("CLOUDFLARE_ENV", "dev");
|
||
const { config: configDev } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{}
|
||
);
|
||
expect(configDev).toEqual(
|
||
expect.objectContaining({
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
})
|
||
);
|
||
|
||
vi.stubEnv("CLOUDFLARE_ENV", "prod");
|
||
const { config: configProd } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{}
|
||
);
|
||
expect(configProd).toEqual(
|
||
expect.objectContaining({
|
||
kv_namespaces: [{ binding: "KV", id: "yyyy-yyyy-yyyy-yyyy" }],
|
||
})
|
||
);
|
||
});
|
||
|
||
it("should use the `--env` CLI arg over the CLOUDFLARE_ENV environment variable to select the active environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
name: "my-worker",
|
||
env: {
|
||
dev: {
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
},
|
||
prod: {
|
||
kv_namespaces: [{ binding: "KV", id: "yyyy-yyyy-yyyy-yyyy" }],
|
||
},
|
||
},
|
||
};
|
||
vi.stubEnv("CLOUDFLARE_ENV", "dev");
|
||
const { config } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "prod" }
|
||
);
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
kv_namespaces: [{ binding: "KV", id: "yyyy-yyyy-yyyy-yyyy" }],
|
||
})
|
||
);
|
||
});
|
||
|
||
it("should warn if we specify an environment but there are no named environments", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
name: "my-worker",
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
};
|
||
const { diagnostics, config } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: "dev",
|
||
}
|
||
);
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
name: "my-worker-dev",
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
})
|
||
);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- No environment found in configuration with name "dev".
|
||
Before using \`--env=dev\` there should be an equivalent environment section in the configuration.
|
||
|
||
Consider adding an environment configuration section to the Wrangler configuration file:
|
||
\`\`\`
|
||
[env.dev]
|
||
\`\`\`
|
||
"
|
||
`);
|
||
});
|
||
|
||
describe("with redirected config", () => {
|
||
it("should error if we specify an environment via an argument that doesn't match the original target environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RedirectedRawConfig = {
|
||
name: "my-worker",
|
||
targetEnvironment: "prod",
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
};
|
||
expect(() =>
|
||
normalizeAndValidateConfig(
|
||
rawConfig,
|
||
"./redirected-config.jsonc",
|
||
"./original-config.jsonc",
|
||
{
|
||
env: "dev",
|
||
}
|
||
)
|
||
).toThrowErrorMatchingInlineSnapshot(`
|
||
[Error: You have specified the environment "dev" via the \`--env/-e\` CLI argument.
|
||
This does not match the target environment "prod" that was used when building the application.
|
||
Perhaps you need to re-run the custom build of the project with "dev" as the selected environment?]
|
||
`);
|
||
});
|
||
|
||
it("should error if we specify an environment via an environment variable that doesn't match the original target environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RedirectedRawConfig = {
|
||
name: "my-worker",
|
||
targetEnvironment: "prod",
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
};
|
||
vi.stubEnv("CLOUDFLARE_ENV", "dev");
|
||
expect(() =>
|
||
normalizeAndValidateConfig(
|
||
rawConfig,
|
||
"./redirected-config.jsonc",
|
||
"./original-config.jsonc",
|
||
{}
|
||
)
|
||
).toThrowErrorMatchingInlineSnapshot(`
|
||
[Error: You have specified the environment "dev" via the CLOUDFLARE_ENV environment variable.
|
||
This does not match the target environment "prod" that was used when building the application.
|
||
Perhaps you need to re-run the custom build of the project with "dev" as the selected environment?]
|
||
`);
|
||
});
|
||
|
||
it("should error if we specify an environment via both an argument and CLOUDFLARE_ENV that doesn't match the original target environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RedirectedRawConfig = {
|
||
name: "my-worker",
|
||
targetEnvironment: "prod",
|
||
kv_namespaces: [{ binding: "KV", id: "xxxx-xxxx-xxxx-xxxx" }],
|
||
};
|
||
vi.stubEnv("CLOUDFLARE_ENV", "staging");
|
||
expect(() =>
|
||
normalizeAndValidateConfig(
|
||
rawConfig,
|
||
"./redirected-config.jsonc",
|
||
"./original-config.jsonc",
|
||
{
|
||
env: "dev",
|
||
}
|
||
)
|
||
).toThrowErrorMatchingInlineSnapshot(`
|
||
[Error: You have specified the environment "dev" via the \`--env/-e\` CLI argument.
|
||
This does not match the target environment "prod" that was used when building the application.
|
||
Perhaps you need to re-run the custom build of the project with "dev" as the selected environment?]
|
||
`);
|
||
});
|
||
});
|
||
|
||
it("should error if we specify an environment that does not match the named environments", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = { env: { ENV1: {} } };
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: "DEV",
|
||
}
|
||
);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- No environment found in configuration with name "DEV".
|
||
Before using \`--env=DEV\` there should be an equivalent environment section in the configuration.
|
||
The available configured environment names are: ["ENV1"]
|
||
|
||
Consider adding an environment configuration section to the Wrangler configuration file:
|
||
\`\`\`
|
||
[env.DEV]
|
||
\`\`\`
|
||
"
|
||
`);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should use top-level values for inheritable config fields", ({
|
||
expect,
|
||
}) => {
|
||
const main = "src/index.ts";
|
||
const resolvedMain = path.resolve(process.cwd(), main);
|
||
const rawConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
routes: ["ROUTE_1", "ROUTE_2"],
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
tsconfig: "path/to/tsconfig.json",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
main,
|
||
build: {
|
||
command: "COMMAND",
|
||
cwd: "CWD",
|
||
watch_dir: "WATCH_DIR",
|
||
},
|
||
no_bundle: true,
|
||
minify: true,
|
||
first_party_worker: true,
|
||
logpush: true,
|
||
upload_source_maps: true,
|
||
observability: {
|
||
enabled: true,
|
||
head_sampling_rate: 0.5,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{ ...rawConfig, env: { dev: {} } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "dev" }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
...rawConfig,
|
||
main: resolvedMain,
|
||
name: "mock-name-dev",
|
||
topLevelName: "mock-name",
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should override top-level values for inheritable config fields", ({
|
||
expect,
|
||
}) => {
|
||
const main = "src/index.ts";
|
||
const resolvedMain = path.resolve(process.cwd(), main);
|
||
const rawEnv: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
tsconfig: "ENV_path/to/tsconfig.json",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
main,
|
||
build: {
|
||
command: "ENV_COMMAND",
|
||
cwd: "ENV_CWD",
|
||
watch_dir: "ENV_WATCH_DIR",
|
||
},
|
||
no_bundle: false,
|
||
minify: false,
|
||
first_party_worker: false,
|
||
logpush: false,
|
||
upload_source_maps: false,
|
||
observability: {
|
||
enabled: false,
|
||
},
|
||
};
|
||
const rawConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
routes: ["ROUTE_1", "ROUTE_2"],
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
tsconfig: "path/to/tsconfig.json",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
main: "top-level.js",
|
||
build: {
|
||
command: "COMMAND",
|
||
cwd: "CWD",
|
||
watch_dir: "WATCH_DIR",
|
||
},
|
||
no_bundle: true,
|
||
minify: true,
|
||
first_party_worker: true,
|
||
logpush: true,
|
||
upload_source_maps: true,
|
||
observability: {
|
||
enabled: true,
|
||
},
|
||
env: {
|
||
ENV1: rawEnv,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
...rawEnv,
|
||
main: resolvedMain,
|
||
topLevelName: "mock-name",
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should warn for non-inherited fields that are missing in environments", ({
|
||
expect,
|
||
}) => {
|
||
const define: RawConfig["define"] = {
|
||
abc: "123",
|
||
};
|
||
const vars: RawConfig["vars"] = {
|
||
FOO: "foo",
|
||
BAR: "bar",
|
||
};
|
||
const durable_objects: RawConfig["durable_objects"] = {
|
||
bindings: [],
|
||
};
|
||
const kv_namespaces: RawConfig["kv_namespaces"] = [];
|
||
const r2_buckets: RawConfig["r2_buckets"] = [];
|
||
const analytics_engine_datasets: RawConfig["analytics_engine_datasets"] =
|
||
[];
|
||
const unsafe: RawConfig["unsafe"] = {
|
||
bindings: undefined,
|
||
metadata: undefined,
|
||
};
|
||
const rawConfig: RawConfig = {
|
||
define,
|
||
vars,
|
||
durable_objects,
|
||
kv_namespaces,
|
||
r2_buckets,
|
||
analytics_engine_datasets,
|
||
unsafe,
|
||
env: {
|
||
ENV1: {},
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.not.objectContaining({
|
||
define,
|
||
vars,
|
||
durable_objects,
|
||
kv_namespaces,
|
||
r2_buckets,
|
||
analytics_engine_datasets,
|
||
unsafe,
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time.
|
||
- "env.ENV1" environment configuration
|
||
- "vars" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "vars" is not inherited by environments.
|
||
Please add "vars" to "env.ENV1".
|
||
- "define" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "define" is not inherited by environments.
|
||
Please add "define" to "env.ENV1".
|
||
- "durable_objects" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "durable_objects" is not inherited by environments.
|
||
Please add "durable_objects" to "env.ENV1".
|
||
- "kv_namespaces" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "kv_namespaces" is not inherited by environments.
|
||
Please add "kv_namespaces" to "env.ENV1".
|
||
- "r2_buckets" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "r2_buckets" is not inherited by environments.
|
||
Please add "r2_buckets" to "env.ENV1".
|
||
- "analytics_engine_datasets" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "analytics_engine_datasets" is not inherited by environments.
|
||
Please add "analytics_engine_datasets" to "env.ENV1".
|
||
- "unsafe" exists at the top level, but not on "env.ENV1".
|
||
This is not what you probably want, since "unsafe" is not inherited by environments.
|
||
Please add "unsafe" to "env.ENV1"."
|
||
`);
|
||
});
|
||
|
||
it("should condense repeated environment warnings", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
vars: {
|
||
DEV_ACCOUNT_ID: "123",
|
||
DEV_ACCOUNT_INTERNAL_ID: "456",
|
||
PRESENT: "789",
|
||
},
|
||
secrets: {
|
||
required: ["TOP_LEVEL_SECRET"],
|
||
},
|
||
env: {
|
||
staging: {
|
||
vars: {
|
||
PRESENT: "789",
|
||
},
|
||
secrets: {
|
||
required: ["ENV_SECRET"],
|
||
},
|
||
},
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: "staging" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.staging" environment configuration
|
||
- The following vars exist at the top level, but not on "env.staging.vars".
|
||
This is probably not what you want, since "vars" configuration is not inherited by environments.
|
||
Please add these vars to "env.staging.vars":
|
||
- DEV_ACCOUNT_ID
|
||
- DEV_ACCOUNT_INTERNAL_ID"
|
||
`);
|
||
});
|
||
|
||
it("should only emit one unsafe experimental warning when unsafe exists at the top level and in the environment", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
unsafe: {
|
||
bindings: [],
|
||
},
|
||
env: {
|
||
staging: {
|
||
unsafe: {
|
||
bindings: [],
|
||
},
|
||
},
|
||
},
|
||
},
|
||
undefined,
|
||
undefined,
|
||
{ env: "staging" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
});
|
||
|
||
it("should error on Date values in vars (parsed by TOML)", ({ expect }) => {
|
||
const rawConfig = TOML.parse(`
|
||
[vars]
|
||
VALID_VAR = "some string"
|
||
DATE_VAR = 2024-01-01
|
||
`) as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "vars.DATE_VAR" is a TOML date, which is not supported. Please use a string instead, e.g. DATE_VAR = "2025-12-19"."
|
||
`);
|
||
});
|
||
|
||
it("should error on Date values in env vars (parsed by TOML)", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = TOML.parse(`
|
||
[env.production.vars]
|
||
VALID_VAR = "some string"
|
||
RELEASE_DATE = 2025-06-15
|
||
`) as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "production" }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.production" environment configuration
|
||
- The field "env.production.vars.RELEASE_DATE" is a TOML date, which is not supported. Please use a string instead, e.g. RELEASE_DATE = "2025-12-19"."
|
||
`);
|
||
});
|
||
|
||
it("should error on node_compat", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error node_compat has been removed
|
||
{ env: { ENV1: { node_compat: true } } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- [1mRemoved[0m: "node_compat":
|
||
The "node_compat" field is no longer supported as of Wrangler v4. Instead, use the \`nodejs_compat\` compatibility flag. This includes the functionality from legacy \`node_compat\` polyfills and natively implemented Node.js APIs. See https://developers.cloudflare.com/workers/runtime-apis/nodejs for more information."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid environment values", ({ expect }) => {
|
||
const expectedConfig: RawEnvironment = {
|
||
name: 111,
|
||
account_id: 222,
|
||
compatibility_date: 333,
|
||
compatibility_flags: [444, 555],
|
||
workers_dev: "BAD",
|
||
routes: [666, 777],
|
||
route: 888,
|
||
jsx_factory: 999,
|
||
jsx_fragment: 1000,
|
||
tsconfig: 123,
|
||
triggers: { crons: [1111, 1222] },
|
||
main: 1333,
|
||
build: {
|
||
command: 1444,
|
||
cwd: 1555,
|
||
watch_dir: 1666,
|
||
},
|
||
no_bundle: "INVALID",
|
||
minify: "INVALID",
|
||
first_party_worker: "INVALID",
|
||
logpush: "INVALID",
|
||
upload_source_maps: "INVALID",
|
||
} as unknown as RawEnvironment;
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: expectedConfig } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- Expected "route" to be either a string, or an object with shape { pattern, custom_domain, zone_id | zone_name, enabled, previews_enabled }, but got 888.
|
||
- Expected "account_id" to be of type string but got 222.
|
||
- Expected "routes" to be an array of either strings or objects with the shape { pattern, custom_domain, zone_id | zone_name, enabled, previews_enabled }, but these weren't valid: [
|
||
666,
|
||
777
|
||
].
|
||
- Expected exactly one of the following fields ["routes","route"].
|
||
- Expected "workers_dev" to be of type boolean but got "BAD".
|
||
- Expected "build.command" to be of type string but got 1444.
|
||
- Expected "build.cwd" to be of type string but got 1555.
|
||
- Expected "build.watch_dir" to be of type string but got 1666.
|
||
- Expected "compatibility_date" to be of type string but got 333.
|
||
- Expected "compatibility_flags" to be of type string array but got [444,555].
|
||
- Expected "jsx_factory" to be of type string but got 999.
|
||
- Expected "jsx_fragment" to be of type string but got 1000.
|
||
- Expected "tsconfig" to be of type string but got 123.
|
||
- Expected "name" to be of type string, alphanumeric and lowercase with dashes only but got 111.
|
||
- Expected "main" to be of type string but got 1333.
|
||
- Expected "no_bundle" to be of type boolean but got "INVALID".
|
||
- Expected "minify" to be of type boolean but got "INVALID".
|
||
- Expected "first_party_worker" to be of type boolean but got "INVALID".
|
||
- Expected "logpush" to be of type boolean but got "INVALID".
|
||
- Expected "upload_source_maps" to be of type boolean but got "INVALID"."
|
||
`);
|
||
});
|
||
|
||
it("should warn on unexpected fields", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
// @ts-expect-error purposely using an invalid field
|
||
{ env: { ENV1: { bla: "haj" } } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- Unexpected fields found in env.ENV1 field: "bla""
|
||
`);
|
||
});
|
||
|
||
describe("[define]", () => {
|
||
it("should accept valid values for config.define", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
define: {
|
||
abc: "def",
|
||
ghi: "123",
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(rawConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if config.define is not an object", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
// @ts-expect-error purposely using an invalid value
|
||
define: 123,
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(rawConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "define" should be an object but got 123.
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should error if the values on config.define are not strings", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
define: {
|
||
// @ts-expect-error purposely using an invalid value
|
||
abc: 123,
|
||
// This one's valid
|
||
def: "xyz",
|
||
// @ts-expect-error purposely using an invalid value
|
||
ghi: true,
|
||
// @ts-expect-error purposely using an invalid value
|
||
jkl: {
|
||
nested: "value",
|
||
},
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(rawConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- The field "define.abc" should be a string but got 123.
|
||
- The field "define.ghi" should be a string but got true.
|
||
- The field "define.jkl" should be a string but got {"nested":"value"}."
|
||
`);
|
||
});
|
||
|
||
describe("named environments", () => {
|
||
it("should accept valid values for config.define inside an environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
define: {
|
||
abc: "def",
|
||
ghi: "123",
|
||
},
|
||
env: {
|
||
ENV1: {
|
||
define: {
|
||
abc: "xyz",
|
||
ghi: "456",
|
||
},
|
||
},
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
assert(rawConfig.env);
|
||
expect(config).toEqual(expect.objectContaining(rawConfig.env.ENV1));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if config.define is not an object inside an environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
define: {
|
||
abc: "def",
|
||
ghi: "123",
|
||
},
|
||
env: {
|
||
ENV1: {
|
||
// @ts-expect-error purposely using an invalid value
|
||
define: 123,
|
||
},
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
assert(rawConfig.env);
|
||
expect(config).toEqual(expect.objectContaining(rawConfig.env.ENV1));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.define" should be an object but got 123.
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should warn if if the shape of .define inside an environment doesn't match the shape of the top level .define", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
define: {
|
||
abc: "def",
|
||
ghi: "123",
|
||
},
|
||
env: {
|
||
ENV1: {
|
||
define: {
|
||
abc: "def",
|
||
xyz: "123",
|
||
},
|
||
},
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
assert(rawConfig.env);
|
||
expect(config).toEqual(expect.objectContaining(rawConfig.env.ENV1));
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The following define entries exist at the top level, but not on "env.ENV1.define".
|
||
This is probably not what you want, since "define" configuration is not inherited by environments.
|
||
Please add these entries to "env.ENV1.define":
|
||
- ghi
|
||
- "xyz" exists on "env.ENV1", but not on the top level.
|
||
This is not what you probably want, since "define" configuration within environments can only override existing top level "define" configuration
|
||
Please remove "env.ENV1.define.xyz", or add "define.xyz"."
|
||
`);
|
||
});
|
||
|
||
it("should error if the values on config.define in an environment are not strings", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
define: {
|
||
abc: "123",
|
||
def: "xyz",
|
||
ghi: "true",
|
||
jkl: "some value",
|
||
},
|
||
env: {
|
||
ENV1: {
|
||
define: {
|
||
// @ts-expect-error purposely using an invalid value
|
||
abc: 123,
|
||
// This one's valid
|
||
def: "xyz",
|
||
// @ts-expect-error purposely using an invalid value
|
||
ghi: true,
|
||
// @ts-expect-error purposely using an invalid value
|
||
jkl: {
|
||
nested: "value",
|
||
},
|
||
},
|
||
},
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
assert(rawConfig.env);
|
||
expect(config).toEqual(expect.objectContaining(rawConfig.env.ENV1));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.define.abc" should be a string but got 123.
|
||
- The field "env.ENV1.define.ghi" should be a string but got true.
|
||
- The field "env.ENV1.define.jkl" should be a string but got {"nested":"value"}."
|
||
`);
|
||
});
|
||
});
|
||
});
|
||
|
||
describe("[secrets]", () => {
|
||
it("should accept valid secrets config", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
secrets: {
|
||
required: ["API_KEY", "DATABASE_PASSWORD"],
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(config.secrets).toEqual({
|
||
required: ["API_KEY", "DATABASE_PASSWORD"],
|
||
});
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error if secrets is not an object", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
// @ts-expect-error purposely using an invalid value
|
||
secrets: "invalid",
|
||
};
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'The field "secrets" should be an object'
|
||
);
|
||
});
|
||
|
||
it("should error if secrets.required is not an array", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
// @ts-expect-error purposely using an invalid value
|
||
secrets: { required: "API_KEY" },
|
||
};
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'Expected "secrets.required" to be an array of strings'
|
||
);
|
||
});
|
||
|
||
it("should error if secrets.required contains non-strings", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
// @ts-expect-error purposely using an invalid value
|
||
secrets: { required: ["VALID_KEY", 123, true] },
|
||
};
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'Expected "secrets.required.[1]" to be of type string'
|
||
);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'Expected "secrets.required.[2]" to be of type string'
|
||
);
|
||
});
|
||
|
||
it("should error on duplicate secret names", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
secrets: { required: ["API_KEY", "API_KEY"] },
|
||
};
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
"API_KEY assigned to multiple Secret bindings"
|
||
);
|
||
});
|
||
|
||
it("should error on secret name conflicting with var", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
vars: { API_KEY: "not-a-secret" },
|
||
secrets: { required: ["API_KEY"] },
|
||
};
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
"API_KEY assigned to Environment Variable and Secret bindings"
|
||
);
|
||
});
|
||
|
||
describe("per-environment overrides", () => {
|
||
it("should accept valid secrets in environment", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
env: {
|
||
production: {
|
||
secrets: { required: ["PROD_API_KEY"] },
|
||
},
|
||
},
|
||
};
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "production" }
|
||
);
|
||
|
||
expect(config.secrets).toEqual({ required: ["PROD_API_KEY"] });
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should warn when secrets exists at top level but not in environment", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
secrets: { required: ["API_KEY"] },
|
||
env: {
|
||
production: {},
|
||
},
|
||
};
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "production" }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toContain(
|
||
'"secrets" exists at the top level, but not on "env.production"'
|
||
);
|
||
});
|
||
});
|
||
});
|
||
|
||
describe("[durable_objects]", () => {
|
||
it("should error if durable_objects is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { durable_objects: [] } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { durable_objects: "BAD" } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { durable_objects: 999 } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { durable_objects: null } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is not defined", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { durable_objects: {} } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects" is missing the required "bindings" property."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is an object", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { durable_objects: { bindings: {} } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects.bindings" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is a string", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { durable_objects: { bindings: "BAD" } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects.bindings" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is a number", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { durable_objects: { bindings: 999 } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects.bindings" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { durable_objects: { bindings: null } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.durable_objects.bindings" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if durable_objects.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: {
|
||
ENV1: {
|
||
durable_objects: {
|
||
bindings: [
|
||
{},
|
||
{ name: "VALID" },
|
||
{ name: 1555, class_name: 1666 },
|
||
{
|
||
name: 1777,
|
||
class_name: 1888,
|
||
script_name: 1999,
|
||
},
|
||
],
|
||
},
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
|
||
- "env.ENV1.durable_objects.bindings[0]": {}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
|
||
- "env.ENV1.durable_objects.bindings[1]": {"name":"VALID"}
|
||
- binding should have a string "class_name" field.
|
||
|
||
- "env.ENV1.durable_objects.bindings[2]": {"name":1555,"class_name":1666}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
|
||
- "env.ENV1.durable_objects.bindings[3]": {"name":1777,"class_name":1888,"script_name":1999}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "class_name" field.
|
||
- the field "script_name", when present, should be a string."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[migrations]", () => {
|
||
it("should override `migrations` config defaults with provided values", ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig: RawConfig = {
|
||
migrations: [
|
||
{
|
||
tag: "TAG",
|
||
new_classes: ["CLASS_1", "CLASS_2"],
|
||
renamed_classes: [
|
||
{
|
||
from: "FROM_CLASS",
|
||
to: "TO_CLASS",
|
||
},
|
||
],
|
||
deleted_classes: ["CLASS_3", "CLASS_4"],
|
||
},
|
||
],
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: expectedConfig } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid `migrations` values", ({ expect }) => {
|
||
const expectedConfig = {
|
||
migrations: [
|
||
{
|
||
tag: 111,
|
||
new_classes: [222, 333],
|
||
new_sqlite_classes: [222, 333],
|
||
renamed_classes: [
|
||
{
|
||
from: 444,
|
||
to: 555,
|
||
},
|
||
],
|
||
deleted_classes: [666, 777],
|
||
},
|
||
],
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: expectedConfig as unknown as RawConfig } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- Expected "migrations[0].tag" to be of type string but got 111.
|
||
- Expected "migrations[0].new_classes.[0]" to be of type string but got 222.
|
||
- Expected "migrations[0].new_classes.[1]" to be of type string but got 333.
|
||
- Expected "migrations[0].new_sqlite_classes.[0]" to be of type string but got 222.
|
||
- Expected "migrations[0].new_sqlite_classes.[1]" to be of type string but got 333.
|
||
- Expected "migrations[0].renamed_classes" to be an array of "{from: string, to: string}" objects but got [{"from":444,"to":555}].
|
||
- Expected "migrations[0].deleted_classes.[0]" to be of type string but got 666.
|
||
- Expected "migrations[0].deleted_classes.[1]" to be of type string but got 777."
|
||
`);
|
||
});
|
||
|
||
it("should warn/error on unexpected fields on `migrations`", async ({
|
||
expect,
|
||
}) => {
|
||
const expectedConfig = {
|
||
migrations: [
|
||
{
|
||
tag: "TAG",
|
||
new_classes: ["CLASS_1", "CLASS_2"],
|
||
renamed_classes: [
|
||
{
|
||
from: "FROM_CLASS",
|
||
to: "TO_CLASS",
|
||
},
|
||
{
|
||
a: "something",
|
||
b: "someone",
|
||
},
|
||
],
|
||
deleted_classes: ["CLASS_3", "CLASS_4"],
|
||
unrecognized_field: "FOO",
|
||
},
|
||
],
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: expectedConfig as unknown as RawConfig } },
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(expectedConfig));
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- Unexpected fields found in migrations field: "unrecognized_field""
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- Expected "migrations[0].renamed_classes" to be an array of "{from: string, to: string}" objects but got [{"from":"FROM_CLASS","to":"TO_CLASS"},{"a":"something","b":"someone"}]."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[kv_namespaces]", () => {
|
||
it("should error if kv_namespaces is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { kv_namespaces: {} } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.kv_namespaces" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { kv_namespaces: "BAD" } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.kv_namespaces" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { kv_namespaces: 999 } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.kv_namespaces" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { kv_namespaces: null } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.kv_namespaces" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if kv_namespaces.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: {
|
||
ENV1: {
|
||
kv_namespaces: [
|
||
{},
|
||
{ binding: "VALID" },
|
||
{ binding: 2000, id: 2111 },
|
||
{
|
||
binding: "KV_BINDING_2",
|
||
id: "KV_ID_2",
|
||
preview_id: 2222,
|
||
},
|
||
],
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "env.ENV1.kv_namespaces[0]" bindings should have a string "binding" field but got {}.
|
||
- "env.ENV1.kv_namespaces[2]" bindings should have a string "binding" field but got {"binding":2000,"id":2111}.
|
||
- "env.ENV1.kv_namespaces[2]" bindings should have a string "id" field but got {"binding":2000,"id":2111}.
|
||
- "env.ENV1.kv_namespaces[3]" bindings should, optionally, have a string "preview_id" field but got {"binding":"KV_BINDING_2","id":"KV_ID_2","preview_id":2222}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[r2_buckets]", () => {
|
||
it("should error if r2_buckets is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { r2_buckets: {} } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.r2_buckets" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { r2_buckets: "BAD" } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.r2_buckets" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { r2_buckets: 999 } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.r2_buckets" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { r2_buckets: null } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.r2_buckets" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if r2_buckets.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: {
|
||
ENV1: {
|
||
r2_buckets: [
|
||
{},
|
||
{ binding: "R2_BINDING_1" },
|
||
{ binding: 2333, bucket_name: 2444 },
|
||
{
|
||
binding: "R2_BINDING_2",
|
||
bucket_name: "R2_BUCKET_2",
|
||
preview_bucket_name: 2555,
|
||
},
|
||
],
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "env.ENV1.r2_buckets[0]" bindings should have a string "binding" field but got {}.
|
||
- "env.ENV1.r2_buckets[2]" bindings should have a string "binding" field but got {"binding":2333,"bucket_name":2444}.
|
||
- "env.ENV1.r2_buckets[2]" bindings should have a string "bucket_name" field but got {"binding":2333,"bucket_name":2444}.
|
||
- env.ENV1.r2_buckets[3].bucket_name="R2_BUCKET_2" is invalid. Bucket names must begin and end with an alphanumeric character, only contain lowercase letters, numbers, and hyphens, and be between 3 and 63 characters long.
|
||
- "env.ENV1.r2_buckets[3]" bindings should, optionally, have a string "preview_bucket_name" field but got {"binding":"R2_BINDING_2","bucket_name":"R2_BUCKET_2","preview_bucket_name":2555}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[analytics_engine_datasets]", () => {
|
||
it("should error if analytics_engine_datasets is an object", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { analytics_engine_datasets: {} } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.analytics_engine_datasets" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets is a string", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { analytics_engine_datasets: "BAD" } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.analytics_engine_datasets" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets is a number", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { analytics_engine_datasets: 999 } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.analytics_engine_datasets" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { analytics_engine_datasets: null } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.analytics_engine_datasets" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if analytics_engine_datasets.bindings are not valid", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: {
|
||
ENV1: {
|
||
analytics_engine_datasets: [
|
||
{},
|
||
{ binding: 2333, dataset: 2444 },
|
||
{
|
||
binding: "AE_BINDING_2",
|
||
dataset: 2555,
|
||
},
|
||
{ binding: "AE_BINDING_1", dataset: "" },
|
||
],
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "env.ENV1.analytics_engine_datasets[0]" bindings should have a string "binding" field but got {}.
|
||
- "env.ENV1.analytics_engine_datasets[1]" bindings should have a string "binding" field but got {"binding":2333,"dataset":2444}.
|
||
- "env.ENV1.analytics_engine_datasets[1]" bindings should, optionally, have a string "dataset" field but got {"binding":2333,"dataset":2444}.
|
||
- "env.ENV1.analytics_engine_datasets[2]" bindings should, optionally, have a string "dataset" field but got {"binding":"AE_BINDING_2","dataset":2555}.
|
||
- "env.ENV1.analytics_engine_datasets[3]" bindings should, optionally, have a string "dataset" field but got {"binding":"AE_BINDING_1","dataset":""}."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[unsafe.bindings]", () => {
|
||
it("should error if unsafe is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { unsafe: [] } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { unsafe: "BAD" } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { unsafe: 999 } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { unsafe: null } } } as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should not error if unsafe is an empty object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{ env: { ENV1: { unsafe: {} } } } as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should not error if at least unsafe.bindings is undefined", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { bindings: [] } } },
|
||
} as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error if unsafe contains unexpected properties", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { invalid: true } } },
|
||
} as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time.
|
||
- Unexpected fields found in unsafe field: "invalid""
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { bindings: {} } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.bindings" should be an array but got {}."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { bindings: "BAD" } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.bindings" should be an array but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { bindings: 999 } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.bindings" should be an array but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { bindings: null } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.bindings" should be an array but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.bindings are not valid", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: {
|
||
ENV1: {
|
||
unsafe: {
|
||
bindings: [
|
||
{},
|
||
{ name: "UNSAFE_BINDING_1" },
|
||
{ name: 2666, type: 2777 },
|
||
{
|
||
name: "UNSAFE_BINDING_2",
|
||
type: "UNSAFE_TYPE_2",
|
||
extra: 2888,
|
||
},
|
||
],
|
||
},
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
|
||
- "env.ENV1.unsafe.bindings[0]": {}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "type" field.
|
||
|
||
- "env.ENV1.unsafe.bindings[1]": {"name":"UNSAFE_BINDING_1"}
|
||
- binding should have a string "type" field.
|
||
|
||
- "env.ENV1.unsafe.bindings[2]": {"name":2666,"type":2777}
|
||
- binding should have a string "name" field.
|
||
- binding should have a string "type" field."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { metadata: [] } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.metadata" should be an object but got []."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is a string", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { metadata: "BAD" } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.metadata" should be an object but got "BAD"."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is a number", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { metadata: 999 } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.metadata" should be an object but got 999."
|
||
`);
|
||
});
|
||
|
||
it("should error if unsafe.metadata is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
env: { ENV1: { unsafe: { metadata: null } } },
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- "unsafe" fields are experimental and may change or break at any time."
|
||
`);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- The field "env.ENV1.unsafe.metadata" should be an object but got null."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[tail_consumers]", () => {
|
||
it("should error if tail_consumers is not an array", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
tail_consumers: "this sure isn't an array",
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "tail_consumers" to be an array but got "this sure isn't an array"."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid tail_consumers", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
tail_consumers: [
|
||
"some string",
|
||
456,
|
||
{
|
||
binding: "other",
|
||
namespace: "shape",
|
||
},
|
||
{ service: {} },
|
||
{
|
||
service: 123,
|
||
environment: "prod",
|
||
},
|
||
// these are valid
|
||
{ service: "tail_listener" },
|
||
{ service: "listener_two", environment: "production" },
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "tail_consumers[0]" should be an object but got "some string".
|
||
- "tail_consumers[1]" should be an object but got 456.
|
||
- "tail_consumers[2].service" is a required field.
|
||
- Expected "tail_consumers[3].service" to be of type string but got {}.
|
||
- Expected "tail_consumers[4].service" to be of type string but got 123."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[streaming_tail_consumers]", () => {
|
||
it("should error if streaming_tail_consumers is not an array", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
streaming_tail_consumers: "this sure isn't an array",
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "streaming_tail_consumers" to be an array but got "this sure isn't an array"."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid streaming_tail_consumers", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
streaming_tail_consumers: [
|
||
"some string",
|
||
456,
|
||
{
|
||
binding: "other",
|
||
namespace: "shape",
|
||
},
|
||
{ service: {} },
|
||
{
|
||
service: 123,
|
||
environment: "prod",
|
||
},
|
||
["some array"],
|
||
],
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "streaming_tail_consumers[0]" should be an object but got "some string".
|
||
- "streaming_tail_consumers[1]" should be an object but got 456.
|
||
- "streaming_tail_consumers[2].service" is a required field.
|
||
- Expected "streaming_tail_consumers[3].service" to be of type string but got {}.
|
||
- Expected "streaming_tail_consumers[4].service" to be of type string but got 123.
|
||
- "streaming_tail_consumers[5]" should be an object but got ["some array"]."
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[observability]", () => {
|
||
it("should error on invalid observability", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
notEnabled: "true",
|
||
head_sampling_rate: true,
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in observability field: "notEnabled""
|
||
`);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "observability.enabled" or "observability.logs.enabled" or "observability.traces.enabled" is required.
|
||
- Expected "observability.head_sampling_rate" to be of type number but got true."
|
||
`);
|
||
});
|
||
|
||
it("should not warn on full observability config", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
enabled: true,
|
||
head_sampling_rate: 1,
|
||
logs: {
|
||
enabled: true,
|
||
head_sampling_rate: 1,
|
||
invocation_logs: true,
|
||
destinations: ["test"],
|
||
persist: true,
|
||
},
|
||
traces: {
|
||
enabled: true,
|
||
head_sampling_rate: 1,
|
||
destinations: ["test"],
|
||
persist: true,
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should error on invalid observability.logs", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
enabled: true,
|
||
logs: "enabled",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "observability.logs" to be of type object but got "enabled"."
|
||
`);
|
||
});
|
||
|
||
it("should not error on nested [observability.logs] config only", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
logs: {
|
||
enabled: true,
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should not error on nested [observability.traces] config only", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
traces: {
|
||
enabled: true,
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should not error on mixed observability config", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
enabled: true,
|
||
logs: {
|
||
invocation_logs: false,
|
||
},
|
||
traces: {
|
||
destinations: [],
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
"
|
||
`);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
it("should error on a sampling rate out of range", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
enabled: true,
|
||
head_sampling_rate: 2,
|
||
},
|
||
} satisfies RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "observability.head_sampling_rate" must be a value between 0 and 1."
|
||
`);
|
||
});
|
||
|
||
it("should error on invalid additional fields", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
observability: {
|
||
enabled: true,
|
||
invalid_key_1: "hello world",
|
||
invalid_key_2: "hey there",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in observability field: "invalid_key_1","invalid_key_2""
|
||
`);
|
||
});
|
||
});
|
||
|
||
describe("[cache]", () => {
|
||
it("should error when cache is not an object", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: "enabled",
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cache" should be an object but got "enabled"."
|
||
`);
|
||
});
|
||
|
||
it("should error when cache is null", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: null,
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cache" should be an object but got null."
|
||
`);
|
||
});
|
||
|
||
it("should error when cache.enabled is missing", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- "cache.enabled" is a required field."
|
||
`);
|
||
});
|
||
|
||
it("should error when cache.enabled is not a boolean", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: "true",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "cache.enabled" to be of type boolean but got "true"."
|
||
`);
|
||
});
|
||
|
||
it("should not error on valid cache config with enabled true", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: true,
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(config.cache).toEqual({ enabled: true });
|
||
});
|
||
|
||
it("should not error on valid cache config with enabled false", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: false,
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(config.cache).toEqual({ enabled: false });
|
||
});
|
||
|
||
it("should not error when cross_version_cache is true and cache is disabled", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: false,
|
||
cross_version_cache: true,
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(config.cache).toEqual({
|
||
enabled: false,
|
||
cross_version_cache: true,
|
||
});
|
||
});
|
||
|
||
it("should error when cache.cross_version_cache is not a boolean", ({
|
||
expect,
|
||
}) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: true,
|
||
cross_version_cache: "true",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected "cache.cross_version_cache" to be of type boolean but got "true"."
|
||
`);
|
||
});
|
||
|
||
it("should warn on unexpected fields in cache config", ({ expect }) => {
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: true,
|
||
invalid_key: "hello",
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(true);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Unexpected fields found in cache field: "invalid_key""
|
||
`);
|
||
});
|
||
|
||
it("should inherit cache from top-level config to environment", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: true,
|
||
},
|
||
env: {
|
||
production: {},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "production" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(config.cache).toEqual({ enabled: true });
|
||
});
|
||
|
||
it("should allow environment to override top-level cache", ({
|
||
expect,
|
||
}) => {
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
{
|
||
cache: {
|
||
enabled: true,
|
||
},
|
||
env: {
|
||
staging: {
|
||
cache: {
|
||
enabled: false,
|
||
},
|
||
},
|
||
},
|
||
} as unknown as RawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "staging" }
|
||
);
|
||
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(config.cache).toEqual({ enabled: false });
|
||
});
|
||
});
|
||
|
||
describe("route & routes fields", () => {
|
||
it("should error if both route and routes are specified in the same environment", ({
|
||
expect,
|
||
}) => {
|
||
const environment: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
route: "ENV_ROUTE_1",
|
||
routes: ["ENV_ROUTE_2", "ENV_ROUTE_3"],
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
};
|
||
const expectedConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
routes: ["ROUTE_1", "ROUTE_2"],
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
env: {
|
||
ENV1: environment,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(environment));
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
|
||
- "env.ENV1" environment configuration
|
||
- Expected exactly one of the following fields ["routes","route"]."
|
||
`);
|
||
});
|
||
|
||
it("should error if both route and routes are specified in the top-level environment", ({
|
||
expect,
|
||
}) => {
|
||
const environment: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
};
|
||
const expectedConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
route: "ROUTE_1",
|
||
routes: ["ROUTE_2", "ROUTE_3"],
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
env: {
|
||
ENV1: environment,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(environment));
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
|
||
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
|
||
"Processing wrangler configuration:
|
||
- Expected exactly one of the following fields ["routes","route"]."
|
||
`);
|
||
});
|
||
|
||
it("should not error if <env>.route and <top-level>.routes are specified", ({
|
||
expect,
|
||
}) => {
|
||
const environment: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
route: "ENV_ROUTE_1",
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
};
|
||
const expectedConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
routes: ["ROUTE_1", "ROUTE_2"],
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
env: {
|
||
ENV1: environment,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(environment));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should not error if <env>.routes and <top-level>.route are specified", ({
|
||
expect,
|
||
}) => {
|
||
const environment: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
routes: ["ENV_ROUTE_1", "ENV_ROUTE_2"],
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
};
|
||
const expectedConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
route: "ROUTE_1",
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
env: {
|
||
ENV1: environment,
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(expect.objectContaining(environment));
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should not error if <env1>.route and <env2>.routes are specified", ({
|
||
expect,
|
||
}) => {
|
||
const environment1: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
routes: ["ENV1_ROUTE_1", "ENV2_ROUTE_2"],
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
};
|
||
const environment2: RawEnvironment = {
|
||
name: "mock-env-name",
|
||
account_id: "ENV_ACCOUNT_ID",
|
||
compatibility_date: "2022-02-02",
|
||
compatibility_flags: ["ENV_FLAG1", "ENV_FLAG2"],
|
||
workers_dev: true,
|
||
route: "ENV2_ROUTE_1",
|
||
jsx_factory: "ENV_JSX_FACTORY",
|
||
jsx_fragment: "ENV_JSX_FRAGMENT",
|
||
triggers: { crons: ["ENV_CRON_1", "ENV_CRON_2"] },
|
||
};
|
||
const expectedConfig: RawConfig = {
|
||
name: "mock-name",
|
||
account_id: "ACCOUNT_ID",
|
||
compatibility_date: "2022-01-01",
|
||
compatibility_flags: ["FLAG1", "FLAG2"],
|
||
workers_dev: false,
|
||
route: "ROUTE_1",
|
||
jsx_factory: "JSX_FACTORY",
|
||
jsx_fragment: "JSX_FRAGMENT",
|
||
triggers: { crons: ["CRON_1", "CRON_2"] },
|
||
env: {
|
||
ENV1: environment1,
|
||
ENV2: environment2,
|
||
},
|
||
};
|
||
|
||
const result1 = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: "ENV1",
|
||
}
|
||
);
|
||
|
||
expect(result1.config).toEqual(expect.objectContaining(environment1));
|
||
expect(result1.diagnostics.hasErrors()).toBe(false);
|
||
expect(result1.diagnostics.hasWarnings()).toBe(false);
|
||
|
||
const result2 = normalizeAndValidateConfig(
|
||
expectedConfig,
|
||
undefined,
|
||
undefined,
|
||
{
|
||
env: "ENV2",
|
||
}
|
||
);
|
||
|
||
expect(result2.config).toEqual(expect.objectContaining(environment2));
|
||
expect(result2.diagnostics.hasErrors()).toBe(false);
|
||
expect(result2.diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe("[assets]", () => {
|
||
it("should inherit from top-level assets", ({ expect }) => {
|
||
const rawConfig: RawConfig = {
|
||
assets: {
|
||
directory: "dist",
|
||
binding: "ASSETS",
|
||
},
|
||
env: {
|
||
ENV1: {},
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
assets: {
|
||
directory: "dist",
|
||
binding: "ASSETS",
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
|
||
it("should resolve assets in named env with top-level env also including assets", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig: RawConfig = {
|
||
assets: {
|
||
directory: "dist",
|
||
binding: "ASSETS",
|
||
},
|
||
env: {
|
||
ENV1: {
|
||
assets: {
|
||
directory: "public",
|
||
binding: "ASSETS",
|
||
run_worker_first: true,
|
||
},
|
||
},
|
||
},
|
||
};
|
||
|
||
const { config, diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "ENV1" }
|
||
);
|
||
|
||
expect(config).toEqual(
|
||
expect.objectContaining({
|
||
assets: {
|
||
directory: "public",
|
||
binding: "ASSETS",
|
||
run_worker_first: true,
|
||
},
|
||
})
|
||
);
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
expect(diagnostics.hasWarnings()).toBe(false);
|
||
});
|
||
});
|
||
|
||
describe("[previews]", () => {
|
||
it("should validate top-level previews config", ({ expect }) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
vars: {
|
||
API_BASE_URL: "https://example.com",
|
||
},
|
||
kv_namespaces: [{ binding: "MY_KV", id: "preview-kv-id" }],
|
||
r2_buckets: [{ binding: "MY_R2", bucket_name: "preview-bucket" }],
|
||
flagship: [{ binding: "FLAGS", app_id: "flagship-app-id" }],
|
||
observability: { enabled: true },
|
||
limits: { cpu_ms: 50 },
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept previews.queues as an object with producers", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
queues: {
|
||
producers: [{ binding: "MY_QUEUE", queue: "my-queue" }],
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept previews.stream as a named simple binding", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
stream: {
|
||
binding: "MY_STREAM",
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept previews.limits with only subrequests", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
limits: {
|
||
subrequests: 123,
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept previews.cache with enabled: true", ({ expect }) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
cache: {
|
||
enabled: true,
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should accept previews.cache with enabled: false", ({ expect }) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
cache: {
|
||
enabled: false,
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(false);
|
||
});
|
||
|
||
it("should reject previews.cache when missing enabled", ({ expect }) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
cache: {},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain("enabled");
|
||
});
|
||
|
||
it("should reject previews.cache when enabled is not a boolean", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
cache: {
|
||
enabled: "yes",
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
});
|
||
|
||
it("should reject previews.queues when passed as a flat array", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = {
|
||
previews: {
|
||
queues: [{ binding: "MY_QUEUE", queue: "my-queue" }],
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: undefined }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain("should be an object");
|
||
});
|
||
|
||
it("should validate previews config inside named environments", ({
|
||
expect,
|
||
}) => {
|
||
const rawConfig = {
|
||
env: {
|
||
staging: {
|
||
previews: {
|
||
browser: "not-an-object" as unknown as { binding: string },
|
||
},
|
||
},
|
||
},
|
||
} as unknown as RawConfig;
|
||
|
||
const { diagnostics } = normalizeAndValidateConfig(
|
||
rawConfig,
|
||
undefined,
|
||
undefined,
|
||
{ env: "staging" }
|
||
);
|
||
|
||
expect(diagnostics.hasErrors()).toBe(true);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'"env.staging" environment configuration'
|
||
);
|
||
expect(diagnostics.renderErrors()).toContain(
|
||
'The field "previews.browser" should be an object'
|
||
);
|
||
});
|
||
});
|
||
});
|
||
});
|
||
|
||
function normalizePath(text: string): string {
|
||
return text
|
||
.replace("project\\wrangler.toml", "project/wrangler.toml")
|
||
.replace("src\\index.ts", "src/index.ts")
|
||
.replace("path\\to\\tsconfig", "path/to/tsconfig");
|
||
}
|