wrangler 0.0.0-e95bea2 → 0.0.0-ea8e701

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.
Files changed (55) hide show
  1. package/README.md +3 -3
  2. package/bin/wrangler.js +10 -1
  3. package/miniflare-dist/index.mjs +79 -0
  4. package/miniflare-dist/index.mjs.map +7 -0
  5. package/package.json +7 -6
  6. package/pages/functions/filepath-routing.test.ts +125 -25
  7. package/pages/functions/filepath-routing.ts +6 -3
  8. package/src/__tests__/configuration.test.ts +826 -223
  9. package/src/__tests__/dev.test.tsx +145 -9
  10. package/src/__tests__/guess-worker-format.test.ts +26 -1
  11. package/src/__tests__/helpers/mock-account-id.ts +4 -0
  12. package/src/__tests__/helpers/mock-kv.ts +9 -16
  13. package/src/__tests__/helpers/mock-oauth-flow.ts +178 -0
  14. package/src/__tests__/helpers/run-in-tmp.ts +3 -0
  15. package/src/__tests__/index.test.ts +9 -13
  16. package/src/__tests__/jest.setup.ts +5 -0
  17. package/src/__tests__/kv.test.ts +43 -71
  18. package/src/__tests__/pages.test.ts +48 -10
  19. package/src/__tests__/publish.test.ts +1456 -327
  20. package/src/__tests__/r2.test.ts +4 -4
  21. package/src/__tests__/tail.test.ts +78 -4
  22. package/src/__tests__/user.test.ts +83 -0
  23. package/src/__tests__/whoami.test.tsx +16 -7
  24. package/src/bundle.ts +15 -2
  25. package/src/cfetch/internal.ts +9 -5
  26. package/src/config/README.md +6 -6
  27. package/src/config/config.ts +17 -78
  28. package/src/config/environment.ts +67 -1
  29. package/src/config/index.ts +13 -3
  30. package/src/config/validation-helpers.ts +177 -11
  31. package/src/config/validation.ts +305 -100
  32. package/src/dev/dev.tsx +76 -41
  33. package/src/dev/local.tsx +105 -114
  34. package/src/dev/remote.tsx +2 -0
  35. package/src/dev/use-esbuild.ts +4 -0
  36. package/src/entry.ts +103 -6
  37. package/src/index.tsx +251 -189
  38. package/src/intl-polyfill.d.ts +139 -0
  39. package/src/{kv/index.tsx → kv.ts} +8 -28
  40. package/src/miniflare-cli/README.md +30 -0
  41. package/src/miniflare-cli/enum-keys.ts +17 -0
  42. package/src/miniflare-cli/index.ts +37 -0
  43. package/src/module-collection.ts +58 -53
  44. package/src/pages.tsx +26 -10
  45. package/src/proxy.ts +5 -3
  46. package/src/publish.ts +17 -21
  47. package/src/sites.tsx +67 -25
  48. package/src/tail/index.ts +1 -1
  49. package/src/tail/printing.ts +2 -2
  50. package/src/user.tsx +161 -81
  51. package/wrangler-dist/cli.js +3418 -1437
  52. package/wrangler-dist/cli.js.map +3 -3
  53. package/src/__tests__/dev2.test.tsx +0 -152
  54. package/src/__tests__/helpers/mock-user.ts +0 -27
  55. package/src/__tests__/logout.test.ts +0 -50
@@ -9,7 +9,7 @@ import { runInTempDir } from "./helpers/run-in-tmp";
9
9
  import { runWrangler } from "./helpers/run-wrangler";
10
10
  import writeWranglerToml from "./helpers/write-wrangler-toml";
11
11
 
