wrangler 0.0.0-e7a0cd5b → 0.0.0-e7cf0caa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/bin/wrangler.js +30 -10
- package/miniflare-dist/index.mjs +126 -74
- package/package.json +27 -19
- package/src/__tests__/api-dev.test.ts +65 -36
- package/src/__tests__/api-devregistry.test.ts +121 -0
- package/src/__tests__/api.test.ts +27 -5
- package/src/__tests__/configuration.test.ts +567 -86
- package/src/__tests__/d1/d1.test.ts +82 -0
- package/src/__tests__/d1/execute.test.ts +66 -0
- package/src/__tests__/d1/migrate.test.ts +157 -0
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +91 -49
- package/src/__tests__/deployments.test.ts +330 -56
- package/src/__tests__/dev.test.tsx +198 -90
- package/src/__tests__/generate.test.ts +12 -10
- package/src/__tests__/guess-worker-format.test.ts +35 -0
- package/src/__tests__/helpers/end-event-loop.ts +6 -0
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-console.ts +6 -0
- package/src/__tests__/helpers/mock-dialogs.ts +71 -85
- package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -5
- package/src/__tests__/helpers/mock-known-routes.ts +7 -2
- package/src/__tests__/helpers/mock-kv.ts +29 -16
- package/src/__tests__/helpers/mock-oauth-flow.ts +103 -92
- package/src/__tests__/helpers/mock-process.ts +8 -13
- package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +128 -27
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +18 -41
- package/src/__tests__/helpers/msw/handlers/oauth.ts +13 -18
- package/src/__tests__/helpers/msw/handlers/r2.ts +14 -34
- package/src/__tests__/helpers/msw/handlers/script.ts +9 -28
- package/src/__tests__/helpers/msw/handlers/user.ts +13 -24
- package/src/__tests__/helpers/msw/handlers/zones.ts +6 -8
- package/src/__tests__/helpers/msw/index.ts +32 -1
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +4 -1
- package/src/__tests__/index.test.ts +90 -72
- package/src/__tests__/init.test.ts +927 -631
- package/src/__tests__/jest.setup.ts +19 -42
- package/src/__tests__/kv.test.ts +355 -231
- package/src/__tests__/logger.test.ts +68 -2
- package/src/__tests__/logout.test.ts +47 -0
- package/src/__tests__/metrics.test.ts +94 -51
- package/src/__tests__/middleware.scheduled.test.ts +42 -32
- package/src/__tests__/middleware.test.ts +212 -122
- package/src/__tests__/mtls-certificates.test.ts +588 -0
- package/src/__tests__/pages/deployment-list.test.ts +80 -0
- package/src/__tests__/pages/functions-build.test.ts +452 -0
- package/src/__tests__/pages/pages.test.ts +81 -0
- package/src/__tests__/pages/project-create.test.ts +63 -0
- package/src/__tests__/pages/project-list.test.ts +110 -0
- package/src/__tests__/pages/project-upload.test.ts +500 -0
- package/src/__tests__/pages/publish.test.ts +2864 -0
- package/src/__tests__/pages-deployment-tail.test.ts +955 -0
- package/src/__tests__/parse.test.ts +106 -0
- package/src/__tests__/publish.test.ts +1615 -852
- package/src/__tests__/pubsub.test.ts +226 -100
- package/src/__tests__/queues.test.ts +238 -77
- package/src/__tests__/r2.test.ts +55 -57
- package/src/__tests__/secret.test.ts +179 -130
- package/src/__tests__/tail.test.ts +267 -109
- package/src/__tests__/test-old-node-version.js +3 -3
- package/src/__tests__/traverse-module-graph.test.ts +220 -0
- package/src/__tests__/tsconfig-sanity.ts +12 -0
- package/src/__tests__/tsconfig.json +8 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/type-generation.test.ts +43 -26
- package/src/__tests__/user.test.ts +35 -72
- package/src/__tests__/whoami.test.tsx +8 -114
- package/src/__tests__/worker-namespace.test.ts +83 -69
- package/src/api/dev.ts +168 -60
- package/src/api/index.ts +10 -1
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +76 -0
- package/src/api/pages/index.ts +5 -0
- package/src/api/pages/publish.tsx +355 -0
- package/src/bundle.ts +263 -140
- package/src/cfetch/index.ts +0 -2
- package/src/cfetch/internal.ts +16 -21
- package/src/cli.ts +4 -4
- package/src/config/config.ts +14 -7
- package/src/config/environment.ts +79 -24
- package/src/config/index.ts +99 -38
- package/src/config/validation-helpers.ts +1 -1
- package/src/config/validation.ts +248 -19
- package/src/create-worker-preview.ts +19 -8
- package/src/create-worker-upload-form.ts +60 -22
- package/src/d1/backups.tsx +43 -42
- package/src/d1/constants.ts +2 -0
- package/src/d1/create.tsx +44 -30
- package/src/d1/{delete.tsx → delete.ts} +11 -14
- package/src/d1/execute.tsx +209 -151
- package/src/d1/index.ts +31 -7
- package/src/d1/list.tsx +22 -10
- package/src/d1/migrations/apply.tsx +212 -0
- package/src/d1/migrations/create.tsx +79 -0
- package/src/d1/migrations/helpers.ts +172 -0
- package/src/d1/migrations/index.ts +3 -0
- package/src/d1/migrations/list.tsx +95 -0
- package/src/d1/migrations/options.ts +23 -0
- package/src/d1/options.ts +12 -2
- package/src/d1/splitter.ts +161 -0
- package/src/d1/{types.tsx → types.ts} +11 -0
- package/src/d1/utils.ts +12 -2
- package/src/delete.ts +8 -16
- package/src/deployments.ts +340 -46
- package/src/deprecated/index.ts +8 -302
- package/src/dev/dev.tsx +57 -44
- package/src/dev/local.tsx +294 -91
- package/src/dev/remote.tsx +32 -3
- package/src/dev/start-server.ts +89 -68
- package/src/dev/use-esbuild.ts +17 -18
- package/src/dev/validate-dev-props.ts +9 -0
- package/src/{dev-registry.tsx → dev-registry.ts} +2 -1
- package/src/dev.tsx +178 -118
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +21 -17
- package/src/docs/index.ts +97 -0
- package/src/entry.ts +19 -11
- package/src/environment-variables/factory.ts +88 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/generate/index.ts +298 -0
- package/src/git-client.ts +15 -4
- package/src/{index.tsx → index.ts} +137 -63
- package/src/init.ts +249 -187
- package/src/inspect.ts +16 -1
- package/src/jest.d.ts +4 -0
- package/src/kv/index.ts +15 -17
- package/src/logger.ts +32 -5
- package/src/metrics/metrics-config.ts +3 -3
- package/src/metrics/send-event.ts +6 -1
- package/src/miniflare-cli/assets.ts +64 -28
- package/src/miniflare-cli/index.ts +4 -7
- package/src/miniflare-cli/tsconfig.json +9 -0
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
- package/src/miniflare-cli/types.ts +11 -0
- package/src/module-collection.ts +91 -25
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/pages/build.ts +410 -0
- package/src/pages/buildFunctions.ts +140 -0
- package/src/pages/deployment-tails.ts +281 -0
- package/src/pages/deployments.tsx +11 -33
- package/src/pages/{dev.tsx → dev.ts} +147 -124
- package/src/pages/errors.ts +1 -0
- package/src/pages/functions/buildPlugin.ts +72 -69
- package/src/pages/functions/buildWorker.ts +249 -114
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/{functions.tsx → functions.ts} +8 -4
- package/src/pages/{index.tsx → index.ts} +11 -3
- package/src/pages/projects.tsx +12 -22
- package/src/pages/prompt-select-project.tsx +31 -0
- package/src/pages/publish.tsx +45 -214
- package/src/pages/types.ts +6 -9
- package/src/pages/upload.tsx +58 -14
- package/src/pages/utils.ts +14 -3
- package/src/parse.ts +23 -1
- package/src/paths.ts +1 -1
- package/src/proxy.ts +5 -0
- package/src/publish/index.ts +20 -16
- package/src/publish/publish.ts +72 -47
- package/src/pubsub/{pubsub-commands.tsx → pubsub-commands.ts} +19 -20
- package/src/queues/cli/commands/consumer/add.ts +24 -24
- package/src/queues/cli/commands/consumer/index.ts +3 -6
- package/src/queues/cli/commands/consumer/remove.ts +11 -18
- package/src/queues/cli/commands/create.ts +8 -8
- package/src/queues/cli/commands/delete.ts +8 -8
- package/src/queues/cli/commands/index.ts +6 -4
- package/src/queues/cli/commands/list.ts +8 -8
- package/src/queues/client.ts +1 -0
- package/src/queues/utils.ts +18 -0
- package/src/r2/constants.ts +4 -0
- package/src/r2/helpers.ts +1 -0
- package/src/r2/index.ts +40 -28
- package/src/secret/index.ts +14 -17
- package/src/{sites.tsx → sites.ts} +1 -1
- package/src/tail/createTail.ts +94 -3
- package/src/tail/filters.ts +1 -1
- package/src/tail/index.ts +8 -11
- package/src/tail/printing.ts +15 -0
- package/src/traverse-module-graph.ts +53 -0
- package/src/tsconfig-sanity.ts +16 -0
- package/src/type-generation.ts +79 -57
- package/src/user/access.ts +0 -1
- package/src/user/auth-variables.ts +113 -0
- package/src/user/choose-account.tsx +1 -31
- package/src/user/index.ts +0 -1
- package/src/user/{user.tsx → user.ts} +123 -82
- package/src/utils/render.ts +93 -0
- package/src/{whoami.tsx → whoami.ts} +37 -71
- package/src/worker.ts +35 -3
- package/src/yargs-types.ts +22 -5
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/checked-fetch.js +9 -3
- package/templates/d1-beta-facade.js +95 -25
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +4 -3
- package/templates/format-dev-errors.ts +8 -6
- package/templates/gitignore +1 -0
- package/templates/init-tests/test-jest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.js +3 -5
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/loader-modules.ts +2 -2
- package/templates/middleware/loader-sw.ts +51 -31
- package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
- package/templates/new-worker.ts +3 -0
- package/templates/pages-dev-pipeline.ts +4 -1
- package/templates/pages-shim.ts +4 -1
- package/templates/pages-template-plugin.ts +19 -10
- package/templates/serve-static-assets.ts +17 -14
- package/templates/service-bindings-module-facade.js +1 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +105 -0
- package/templates/tsconfig.json +5 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +826 -77
- package/wrangler-dist/cli.js +130734 -140838
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/src/__tests__/api-devregistry.test.js +0 -57
- package/src/__tests__/d1.test.ts +0 -72
- package/src/__tests__/dialogs.test.tsx +0 -40
- package/src/__tests__/helpers/mock-cfetch.ts +0 -333
- package/src/__tests__/pages.test.ts +0 -2223
- package/src/dialogs.tsx +0 -163
- package/src/environment-variables.ts +0 -50
- package/src/pages/build.tsx +0 -238
- package/src/user/env-vars.ts +0 -46
- package/templates/experimental-local-cache-stubs.js +0 -27
- /package/src/{bundle-reporter.tsx → bundle-reporter.ts} +0 -0
- /package/src/dev/{get-local-persistence-path.tsx → get-local-persistence-path.ts} +0 -0
- /package/src/pages/{hash.tsx → hash.ts} +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const ORIGINAL_WRANGLER_AUTH_DOMAIN = process.env.WRANGLER_AUTH_DOMAIN;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Mock the Auth URL domain so that we can control where we attempt to login.
|
|
5
|
+
*
|
|
6
|
+
* Note that you can remove any API token from the environment by setting the value to `null`.
|
|
7
|
+
* This is useful if a higher `describe()` block has already called `mockAuthDomain()`.
|
|
8
|
+
*/
|
|
9
|
+
export function mockAuthDomain({ domain }: { domain: string | null }) {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
if (domain === null) {
|
|
12
|
+
delete process.env.WRANGLER_AUTH_DOMAIN;
|
|
13
|
+
} else {
|
|
14
|
+
process.env.WRANGLER_AUTH_DOMAIN = domain;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
process.env.WRANGLER_AUTH_DOMAIN = ORIGINAL_WRANGLER_AUTH_DOMAIN;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -8,6 +8,7 @@ import { logger } from "../../logger";
|
|
|
8
8
|
|
|
9
9
|
let debugSpy: jest.SpyInstance,
|
|
10
10
|
logSpy: jest.SpyInstance,
|
|
11
|
+
infoSpy: jest.SpyInstance,
|
|
11
12
|
errorSpy: jest.SpyInstance,
|
|
12
13
|
warnSpy: jest.SpyInstance;
|
|
13
14
|
|
|
@@ -18,6 +19,9 @@ const std = {
|
|
|
18
19
|
get out() {
|
|
19
20
|
return normalizeOutput(logSpy);
|
|
20
21
|
},
|
|
22
|
+
get info() {
|
|
23
|
+
return normalizeOutput(infoSpy);
|
|
24
|
+
},
|
|
21
25
|
get err() {
|
|
22
26
|
return normalizeOutput(errorSpy);
|
|
23
27
|
},
|
|
@@ -47,12 +51,14 @@ export function mockConsoleMethods() {
|
|
|
47
51
|
logger.columns = 100;
|
|
48
52
|
debugSpy = jest.spyOn(console, "debug").mockImplementation();
|
|
49
53
|
logSpy = jest.spyOn(console, "log").mockImplementation();
|
|
54
|
+
infoSpy = jest.spyOn(console, "info").mockImplementation();
|
|
50
55
|
errorSpy = jest.spyOn(console, "error").mockImplementation();
|
|
51
56
|
warnSpy = jest.spyOn(console, "warn").mockImplementation();
|
|
52
57
|
});
|
|
53
58
|
afterEach(() => {
|
|
54
59
|
debugSpy.mockRestore();
|
|
55
60
|
logSpy.mockRestore();
|
|
61
|
+
infoSpy.mockRestore();
|
|
56
62
|
errorSpy.mockRestore();
|
|
57
63
|
warnSpy.mockRestore();
|
|
58
64
|
});
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { normalizeSlashes } from "./mock-console";
|
|
1
|
+
import prompts from "prompts";
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* The expected values for a confirmation request.
|
|
@@ -7,6 +6,8 @@ import { normalizeSlashes } from "./mock-console";
|
|
|
7
6
|
export interface ConfirmExpectation {
|
|
8
7
|
/** The text expected to be seen in the confirmation dialog. */
|
|
9
8
|
text: string;
|
|
9
|
+
|
|
10
|
+
options?: { defaultValue: boolean };
|
|
10
11
|
/** The mock response send back from the confirmation dialog. */
|
|
11
12
|
result: boolean;
|
|
12
13
|
}
|
|
@@ -19,35 +20,22 @@ export interface ConfirmExpectation {
|
|
|
19
20
|
* then an error is thrown.
|
|
20
21
|
*/
|
|
21
22
|
export function mockConfirm(...expectations: ConfirmExpectation[]) {
|
|
22
|
-
(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
throw new Error(
|
|
34
|
-
"The following expected confirmation dialogs were not used:\n" +
|
|
35
|
-
expectations.map((e) => `- "${e.text}"`).join("\n")
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
}
|
|
23
|
+
for (const expectation of expectations) {
|
|
24
|
+
(prompts as unknown as jest.Mock).mockImplementationOnce(
|
|
25
|
+
({ type, name, message, initial }) => {
|
|
26
|
+
expect({ type, name, message }).toStrictEqual({
|
|
27
|
+
type: "confirm",
|
|
28
|
+
name: "value",
|
|
29
|
+
message: expectation.text,
|
|
30
|
+
});
|
|
31
|
+
if (expectation.options) {
|
|
32
|
+
expect(initial).toStrictEqual(expectation.options?.defaultValue);
|
|
33
|
+
}
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// Because confirm was originally a spy, calling mockReset will simply reset
|
|
44
|
-
// it as a function with no return value (!), so we need to accitionally reset
|
|
45
|
-
// the mock implementation to the one that throws (from jest.setup.js).
|
|
46
|
-
(confirm as jest.Mock).mockImplementation((text: string) => {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`Unexpected call to \`confirm("${text}")\`.\nYou should use \`mockConfirm()\` to mock calls to \`confirm()\` with expectations. Search the codebase for \`mockConfirm\` to learn more.`
|
|
35
|
+
return Promise.resolve({ value: expectation.result });
|
|
36
|
+
}
|
|
49
37
|
);
|
|
50
|
-
}
|
|
38
|
+
}
|
|
51
39
|
}
|
|
52
40
|
|
|
53
41
|
/**
|
|
@@ -57,7 +45,10 @@ export interface PromptExpectation {
|
|
|
57
45
|
/** The text expected to be seen in the prompt dialog. */
|
|
58
46
|
text: string;
|
|
59
47
|
/** The type of the prompt. */
|
|
60
|
-
|
|
48
|
+
options?: {
|
|
49
|
+
defaultValue?: string;
|
|
50
|
+
isSecret?: boolean;
|
|
51
|
+
};
|
|
61
52
|
/** The mock response send back from the prompt dialog. */
|
|
62
53
|
result: string;
|
|
63
54
|
}
|
|
@@ -70,45 +61,44 @@ export interface PromptExpectation {
|
|
|
70
61
|
* then an error is thrown.
|
|
71
62
|
*/
|
|
72
63
|
export function mockPrompt(...expectations: PromptExpectation[]) {
|
|
73
|
-
(
|
|
74
|
-
(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
for (const expectation of expectations) {
|
|
65
|
+
(prompts as unknown as jest.Mock).mockImplementationOnce(
|
|
66
|
+
({ type, name, message, initial, style }) => {
|
|
67
|
+
expect({ type, name, message }).toStrictEqual({
|
|
68
|
+
type: "text",
|
|
69
|
+
name: "value",
|
|
70
|
+
message: expectation.text,
|
|
71
|
+
});
|
|
72
|
+
if (expectation.options) {
|
|
73
|
+
expect(initial).toStrictEqual(expectation.options?.defaultValue);
|
|
74
|
+
expect(style).toStrictEqual(
|
|
75
|
+
expectation.options?.isSecret ? "password" : "default"
|
|
76
|
+
);
|
|
79
77
|
}
|
|
78
|
+
return Promise.resolve({ value: expectation.result });
|
|
80
79
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
);
|
|
84
|
-
return () => {
|
|
85
|
-
if (expectations.length > 0) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
"The following expected prompt dialogs were not used:\n" +
|
|
88
|
-
expectations.map((e) => `- "${e.text}"`).join("\n")
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
};
|
|
80
|
+
);
|
|
81
|
+
}
|
|
92
82
|
}
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
// it as a function with no return value (!), so we need to accitionally reset
|
|
98
|
-
// the mock implementation to the one that throws (from jest.setup.js).
|
|
99
|
-
(prompt as jest.Mock).mockImplementation((text: string) => {
|
|
100
|
-
throw new Error(
|
|
101
|
-
`Unexpected call to \`prompt(${text}, ...)\`.\nYou should use \`mockPrompt()\` to mock calls to \`prompt()\` with expectations. Search the codebase for \`mockPrompt\` to learn more.`
|
|
102
|
-
);
|
|
103
|
-
});
|
|
84
|
+
interface SelectOptions<Values> {
|
|
85
|
+
choices: SelectOption<Values>[];
|
|
86
|
+
defaultOption?: number;
|
|
104
87
|
}
|
|
105
88
|
|
|
89
|
+
interface SelectOption<Values> {
|
|
90
|
+
title: string;
|
|
91
|
+
description?: string;
|
|
92
|
+
value: Values;
|
|
93
|
+
}
|
|
106
94
|
/**
|
|
107
95
|
* The expected values for a select request.
|
|
108
96
|
*/
|
|
109
|
-
export interface SelectExpectation {
|
|
97
|
+
export interface SelectExpectation<Values> {
|
|
110
98
|
/** The text expected to be seen in the select dialog. */
|
|
111
99
|
text: string;
|
|
100
|
+
|
|
101
|
+
options?: SelectOptions<Values>;
|
|
112
102
|
/** The mock response send back from the select dialog. */
|
|
113
103
|
result: string;
|
|
114
104
|
}
|
|
@@ -120,34 +110,30 @@ export interface SelectExpectation {
|
|
|
120
110
|
* If there is a call to `select()` that does not match any of the expectations
|
|
121
111
|
* then an error is thrown.
|
|
122
112
|
*/
|
|
123
|
-
export function mockSelect(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
113
|
+
export function mockSelect<Values>(
|
|
114
|
+
...expectations: SelectExpectation<Values>[]
|
|
115
|
+
) {
|
|
116
|
+
for (const expectation of expectations) {
|
|
117
|
+
(prompts as unknown as jest.Mock).mockImplementationOnce(
|
|
118
|
+
({ type, name, message, choices, initial }) => {
|
|
119
|
+
expect({ type, name, message }).toStrictEqual({
|
|
120
|
+
type: "select",
|
|
121
|
+
name: "value",
|
|
122
|
+
message: expectation.text,
|
|
123
|
+
});
|
|
124
|
+
if (expectation.options) {
|
|
125
|
+
expect(choices).toStrictEqual(expectation.options?.choices);
|
|
126
|
+
expect(initial).toStrictEqual(expectation.options?.defaultOption);
|
|
127
|
+
}
|
|
128
|
+
return Promise.resolve({ value: expectation.result });
|
|
129
129
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
});
|
|
133
|
-
return () => {
|
|
134
|
-
if (expectations.length > 0) {
|
|
135
|
-
throw new Error(
|
|
136
|
-
"The following expected select dialogs were not used:\n" +
|
|
137
|
-
expectations.map((e) => `- "${e.text}"`).join("\n")
|
|
138
|
-
);
|
|
139
|
-
}
|
|
140
|
-
};
|
|
130
|
+
);
|
|
131
|
+
}
|
|
141
132
|
}
|
|
142
133
|
|
|
143
|
-
export function
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
(select as jest.Mock).mockImplementation((text: string) => {
|
|
149
|
-
throw new Error(
|
|
150
|
-
`Unexpected call to \`select("${text}")\`.\nYou should use \`mockSelect()\` to mock calls to \`select()\` with expectations. Search the codebase for \`mockSelect\` to learn more.`
|
|
151
|
-
);
|
|
152
|
-
});
|
|
134
|
+
export function clearDialogs() {
|
|
135
|
+
// No dialog mocks should be left after each test, and so calling the dialog methods should throw
|
|
136
|
+
expect(() => prompts({ type: "select", name: "unknown" })).toThrow(
|
|
137
|
+
"Unexpected call to "
|
|
138
|
+
);
|
|
153
139
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { msw } from "./msw";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Mocks the `/accounts/:accountId/pages/projects/:projectName/upload-token` GET request
|
|
6
|
+
*/
|
|
7
|
+
export function mockGetUploadTokenRequest(
|
|
8
|
+
jwt: string,
|
|
9
|
+
accountId: string,
|
|
10
|
+
projectName: string
|
|
11
|
+
) {
|
|
12
|
+
msw.use(
|
|
13
|
+
rest.get(
|
|
14
|
+
`*/accounts/:accountId/pages/projects/${projectName}/upload-token`,
|
|
15
|
+
(req, res, ctx) => {
|
|
16
|
+
expect(req.params.accountId).toEqual(accountId);
|
|
17
|
+
|
|
18
|
+
return res(
|
|
19
|
+
ctx.status(200),
|
|
20
|
+
ctx.json({ success: true, errors: [], messages: [], result: { jwt } })
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { msw, createFetchResult } from "./msw";
|
|
2
3
|
|
|
3
4
|
export function mockGetZoneFromHostRequest(host: string, zone?: string) {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
msw.use(
|
|
6
|
+
rest.get("*/zones", (req, res, ctx) => {
|
|
7
|
+
expect(req.url.searchParams.get("name")).toEqual(host);
|
|
8
|
+
return res(ctx.json(createFetchResult(zone ? [{ id: zone }] : [])));
|
|
9
|
+
})
|
|
10
|
+
);
|
|
8
11
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createFetchResult, msw } from "./msw";
|
|
2
3
|
|
|
3
4
|
export function mockCollectKnownRoutesRequest(
|
|
4
5
|
routes: { pattern: string; script: string }[]
|
|
5
6
|
) {
|
|
6
|
-
|
|
7
|
+
msw.use(
|
|
8
|
+
rest.get(`*/zones/:zoneId/workers/routes`, (_, res, ctx) =>
|
|
9
|
+
res.once(ctx.json(createFetchResult(routes)))
|
|
10
|
+
)
|
|
11
|
+
);
|
|
7
12
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
import { createFetchResult, msw } from "./msw";
|
|
2
3
|
import type { NamespaceKeyInfo } from "../../kv/helpers";
|
|
3
4
|
|
|
4
5
|
export function mockKeyListRequest(
|
|
@@ -9,25 +10,37 @@ export function mockKeyListRequest(
|
|
|
9
10
|
) {
|
|
10
11
|
const requests = { count: 0 };
|
|
11
12
|
// See https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
|
|
13
|
+
msw.use(
|
|
14
|
+
rest.get(
|
|
15
|
+
"*/accounts/:accountId/storage/kv/namespaces/:namespaceId/keys",
|
|
16
|
+
(req, res, ctx) => {
|
|
17
|
+
requests.count++;
|
|
18
|
+
expect(req.params.accountId).toEqual("some-account-id");
|
|
19
|
+
expect(req.params.namespaceId).toEqual(expectedNamespaceId);
|
|
20
|
+
let response: undefined | NamespaceKeyInfo[];
|
|
21
|
+
if (expectedKeys.length <= keysPerRequest) {
|
|
22
|
+
response = expectedKeys;
|
|
23
|
+
}
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
"/accounts/:accountId/storage/kv/namespaces/:namespaceId/keys",
|
|
15
|
-
"GET",
|
|
16
|
-
([_url, accountId, namespaceId], _init, query) => {
|
|
17
|
-
requests.count++;
|
|
18
|
-
expect(accountId).toEqual("some-account-id");
|
|
19
|
-
expect(namespaceId).toEqual(expectedNamespaceId);
|
|
20
|
-
if (expectedKeys.length <= keysPerRequest) {
|
|
21
|
-
return createFetchResult(expectedKeys);
|
|
22
|
-
} else {
|
|
23
|
-
const start = parseInt(query.get("cursor") ?? "0") || 0;
|
|
25
|
+
const start = parseInt(req.url.searchParams.get("cursor") ?? "0") || 0;
|
|
24
26
|
const end = start + keysPerRequest;
|
|
25
27
|
const cursor = end < expectedKeys.length ? end : blankCursorValue;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
|
|
29
|
+
return res(
|
|
30
|
+
ctx.json(
|
|
31
|
+
createFetchResult(
|
|
32
|
+
response ? response : expectedKeys.slice(start, end),
|
|
33
|
+
true,
|
|
34
|
+
[],
|
|
35
|
+
[],
|
|
36
|
+
{
|
|
37
|
+
cursor,
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
);
|
|
29
42
|
}
|
|
30
|
-
|
|
43
|
+
)
|
|
31
44
|
);
|
|
32
45
|
return requests;
|
|
33
46
|
}
|
|
@@ -1,40 +1,34 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { rest } from "msw";
|
|
2
2
|
import { Request } from "undici";
|
|
3
3
|
import openInBrowser from "../../open-in-browser";
|
|
4
|
-
import {
|
|
5
|
-
createFetchResult,
|
|
6
|
-
setMockRawResponse,
|
|
7
|
-
setMockResponse,
|
|
8
|
-
} from "./mock-cfetch";
|
|
9
4
|
import { mockHttpServer } from "./mock-http-server";
|
|
5
|
+
import { createFetchResult, msw } from "./msw";
|
|
10
6
|
|
|
11
7
|
export function mockGetMemberships(
|
|
12
8
|
accounts: { id: string; account: { id: string; name: string } }[]
|
|
13
9
|
) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
msw.use(
|
|
11
|
+
rest.get("*/memberships", (_, res, ctx) => {
|
|
12
|
+
return res.once(ctx.json(createFetchResult(accounts)));
|
|
13
|
+
})
|
|
14
|
+
);
|
|
17
15
|
}
|
|
18
|
-
|
|
19
16
|
export function mockGetMembershipsFail() {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
msw.use(
|
|
18
|
+
rest.get("*/memberships", (_, res, ctx) => {
|
|
19
|
+
return res.once(ctx.json(createFetchResult([], false)));
|
|
20
|
+
})
|
|
21
|
+
);
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
// the response to send when wrangler wants an oauth grant
|
|
26
|
-
let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
|
|
27
|
-
|
|
28
24
|
/**
|
|
29
25
|
* Functions to help with mocking various parts of the OAuth Flow
|
|
30
26
|
*/
|
|
31
27
|
export const mockOAuthFlow = () => {
|
|
28
|
+
// the response to send when wrangler wants an oauth grant
|
|
29
|
+
let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
|
|
32
30
|
const fetchHttp = mockHttpServer();
|
|
33
31
|
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
fetchMock.resetMocks();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
32
|
/**
|
|
39
33
|
* Mock out the callback from a browser to our HttpServer.
|
|
40
34
|
*
|
|
@@ -42,10 +36,13 @@ export const mockOAuthFlow = () => {
|
|
|
42
36
|
* at the OAuth URL, it will automatically trigger the callback URL on the mock HttpServer that
|
|
43
37
|
* we have created as part of the call to `mockOAuthFlow()`.
|
|
44
38
|
*/
|
|
45
|
-
const mockOAuthServerCallback = (
|
|
39
|
+
const mockOAuthServerCallback = (
|
|
40
|
+
respondWith?: "timeout" | "success" | "failure" | GrantResponseOptions
|
|
41
|
+
) => {
|
|
46
42
|
(
|
|
47
43
|
openInBrowser as jest.MockedFunction<typeof openInBrowser>
|
|
48
44
|
).mockImplementation(async (url: string) => {
|
|
45
|
+
if (respondWith) mockGrantAuthorization({ respondWith });
|
|
49
46
|
// We don't support the grant response timing out.
|
|
50
47
|
if (oauthGrantResponse === "timeout") {
|
|
51
48
|
throw "unimplemented";
|
|
@@ -68,6 +65,7 @@ export const mockOAuthFlow = () => {
|
|
|
68
65
|
});
|
|
69
66
|
};
|
|
70
67
|
|
|
68
|
+
// Handled in `mockOAuthServerCallback`
|
|
71
69
|
const mockGrantAuthorization = ({
|
|
72
70
|
respondWith,
|
|
73
71
|
}: {
|
|
@@ -88,97 +86,110 @@ export const mockOAuthFlow = () => {
|
|
|
88
86
|
}
|
|
89
87
|
};
|
|
90
88
|
|
|
91
|
-
const mockRevokeAuthorization = () => {
|
|
92
|
-
const outcome = {
|
|
93
|
-
actual: new Request("https://example.org"),
|
|
94
|
-
expected: new Request("https://dash.cloudflare.com/oauth2/revoke", {
|
|
95
|
-
method: "POST",
|
|
96
|
-
}),
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
fetchMock.mockIf(outcome.expected.url, async (req) => {
|
|
100
|
-
// TODO: update Miniflare typings to match full undici Request
|
|
101
|
-
outcome.actual = req as unknown as Request;
|
|
102
|
-
return "";
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
return outcome;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
89
|
const mockGrantAccessToken = ({
|
|
109
90
|
respondWith,
|
|
91
|
+
domain = "dash.cloudflare.com",
|
|
110
92
|
}: {
|
|
111
93
|
respondWith: MockTokenResponse;
|
|
94
|
+
domain?: string;
|
|
112
95
|
}) => {
|
|
113
96
|
const outcome = {
|
|
114
|
-
actual:
|
|
115
|
-
expected:
|
|
116
|
-
method: "POST",
|
|
117
|
-
}),
|
|
97
|
+
actual: "https://example.org",
|
|
98
|
+
expected: `https://${domain}/oauth2/token`,
|
|
118
99
|
};
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
100
|
+
msw.use(
|
|
101
|
+
rest.post(outcome.expected, async (req, res, ctx) => {
|
|
102
|
+
// TODO: update Miniflare typings to match full undici Request
|
|
103
|
+
outcome.actual = req.url.toString();
|
|
104
|
+
return res.once(ctx.json(makeTokenResponse(respondWith)));
|
|
105
|
+
})
|
|
106
|
+
);
|
|
125
107
|
|
|
126
108
|
return outcome;
|
|
127
109
|
};
|
|
128
110
|
|
|
129
|
-
|
|
130
|
-
|
|
111
|
+
function mockDomainUsesAccess({
|
|
112
|
+
usesAccess,
|
|
113
|
+
domain = "dash.cloudflare.com",
|
|
131
114
|
}: {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
token_type: "bearer",
|
|
147
|
-
}),
|
|
148
|
-
};
|
|
149
|
-
case "refreshError":
|
|
150
|
-
return {
|
|
151
|
-
status: 400,
|
|
152
|
-
body: JSON.stringify({
|
|
153
|
-
error: "invalid_request",
|
|
154
|
-
error_description: "error_description_mock",
|
|
155
|
-
error_hint: "error_hint_mock",
|
|
156
|
-
error_verbose: "error_verbose_mock",
|
|
157
|
-
status_code: 400,
|
|
158
|
-
}),
|
|
159
|
-
};
|
|
160
|
-
case "badResponse":
|
|
161
|
-
return {
|
|
162
|
-
status: 400,
|
|
163
|
-
body: `<html> <body> This shouldn't be sent, but should be handled </body> </html>`,
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
default:
|
|
167
|
-
return "Not a respondWith option for `mockExchangeRefreshTokenForAccessToken`";
|
|
115
|
+
usesAccess: boolean;
|
|
116
|
+
domain?: string;
|
|
117
|
+
}) {
|
|
118
|
+
// If the domain relies upon Cloudflare Access, then a request to the domain
|
|
119
|
+
// will result in a redirect to the `cloudflareaccess.com` domain.
|
|
120
|
+
msw.use(
|
|
121
|
+
rest.get(`https://${domain}/`, (_, res, ctx) => {
|
|
122
|
+
let status = 200;
|
|
123
|
+
let headers: Record<string, string> = {
|
|
124
|
+
"Content-Type": "application/json",
|
|
125
|
+
};
|
|
126
|
+
if (usesAccess) {
|
|
127
|
+
status = 302;
|
|
128
|
+
headers = { location: "cloudflareaccess.com" };
|
|
168
129
|
}
|
|
169
|
-
|
|
130
|
+
return res.once(ctx.status(status), ctx.set(headers));
|
|
131
|
+
})
|
|
170
132
|
);
|
|
171
|
-
}
|
|
133
|
+
}
|
|
172
134
|
|
|
173
135
|
return {
|
|
136
|
+
mockHttpServer,
|
|
137
|
+
mockDomainUsesAccess,
|
|
174
138
|
mockGrantAccessToken,
|
|
175
|
-
mockGrantAuthorization,
|
|
176
139
|
mockOAuthServerCallback,
|
|
177
|
-
mockRevokeAuthorization,
|
|
178
140
|
mockExchangeRefreshTokenForAccessToken,
|
|
179
141
|
};
|
|
180
142
|
};
|
|
181
143
|
|
|
144
|
+
export function mockExchangeRefreshTokenForAccessToken({
|
|
145
|
+
respondWith,
|
|
146
|
+
domain = "dash.cloudflare.com",
|
|
147
|
+
}: {
|
|
148
|
+
respondWith: "refreshSuccess" | "refreshError" | "badResponse";
|
|
149
|
+
domain?: string;
|
|
150
|
+
}) {
|
|
151
|
+
msw.use(
|
|
152
|
+
rest.post(`https://${domain}/oauth2/token`, async (_, res, ctx) => {
|
|
153
|
+
switch (respondWith) {
|
|
154
|
+
case "refreshSuccess":
|
|
155
|
+
return res.once(
|
|
156
|
+
ctx.status(200),
|
|
157
|
+
ctx.json({
|
|
158
|
+
access_token: "access_token_success_mock",
|
|
159
|
+
expires_in: 1701,
|
|
160
|
+
refresh_token: "refresh_token_success_mock",
|
|
161
|
+
scope: "scope_success_mock",
|
|
162
|
+
token_type: "bearer",
|
|
163
|
+
})
|
|
164
|
+
);
|
|
165
|
+
case "refreshError":
|
|
166
|
+
return res.once(
|
|
167
|
+
ctx.status(400),
|
|
168
|
+
ctx.json({
|
|
169
|
+
error: "invalid_request",
|
|
170
|
+
error_description: "error_description_mock",
|
|
171
|
+
error_hint: "error_hint_mock",
|
|
172
|
+
error_verbose: "error_verbose_mock",
|
|
173
|
+
status_code: 400,
|
|
174
|
+
})
|
|
175
|
+
);
|
|
176
|
+
case "badResponse":
|
|
177
|
+
return res.once(
|
|
178
|
+
ctx.status(400),
|
|
179
|
+
ctx.text(
|
|
180
|
+
`<html> <body> This shouldn't be sent, but should be handled </body> </html>`
|
|
181
|
+
)
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
default:
|
|
185
|
+
throw new Error(
|
|
186
|
+
"Not a respondWith option for `mockExchangeRefreshTokenForAccessToken`"
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
182
193
|
type GrantResponseOptions = {
|
|
183
194
|
code?: string;
|
|
184
195
|
error?: ErrorType | ErrorType[];
|
|
@@ -230,7 +241,7 @@ type MockTokenResponse =
|
|
|
230
241
|
error: ErrorType;
|
|
231
242
|
};
|
|
232
243
|
|
|
233
|
-
const makeTokenResponse = (partialResponse: MockTokenResponse)
|
|
244
|
+
const makeTokenResponse = (partialResponse: MockTokenResponse) => {
|
|
234
245
|
let fullResponse: MockTokenResponse;
|
|
235
246
|
|
|
236
247
|
if (partialResponse === "ok") {
|
|
@@ -248,5 +259,5 @@ const makeTokenResponse = (partialResponse: MockTokenResponse): string => {
|
|
|
248
259
|
fullResponse = partialResponse;
|
|
249
260
|
}
|
|
250
261
|
|
|
251
|
-
return
|
|
262
|
+
return fullResponse;
|
|
252
263
|
};
|