wrangler 2.0.6 → 2.0.9

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 (46) hide show
  1. package/README.md +1 -1
  2. package/bin/wrangler.js +16 -4
  3. package/package.json +6 -4
  4. package/pages/functions/buildPlugin.ts +13 -0
  5. package/pages/functions/buildWorker.ts +13 -0
  6. package/src/__tests__/configuration.test.ts +132 -60
  7. package/src/__tests__/dev.test.tsx +168 -67
  8. package/src/__tests__/helpers/mock-dialogs.ts +41 -1
  9. package/src/__tests__/index.test.ts +25 -10
  10. package/src/__tests__/init.test.ts +252 -131
  11. package/src/__tests__/kv.test.ts +16 -16
  12. package/src/__tests__/package-manager.test.ts +154 -7
  13. package/src/__tests__/pages.test.ts +442 -38
  14. package/src/__tests__/parse.test.ts +5 -1
  15. package/src/__tests__/publish.test.ts +377 -84
  16. package/src/__tests__/secret.test.ts +4 -4
  17. package/src/__tests__/whoami.test.tsx +34 -0
  18. package/src/abort.d.ts +3 -0
  19. package/src/cfetch/index.ts +21 -4
  20. package/src/cfetch/internal.ts +20 -18
  21. package/src/config/config.ts +1 -1
  22. package/src/config/index.ts +162 -0
  23. package/src/config/validation.ts +77 -29
  24. package/src/create-worker-preview.ts +32 -22
  25. package/src/dev/dev.tsx +6 -16
  26. package/src/dev/remote.tsx +40 -16
  27. package/src/dialogs.tsx +48 -0
  28. package/src/durable.ts +102 -0
  29. package/src/index.tsx +291 -207
  30. package/src/inspect.ts +39 -0
  31. package/src/kv.ts +74 -25
  32. package/src/open-in-browser.ts +5 -12
  33. package/src/package-manager.ts +50 -3
  34. package/src/pages.tsx +218 -61
  35. package/src/parse.ts +21 -4
  36. package/src/proxy.ts +38 -22
  37. package/src/publish.ts +166 -108
  38. package/src/sites.tsx +8 -8
  39. package/src/user.tsx +12 -1
  40. package/src/whoami.tsx +3 -2
  41. package/src/worker.ts +2 -1
  42. package/src/zones.ts +73 -0
  43. package/templates/new-worker-scheduled.js +17 -0
  44. package/templates/new-worker-scheduled.ts +32 -0
  45. package/templates/new-worker.ts +16 -1
  46. package/wrangler-dist/cli.js +33066 -20052
@@ -3,7 +3,6 @@ import getPort from "get-port";
3
3
  import patchConsole from "patch-console";
4
4
  import dedent from "ts-dedent";
5
5
  import Dev from "../dev/dev";
6
- import { mockAccountId, mockApiToken } from "./helpers/mock-account-id";
7
6
  import { setMockResponse, unsetAllMocks } from "./helpers/mock-cfetch";
8
7
  import { mockConsoleMethods } from "./helpers/mock-console";
9
8
  import { runInTempDir } from "./helpers/run-in-tmp";
@@ -11,8 +10,6 @@ import { runWrangler } from "./helpers/run-wrangler";
11
10
  import writeWranglerToml from "./helpers/write-wrangler-toml";
12
11
 