12
- describe("Dev component", () => {
12
+ describe("wrangler dev", () => {
13
13
  mockAccountId();
14
14
  mockApiToken();
15
15
  runInTempDir();
@@ -37,6 +37,57 @@ describe("Dev component", () => {
37
37
  %s If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
38
38
  `);
39
39
  });
40
+
41
+ it("should use `main` from the top-level environment", async () => {
42
+ writeWranglerToml({
43
+ main: "index.js",
44
+ });
45
+ fs.writeFileSync("index.js", `export default {};`);
46
+ await runWrangler("dev");
47
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
48
+ /index\.js$/
49
+ );
50
+ expect(std.out).toMatchInlineSnapshot(`""`);
51
+ expect(std.warn).toMatchInlineSnapshot(`""`);
52
+ expect(std.err).toMatchInlineSnapshot(`""`);
53
+ });
54
+
55
+ it("should use `main` from a named environment", async () => {
56
+ writeWranglerToml({
57
+ env: {
58
+ ENV1: {
59
+ main: "index.js",
60
+ },
61
+ },
62
+ });
63
+ fs.writeFileSync("index.js", `export default {};`);
64
+ await runWrangler("dev --env=ENV1");
65
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
66
+ /index\.js$/
67
+ );
68
+ expect(std.out).toMatchInlineSnapshot(`""`);
69
+ expect(std.warn).toMatchInlineSnapshot(`""`);
70
+ expect(std.err).toMatchInlineSnapshot(`""`);
71
+ });
72
+
73
+ it("should use `main` from a named environment, rather than the top-level", async () => {
74
+ writeWranglerToml({
75
+ main: "other.js",
76
+ env: {
77
+ ENV1: {
78
+ main: "index.js",
79
+ },
80
+ },
81
+ });
82
+ fs.writeFileSync("index.js", `export default {};`);
83
+ await runWrangler("dev --env=ENV1");
84
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
85
+ /index\.js$/
86
+ );
87
+ expect(std.out).toMatchInlineSnapshot(`""`);
88
+ expect(std.warn).toMatchInlineSnapshot(`""`);
89
+ expect(std.err).toMatchInlineSnapshot(`""`);
90
+ });
40
91
  });
41
92
 
42
93
  describe("host", () => {
@@ -135,7 +186,7 @@ describe("Dev component", () => {
135
186
  });
136
187
  });
137
188
 
138
- it("should, in order, use args.host/config.dev.host/args.routes/config.route/config.routes", async () => {
189
+ it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
139
190
  // This test might seem like it's testing implementation details, but let's be specific and consider it a spec
140
191
 
141
192
  fs.writeFileSync("index.js", `export default {};`);
@@ -158,7 +209,6 @@ describe("Dev component", () => {
158
209
  writeWranglerToml({
159
210
  main: "index.js",
160
211
  route: "https://4.some-host.com/some/path/*",
161
- routes: ["http://5.some-host.com/some/path/*"],
162
212
  });
163
213
  await runWrangler("dev");
164
214
  expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
@@ -172,7 +222,6 @@ describe("Dev component", () => {
172
222
  writeWranglerToml({
173
223
  main: "index.js",
174
224
  route: "https://4.some-host.com/some/path/*",
175
- routes: ["http://5.some-host.com/some/path/*"],
176
225
  });
177
226
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
178
227
  expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
@@ -189,7 +238,6 @@ describe("Dev component", () => {
189
238
  host: `2.some-host.com`,
190
239
  },
191
240
  route: "4.some-host.com/some/path/*",
192
- routes: ["5.some-host.com/some/path/*"],
193
241
  });
194
242
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
195
243
  expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
@@ -206,7 +254,6 @@ describe("Dev component", () => {
206
254
  host: `2.some-host.com`,
207
255
  },
208
256
  route: "4.some-host.com/some/path/*",
209
- routes: ["5.some-host.com/some/path/*"],
210
257
  });
211
258
  await runWrangler(
212
259
  "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
@@ -230,6 +277,15 @@ describe("Dev component", () => {
230
277
  `"Could not find zone for some-host.com"`
231
278
  );
232
279
  });
280
+
281
+ it("should not try to resolve a zone when starting in local mode", async () => {
282
+ writeWranglerToml({
283
+ main: "index.js",
284
+ });
285
+ fs.writeFileSync("index.js", `export default {};`);
286
+ await runWrangler("dev --host some-host.com --local");
287
+ expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual(undefined);
288
+ });
233
289
  });
234
290
 
235
291
  describe("custom builds", () => {
@@ -247,11 +303,11 @@ describe("Dev component", () => {
247
303
  );
248
304
 
249
305
  // and the command would pass through
250
- expect((Dev as jest.Mock).mock.calls[0][0].buildCommand).toEqual({
306
+ expect((Dev as jest.Mock).mock.calls[0][0].build).toEqual({
251
307
  command:
252
308
  "node -e \"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\"",
253
309
  cwd: undefined,
254
- watch_dir: undefined,
310
+ watch_dir: "src",
255
311
  });
256
312
  expect(std.out).toMatchInlineSnapshot(
257
313
  `"running: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\""`
@@ -355,7 +411,7 @@ describe("Dev component", () => {
355
411
  expect(std.err).toMatchInlineSnapshot(`""`);
356
412
  });
357
413
 
358
- it("should use to `local_protocol` from `wrangler.toml`, if available", async () => {
414
+ it("should use `local_protocol` from `wrangler.toml`, if available", async () => {
359
415
  writeWranglerToml({
360
416
  main: "index.js",
361
417
  dev: {
@@ -389,6 +445,86 @@ describe("Dev component", () => {
389
445
  expect(std.err).toMatchInlineSnapshot(`""`);
390
446
  });
391
447
  });
448
+
449
+ describe("ip", () => {
450
+ it("should default ip to localhost", async () => {
451
+ writeWranglerToml({
452
+ main: "index.js",
453
+ });
454
+ fs.writeFileSync("index.js", `export default {};`);
455
+ await runWrangler("dev");
456
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
457
+ expect(std.out).toMatchInlineSnapshot(`""`);
458
+ expect(std.warn).toMatchInlineSnapshot(`""`);
459
+ expect(std.err).toMatchInlineSnapshot(`""`);
460
+ });
461
+
462
+ it("should use to `ip` from `wrangler.toml`, if available", async () => {
463
+ writeWranglerToml({
464
+ main: "index.js",
465
+ dev: {
466
+ ip: "0.0.0.0",
467
+ },
468
+ });
469
+ fs.writeFileSync("index.js", `export default {};`);
470
+ await runWrangler("dev");
471
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
472
+ expect(std.out).toMatchInlineSnapshot(`""`);
473
+ expect(std.warn).toMatchInlineSnapshot(`""`);
474
+ expect(std.err).toMatchInlineSnapshot(`""`);
475
+ });
476
+
477
+ it("should use --ip command line arg, if provided", async () => {
478
+ writeWranglerToml({
479
+ main: "index.js",
480
+ dev: {
481
+ ip: "1.1.1.1",
482
+ },
483
+ });
484
+ fs.writeFileSync("index.js", `export default {};`);
485
+ await runWrangler("dev --ip=0.0.0.0");
486
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
487
+ expect(std.out).toMatchInlineSnapshot(`""`);
488
+ expect(std.warn).toMatchInlineSnapshot(`""`);
489
+ expect(std.err).toMatchInlineSnapshot(`""`);
490
+ });
491
+ });
492
+
493
+ describe("durable_objects", () => {
494
+ it("should warn if there is one or more remote Durable Object", async () => {
495
+ writeWranglerToml({
496
+ main: "index.js",
497
+ durable_objects: {
498
+ bindings: [
499
+ { name: "NAME_1", class_name: "CLASS_1" },
500
+ {
501
+ name: "NAME_2",
502
+ class_name: "CLASS_2",
503
+ script_name: "SCRIPT_A",
504
+ },
505
+ { name: "NAME_3", class_name: "CLASS_3" },
506
+ {
507
+ name: "NAME_4",
508
+ class_name: "CLASS_4",
509
+ script_name: "SCRIPT_B",
510
+ },
511
+ ],
512
+ },
513
+ });
514
+ fs.writeFileSync("index.js", `export default {};`);
515
+ await runWrangler("dev");
516
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
517
+ expect(std.out).toMatchInlineSnapshot(`""`);
518
+ expect(std.warn).toMatchInlineSnapshot(`
519
+ "WARNING: You have Durable Object bindings, which are not defined locally in the worker being developed.
520
+ Be aware that changes to the data stored in these Durable Objects will be permanent and affect the live instances.
521
+ Remote Durable Objects that are affected:
522
+ - {\\"name\\":\\"NAME_2\\",\\"class_name\\":\\"CLASS_2\\",\\"script_name\\":\\"SCRIPT_A\\"}
523
+ - {\\"name\\":\\"NAME_4\\",\\"class_name\\":\\"CLASS_4\\",\\"script_name\\":\\"SCRIPT_B\\"}"
524
+ `);
525
+ expect(std.err).toMatchInlineSnapshot(`""`);
526
+ });
527
+ });
392
528
  });
393
529
 
394
530
  function mockGetZones(domain: string, zones: { id: string }[] = []) {
@@ -1,10 +1,12 @@
1
1
  import { writeFile } from "fs/promises";
2
2
  import path from "path";
3
3
  import guessWorkerFormat from "../entry";
4
+ import { mockConsoleMethods } from "./helpers/mock-console";
4
5
  import { runInTempDir } from "./helpers/run-in-tmp";
5
6
 
6
7
  describe("guess worker format", () => {
7
8
  runInTempDir();
9
+ const std = mockConsoleMethods();
8
10
  it('should detect a "modules" worker', async () => {
9
11
  await writeFile("./index.ts", "export default {};");
10
12
  // Note that this isn't actually a valid worker, because it's missing
@@ -39,7 +41,7 @@ describe("guess worker format", () => {
39
41
  "service-worker"
40
42
  )
41
43
  ).rejects.toThrow(
42
- "You configured this worker to be a 'service-worker', but the file you are trying to build appears to have ES module exports. Please pass `--format modules`, or simply remove the configuration."
44
+ "You configured this worker to be a 'service-worker', but the file you are trying to build appears to have a `default` export like a module worker. Please pass `--format modules`, or simply remove the configuration."
43
45
  );
44
46
  });
45
47
 
@@ -55,4 +57,27 @@ describe("guess worker format", () => {
55
57
  "You configured this worker to be 'modules', but the file you are trying to build doesn't export a handler. Please pass `--format service-worker`, or simply remove the configuration."
56
58
  );
57
59
  });
60
+
61
+ it("should not error if a .js entry point has jsx", async () => {
62
+ await writeFile("./index.js", "console.log(<div/>)");
63
+ const guess = await guessWorkerFormat(
64
+ path.join(process.cwd(), "./index.js"),
65
+ process.cwd(),
66
+ undefined
67
+ );
68
+ expect(guess).toBe("service-worker");
69
+ });
70
+
71
+ it("logs a warning when a worker has exports, but not a default one", async () => {
72
+ await writeFile("./index.ts", "export const foo = 1;");
73
+ const guess = await guessWorkerFormat(
74
+ path.join(process.cwd(), "./index.ts"),
75
+ process.cwd(),
76
+ undefined
77
+ );
78
+ expect(guess).toBe("service-worker");
79
+ expect(std.warn).toMatchInlineSnapshot(
80
+ `"The entrypoint index.ts has exports like an ES Module, but hasn't defined a default export like a module worker normally would. Building the worker using \\"service-worker\\" format..."`
81
+ );
82
+ });
58
83
  });
@@ -1,3 +1,5 @@
1
+ import { reinitialiseAuthTokens } from "../../user";
2
+
1
3
  const ORIGINAL_CLOUDFLARE_API_TOKEN = process.env.CLOUDFLARE_API_TOKEN;
2
4
  const ORIGINAL_CLOUDFLARE_ACCOUNT_ID = process.env.CLOUDFLARE_ACCOUNT_ID;
3
5
 
@@ -16,6 +18,8 @@ export function mockApiToken({
16
18
  } else {
17
19
  process.env.CLOUDFLARE_API_TOKEN = apiToken;
18
20
  }
21
+ // Now we have updated the environment, we must reinitialize the user auth state.
22
+ reinitialiseAuthTokens();
19
23
  });
20
24
  afterEach(() => {
21
25
  process.env.CLOUDFLARE_API_TOKEN = ORIGINAL_CLOUDFLARE_API_TOKEN;
@@ -1,18 +1,15 @@
1
1
  import { createFetchResult, setMockRawResponse } from "./mock-cfetch";
2
+ import type { NamespaceKeyInfo } from "../../kv";
2
3
 
3
4
  export function mockKeyListRequest(
4
5
  expectedNamespaceId: string,
5
- expectedKeys: string[],
6
+ expectedKeys: NamespaceKeyInfo[],
6
7
  keysPerRequest = 1000,
7
8
  blankCursorValue: "" | undefined | null = undefined
8
9
  ) {
9
10
  const requests = { count: 0 };
10
11
  // See https://api.cloudflare.com/#workers-kv-namespace-list-a-namespace-s-keys
11
- const expectedKeyObjects = expectedKeys.map((name) => ({
12
- name,
13
- expiration: 123456789,
14
- metadata: {},
15
- }));
12
+
16
13
  setMockRawResponse(
17
14
  "/accounts/:accountId/storage/kv/namespaces/:namespaceId/keys",
18
15
  "GET",
@@ -20,19 +17,15 @@ export function mockKeyListRequest(
20
17
  requests.count++;
21
18
  expect(accountId).toEqual("some-account-id");
22
19
  expect(namespaceId).toEqual(expectedNamespaceId);
23
- if (expectedKeyObjects.length <= keysPerRequest) {
24
- return createFetchResult(expectedKeyObjects);
20
+ if (expectedKeys.length <= keysPerRequest) {
21
+ return createFetchResult(expectedKeys);
25
22
  } else {
26
23
  const start = parseInt(query.get("cursor") ?? "0") || 0;
27
24
  const end = start + keysPerRequest;
28
- const cursor = end < expectedKeyObjects.length ? end : blankCursorValue;
29
- return createFetchResult(
30
- expectedKeyObjects.slice(start, end),
31
- true,
32
- [],
33
- [],
34
- { cursor }
35
- );
25
+ const cursor = end < expectedKeys.length ? end : blankCursorValue;
26
+ return createFetchResult(expectedKeys.slice(start, end), true, [], [], {
27
+ cursor,
28
+ });
36
29
  }
37
30
  }
38
31
  );
@@ -0,0 +1,178 @@
1
+ import { ChildProcess } from "child_process";
2
+ import fetchMock from "jest-fetch-mock";
3
+ import { Request } from "undici";
4
+ const { fetch } = jest.requireActual("undici") as {
5
+ fetch: (input: string) => Promise<unknown>;
6
+ };
7
+
8
+ // the response to send when wrangler wants an oauth grant
9
+ let oauthGrantResponse: GrantResponseOptions | "timeout" = {};
10
+
11
+ /**
12
+ * A mock implementation for `openInBrowser` that sends an oauth grant response
13
+ * to wrangler. Use it like this:
14
+ *
15
+ * ```js
16
+ * jest.mock("../open-in-browser");
17
+ * (openInBrowser as jest.Mock).mockImplementation(mockOpenInBrowser);
18
+ * ```
19
+ */
20
+ export const mockOpenInBrowser = async (url: string, ..._args: unknown[]) => {
21
+ const { searchParams } = new URL(url);
22
+ if (oauthGrantResponse === "timeout") {
23
+ throw "unimplemented";
24
+ } else {
25
+ const queryParams = toQueryParams(oauthGrantResponse, searchParams);
26
+ // don't await this -- it will block the rest of the login flow
27
+ fetch(`${searchParams.get("redirect_uri")}?${queryParams}`).catch((e) => {
28
+ throw new Error(
29
+ "Failed to send OAuth Grant to wrangler, maybe the server was closed?",
30
+ e as Error
31
+ );
32
+ });
33
+ return new ChildProcess();
34
+ }
35
+ };
36
+
37
+ /**
38
+ * Functions to help with mocking various parts of the OAuth Flow
39
+ */
40
+ export const mockOAuthFlow = () => {
41
+ afterEach(() => {
42
+ fetchMock.resetMocks();
43
+ });
44
+
45
+ const mockGrantAuthorization = ({
46
+ respondWith,
47
+ }: {
48
+ respondWith: "timeout" | "success" | "failure" | GrantResponseOptions;
49
+ }) => {
50
+ if (respondWith === "failure") {
51
+ oauthGrantResponse = {
52
+ error: "access_denied",
53
+ };
54
+ } else if (respondWith === "success") {
55
+ oauthGrantResponse = {
56
+ code: "test-oauth-code",
57
+ };
58
+ } else if (respondWith === "timeout") {
59
+ oauthGrantResponse = "timeout";
60
+ } else {
61
+ oauthGrantResponse = respondWith;
62
+ }
63
+ };
64
+
65
+ const mockRevokeAuthorization = () => {
66
+ const outcome = {
67
+ actual: new Request("https://example.org"),
68
+ expected: new Request("https://dash.cloudflare.com/oauth2/revoke", {
69
+ method: "POST",
70
+ }),
71
+ };
72
+
73
+ fetchMock.mockIf(outcome.expected.url, async (req) => {
74
+ outcome.actual = req;
75
+ return "";
76
+ });
77
+
78
+ return outcome;
79
+ };
80
+
81
+ const mockGrantAccessToken = ({
82
+ respondWith,
83
+ }: {
84
+ respondWith: MockTokenResponse;
85
+ }) => {
86
+ const outcome = {
87
+ actual: new Request("https://example.org"),
88
+ expected: new Request("https://dash.cloudflare.com/oauth2/token", {
89
+ method: "POST",
90
+ }),
91
+ };
92
+
93
+ fetchMock.mockOnceIf(outcome.expected.url, async (req) => {
94
+ outcome.actual = req;
95
+ return makeTokenResponse(respondWith);
96
+ });
97
+
98
+ return outcome;
99
+ };
100
+
101
+ return {
102
+ mockGrantAuthorization,
103
+ mockRevokeAuthorization,
104
+ mockGrantAccessToken,
105
+ };
106
+ };
107
+
108
+ type GrantResponseOptions = {
109
+ code?: string;
110
+ error?: ErrorType | ErrorType[];
111
+ };
112
+
113
+ const toQueryParams = (
114
+ { code, error }: GrantResponseOptions,
115
+ wranglerRequestParams: URLSearchParams
116
+ ): string => {
117
+ const queryParams = [];
118
+ if (code) {
119
+ queryParams.push(`code=${code}`);
120
+ }
121
+ if (error) {
122
+ const stringifiedErr = Array.isArray(error) ? error.join(",") : error;
123
+ queryParams.push(`error=${stringifiedErr}`);
124
+ }
125
+
126
+ queryParams.push(`state=${wranglerRequestParams.get("state")}`);
127
+
128
+ return queryParams.join("&");
129
+ };
130
+
131
+ type ErrorType =
132
+ | "invalid_request"
133
+ | "invalid_grant"
134
+ | "unauthorized_client"
135
+ | "access_denied"
136
+ | "unsupported_response_type"
137
+ | "invalid_scope"
138
+ | "server_error"
139
+ | "temporarily_unavailable"
140
+ | "invalid_client"
141
+ | "unsupported_grant_type"
142
+ | "invalid_json"
143
+ | "invalid_token"
144
+ | "test-token-grant-error";
145
+
146
+ type MockTokenResponse =
147
+ | "ok"
148
+ | "error"
149
+ | {
150
+ access_token: string;
151
+ expires_in: number;
152
+ refresh_token: string;
153
+ scope: string;
154
+ }
155
+ | {
156
+ error: ErrorType;
157
+ };
158
+
159
+ const makeTokenResponse = (partialResponse: MockTokenResponse): string => {
160
+ let fullResponse: MockTokenResponse;
161
+
162
+ if (partialResponse === "ok") {
163
+ fullResponse = {
164
+ access_token: "test-access-token",
165
+ expires_in: 100000,
166
+ refresh_token: "test-refresh-token",
167
+ scope: "account:read",
168
+ };
169
+ } else if (partialResponse === "error") {
170
+ fullResponse = {
171
+ error: "test-token-grant-error",
172
+ };
173
+ } else {
174
+ fullResponse = partialResponse;
175
+ }
176
+
177
+ return JSON.stringify(fullResponse);
178
+ };
@@ -1,6 +1,7 @@
1
1
  import * as fs from "node:fs";
2
2
  import os from "node:os";
3
3
  import * as path from "node:path";
4
+ import { reinitialiseAuthTokens } from "../../user";
4
5
 
5
6
  const originalCwd = process.cwd();
6
7
 
@@ -19,6 +20,8 @@ export function runInTempDir({ homedir }: { homedir?: string } = {}) {
19
20
  // This is because the module gets transpiled so that the "method" `homedir()` gets converted to a
20
21
  // getter that is not configurable (and so cannot be spied upon).
21
22
  jest.spyOn(os, "homedir").mockReturnValue(homedir);
23
+ // Now that we have changed the home directory location, we must reinitialize the user auth state
24
+ reinitialiseAuthTokens();
22
25
  }
23
26
  });
24
27
 
@@ -36,7 +36,6 @@ describe("wrangler", () => {
36
36
 
37
37
  Commands:
38
38
  wrangler init [name] 📥 Create a wrangler.toml configuration file
39
- wrangler whoami 🕵️ Retrieve your user info and test your auth config
40
39
  wrangler dev [script] 👂 Start a local server for developing your worker
41
40
  wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
42
41
  wrangler tail [name] 🦚 Starts a log tailing session for a published Worker.
@@ -46,6 +45,9 @@ describe("wrangler", () => {
46
45
  wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
47
46
  wrangler pages ⚡️ Configure Cloudflare Pages
48
47
  wrangler r2 📦 Interact with an R2 store
48
+ wrangler login 🔓 Login to Cloudflare
49
+ wrangler logout 🚪 Logout from Cloudflare
50
+ wrangler whoami 🕵️ Retrieve your user info and test your auth config
49
51
 
50
52
  Flags:
51
53
  -c, --config Path to .toml configuration file [string]
@@ -63,7 +65,7 @@ describe("wrangler", () => {
63
65
  await expect(
64
66
  runWrangler("invalid-command")
65
67
  ).rejects.toThrowErrorMatchingInlineSnapshot(
66
- `"Unknown command: invalid-command."`
68
+ `"Unknown argument: invalid-command"`
67
69
  );
68
70
 
69
71
  expect(std.out).toMatchInlineSnapshot(`""`);
@@ -72,7 +74,6 @@ describe("wrangler", () => {
72
74
 
73
75
  Commands:
74
76
  wrangler init [name] 📥 Create a wrangler.toml configuration file
75
- wrangler whoami 🕵️ Retrieve your user info and test your auth config
76
77
  wrangler dev [script] 👂 Start a local server for developing your worker
77
78
  wrangler publish [script] 🆙 Publish your Worker to Cloudflare.
78
79
  wrangler tail [name] 🦚 Starts a log tailing session for a published Worker.
@@ -82,6 +83,9 @@ describe("wrangler", () => {
82
83
  wrangler kv:bulk 💪 Interact with multiple Workers KV key-value pairs at once
83
84
  wrangler pages ⚡️ Configure Cloudflare Pages
84
85
  wrangler r2 📦 Interact with an R2 store
86
+ wrangler login 🔓 Login to Cloudflare
87
+ wrangler logout 🚪 Logout from Cloudflare
88
+ wrangler whoami 🕵️ Retrieve your user info and test your auth config
85
89
 
86
90
  Flags:
87
91
  -c, --config Path to .toml configuration file [string]
@@ -89,7 +93,7 @@ describe("wrangler", () => {
89
93
  -v, --version Show version number [boolean]
90
94
  --legacy-env Use legacy environments [boolean]
91
95
 
92
- Unknown command: invalid-command."
96
+ Unknown argument: invalid-command"
93
97
  `);
94
98
  });
95
99
  });
@@ -812,14 +816,6 @@ describe("wrangler", () => {
812
816
  expect(fs.existsSync("./wrangler.toml")).toBe(true);
813
817
  });
814
818
 
815
- it("should error if `--type` is used", async () => {
816
- await expect(
817
- runWrangler("init --type")
818
- ).rejects.toThrowErrorMatchingInlineSnapshot(
819
- `"The --type option is no longer supported."`
820
- );
821
- });
822
-
823
819
  it("should error if `--type javascript` is used", async () => {
824
820
  await expect(
825
821
  runWrangler("init --type javascript")
@@ -854,7 +850,7 @@ describe("wrangler", () => {
854
850
  Try using \`wrangler dev\` to to try out a worker during development.
855
851
  "
856
852
  `);
857
- await expect(runWrangler("preview GET 'Some Body'")).rejects
853
+ await expect(runWrangler(`preview GET "SomeBody"`)).rejects
858
854
  .toThrowErrorMatchingInlineSnapshot(`
859
855
  "DEPRECATION WARNING:
860
856
  The \`wrangler preview\` command has been deprecated.
@@ -5,7 +5,9 @@ import {
5
5
  getCloudflareAPIBaseURL,
6
6
  } from "../cfetch/internal";
7
7
  import { confirm, prompt } from "../dialogs";
8
+ import openInBrowser from "../open-in-browser";
8
9
  import { mockFetchInternal, mockFetchKVGetValue } from "./helpers/mock-cfetch";
10
+ import { mockOpenInBrowser as mockOpenInBrowserForOAuthFlow } from "./helpers/mock-oauth-flow";
9
11
  import { MockWebSocket } from "./helpers/mock-web-socket";
10
12
 
11
13
  jest.mock("ws", () => {
@@ -67,3 +69,6 @@ jest.mock("../dev/dev", () => {
67
69
  return null;
68
70
  });
69
71
  });
72
+
73
+ jest.mock("../open-in-browser");
74
+ (openInBrowser as jest.Mock).mockImplementation(mockOpenInBrowserForOAuthFlow);