wrangler 2.1.0 → 2.1.3
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/miniflare-dist/index.mjs +1 -1
- package/package.json +2 -1
- package/src/__tests__/dev.test.tsx +2 -1
- package/src/__tests__/dialogs.test.tsx +40 -0
- package/src/__tests__/helpers/mock-cfetch.ts +35 -15
- package/src/__tests__/helpers/msw/handlers/index.ts +13 -0
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
- package/src/__tests__/helpers/msw/handlers/oauth.ts +36 -0
- package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
- package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
- package/src/__tests__/helpers/msw/index.ts +4 -0
- package/src/__tests__/index.test.ts +2 -0
- package/src/__tests__/jest.setup.ts +16 -0
- package/src/__tests__/publish.test.ts +52 -0
- package/src/__tests__/r2.test.ts +128 -93
- package/src/__tests__/secret.test.ts +78 -0
- package/src/__tests__/whoami.test.tsx +49 -64
- package/src/api/dev.ts +2 -1
- package/src/dev/dev.tsx +2 -2
- package/src/dev/local.tsx +2 -12
- package/src/dev/start-server.ts +2 -13
- package/src/dev.tsx +39 -6
- package/src/dialogs.tsx +8 -1
- package/src/index.tsx +90 -0
- package/src/miniflare-cli/assets.ts +1 -1
- package/src/pages/dev.tsx +28 -4
- package/src/publish.ts +21 -13
- package/wrangler-dist/cli.d.ts +2 -1
- package/wrangler-dist/cli.js +188 -44
package/miniflare-dist/index.mjs
CHANGED
|
@@ -6033,7 +6033,7 @@ async function generateAssetsFetch(directory, log) {
|
|
|
6033
6033
|
let metadata = createMetadataObject({
|
|
6034
6034
|
redirects,
|
|
6035
6035
|
headers,
|
|
6036
|
-
logger: log.warn
|
|
6036
|
+
logger: log.warn.bind(log)
|
|
6037
6037
|
});
|
|
6038
6038
|
watch([headersFile, redirectsFile], { persistent: true }).on(
|
|
6039
6039
|
"change",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wrangler",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "Command-line interface for all things Cloudflare Workers",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"wrangler",
|
|
@@ -148,6 +148,7 @@
|
|
|
148
148
|
"jest-fetch-mock": "^3.0.3",
|
|
149
149
|
"jest-websocket-mock": "^2.3.0",
|
|
150
150
|
"mime": "^3.0.0",
|
|
151
|
+
"msw": "^0.47.1",
|
|
151
152
|
"open": "^8.4.0",
|
|
152
153
|
"p-queue": "^7.2.0",
|
|
153
154
|
"pretty-bytes": "^6.0.0",
|
|
@@ -1025,7 +1025,8 @@ describe("wrangler dev", () => {
|
|
|
1025
1025
|
-l, --local Run on my machine [boolean] [default: false]
|
|
1026
1026
|
--minify Minify the script [boolean]
|
|
1027
1027
|
--node-compat Enable node.js compatibility [boolean]
|
|
1028
|
-
--
|
|
1028
|
+
--persist Enable persistence for local mode, using default path: .wrangler/state [boolean]
|
|
1029
|
+
--persist-to Specify directory to use for local persistence (implies --persist) [string]
|
|
1029
1030
|
--inspect Enable dev tools [deprecated] [boolean]",
|
|
1030
1031
|
"warn": "",
|
|
1031
1032
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
jest.unmock("../dialogs");
|
|
2
|
+
import { fromDashMessagePrompt } from "../dialogs";
|
|
3
|
+
import { CI } from "../is-ci";
|
|
4
|
+
|
|
5
|
+
describe("fromDashMessagePrompt", () => {
|
|
6
|
+
it("should return undefined in CI when last deployed from api", async () => {
|
|
7
|
+
//in CI
|
|
8
|
+
jest.spyOn(CI, "isCI").mockReturnValue(true);
|
|
9
|
+
const result = await fromDashMessagePrompt("api");
|
|
10
|
+
expect(result).toBe(undefined);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should return undefined in CI when last deployed from wrangler", async () => {
|
|
14
|
+
//in CI
|
|
15
|
+
jest.spyOn(CI, "isCI").mockReturnValue(true);
|
|
16
|
+
const result = await fromDashMessagePrompt("wrangler");
|
|
17
|
+
expect(result).toBe(undefined);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("should return true in CI when last deployed from dash", async () => {
|
|
21
|
+
//in CI
|
|
22
|
+
jest.spyOn(CI, "isCI").mockReturnValue(true);
|
|
23
|
+
const result = await fromDashMessagePrompt("dash");
|
|
24
|
+
expect(result).toBe(true);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("should return undefined when last deployed from api", async () => {
|
|
28
|
+
//not in CI
|
|
29
|
+
jest.spyOn(CI, "isCI").mockReturnValue(false);
|
|
30
|
+
const result = await fromDashMessagePrompt("api");
|
|
31
|
+
expect(result).toBe(undefined);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("should return undefined when last deployed from wrangler", async () => {
|
|
35
|
+
//not in CI
|
|
36
|
+
jest.spyOn(CI, "isCI").mockReturnValue(false);
|
|
37
|
+
const result = await fromDashMessagePrompt("wrangler");
|
|
38
|
+
expect(result).toBe(undefined);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -4,8 +4,24 @@ import { pathToRegexp } from "path-to-regexp";
|
|
|
4
4
|
import { Response } from "undici";
|
|
5
5
|
import { getCloudflareApiBaseUrl } from "../../cfetch";
|
|
6
6
|
import type { FetchResult, FetchError } from "../../cfetch";
|
|
7
|
+
import type { fetchInternal, fetchR2Objects } from "../../cfetch/internal";
|
|
7
8
|
import type { RequestInit, BodyInit, HeadersInit } from "undici";
|
|
8
9
|
|
|
10
|
+
/**
|
|
11
|
+
* When the custom mocks fallthrough in tests because they aren't set, instead of throwing an error,
|
|
12
|
+
* we use real fetch to make the request which will use Mock Service Workers.
|
|
13
|
+
*/
|
|
14
|
+
const {
|
|
15
|
+
fetchInternal: realFetchInternal,
|
|
16
|
+
}: { fetchInternal: typeof fetchInternal } = jest.requireActual(
|
|
17
|
+
"../../cfetch/internal"
|
|
18
|
+
);
|
|
19
|
+
const {
|
|
20
|
+
fetchR2Objects: realFetchR2Objects,
|
|
21
|
+
}: { fetchR2Objects: typeof fetchR2Objects } = jest.requireActual(
|
|
22
|
+
"../../cfetch/internal"
|
|
23
|
+
);
|
|
24
|
+
|
|
9
25
|
/**
|
|
10
26
|
* The signature of the function that will handle a mock request.
|
|
11
27
|
*/
|
|
@@ -34,7 +50,7 @@ const mocks: MockFetch<unknown>[] = [];
|
|
|
34
50
|
export async function mockFetchInternal(
|
|
35
51
|
resource: string,
|
|
36
52
|
init: RequestInit = {},
|
|
37
|
-
queryParams: URLSearchParams
|
|
53
|
+
queryParams: URLSearchParams | undefined
|
|
38
54
|
) {
|
|
39
55
|
for (const { regexp, method, handler } of mocks) {
|
|
40
56
|
const resourcePath = new URL(resource, getCloudflareApiBaseUrl()).pathname;
|
|
@@ -43,12 +59,13 @@ export async function mockFetchInternal(
|
|
|
43
59
|
if (uri !== null && (!method || method === (init.method ?? "GET"))) {
|
|
44
60
|
// The `resource` regular expression will extract the labelled groups from the URL.
|
|
45
61
|
// These are passed through to the `handler` call, to allow it to do additional checks or behaviour.
|
|
46
|
-
return await handler(uri, init, queryParams); // TODO: should we have some kind of fallthrough system? we'll see.
|
|
62
|
+
return await handler(uri, init, queryParams ?? new URLSearchParams()); // TODO: should we have some kind of fallthrough system? we'll see.
|
|
47
63
|
}
|
|
48
64
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
65
|
+
|
|
66
|
+
// let it fall through to mock-service-worker
|
|
67
|
+
// (do a real, unmocked fetch)
|
|
68
|
+
return await realFetchInternal(resource, init, queryParams);
|
|
52
69
|
}
|
|
53
70
|
|
|
54
71
|
/**
|
|
@@ -221,21 +238,24 @@ export async function mockFetchR2Objects(
|
|
|
221
238
|
method: "PUT" | "GET" | "DELETE";
|
|
222
239
|
}
|
|
223
240
|
): Promise<Response> {
|
|
224
|
-
/**
|
|
225
|
-
* Here we destroy & removeListeners to "drain" the stream, for testing purposes
|
|
226
|
-
* mimicking the fetch request taking in the stream and draining it.
|
|
227
|
-
*/
|
|
228
|
-
if (bodyInit.body instanceof Readable) {
|
|
229
|
-
bodyInit.body.destroy();
|
|
230
|
-
bodyInit.body.removeAllListeners();
|
|
231
|
-
}
|
|
232
|
-
|
|
233
241
|
if (r2GetMocks.has(resource)) {
|
|
242
|
+
/**
|
|
243
|
+
* Here we destroy & removeListeners to "drain" the stream, for testing purposes
|
|
244
|
+
* mimicking the fetch request taking in the stream and draining it.
|
|
245
|
+
*/
|
|
246
|
+
if (bodyInit.body instanceof Readable) {
|
|
247
|
+
bodyInit.body.destroy();
|
|
248
|
+
bodyInit.body.removeAllListeners();
|
|
249
|
+
}
|
|
250
|
+
|
|
234
251
|
const value = r2GetMocks.get(resource);
|
|
235
252
|
|
|
236
253
|
return new Response(value);
|
|
237
254
|
}
|
|
238
|
-
|
|
255
|
+
|
|
256
|
+
// No mocks found for ${init.method ?? "any HTTP"} request to ${resource}
|
|
257
|
+
// let it fall through to Mock Service Worker with a real fetch.
|
|
258
|
+
return await realFetchR2Objects(resource, bodyInit);
|
|
239
259
|
}
|
|
240
260
|
|
|
241
261
|
/**
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// barrel import for msw handlers
|
|
2
|
+
import { mswNamespacesHandlers } from "./namespaces";
|
|
3
|
+
import { mswOauthHandlers } from "./oauth";
|
|
4
|
+
import { mswR2handlers } from "./r2";
|
|
5
|
+
import { mswUserHandlers } from "./user";
|
|
6
|
+
|
|
7
|
+
// All the handlers are used in msw/index for setting up the server
|
|
8
|
+
export const mswDefaultHandlers = [
|
|
9
|
+
...mswOauthHandlers,
|
|
10
|
+
...mswR2handlers,
|
|
11
|
+
...mswUserHandlers,
|
|
12
|
+
...mswNamespacesHandlers,
|
|
13
|
+
];
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
|
|
3
|
+
export const mswNamespacesHandlers = [
|
|
4
|
+
rest.post(
|
|
5
|
+
"*/accounts/:accountId/workers/dispatch/namespaces",
|
|
6
|
+
(request, response, context) => {
|
|
7
|
+
return response(
|
|
8
|
+
context.status(200),
|
|
9
|
+
context.json({
|
|
10
|
+
success: true,
|
|
11
|
+
errors: [],
|
|
12
|
+
messages: [],
|
|
13
|
+
result: {
|
|
14
|
+
namespace_id: "some-namespace-id",
|
|
15
|
+
namespace_name: "namespace-name",
|
|
16
|
+
created_on: "2022-06-29T14:30:08.16152Z",
|
|
17
|
+
created_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
18
|
+
modified_on: "2022-06-29T14:30:08.16152Z",
|
|
19
|
+
modified_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
),
|
|
25
|
+
rest.delete(
|
|
26
|
+
"*/accounts/:accountId/workers/dispatch/namespaces/:namespaceName",
|
|
27
|
+
(_, response, context) => {
|
|
28
|
+
return response(
|
|
29
|
+
context.status(200),
|
|
30
|
+
context.json({
|
|
31
|
+
success: true,
|
|
32
|
+
errors: [],
|
|
33
|
+
messages: [],
|
|
34
|
+
result: null,
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
rest.put(
|
|
40
|
+
"*/accounts/:accountId/workers/dispatch/namespaces/:namespaceName",
|
|
41
|
+
(_, response, context) => {
|
|
42
|
+
return response(
|
|
43
|
+
context.status(200),
|
|
44
|
+
context.json({
|
|
45
|
+
success: true,
|
|
46
|
+
errors: [],
|
|
47
|
+
messages: [],
|
|
48
|
+
result: {
|
|
49
|
+
namespace_id: "some-namespace-id",
|
|
50
|
+
namespace_name: "namespace-name",
|
|
51
|
+
created_on: "2022-06-29T14:30:08.16152Z",
|
|
52
|
+
created_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
53
|
+
modified_on: "2022-06-29T14:30:08.16152Z",
|
|
54
|
+
modified_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
rest.get(
|
|
61
|
+
"*/accounts/:accountId/workers/dispatch/namespaces/:namespaceName",
|
|
62
|
+
(_, response, context) => {
|
|
63
|
+
return response(
|
|
64
|
+
context.status(200),
|
|
65
|
+
context.json({
|
|
66
|
+
success: true,
|
|
67
|
+
errors: [],
|
|
68
|
+
messages: [],
|
|
69
|
+
result: {
|
|
70
|
+
namespace_id: "some-namespace-id",
|
|
71
|
+
namespace_name: "namespace-name",
|
|
72
|
+
created_on: "2022-06-29T14:30:08.16152Z",
|
|
73
|
+
created_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
74
|
+
modified_on: "2022-06-29T14:30:08.16152Z",
|
|
75
|
+
modified_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
76
|
+
},
|
|
77
|
+
})
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
rest.get(
|
|
82
|
+
"*/accounts/:accountId/workers/dispatch/namespaces",
|
|
83
|
+
(_, response, context) => {
|
|
84
|
+
return response(
|
|
85
|
+
context.status(200),
|
|
86
|
+
context.json({
|
|
87
|
+
success: true,
|
|
88
|
+
errors: [],
|
|
89
|
+
messages: [],
|
|
90
|
+
result: [
|
|
91
|
+
{
|
|
92
|
+
namespace_id: "some-namespace-id",
|
|
93
|
+
namespace_name: "namespace-name",
|
|
94
|
+
created_on: "2022-06-29T14:30:08.16152Z",
|
|
95
|
+
created_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
96
|
+
modified_on: "2022-06-29T14:30:08.16152Z",
|
|
97
|
+
modified_by: "1fc1df98cc4420fe00367c3ab68c1639",
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
),
|
|
104
|
+
];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
|
|
3
|
+
export const mswOauthHandlers = [
|
|
4
|
+
rest.all("*/oauth/callback", (_, response, context) => {
|
|
5
|
+
return response(
|
|
6
|
+
context.status(200),
|
|
7
|
+
context.json({
|
|
8
|
+
success: true,
|
|
9
|
+
errors: [],
|
|
10
|
+
messages: [],
|
|
11
|
+
code: "test-oauth-code",
|
|
12
|
+
})
|
|
13
|
+
);
|
|
14
|
+
}),
|
|
15
|
+
// revoke access token
|
|
16
|
+
rest.post(
|
|
17
|
+
"https://dash.cloudflare.com/oauth2/revoke",
|
|
18
|
+
(_, response, context) => response(context.status(200), context.text(""))
|
|
19
|
+
),
|
|
20
|
+
|
|
21
|
+
// exchange (auth code | refresh token) for access token
|
|
22
|
+
rest.post(
|
|
23
|
+
"https://dash.cloudflare.com/oauth2/token",
|
|
24
|
+
(_, response, context) => {
|
|
25
|
+
return response(
|
|
26
|
+
context.status(200),
|
|
27
|
+
context.json({
|
|
28
|
+
access_token: "test-access-token",
|
|
29
|
+
expires_in: 100000,
|
|
30
|
+
refresh_token: "test-refresh-token",
|
|
31
|
+
scope: "account:read",
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
),
|
|
36
|
+
];
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
|
|
3
|
+
export const mswR2handlers = [
|
|
4
|
+
// List endpoint r2Buckets
|
|
5
|
+
rest.get("*/accounts/:accountId/r2/buckets", (_, response, context) =>
|
|
6
|
+
response(
|
|
7
|
+
context.status(200),
|
|
8
|
+
context.json({
|
|
9
|
+
success: true,
|
|
10
|
+
errors: [],
|
|
11
|
+
messages: [],
|
|
12
|
+
result: {
|
|
13
|
+
buckets: [
|
|
14
|
+
{ name: "bucket-1", creation_date: "01-01-2001" },
|
|
15
|
+
{ name: "bucket-2", creation_date: "01-01-2001" },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
)
|
|
20
|
+
),
|
|
21
|
+
rest.post("*/accounts/:accountId/r2/buckets", (_, response, context) =>
|
|
22
|
+
response(
|
|
23
|
+
context.status(200),
|
|
24
|
+
context.json({ success: true, errors: [], messages: [], result: {} })
|
|
25
|
+
)
|
|
26
|
+
),
|
|
27
|
+
rest.put(
|
|
28
|
+
"*/accounts/:accountId/r2/buckets/:bucketName",
|
|
29
|
+
(_, response, context) =>
|
|
30
|
+
response(
|
|
31
|
+
context.status(200),
|
|
32
|
+
context.json({ success: true, errors: [], messages: [], result: {} })
|
|
33
|
+
)
|
|
34
|
+
),
|
|
35
|
+
rest.delete(
|
|
36
|
+
"*/accounts/:accountId/r2/buckets/:bucketName",
|
|
37
|
+
(_, response, context) =>
|
|
38
|
+
response(
|
|
39
|
+
context.status(200),
|
|
40
|
+
context.json({ success: true, errors: [], messages: [], result: null })
|
|
41
|
+
)
|
|
42
|
+
),
|
|
43
|
+
rest.get(
|
|
44
|
+
"*/accounts/:accountId/r2/buckets/:bucketName/objects/:objectName",
|
|
45
|
+
(_, response, context) => {
|
|
46
|
+
const imageBuffer = Buffer.from("wormhole-img.png");
|
|
47
|
+
return response(
|
|
48
|
+
context.set("Content-Length", imageBuffer.byteLength.toString()),
|
|
49
|
+
context.set("Content-Type", "image/png"),
|
|
50
|
+
context.status(200),
|
|
51
|
+
context.body(imageBuffer)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
),
|
|
55
|
+
rest.put(
|
|
56
|
+
"*/accounts/:accountId/r2/buckets/:bucketName/objects/:objectName",
|
|
57
|
+
(_, response, context) =>
|
|
58
|
+
response(
|
|
59
|
+
context.status(200),
|
|
60
|
+
context.json({
|
|
61
|
+
success: true,
|
|
62
|
+
errors: [],
|
|
63
|
+
messages: [],
|
|
64
|
+
result: {
|
|
65
|
+
accountId: "some-account-id",
|
|
66
|
+
bucketName: "bucketName-object-test",
|
|
67
|
+
objectName: "wormhole-img.png",
|
|
68
|
+
},
|
|
69
|
+
})
|
|
70
|
+
)
|
|
71
|
+
),
|
|
72
|
+
rest.delete(
|
|
73
|
+
"*/accounts/:accountId/r2/buckets/:bucketName/objects/:objectName",
|
|
74
|
+
(_, response, context) =>
|
|
75
|
+
response(
|
|
76
|
+
context.status(200),
|
|
77
|
+
context.json({ success: true, errors: [], messages: [], result: null })
|
|
78
|
+
)
|
|
79
|
+
),
|
|
80
|
+
];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { rest } from "msw";
|
|
2
|
+
|
|
3
|
+
export const mswUserHandlers = [
|
|
4
|
+
rest.get("*/user", (_, res, cxt) => {
|
|
5
|
+
return res(
|
|
6
|
+
cxt.status(200),
|
|
7
|
+
cxt.json({
|
|
8
|
+
success: true,
|
|
9
|
+
errors: [],
|
|
10
|
+
messages: [],
|
|
11
|
+
result: {
|
|
12
|
+
id: "7c5dae5552338874e5053f2534d2767a",
|
|
13
|
+
email: "user@example.com",
|
|
14
|
+
first_name: "John",
|
|
15
|
+
last_name: "Appleseed",
|
|
16
|
+
username: "cfuser12345",
|
|
17
|
+
telephone: "+1 123-123-1234",
|
|
18
|
+
country: "US",
|
|
19
|
+
zipcode: "12345",
|
|
20
|
+
created_on: "2014-01-01T05:20:00Z",
|
|
21
|
+
modified_on: "2014-01-01T05:20:00Z",
|
|
22
|
+
two_factor_authentication_enabled: false,
|
|
23
|
+
suspended: false,
|
|
24
|
+
},
|
|
25
|
+
})
|
|
26
|
+
);
|
|
27
|
+
}),
|
|
28
|
+
rest.get("*/accounts", (_, res, cxt) => {
|
|
29
|
+
return res(
|
|
30
|
+
cxt.status(200),
|
|
31
|
+
cxt.json({
|
|
32
|
+
success: true,
|
|
33
|
+
errors: [],
|
|
34
|
+
messages: [],
|
|
35
|
+
result: [
|
|
36
|
+
{ name: "Account One", id: "account-1" },
|
|
37
|
+
{ name: "Account Two", id: "account-2" },
|
|
38
|
+
{ name: "Account Three", id: "account-3" },
|
|
39
|
+
],
|
|
40
|
+
})
|
|
41
|
+
);
|
|
42
|
+
}),
|
|
43
|
+
rest.get("*/memberships", (_, response, context) => {
|
|
44
|
+
return response(
|
|
45
|
+
context.status(200),
|
|
46
|
+
context.json({
|
|
47
|
+
success: true,
|
|
48
|
+
errors: [],
|
|
49
|
+
messages: [],
|
|
50
|
+
result: [
|
|
51
|
+
{
|
|
52
|
+
id: "membership-id-1",
|
|
53
|
+
account: { id: "account-id-1", name: "My Personal Account" },
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "membership-id-2",
|
|
57
|
+
account: { id: "account-id-2", name: "Enterprise Account" },
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
}),
|
|
63
|
+
];
|
|
@@ -36,6 +36,7 @@ describe("wrangler", () => {
|
|
|
36
36
|
wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
|
|
37
37
|
wrangler tail [worker] 🦚 Starts a log tailing session for a published Worker.
|
|
38
38
|
wrangler secret 🤫 Generate a secret that can be referenced in a Worker
|
|
39
|
+
wrangler secret:bulk <json> 🗄️ Bulk upload secrets for a Worker
|
|
39
40
|
wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
|
|
40
41
|
wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
|
|
41
42
|
wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
|
|
@@ -75,6 +76,7 @@ describe("wrangler", () => {
|
|
|
75
76
|
wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
|
|
76
77
|
wrangler tail [worker] 🦚 Starts a log tailing session for a published Worker.
|
|
77
78
|
wrangler secret 🤫 Generate a secret that can be referenced in a Worker
|
|
79
|
+
wrangler secret:bulk <json> 🗄️ Bulk upload secrets for a Worker
|
|
78
80
|
wrangler kv:namespace 🗂️ Interact with your Workers KV Namespaces
|
|
79
81
|
wrangler kv:key 🔑 Individually manage Workers KV key-value pairs
|
|
80
82
|
wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
mockFetchR2Objects,
|
|
15
15
|
} from "./helpers/mock-cfetch";
|
|
16
16
|
import { MockWebSocket } from "./helpers/mock-web-socket";
|
|
17
|
+
import { msw } from "./helpers/msw";
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* The relative path between the bundled code and the Wrangler package.
|
|
@@ -57,6 +58,21 @@ fetchMock.doMock(() => {
|
|
|
57
58
|
|
|
58
59
|
jest.mock("../package-manager");
|
|
59
60
|
|
|
61
|
+
// requests not mocked with `jest-fetch-mock` fall through
|
|
62
|
+
// to `mock-service-worker`
|
|
63
|
+
fetchMock.dontMock();
|
|
64
|
+
beforeAll(() => {
|
|
65
|
+
msw.listen({
|
|
66
|
+
onUnhandledRequest: (request) => {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`No mock found for ${request.method} ${request.url.href}`
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
afterEach(() => msw.resetHandlers());
|
|
74
|
+
afterAll(() => msw.close());
|
|
75
|
+
|
|
60
76
|
jest.mock("../cfetch/internal");
|
|
61
77
|
(fetchInternal as jest.Mock).mockImplementation(mockFetchInternal);
|
|
62
78
|
(fetchKVGetValue as jest.Mock).mockImplementation(mockFetchKVGetValue);
|
|
@@ -6488,6 +6488,58 @@ addEventListener('fetch', event => {});`
|
|
|
6488
6488
|
`);
|
|
6489
6489
|
});
|
|
6490
6490
|
});
|
|
6491
|
+
|
|
6492
|
+
it("should publish if the last deployed source check fails", async () => {
|
|
6493
|
+
unsetAllMocks();
|
|
6494
|
+
writeWorkerSource();
|
|
6495
|
+
writeWranglerToml();
|
|
6496
|
+
mockSubDomainRequest();
|
|
6497
|
+
mockUploadWorkerRequest();
|
|
6498
|
+
setMockRawResponse(
|
|
6499
|
+
"/accounts/:accountId/workers/services/:scriptName",
|
|
6500
|
+
"GET",
|
|
6501
|
+
() => {
|
|
6502
|
+
return createFetchResult(null, false, [
|
|
6503
|
+
{ code: 10090, message: "workers.api.error.service_not_found" },
|
|
6504
|
+
]);
|
|
6505
|
+
}
|
|
6506
|
+
);
|
|
6507
|
+
|
|
6508
|
+
await runWrangler("publish index.js");
|
|
6509
|
+
expect(std).toMatchInlineSnapshot(`
|
|
6510
|
+
Object {
|
|
6511
|
+
"debug": "",
|
|
6512
|
+
"err": "",
|
|
6513
|
+
"out": "Total Upload: xx KiB / gzip: xx KiB
|
|
6514
|
+
Uploaded test-name (TIMINGS)
|
|
6515
|
+
Published test-name (TIMINGS)
|
|
6516
|
+
https://test-name.test-sub-domain.workers.dev",
|
|
6517
|
+
"warn": "",
|
|
6518
|
+
}
|
|
6519
|
+
`);
|
|
6520
|
+
});
|
|
6521
|
+
|
|
6522
|
+
it("should not publish if there's any other kind of error when checking deployment source", async () => {
|
|
6523
|
+
unsetAllMocks();
|
|
6524
|
+
writeWorkerSource();
|
|
6525
|
+
writeWranglerToml();
|
|
6526
|
+
mockSubDomainRequest();
|
|
6527
|
+
mockUploadWorkerRequest();
|
|
6528
|
+
setMockRawResponse(
|
|
6529
|
+
"/accounts/:accountId/workers/services/:scriptName",
|
|
6530
|
+
"GET",
|
|
6531
|
+
() => {
|
|
6532
|
+
return createFetchResult(null, false, [
|
|
6533
|
+
{ code: 10000, message: "Authentication error" },
|
|
6534
|
+
]);
|
|
6535
|
+
}
|
|
6536
|
+
);
|
|
6537
|
+
|
|
6538
|
+
await runWrangler("publish index.js");
|
|
6539
|
+
expect(std.err).toContain(
|
|
6540
|
+
`A request to the Cloudflare API (/accounts/some-account-id/workers/services/test-name) failed`
|
|
6541
|
+
);
|
|
6542
|
+
});
|
|
6491
6543
|
});
|
|
6492
6544
|
|
|
6493
6545
|
/** Write mock assets to the file system so they can be uploaded. */
|