13
12
  describe("wrangler dev", () => {
14
- mockAccountId();
15
- mockApiToken();
16
13
  runInTempDir();
17
14
  const std = mockConsoleMethods();
18
15
  afterEach(() => {
@@ -83,7 +80,7 @@ describe("wrangler dev", () => {
83
80
 
84
81
  expect(std.out).toMatchInlineSnapshot(`
85
82
  "
86
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
83
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
87
84
  `);
88
85
  expect(std.err).toMatchInlineSnapshot(`
89
86
  "X [ERROR] Missing entry-point: The entry-point should be specified via the command line (e.g. \`wrangler dev path/to/script\`) or the \`main\` config field.
@@ -152,10 +149,12 @@ describe("wrangler dev", () => {
152
149
  fs.writeFileSync("index.js", `export default {};`);
153
150
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
154
151
  await runWrangler("dev --host some-host.com");
155
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
156
- host: "some-host.com",
157
- id: "some-zone-id",
158
- });
152
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
153
+ expect.objectContaining({
154
+ host: "some-host.com",
155
+ zone: "some-zone-id",
156
+ })
157
+ );
159
158
  });
160
159
 
161
160
  it("should read wrangler.toml's dev.host", async () => {
@@ -168,9 +167,7 @@ describe("wrangler dev", () => {
168
167
  fs.writeFileSync("index.js", `export default {};`);
169
168
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
170
169
  await runWrangler("dev");
171
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
172
- "some-host.com"
173
- );
170
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
174
171
  });
175
172
 
176
173
  it("should read --route", async () => {
@@ -180,9 +177,7 @@ describe("wrangler dev", () => {
180
177
  fs.writeFileSync("index.js", `export default {};`);
181
178
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
182
179
  await runWrangler("dev --route http://some-host.com/some/path/*");
183
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
184
- "some-host.com"
185
- );
180
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
186
181
  });
187
182
 
188
183
  it("should read wrangler.toml's routes", async () => {
@@ -196,9 +191,7 @@ describe("wrangler dev", () => {
196
191
  fs.writeFileSync("index.js", `export default {};`);
197
192
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
198
193
  await runWrangler("dev");
199
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
200
- "some-host.com"
201
- );
194
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
202
195
  });
203
196
 
204
197
  it("should read wrangler.toml's environment specific routes", async () => {
@@ -220,9 +213,7 @@ describe("wrangler dev", () => {
220
213
  fs.writeFileSync("index.js", `export default {};`);
221
214
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
222
215
  await runWrangler("dev --env staging");
223
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
224
- "some-host.com"
225
- );
216
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
226
217
  });
227
218
 
228
219
  it("should strip leading `*` from given host when deducing a zone id", async () => {
@@ -233,9 +224,7 @@ describe("wrangler dev", () => {
233
224
  fs.writeFileSync("index.js", `export default {};`);
234
225
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
235
226
  await runWrangler("dev");
236
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
237
- "some-host.com"
238
- );
227
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
239
228
  });
240
229
 
241
230
  it("should strip leading `*.` from given host when deducing a zone id", async () => {
@@ -246,9 +235,7 @@ describe("wrangler dev", () => {
246
235
  fs.writeFileSync("index.js", `export default {};`);
247
236
  mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
248
237
  await runWrangler("dev");
249
- expect((Dev as jest.Mock).mock.calls[0][0].zone.host).toEqual(
250
- "some-host.com"
251
- );
238
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
252
239
  });
253
240
 
254
241
  it("should, when provided, use a configured zone_id", async () => {
@@ -260,10 +247,12 @@ describe("wrangler dev", () => {
260
247
  });
261
248
  fs.writeFileSync("index.js", `export default {};`);
262
249
  await runWrangler("dev");
263
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
264
- host: "some-domain.com",
265
- id: "some-zone-id",
266
- });
250
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
251
+ expect.objectContaining({
252
+ host: "some-domain.com",
253
+ zone: "some-zone-id",
254
+ })
255
+ );
267
256
  });
268
257
 
269
258
  it("should, when provided, use a zone_name to get a zone_id", async () => {
@@ -276,11 +265,13 @@ describe("wrangler dev", () => {
276
265
  fs.writeFileSync("index.js", `export default {};`);
277
266
  mockGetZones("some-zone.com", [{ id: "a-zone-id" }]);
278
267
  await runWrangler("dev");
279
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
280
- // note that it uses the provided zone_name as a host too
281
- host: "some-zone.com",
282
- id: "a-zone-id",
283
- });
268
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
269
+ expect.objectContaining({
270
+ // note that it uses the provided zone_name as a host too
271
+ host: "some-zone.com",
272
+ zone: "a-zone-id",
273
+ })
274
+ );
284
275
  });
285
276
 
286
277
  it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
@@ -292,10 +283,12 @@ describe("wrangler dev", () => {
292
283
  mockGetZones("222.333.some-host.com", []);
293
284
  mockGetZones("333.some-host.com", [{ id: "some-zone-id" }]);
294
285
  await runWrangler("dev --host 111.222.333.some-host.com");
295
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
296
- host: "111.222.333.some-host.com",
297
- id: "some-zone-id",
298
- });
286
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
287
+ expect.objectContaining({
288
+ host: "111.222.333.some-host.com",
289
+ zone: "some-zone-id",
290
+ })
291
+ );
299
292
  });
300
293
 
301
294
  it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
@@ -310,10 +303,12 @@ describe("wrangler dev", () => {
310
303
  routes: ["http://5.some-host.com/some/path/*"],
311
304
  });
312
305
  await runWrangler("dev");
313
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
314
- host: "5.some-host.com",
315
- id: "some-zone-id-5",
316
- });
306
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
307
+ expect.objectContaining({
308
+ host: "5.some-host.com",
309
+ zone: "some-zone-id-5",
310
+ })
311
+ );
317
312
  (Dev as jest.Mock).mockClear();
318
313
 
319
314
  // config.route
@@ -323,10 +318,12 @@ describe("wrangler dev", () => {
323
318
  route: "https://4.some-host.com/some/path/*",
324
319
  });
325
320
  await runWrangler("dev");
326
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
327
- host: "4.some-host.com",
328
- id: "some-zone-id-4",
329
- });
321
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
322
+ expect.objectContaining({
323
+ host: "4.some-host.com",
324
+ zone: "some-zone-id-4",
325
+ })
326
+ );
330
327
  (Dev as jest.Mock).mockClear();
331
328
 
332
329
  // --routes
@@ -336,10 +333,12 @@ describe("wrangler dev", () => {
336
333
  route: "https://4.some-host.com/some/path/*",
337
334
  });
338
335
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
339
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
340
- host: "3.some-host.com",
341
- id: "some-zone-id-3",
342
- });
336
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
337
+ expect.objectContaining({
338
+ host: "3.some-host.com",
339
+ zone: "some-zone-id-3",
340
+ })
341
+ );
343
342
  (Dev as jest.Mock).mockClear();
344
343
 
345
344
  // config.dev.host
@@ -352,10 +351,12 @@ describe("wrangler dev", () => {
352
351
  route: "4.some-host.com/some/path/*",
353
352
  });
354
353
  await runWrangler("dev --routes http://3.some-host.com/some/path/*");
355
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
356
- host: "2.some-host.com",
357
- id: "some-zone-id-2",
358
- });
354
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
355
+ expect.objectContaining({
356
+ host: "2.some-host.com",
357
+ zone: "some-zone-id-2",
358
+ })
359
+ );
359
360
  (Dev as jest.Mock).mockClear();
360
361
 
361
362
  // --host
@@ -370,10 +371,12 @@ describe("wrangler dev", () => {
370
371
  await runWrangler(
371
372
  "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
372
373
  );
373
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual({
374
- host: "1.some-host.com",
375
- id: "some-zone-id-1",
376
- });
374
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
375
+ expect.objectContaining({
376
+ host: "1.some-host.com",
377
+ zone: "some-zone-id-1",
378
+ })
379
+ );
377
380
  (Dev as jest.Mock).mockClear();
378
381
  });
379
382
 
@@ -467,7 +470,7 @@ describe("wrangler dev", () => {
467
470
  expect(std.out).toMatchInlineSnapshot(`
468
471
  "Running custom build: node -e \\"console.log('custom build');\\"
469
472
 
470
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
473
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
471
474
  `);
472
475
  expect(std.err).toMatchInlineSnapshot(`
473
476
  "X [ERROR] The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
@@ -675,7 +678,7 @@ describe("wrangler dev", () => {
675
678
  });
676
679
 
677
680
  describe("durable_objects", () => {
678
- it("should warn if there is one or more remote Durable Object", async () => {
681
+ it("should warn if there are remote Durable Objects, or missing migrations for local Durable Objects", async () => {
679
682
  writeWranglerToml({
680
683
  main: "index.js",
681
684
  durable_objects: {
@@ -698,9 +701,33 @@ describe("wrangler dev", () => {
698
701
  fs.writeFileSync("index.js", `export default {};`);
699
702
  await runWrangler("dev");
700
703
  expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
701
- expect(std.out).toMatchInlineSnapshot(`""`);
704
+ expect(std.out).toMatchInlineSnapshot(`
705
+ "Your worker has access to the following bindings:
706
+ - Durable Objects:
707
+ - NAME_1: CLASS_1
708
+ - NAME_2: CLASS_2 (defined in SCRIPT_A)
709
+ - NAME_3: CLASS_3
710
+ - NAME_4: CLASS_4 (defined in SCRIPT_B)"
711
+ `);
702
712
  expect(std.warn).toMatchInlineSnapshot(`
703
- "â–² [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed.
713
+ "â–² [WARNING] Processing wrangler.toml configuration:
714
+
715
+ - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS_1,
716
+ CLASS_3), but no [migrations] for them. This may not work as expected until you add a [migrations]
717
+ section to your wrangler.toml. Add this configuration to your wrangler.toml:
718
+
719
+ \`\`\`
720
+ [[migrations]]
721
+ tag = \\"v1\\" # Should be unique for each entry
722
+ new_classes = [\\"CLASS_1\\", \\"CLASS_3\\"]
723
+ \`\`\`
724
+
725
+ Refer to
726
+ https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml
727
+ for more details.
728
+
729
+
730
+ â–² [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed.
704
731
 
705
732
  Be aware that changes to the data stored in these Durable Objects will be permanent and affect the
706
733
  live instances.
@@ -755,9 +782,18 @@ describe("wrangler dev", () => {
755
782
  EMPTY: "",
756
783
  UNQUOTED: "unquoted value", // Note that whitespace is trimmed
757
784
  });
758
- expect(std.out).toMatchInlineSnapshot(
759
- `"Using vars defined in .dev.vars"`
760
- );
785
+ expect(std.out).toMatchInlineSnapshot(`
786
+ "Using vars defined in .dev.vars
787
+ Your worker has access to the following bindings:
788
+ - Vars:
789
+ - VAR_1: \\"(hidden)\\"
790
+ - VAR_2: \\"original value 2\\"
791
+ - VAR_3: \\"(hidden)\\"
792
+ - VAR_MULTI_LINE_1: \\"(hidden)\\"
793
+ - VAR_MULTI_LINE_2: \\"(hidden)\\"
794
+ - EMPTY: \\"(hidden)\\"
795
+ - UNQUOTED: \\"(hidden)\\""
796
+ `);
761
797
  expect(std.warn).toMatchInlineSnapshot(`""`);
762
798
  expect(std.err).toMatchInlineSnapshot(`""`);
763
799
  });
@@ -853,7 +889,10 @@ describe("wrangler dev", () => {
853
889
  Object {
854
890
  "debug": "",
855
891
  "err": "",
856
- "out": "",
892
+ "out": "Your worker has access to the following bindings:
893
+ - Services:
894
+ - WorkerA: A
895
+ - WorkerB: B - staging",
857
896
  "warn": "â–² [WARNING] Processing wrangler.toml configuration:
858
897
 
859
898
  - \\"services\\" fields are experimental and may change or break at any time.
@@ -866,6 +905,68 @@ describe("wrangler dev", () => {
866
905
  `);
867
906
  });
868
907
  });
908
+
909
+ describe("print bindings", () => {
910
+ it("should print bindings", async () => {
911
+ writeWranglerToml({
912
+ services: [
913
+ { binding: "WorkerA", service: "A" },
914
+ { binding: "WorkerB", service: "B", environment: "staging" },
915
+ ],
916
+ });
917
+ fs.writeFileSync("index.js", `export default {};`);
918
+ await runWrangler("dev index.js");
919
+ expect(std).toMatchInlineSnapshot(`
920
+ Object {
921
+ "debug": "",
922
+ "err": "",
923
+ "out": "Your worker has access to the following bindings:
924
+ - Services:
925
+ - WorkerA: A
926
+ - WorkerB: B - staging",
927
+ "warn": "â–² [WARNING] Processing wrangler.toml configuration:
928
+
929
+ - \\"services\\" fields are experimental and may change or break at any time.
930
+
931
+
932
+ â–² [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
933
+
934
+ ",
935
+ }
936
+ `);
937
+ });
938
+
939
+ it("should mask vars that were overriden in .dev.vars", async () => {
940
+ writeWranglerToml({
941
+ vars: {
942
+ variable: 123,
943
+ overriden: "original values",
944
+ },
945
+ });
946
+ fs.writeFileSync(
947
+ ".dev.vars",
948
+ `
949
+ SECRET = "A secret"
950
+ overriden = "overriden value"
951
+ `
952
+ );
953
+ fs.writeFileSync("index.js", `export default {};`);
954
+ await runWrangler("dev index.js");
955
+ expect(std).toMatchInlineSnapshot(`
956
+ Object {
957
+ "debug": "",
958
+ "err": "",
959
+ "out": "Using vars defined in .dev.vars
960
+ Your worker has access to the following bindings:
961
+ - Vars:
962
+ - variable: \\"123\\"
963
+ - overriden: \\"(hidden)\\"
964
+ - SECRET: \\"(hidden)\\"",
965
+ "warn": "",
966
+ }
967
+ `);
968
+ });
969
+ });
869
970
  });
870
971
 
871
972
  function mockGetZones(domain: string, zones: { id: string }[] = []) {
@@ -1,4 +1,4 @@
1
- import { confirm, prompt } from "../../dialogs";
1
+ import { confirm, prompt, select } from "../../dialogs";
2
2
  import { normalizeSlashes } from "./mock-console";
3
3
 
4
4
  /**
@@ -88,3 +88,43 @@ export function clearPromptMocks() {
88
88
  );
89
89
  });
90
90
  }
91
+
92
+ /**
93
+ * The expected values for a select request.
94
+ */
95
+ export interface SelectExpectation {
96
+ /** The text expected to be seen in the select dialog. */
97
+ text: string;
98
+ /** The mock response send back from the select dialog. */
99
+ result: string;
100
+ }
101
+
102
+ /**
103
+ * Mock the implementation of `select()` that will respond with configured results
104
+ * for configured select text messages.
105
+ *
106
+ * If there is a call to `select()` that does not match any of the expectations
107
+ * then an error is thrown.
108
+ */
109
+ export function mockSelect(...expectations: SelectExpectation[]) {
110
+ (select as jest.Mock).mockImplementation((text: string) => {
111
+ for (const { text: expectedText, result } of expectations) {
112
+ if (normalizeSlashes(text) === normalizeSlashes(expectedText)) {
113
+ return Promise.resolve(result);
114
+ }
115
+ }
116
+ throw new Error(`Unexpected select message: ${text}`);
117
+ });
118
+ }
119
+
120
+ export function clearSelectMocks() {
121
+ (select as jest.Mock).mockReset();
122
+ // Because select was originally a spy, calling mockReset will simply reset
123
+ // it as a function with no return value (!), so we need to additionally reset
124
+ // the mock implementation to the one that throws (from jest.setup.js).
125
+ (select as jest.Mock).mockImplementation((text: string) => {
126
+ throw new Error(
127
+ `Unexpected call to \`select("${text}")\`.\nYou should use \`mockSelect()\` to mock calls to \`select()\` with expectations. Search the codebase for \`mockSelect\` to learn more.`
128
+ );
129
+ });
130
+ }
@@ -2,6 +2,8 @@ import { getPackageManager } from "../package-manager";
2
2
  import { mockConsoleMethods } from "./helpers/mock-console";
3
3
  import { runInTempDir } from "./helpers/run-in-tmp";
4
4
  import { runWrangler } from "./helpers/run-wrangler";
5
+ import { writeWorkerSource } from "./helpers/write-worker-source";
6
+ import writeWranglerToml from "./helpers/write-wrangler-toml";
5
7
  import type { PackageManager } from "../package-manager";
6
8
 
7
9
  describe("wrangler", () => {
@@ -113,9 +115,6 @@ describe("wrangler", () => {
113
115
  });
114
116
 
115
117
  describe("subcommand implicit help ran on incomplete command execution", () => {
116
- function endEventLoop() {
117
- return new Promise((resolve) => setImmediate(resolve));
118
- }
119
118
  it("no subcommand for 'secret' should display a list of available subcommands", async () => {
120
119
  await runWrangler("secret");
121
120
  await endEventLoop();
@@ -195,6 +194,7 @@ describe("wrangler", () => {
195
194
  -v, --version Show version number [boolean]"
196
195
  `);
197
196
  });
197
+
198
198
  it("no subcommand 'r2' should display a list of available subcommands", async () => {
199
199
  await runWrangler("r2");
200
200
  await endEventLoop();
@@ -213,6 +213,7 @@ describe("wrangler", () => {
213
213
  `);
214
214
  });
215
215
  });
216
+
216
217
  describe("Deprecated commands", () => {
217
218
  it("should print a deprecation message for 'generate'", async () => {
218
219
  await runWrangler("generate").catch((err) => {
@@ -229,13 +230,27 @@ describe("wrangler", () => {
229
230
  `);
230
231
  });
231
232
  });
232
- it("should print a deprecation message for 'build'", async () => {
233
- await runWrangler("build").catch((err) => {
234
- expect(err.message).toMatchInlineSnapshot(`
235
- "Deprecation:
236
- \`wrangler build\` has been deprecated, please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for alternatives"
237
- `);
238
- });
233
+ });
234
+
235
+ it("should print a deprecation message for 'build' and then try to run `publish --dry-run --outdir`", async () => {
236
+ writeWranglerToml({
237
+ main: "index.js",
239
238
  });
239
+ writeWorkerSource();
240
+ await runWrangler("build");
241
+ await endEventLoop();
242
+ expect(std.out).toMatchInlineSnapshot(`
243
+ "â–² [WARNING] Deprecation: \`wrangler build\` has been deprecated.
244
+
245
+ Please refer to https://developers.cloudflare.com/workers/wrangler/migration/deprecations/#build for more information.
246
+ Attempting to run \`wrangler publish --dry-run --outdir=dist\` for you instead:
247
+
248
+
249
+ --dry-run: exiting now."
250
+ `);
240
251
  });
241
252
  });
253
+
254
+ function endEventLoop() {
255
+ return new Promise((resolve) => setImmediate(resolve));
256
+ }