wrangler 2.0.12 → 2.0.16

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 (149) hide show
  1. package/README.md +7 -1
  2. package/bin/wrangler.js +111 -57
  3. package/miniflare-dist/index.mjs +9 -2
  4. package/package.json +156 -154
  5. package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
  6. package/src/__tests__/config-cache.test.ts +30 -24
  7. package/src/__tests__/configuration.test.ts +3935 -3476
  8. package/src/__tests__/dev.test.tsx +1128 -979
  9. package/src/__tests__/guess-worker-format.test.ts +68 -68
  10. package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
  11. package/src/__tests__/helpers/faye-websocket.d.ts +4 -4
  12. package/src/__tests__/helpers/mock-account-id.ts +24 -24
  13. package/src/__tests__/helpers/mock-bin.ts +20 -20
  14. package/src/__tests__/helpers/mock-cfetch.ts +92 -92
  15. package/src/__tests__/helpers/mock-console.ts +49 -39
  16. package/src/__tests__/helpers/mock-dialogs.ts +94 -71
  17. package/src/__tests__/helpers/mock-http-server.ts +30 -30
  18. package/src/__tests__/helpers/mock-istty.ts +65 -18
  19. package/src/__tests__/helpers/mock-kv.ts +26 -26
  20. package/src/__tests__/helpers/mock-oauth-flow.ts +223 -228
  21. package/src/__tests__/helpers/mock-process.ts +39 -0
  22. package/src/__tests__/helpers/mock-stdin.ts +82 -77
  23. package/src/__tests__/helpers/mock-web-socket.ts +21 -21
  24. package/src/__tests__/helpers/run-in-tmp.ts +27 -27
  25. package/src/__tests__/helpers/run-wrangler.ts +8 -8
  26. package/src/__tests__/helpers/write-worker-source.ts +16 -16
  27. package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
  28. package/src/__tests__/https-options.test.ts +104 -104
  29. package/src/__tests__/index.test.ts +239 -234
  30. package/src/__tests__/init.test.ts +1605 -1250
  31. package/src/__tests__/jest.setup.ts +63 -33
  32. package/src/__tests__/kv.test.ts +1128 -1011
  33. package/src/__tests__/logger.test.ts +100 -74
  34. package/src/__tests__/package-manager.test.ts +303 -303
  35. package/src/__tests__/pages.test.ts +1152 -652
  36. package/src/__tests__/parse.test.ts +252 -252
  37. package/src/__tests__/publish.test.ts +6371 -5622
  38. package/src/__tests__/pubsub.test.ts +367 -0
  39. package/src/__tests__/r2.test.ts +133 -133
  40. package/src/__tests__/route.test.ts +18 -18
  41. package/src/__tests__/secret.test.ts +382 -377
  42. package/src/__tests__/tail.test.ts +530 -530
  43. package/src/__tests__/user.test.ts +123 -111
  44. package/src/__tests__/whoami.test.tsx +198 -117
  45. package/src/__tests__/worker-namespace.test.ts +327 -0
  46. package/src/abort.d.ts +1 -1
  47. package/src/api/dev.ts +49 -0
  48. package/src/api/index.ts +1 -0
  49. package/src/bundle-reporter.tsx +29 -0
  50. package/src/bundle.ts +157 -149
  51. package/src/cfetch/index.ts +80 -80
  52. package/src/cfetch/internal.ts +90 -83
  53. package/src/cli.ts +21 -7
  54. package/src/config/config.ts +204 -195
  55. package/src/config/diagnostics.ts +61 -61
  56. package/src/config/environment.ts +390 -357
  57. package/src/config/index.ts +206 -193
  58. package/src/config/validation-helpers.ts +366 -366
  59. package/src/config/validation.ts +1573 -1376
  60. package/src/config-cache.ts +79 -41
  61. package/src/create-worker-preview.ts +206 -136
  62. package/src/create-worker-upload-form.ts +247 -238
  63. package/src/dev/dev-vars.ts +13 -13
  64. package/src/dev/dev.tsx +329 -307
  65. package/src/dev/local.tsx +304 -275
  66. package/src/dev/remote.tsx +366 -224
  67. package/src/dev/use-esbuild.ts +126 -91
  68. package/src/dev.tsx +538 -0
  69. package/src/dialogs.tsx +97 -97
  70. package/src/durable.ts +87 -87
  71. package/src/entry.ts +234 -228
  72. package/src/environment-variables.ts +23 -23
  73. package/src/errors.ts +6 -6
  74. package/src/generate.ts +33 -0
  75. package/src/git-client.ts +42 -0
  76. package/src/https-options.ts +79 -79
  77. package/src/index.tsx +1775 -2763
  78. package/src/init.ts +549 -0
  79. package/src/inspect.ts +593 -593
  80. package/src/intl-polyfill.d.ts +123 -123
  81. package/src/is-interactive.ts +12 -0
  82. package/src/kv.ts +277 -277
  83. package/src/logger.ts +46 -39
  84. package/src/miniflare-cli/enum-keys.ts +8 -8
  85. package/src/miniflare-cli/index.ts +42 -31
  86. package/src/miniflare-cli/request-context.ts +18 -18
  87. package/src/module-collection.ts +212 -212
  88. package/src/open-in-browser.ts +4 -6
  89. package/src/package-manager.ts +123 -123
  90. package/src/pages/build.tsx +202 -0
  91. package/src/pages/constants.ts +7 -0
  92. package/src/pages/deployments.tsx +101 -0
  93. package/src/pages/dev.tsx +964 -0
  94. package/src/pages/functions/buildPlugin.ts +105 -0
  95. package/src/pages/functions/buildWorker.ts +151 -0
  96. package/{pages → src/pages}/functions/filepath-routing.test.ts +113 -113
  97. package/src/pages/functions/filepath-routing.ts +189 -0
  98. package/src/pages/functions/identifiers.ts +78 -0
  99. package/src/pages/functions/routes.ts +151 -0
  100. package/src/pages/index.tsx +84 -0
  101. package/src/pages/projects.tsx +157 -0
  102. package/src/pages/publish.tsx +335 -0
  103. package/src/pages/types.ts +40 -0
  104. package/src/pages/upload.tsx +384 -0
  105. package/src/pages/utils.ts +12 -0
  106. package/src/parse.ts +202 -138
  107. package/src/paths.ts +6 -6
  108. package/src/preview.ts +31 -0
  109. package/src/proxy.ts +400 -402
  110. package/src/publish.ts +667 -621
  111. package/src/pubsub/index.ts +286 -0
  112. package/src/pubsub/pubsub-commands.tsx +577 -0
  113. package/src/r2.ts +19 -19
  114. package/src/selfsigned.d.ts +23 -23
  115. package/src/sites.tsx +271 -225
  116. package/src/tail/filters.ts +108 -108
  117. package/src/tail/index.ts +217 -217
  118. package/src/tail/printing.ts +45 -45
  119. package/src/update-check.ts +11 -11
  120. package/src/user/choose-account.tsx +60 -0
  121. package/src/user/env-vars.ts +46 -0
  122. package/src/user/generate-auth-url.ts +33 -0
  123. package/src/user/generate-random-state.ts +16 -0
  124. package/src/user/index.ts +3 -0
  125. package/src/user/user.tsx +1161 -0
  126. package/src/whoami.tsx +61 -42
  127. package/src/worker-namespace.ts +190 -0
  128. package/src/worker.ts +110 -100
  129. package/src/zones.ts +39 -36
  130. package/templates/checked-fetch.js +17 -0
  131. package/templates/new-worker-scheduled.js +3 -3
  132. package/templates/new-worker-scheduled.ts +15 -15
  133. package/templates/new-worker.js +3 -3
  134. package/templates/new-worker.ts +15 -15
  135. package/templates/no-op-worker.js +10 -0
  136. package/templates/pages-template-plugin.ts +155 -0
  137. package/templates/pages-template-worker.ts +161 -0
  138. package/templates/static-asset-facade.js +31 -31
  139. package/templates/tsconfig.json +95 -95
  140. package/wrangler-dist/cli.js +55383 -54138
  141. package/pages/functions/buildPlugin.ts +0 -105
  142. package/pages/functions/buildWorker.ts +0 -151
  143. package/pages/functions/filepath-routing.ts +0 -189
  144. package/pages/functions/identifiers.ts +0 -78
  145. package/pages/functions/routes.ts +0 -156
  146. package/pages/functions/template-plugin.ts +0 -147
  147. package/pages/functions/template-worker.ts +0 -143
  148. package/src/pages.tsx +0 -2093
  149. package/src/user.tsx +0 -1214
@@ -10,742 +10,803 @@ import { runWrangler } from "./helpers/run-wrangler";
10
10
  import writeWranglerToml from "./helpers/write-wrangler-toml";
11
11
 
12
12
  describe("wrangler dev", () => {
13
- runInTempDir();
14
- const std = mockConsoleMethods();
15
- afterEach(() => {
16
- (Dev as jest.Mock).mockClear();
17
- patchConsole(() => {});
18
- unsetAllMocks();
19
- });
20
-
21
- describe("compatibility-date", () => {
22
- it("should not warn if there is no wrangler.toml and no compatibility-date specified", async () => {
23
- fs.writeFileSync("index.js", `export default {};`);
24
- await runWrangler("dev index.js");
25
- expect(std.out).toMatchInlineSnapshot(`""`);
26
- expect(std.warn).toMatchInlineSnapshot(`""`);
27
- expect(std.err).toMatchInlineSnapshot(`""`);
28
- });
29
-
30
- it("should warn if there is a wrangler.toml but no compatibility-date", async () => {
31
- writeWranglerToml({
32
- main: "index.js",
33
- compatibility_date: undefined,
34
- });
35
- fs.writeFileSync("index.js", `export default {};`);
36
- await runWrangler("dev");
37
- const currentDate = new Date().toISOString().substring(0, 10);
38
- expect(std.out).toMatchInlineSnapshot(`""`);
39
- expect(std.warn.replaceAll(currentDate, "<current-date>"))
40
- .toMatchInlineSnapshot(`
41
- "▲ [WARNING] No compatibility_date was specified. Using today's date: <current-date>.
42
-
43
- Add one to your wrangler.toml file:
44
- \`\`\`
45
- compatibility_date = \\"<current-date>\\"
46
- \`\`\`
47
- or pass it in your terminal:
48
- \`\`\`
49
- --compatibility-date=<current-date>
50
- \`\`\`
51
- See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.
52
-
53
- "
54
- `);
55
- expect(std.err).toMatchInlineSnapshot(`""`);
56
- });
57
-
58
- it("should not warn if there is a wrangler.toml but compatibility-date is specified at the command line", async () => {
59
- writeWranglerToml({
60
- main: "index.js",
61
- compatibility_date: undefined,
62
- });
63
- fs.writeFileSync("index.js", `export default {};`);
64
- await runWrangler("dev --compatibility-date=2020-01-01");
65
- expect(std.out).toMatchInlineSnapshot(`""`);
66
- expect(std.warn).toMatchInlineSnapshot(`""`);
67
- expect(std.err).toMatchInlineSnapshot(`""`);
68
- });
69
- });
70
-
71
- describe("entry-points", () => {
72
- it("should error if there is no entry-point specified", async () => {
73
- writeWranglerToml();
74
-
75
- await expect(
76
- runWrangler("dev")
77
- ).rejects.toThrowErrorMatchingInlineSnapshot(
78
- `"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."`
79
- );
80
-
81
- expect(std.out).toMatchInlineSnapshot(`
82
- "
83
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
84
- `);
85
- expect(std.err).toMatchInlineSnapshot(`
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.
87
-
88
- "
89
- `);
90
- });
91
-
92
- it("should use `main` from the top-level environment", async () => {
93
- writeWranglerToml({
94
- main: "index.js",
95
- });
96
- fs.writeFileSync("index.js", `export default {};`);
97
- await runWrangler("dev");
98
- expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
99
- /index\.js$/
100
- );
101
- expect(std.out).toMatchInlineSnapshot(`""`);
102
- expect(std.warn).toMatchInlineSnapshot(`""`);
103
- expect(std.err).toMatchInlineSnapshot(`""`);
104
- });
105
-
106
- it("should use `main` from a named environment", async () => {
107
- writeWranglerToml({
108
- env: {
109
- ENV1: {
110
- main: "index.js",
111
- },
112
- },
113
- });
114
- fs.writeFileSync("index.js", `export default {};`);
115
- await runWrangler("dev --env=ENV1");
116
- expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
117
- /index\.js$/
118
- );
119
- expect(std.out).toMatchInlineSnapshot(`""`);
120
- expect(std.warn).toMatchInlineSnapshot(`""`);
121
- expect(std.err).toMatchInlineSnapshot(`""`);
122
- });
123
-
124
- it("should use `main` from a named environment, rather than the top-level", async () => {
125
- writeWranglerToml({
126
- main: "other.js",
127
- env: {
128
- ENV1: {
129
- main: "index.js",
130
- },
131
- },
132
- });
133
- fs.writeFileSync("index.js", `export default {};`);
134
- await runWrangler("dev --env=ENV1");
135
- expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
136
- /index\.js$/
137
- );
138
- expect(std.out).toMatchInlineSnapshot(`""`);
139
- expect(std.warn).toMatchInlineSnapshot(`""`);
140
- expect(std.err).toMatchInlineSnapshot(`""`);
141
- });
142
- });
143
-
144
- describe("host", () => {
145
- it("should resolve a host to its zone", async () => {
146
- writeWranglerToml({
147
- main: "index.js",
148
- });
149
- fs.writeFileSync("index.js", `export default {};`);
150
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
151
- await runWrangler("dev --host some-host.com");
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
- );
158
- });
159
-
160
- it("should read wrangler.toml's dev.host", async () => {
161
- writeWranglerToml({
162
- main: "index.js",
163
- dev: {
164
- host: "some-host.com",
165
- },
166
- });
167
- fs.writeFileSync("index.js", `export default {};`);
168
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
169
- await runWrangler("dev");
170
- expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
171
- });
172
-
173
- it("should read --route", async () => {
174
- writeWranglerToml({
175
- main: "index.js",
176
- });
177
- fs.writeFileSync("index.js", `export default {};`);
178
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
179
- await runWrangler("dev --route http://some-host.com/some/path/*");
180
- expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
181
- });
182
-
183
- it("should read wrangler.toml's routes", async () => {
184
- writeWranglerToml({
185
- main: "index.js",
186
- routes: [
187
- "http://some-host.com/some/path/*",
188
- "http://some-other-host.com/path/*",
189
- ],
190
- });
191
- fs.writeFileSync("index.js", `export default {};`);
192
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
193
- await runWrangler("dev");
194
- expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
195
- });
196
-
197
- it("should read wrangler.toml's environment specific routes", async () => {
198
- writeWranglerToml({
199
- main: "index.js",
200
- routes: [
201
- "http://a-host.com/some/path/*",
202
- "http://another-host.com/path/*",
203
- ],
204
- env: {
205
- staging: {
206
- routes: [
207
- "http://some-host.com/some/path/*",
208
- "http://some-other-host.com/path/*",
209
- ],
210
- },
211
- },
212
- });
213
- fs.writeFileSync("index.js", `export default {};`);
214
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
215
- await runWrangler("dev --env staging");
216
- expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
217
- });
218
-
219
- it("should strip leading `*` from given host when deducing a zone id", async () => {
220
- writeWranglerToml({
221
- main: "index.js",
222
- route: "*some-host.com/some/path/*",
223
- });
224
- fs.writeFileSync("index.js", `export default {};`);
225
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
226
- await runWrangler("dev");
227
- expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
228
- });
229
-
230
- it("should strip leading `*.` from given host when deducing a zone id", async () => {
231
- writeWranglerToml({
232
- main: "index.js",
233
- route: "*.some-host.com/some/path/*",
234
- });
235
- fs.writeFileSync("index.js", `export default {};`);
236
- mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
237
- await runWrangler("dev");
238
- expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
239
- });
240
-
241
- it("should, when provided, use a configured zone_id", async () => {
242
- writeWranglerToml({
243
- main: "index.js",
244
- routes: [
245
- { pattern: "https://some-domain.com/*", zone_id: "some-zone-id" },
246
- ],
247
- });
248
- fs.writeFileSync("index.js", `export default {};`);
249
- await runWrangler("dev");
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
- );
256
- });
257
-
258
- it("should, when provided, use a zone_name to get a zone_id", async () => {
259
- writeWranglerToml({
260
- main: "index.js",
261
- routes: [
262
- { pattern: "https://some-domain.com/*", zone_name: "some-zone.com" },
263
- ],
264
- });
265
- fs.writeFileSync("index.js", `export default {};`);
266
- mockGetZones("some-zone.com", [{ id: "a-zone-id" }]);
267
- await runWrangler("dev");
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
- );
275
- });
276
-
277
- it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
278
- writeWranglerToml({
279
- main: "index.js",
280
- });
281
- fs.writeFileSync("index.js", `export default {};`);
282
- mockGetZones("111.222.333.some-host.com", []);
283
- mockGetZones("222.333.some-host.com", []);
284
- mockGetZones("333.some-host.com", [{ id: "some-zone-id" }]);
285
- await runWrangler("dev --host 111.222.333.some-host.com");
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
- );
292
- });
293
-
294
- it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
295
- // This test might seem like it's testing implementation details, but let's be specific and consider it a spec
296
-
297
- fs.writeFileSync("index.js", `export default {};`);
298
-
299
- // config.routes
300
- mockGetZones("5.some-host.com", [{ id: "some-zone-id-5" }]);
301
- writeWranglerToml({
302
- main: "index.js",
303
- routes: ["http://5.some-host.com/some/path/*"],
304
- });
305
- await runWrangler("dev");
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
- );
312
- (Dev as jest.Mock).mockClear();
313
-
314
- // config.route
315
- mockGetZones("4.some-host.com", [{ id: "some-zone-id-4" }]);
316
- writeWranglerToml({
317
- main: "index.js",
318
- route: "https://4.some-host.com/some/path/*",
319
- });
320
- await runWrangler("dev");
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
- );
327
- (Dev as jest.Mock).mockClear();
328
-
329
- // --routes
330
- mockGetZones("3.some-host.com", [{ id: "some-zone-id-3" }]);
331
- writeWranglerToml({
332
- main: "index.js",
333
- route: "https://4.some-host.com/some/path/*",
334
- });
335
- await runWrangler("dev --routes http://3.some-host.com/some/path/*");
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
- );
342
- (Dev as jest.Mock).mockClear();
343
-
344
- // config.dev.host
345
- mockGetZones("2.some-host.com", [{ id: "some-zone-id-2" }]);
346
- writeWranglerToml({
347
- main: "index.js",
348
- dev: {
349
- host: `2.some-host.com`,
350
- },
351
- route: "4.some-host.com/some/path/*",
352
- });
353
- await runWrangler("dev --routes http://3.some-host.com/some/path/*");
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
- );
360
- (Dev as jest.Mock).mockClear();
361
-
362
- // --host
363
- mockGetZones("1.some-host.com", [{ id: "some-zone-id-1" }]);
364
- writeWranglerToml({
365
- main: "index.js",
366
- dev: {
367
- host: `2.some-host.com`,
368
- },
369
- route: "4.some-host.com/some/path/*",
370
- });
371
- await runWrangler(
372
- "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
373
- );
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
- );
380
- (Dev as jest.Mock).mockClear();
381
- });
382
-
383
- it("should error if a host can't resolve to a zone", async () => {
384
- writeWranglerToml({
385
- main: "index.js",
386
- });
387
- fs.writeFileSync("index.js", `export default {};`);
388
- mockGetZones("some-host.com", []);
389
- await expect(
390
- runWrangler("dev --host some-host.com")
391
- ).rejects.toThrowErrorMatchingInlineSnapshot(
392
- `"Could not find zone for some-host.com"`
393
- );
394
- });
395
-
396
- it("should not try to resolve a zone when starting in local mode", async () => {
397
- writeWranglerToml({
398
- main: "index.js",
399
- });
400
- fs.writeFileSync("index.js", `export default {};`);
401
- await runWrangler("dev --host some-host.com --local");
402
- expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual(undefined);
403
- });
404
- });
405
-
406
- describe("custom builds", () => {
407
- it("should run a custom build before starting `dev`", async () => {
408
- writeWranglerToml({
409
- build: {
410
- command: `node -e "console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')"`,
411
- },
412
- });
413
-
414
- await runWrangler("dev index.js");
415
-
416
- expect(fs.readFileSync("index.js", "utf-8")).toMatchInlineSnapshot(
417
- `"export default { fetch(){ return new Response(123) } }"`
418
- );
419
-
420
- // and the command would pass through
421
- expect((Dev as jest.Mock).mock.calls[0][0].build).toEqual({
422
- command:
423
- "node -e \"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\"",
424
- cwd: undefined,
425
- watch_dir: "src",
426
- });
427
- expect(std.out).toMatchInlineSnapshot(
428
- `"Running custom build: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\""`
429
- );
430
- expect(std.err).toMatchInlineSnapshot(`""`);
431
- expect(std.warn).toMatchInlineSnapshot(`""`);
432
- });
433
-
434
- if (process.platform !== "win32") {
435
- it("should run a custom build of multiple steps combined by && before starting `dev`", async () => {
436
- writeWranglerToml({
437
- build: {
438
- command: `echo "custom build" && echo "export default { fetch(){ return new Response(123) } }" > index.js`,
439
- },
440
- });
441
-
442
- await runWrangler("dev index.js");
443
-
444
- expect(fs.readFileSync("index.js", "utf-8")).toMatchInlineSnapshot(`
445
- "export default { fetch(){ return new Response(123) } }
446
- "
447
- `);
448
-
449
- expect(std.out).toMatchInlineSnapshot(
450
- `"Running custom build: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js"`
451
- );
452
- expect(std.err).toMatchInlineSnapshot(`""`);
453
- expect(std.warn).toMatchInlineSnapshot(`""`);
454
- });
455
- }
456
-
457
- it("should throw an error if the entry doesn't exist after the build finishes", async () => {
458
- writeWranglerToml({
459
- main: "index.js",
460
- build: {
461
- command: `node -e "console.log('custom build');"`,
462
- },
463
- });
464
-
465
- await expect(runWrangler("dev")).rejects
466
- .toThrowErrorMatchingInlineSnapshot(`
13
+ runInTempDir();
14
+ const std = mockConsoleMethods();
15
+ afterEach(() => {
16
+ (Dev as jest.Mock).mockClear();
17
+ patchConsole(() => {});
18
+ unsetAllMocks();
19
+ });
20
+
21
+ describe("compatibility-date", () => {
22
+ it("should not warn if there is no wrangler.toml and no compatibility-date specified", async () => {
23
+ fs.writeFileSync("index.js", `export default {};`);
24
+ await runWrangler("dev index.js");
25
+ expect(std.out).toMatchInlineSnapshot(`""`);
26
+ expect(std.warn).toMatchInlineSnapshot(`""`);
27
+ expect(std.err).toMatchInlineSnapshot(`""`);
28
+ });
29
+
30
+ it("should warn if there is a wrangler.toml but no compatibility-date", async () => {
31
+ writeWranglerToml({
32
+ main: "index.js",
33
+ compatibility_date: undefined,
34
+ });
35
+ fs.writeFileSync("index.js", `export default {};`);
36
+ await runWrangler("dev");
37
+ const currentDate = new Date().toISOString().substring(0, 10);
38
+ expect(std.out).toMatchInlineSnapshot(`""`);
39
+ expect(std.warn.replaceAll(currentDate, "<current-date>"))
40
+ .toMatchInlineSnapshot(`
41
+ "▲ [WARNING] No compatibility_date was specified. Using today's date: <current-date>.
42
+
43
+ Add one to your wrangler.toml file:
44
+ \`\`\`
45
+ compatibility_date = \\"<current-date>\\"
46
+ \`\`\`
47
+ or pass it in your terminal:
48
+ \`\`\`
49
+ --compatibility-date=<current-date>
50
+ \`\`\`
51
+ See https://developers.cloudflare.com/workers/platform/compatibility-dates for more information.
52
+
53
+ "
54
+ `);
55
+ expect(std.err).toMatchInlineSnapshot(`""`);
56
+ });
57
+
58
+ it("should not warn if there is a wrangler.toml but compatibility-date is specified at the command line", async () => {
59
+ writeWranglerToml({
60
+ main: "index.js",
61
+ compatibility_date: undefined,
62
+ });
63
+ fs.writeFileSync("index.js", `export default {};`);
64
+ await runWrangler("dev --compatibility-date=2020-01-01");
65
+ expect(std.out).toMatchInlineSnapshot(`""`);
66
+ expect(std.warn).toMatchInlineSnapshot(`""`);
67
+ expect(std.err).toMatchInlineSnapshot(`""`);
68
+ });
69
+ });
70
+
71
+ describe("entry-points", () => {
72
+ it("should error if there is no entry-point specified", async () => {
73
+ writeWranglerToml();
74
+
75
+ await expect(
76
+ runWrangler("dev")
77
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
78
+ `"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."`
79
+ );
80
+
81
+ expect(std.out).toMatchInlineSnapshot(`
82
+ "
83
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
84
+ `);
85
+ expect(std.err).toMatchInlineSnapshot(`
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.
87
+
88
+ "
89
+ `);
90
+ });
91
+
92
+ it("should use `main` from the top-level environment", async () => {
93
+ writeWranglerToml({
94
+ main: "index.js",
95
+ });
96
+ fs.writeFileSync("index.js", `export default {};`);
97
+ await runWrangler("dev");
98
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
99
+ /index\.js$/
100
+ );
101
+ expect(std.out).toMatchInlineSnapshot(`""`);
102
+ expect(std.warn).toMatchInlineSnapshot(`""`);
103
+ expect(std.err).toMatchInlineSnapshot(`""`);
104
+ });
105
+
106
+ it("should use `main` from a named environment", async () => {
107
+ writeWranglerToml({
108
+ env: {
109
+ ENV1: {
110
+ main: "index.js",
111
+ },
112
+ },
113
+ });
114
+ fs.writeFileSync("index.js", `export default {};`);
115
+ await runWrangler("dev --env=ENV1");
116
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
117
+ /index\.js$/
118
+ );
119
+ expect(std.out).toMatchInlineSnapshot(`""`);
120
+ expect(std.warn).toMatchInlineSnapshot(`""`);
121
+ expect(std.err).toMatchInlineSnapshot(`""`);
122
+ });
123
+
124
+ it("should use `main` from a named environment, rather than the top-level", async () => {
125
+ writeWranglerToml({
126
+ main: "other.js",
127
+ env: {
128
+ ENV1: {
129
+ main: "index.js",
130
+ },
131
+ },
132
+ });
133
+ fs.writeFileSync("index.js", `export default {};`);
134
+ await runWrangler("dev --env=ENV1");
135
+ expect((Dev as jest.Mock).mock.calls[0][0].entry.file).toMatch(
136
+ /index\.js$/
137
+ );
138
+ expect(std.out).toMatchInlineSnapshot(`""`);
139
+ expect(std.warn).toMatchInlineSnapshot(`""`);
140
+ expect(std.err).toMatchInlineSnapshot(`""`);
141
+ });
142
+ });
143
+
144
+ describe("routes", () => {
145
+ it("should pass routes to <Dev/>", async () => {
146
+ fs.writeFileSync("index.js", `export default {};`);
147
+
148
+ // config.routes
149
+ mockGetZones("5.some-host.com", [{ id: "some-zone-id-5" }]);
150
+ writeWranglerToml({
151
+ main: "index.js",
152
+ routes: ["http://5.some-host.com/some/path/*"],
153
+ });
154
+ await runWrangler("dev");
155
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
156
+ expect.objectContaining({
157
+ host: "5.some-host.com",
158
+ zone: "some-zone-id-5",
159
+ routes: ["http://5.some-host.com/some/path/*"],
160
+ })
161
+ );
162
+ });
163
+ });
164
+
165
+ describe("host", () => {
166
+ it("should resolve a host to its zone", async () => {
167
+ writeWranglerToml({
168
+ main: "index.js",
169
+ });
170
+ fs.writeFileSync("index.js", `export default {};`);
171
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
172
+ await runWrangler("dev --host some-host.com");
173
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
174
+ expect.objectContaining({
175
+ host: "some-host.com",
176
+ zone: "some-zone-id",
177
+ })
178
+ );
179
+ });
180
+
181
+ it("should read wrangler.toml's dev.host", async () => {
182
+ writeWranglerToml({
183
+ main: "index.js",
184
+ dev: {
185
+ host: "some-host.com",
186
+ },
187
+ });
188
+ fs.writeFileSync("index.js", `export default {};`);
189
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
190
+ await runWrangler("dev");
191
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
192
+ });
193
+
194
+ it("should read --route", async () => {
195
+ writeWranglerToml({
196
+ main: "index.js",
197
+ });
198
+ fs.writeFileSync("index.js", `export default {};`);
199
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
200
+ await runWrangler("dev --route http://some-host.com/some/path/*");
201
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
202
+ });
203
+
204
+ it("should read wrangler.toml's routes", async () => {
205
+ writeWranglerToml({
206
+ main: "index.js",
207
+ routes: [
208
+ "http://some-host.com/some/path/*",
209
+ "http://some-other-host.com/path/*",
210
+ ],
211
+ });
212
+ fs.writeFileSync("index.js", `export default {};`);
213
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
214
+ await runWrangler("dev");
215
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
216
+ });
217
+
218
+ it("should read wrangler.toml's environment specific routes", async () => {
219
+ writeWranglerToml({
220
+ main: "index.js",
221
+ routes: [
222
+ "http://a-host.com/some/path/*",
223
+ "http://another-host.com/path/*",
224
+ ],
225
+ env: {
226
+ staging: {
227
+ routes: [
228
+ "http://some-host.com/some/path/*",
229
+ "http://some-other-host.com/path/*",
230
+ ],
231
+ },
232
+ },
233
+ });
234
+ fs.writeFileSync("index.js", `export default {};`);
235
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
236
+ await runWrangler("dev --env staging");
237
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
238
+ });
239
+
240
+ it("should strip leading `*` from given host when deducing a zone id", async () => {
241
+ writeWranglerToml({
242
+ main: "index.js",
243
+ route: "*some-host.com/some/path/*",
244
+ });
245
+ fs.writeFileSync("index.js", `export default {};`);
246
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
247
+ await runWrangler("dev");
248
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
249
+ });
250
+
251
+ it("should strip leading `*.` from given host when deducing a zone id", async () => {
252
+ writeWranglerToml({
253
+ main: "index.js",
254
+ route: "*.some-host.com/some/path/*",
255
+ });
256
+ fs.writeFileSync("index.js", `export default {};`);
257
+ mockGetZones("some-host.com", [{ id: "some-zone-id" }]);
258
+ await runWrangler("dev");
259
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual("some-host.com");
260
+ });
261
+
262
+ it("should, when provided, use a configured zone_id", async () => {
263
+ writeWranglerToml({
264
+ main: "index.js",
265
+ routes: [
266
+ { pattern: "https://some-domain.com/*", zone_id: "some-zone-id" },
267
+ ],
268
+ });
269
+ fs.writeFileSync("index.js", `export default {};`);
270
+ await runWrangler("dev");
271
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
272
+ expect.objectContaining({
273
+ host: "some-domain.com",
274
+ zone: "some-zone-id",
275
+ })
276
+ );
277
+ });
278
+
279
+ it("should, when provided, use a zone_name to get a zone_id", async () => {
280
+ writeWranglerToml({
281
+ main: "index.js",
282
+ routes: [
283
+ { pattern: "https://some-domain.com/*", zone_name: "some-zone.com" },
284
+ ],
285
+ });
286
+ fs.writeFileSync("index.js", `export default {};`);
287
+ mockGetZones("some-zone.com", [{ id: "a-zone-id" }]);
288
+ await runWrangler("dev");
289
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
290
+ expect.objectContaining({
291
+ // note that it uses the provided zone_name as a host too
292
+ host: "some-zone.com",
293
+ zone: "a-zone-id",
294
+ })
295
+ );
296
+ });
297
+
298
+ it("given a long host, it should use the longest subdomain that resolves to a zone", async () => {
299
+ writeWranglerToml({
300
+ main: "index.js",
301
+ });
302
+ fs.writeFileSync("index.js", `export default {};`);
303
+ mockGetZones("111.222.333.some-host.com", []);
304
+ mockGetZones("222.333.some-host.com", []);
305
+ mockGetZones("333.some-host.com", [{ id: "some-zone-id" }]);
306
+ await runWrangler("dev --host 111.222.333.some-host.com");
307
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
308
+ expect.objectContaining({
309
+ host: "111.222.333.some-host.com",
310
+ zone: "some-zone-id",
311
+ })
312
+ );
313
+ });
314
+
315
+ it("should, in order, use args.host/config.dev.host/args.routes/(config.route|config.routes)", async () => {
316
+ // This test might seem like it's testing implementation details, but let's be specific and consider it a spec
317
+
318
+ fs.writeFileSync("index.js", `export default {};`);
319
+
320
+ // config.routes
321
+ mockGetZones("5.some-host.com", [{ id: "some-zone-id-5" }]);
322
+ writeWranglerToml({
323
+ main: "index.js",
324
+ routes: ["http://5.some-host.com/some/path/*"],
325
+ });
326
+ await runWrangler("dev");
327
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
328
+ expect.objectContaining({
329
+ host: "5.some-host.com",
330
+ zone: "some-zone-id-5",
331
+ })
332
+ );
333
+ (Dev as jest.Mock).mockClear();
334
+
335
+ // config.route
336
+ mockGetZones("4.some-host.com", [{ id: "some-zone-id-4" }]);
337
+ writeWranglerToml({
338
+ main: "index.js",
339
+ route: "https://4.some-host.com/some/path/*",
340
+ });
341
+ await runWrangler("dev");
342
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
343
+ expect.objectContaining({
344
+ host: "4.some-host.com",
345
+ zone: "some-zone-id-4",
346
+ })
347
+ );
348
+ (Dev as jest.Mock).mockClear();
349
+
350
+ // --routes
351
+ mockGetZones("3.some-host.com", [{ id: "some-zone-id-3" }]);
352
+ writeWranglerToml({
353
+ main: "index.js",
354
+ route: "https://4.some-host.com/some/path/*",
355
+ });
356
+ await runWrangler("dev --routes http://3.some-host.com/some/path/*");
357
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
358
+ expect.objectContaining({
359
+ host: "3.some-host.com",
360
+ zone: "some-zone-id-3",
361
+ })
362
+ );
363
+ (Dev as jest.Mock).mockClear();
364
+
365
+ // config.dev.host
366
+ mockGetZones("2.some-host.com", [{ id: "some-zone-id-2" }]);
367
+ writeWranglerToml({
368
+ main: "index.js",
369
+ dev: {
370
+ host: `2.some-host.com`,
371
+ },
372
+ route: "4.some-host.com/some/path/*",
373
+ });
374
+ await runWrangler("dev --routes http://3.some-host.com/some/path/*");
375
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
376
+ expect.objectContaining({
377
+ host: "2.some-host.com",
378
+ zone: "some-zone-id-2",
379
+ })
380
+ );
381
+ (Dev as jest.Mock).mockClear();
382
+
383
+ // --host
384
+ mockGetZones("1.some-host.com", [{ id: "some-zone-id-1" }]);
385
+ writeWranglerToml({
386
+ main: "index.js",
387
+ dev: {
388
+ host: `2.some-host.com`,
389
+ },
390
+ route: "4.some-host.com/some/path/*",
391
+ });
392
+ await runWrangler(
393
+ "dev --routes http://3.some-host.com/some/path/* --host 1.some-host.com"
394
+ );
395
+ expect((Dev as jest.Mock).mock.calls[0][0]).toEqual(
396
+ expect.objectContaining({
397
+ host: "1.some-host.com",
398
+ zone: "some-zone-id-1",
399
+ })
400
+ );
401
+ (Dev as jest.Mock).mockClear();
402
+ });
403
+
404
+ it("should error if a host can't resolve to a zone", async () => {
405
+ writeWranglerToml({
406
+ main: "index.js",
407
+ });
408
+ fs.writeFileSync("index.js", `export default {};`);
409
+ mockGetZones("some-host.com", []);
410
+ await expect(
411
+ runWrangler("dev --host some-host.com")
412
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
413
+ `"Could not find zone for some-host.com"`
414
+ );
415
+ });
416
+
417
+ it("should not try to resolve a zone when starting in local mode", async () => {
418
+ writeWranglerToml({
419
+ main: "index.js",
420
+ });
421
+ fs.writeFileSync("index.js", `export default {};`);
422
+ await runWrangler("dev --host some-host.com --local");
423
+ expect((Dev as jest.Mock).mock.calls[0][0].zone).toEqual(undefined);
424
+ });
425
+ });
426
+
427
+ describe("local upstream", () => {
428
+ it("should use dev.host from toml by default", async () => {
429
+ writeWranglerToml({
430
+ main: "index.js",
431
+ dev: {
432
+ host: `2.some-host.com`,
433
+ },
434
+ });
435
+ fs.writeFileSync("index.js", `export default {};`);
436
+ await runWrangler("dev --local");
437
+ expect((Dev as jest.Mock).mock.calls[0][0].localUpstream).toEqual(
438
+ "2.some-host.com"
439
+ );
440
+ });
441
+
442
+ it("should use route from toml by default", async () => {
443
+ writeWranglerToml({
444
+ main: "index.js",
445
+ route: "https://4.some-host.com/some/path/*",
446
+ });
447
+ fs.writeFileSync("index.js", `export default {};`);
448
+ await runWrangler("dev --local");
449
+ expect((Dev as jest.Mock).mock.calls[0][0].host).toEqual(
450
+ "4.some-host.com"
451
+ );
452
+ });
453
+
454
+ it("should respect the option when provided", async () => {
455
+ writeWranglerToml({
456
+ main: "index.js",
457
+ route: `2.some-host.com`,
458
+ });
459
+ fs.writeFileSync("index.js", `export default {};`);
460
+ await runWrangler("dev --local-upstream some-host.com --local");
461
+ expect((Dev as jest.Mock).mock.calls[0][0].localUpstream).toEqual(
462
+ "some-host.com"
463
+ );
464
+ });
465
+ });
466
+
467
+ describe("custom builds", () => {
468
+ it("should run a custom build before starting `dev`", async () => {
469
+ writeWranglerToml({
470
+ build: {
471
+ command: `node -e "console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')"`,
472
+ },
473
+ });
474
+
475
+ await runWrangler("dev index.js");
476
+
477
+ expect(fs.readFileSync("index.js", "utf-8")).toMatchInlineSnapshot(
478
+ `"export default { fetch(){ return new Response(123) } }"`
479
+ );
480
+
481
+ // and the command would pass through
482
+ expect((Dev as jest.Mock).mock.calls[0][0].build).toEqual({
483
+ command:
484
+ "node -e \"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\"",
485
+ cwd: undefined,
486
+ watch_dir: "src",
487
+ });
488
+ expect(std.out).toMatchInlineSnapshot(
489
+ `"Running custom build: node -e \\"console.log('custom build'); require('fs').writeFileSync('index.js', 'export default { fetch(){ return new Response(123) } }')\\""`
490
+ );
491
+ expect(std.err).toMatchInlineSnapshot(`""`);
492
+ expect(std.warn).toMatchInlineSnapshot(`""`);
493
+ });
494
+
495
+ if (process.platform !== "win32") {
496
+ it("should run a custom build of multiple steps combined by && before starting `dev`", async () => {
497
+ writeWranglerToml({
498
+ build: {
499
+ command: `echo "custom build" && echo "export default { fetch(){ return new Response(123) } }" > index.js`,
500
+ },
501
+ });
502
+
503
+ await runWrangler("dev index.js");
504
+
505
+ expect(fs.readFileSync("index.js", "utf-8")).toMatchInlineSnapshot(`
506
+ "export default { fetch(){ return new Response(123) } }
507
+ "
508
+ `);
509
+
510
+ expect(std.out).toMatchInlineSnapshot(
511
+ `"Running custom build: echo \\"custom build\\" && echo \\"export default { fetch(){ return new Response(123) } }\\" > index.js"`
512
+ );
513
+ expect(std.err).toMatchInlineSnapshot(`""`);
514
+ expect(std.warn).toMatchInlineSnapshot(`""`);
515
+ });
516
+ }
517
+
518
+ it("should throw an error if the entry doesn't exist after the build finishes", async () => {
519
+ writeWranglerToml({
520
+ main: "index.js",
521
+ build: {
522
+ command: `node -e "console.log('custom build');"`,
523
+ },
524
+ });
525
+
526
+ await expect(runWrangler("dev")).rejects
527
+ .toThrowErrorMatchingInlineSnapshot(`
467
528
  "The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
468
529
  The \`main\` property in wrangler.toml should point to the file generated by the custom build."
469
530
  `);
470
- expect(std.out).toMatchInlineSnapshot(`
471
- "Running custom build: node -e \\"console.log('custom build');\\"
472
-
473
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
474
- `);
475
- expect(std.err).toMatchInlineSnapshot(`
476
- "X [ERROR] The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
477
-
478
- The \`main\` property in wrangler.toml should point to the file generated by the custom build.
479
-
480
- "
481
- `);
482
- expect(std.warn).toMatchInlineSnapshot(`""`);
483
- });
484
- });
485
-
486
- describe("upstream-protocol", () => {
487
- it("should default upstream-protocol to `https`", async () => {
488
- writeWranglerToml({
489
- main: "index.js",
490
- });
491
- fs.writeFileSync("index.js", `export default {};`);
492
- await runWrangler("dev");
493
- expect((Dev as jest.Mock).mock.calls[0][0].upstreamProtocol).toEqual(
494
- "https"
495
- );
496
- expect(std.out).toMatchInlineSnapshot(`""`);
497
- expect(std.warn).toMatchInlineSnapshot(`""`);
498
- expect(std.err).toMatchInlineSnapshot(`""`);
499
- });
500
-
501
- it("should warn if `--upstream-protocol=http` is used", async () => {
502
- writeWranglerToml({
503
- main: "index.js",
504
- });
505
- fs.writeFileSync("index.js", `export default {};`);
506
- await runWrangler("dev --upstream-protocol=http");
507
- expect((Dev as jest.Mock).mock.calls[0][0].upstreamProtocol).toEqual(
508
- "http"
509
- );
510
- expect(std.out).toMatchInlineSnapshot(`""`);
511
- expect(std.warn).toMatchInlineSnapshot(`
512
- "▲ [WARNING] Setting upstream-protocol to http is not currently implemented.
513
-
514
- If this is required in your project, please add your use case to the following issue:
515
- https://github.com/cloudflare/wrangler2/issues/583.
516
-
517
- "
518
- `);
519
- expect(std.err).toMatchInlineSnapshot(`""`);
520
- });
521
- });
522
-
523
- describe("local-protocol", () => {
524
- it("should default local-protocol to `http`", async () => {
525
- writeWranglerToml({
526
- main: "index.js",
527
- });
528
- fs.writeFileSync("index.js", `export default {};`);
529
- await runWrangler("dev");
530
- expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual("http");
531
- expect(std.out).toMatchInlineSnapshot(`""`);
532
- expect(std.warn).toMatchInlineSnapshot(`""`);
533
- expect(std.err).toMatchInlineSnapshot(`""`);
534
- });
535
-
536
- it("should use `local_protocol` from `wrangler.toml`, if available", async () => {
537
- writeWranglerToml({
538
- main: "index.js",
539
- dev: {
540
- local_protocol: "https",
541
- },
542
- });
543
- fs.writeFileSync("index.js", `export default {};`);
544
- await runWrangler("dev");
545
- expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual(
546
- "https"
547
- );
548
- expect(std.out).toMatchInlineSnapshot(`""`);
549
- expect(std.warn).toMatchInlineSnapshot(`""`);
550
- expect(std.err).toMatchInlineSnapshot(`""`);
551
- });
552
-
553
- it("should use --local-protocol command line arg, if provided", async () => {
554
- // Here we show that the command line overrides the wrangler.toml by
555
- // setting the config to https, and then setting it back to http on the command line.
556
- writeWranglerToml({
557
- main: "index.js",
558
- dev: {
559
- local_protocol: "https",
560
- },
561
- });
562
- fs.writeFileSync("index.js", `export default {};`);
563
- await runWrangler("dev --local-protocol=http");
564
- expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual("http");
565
- expect(std.out).toMatchInlineSnapshot(`""`);
566
- expect(std.warn).toMatchInlineSnapshot(`""`);
567
- expect(std.err).toMatchInlineSnapshot(`""`);
568
- });
569
- });
570
-
571
- describe("ip", () => {
572
- it("should default ip to localhost", async () => {
573
- writeWranglerToml({
574
- main: "index.js",
575
- });
576
- fs.writeFileSync("index.js", `export default {};`);
577
- await runWrangler("dev");
578
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
579
- expect(std.out).toMatchInlineSnapshot(`""`);
580
- expect(std.warn).toMatchInlineSnapshot(`""`);
581
- expect(std.err).toMatchInlineSnapshot(`""`);
582
- });
583
-
584
- it("should use to `ip` from `wrangler.toml`, if available", async () => {
585
- writeWranglerToml({
586
- main: "index.js",
587
- dev: {
588
- ip: "0.0.0.0",
589
- },
590
- });
591
- fs.writeFileSync("index.js", `export default {};`);
592
- await runWrangler("dev");
593
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
594
- expect(std.out).toMatchInlineSnapshot(`""`);
595
- expect(std.warn).toMatchInlineSnapshot(`""`);
596
- expect(std.err).toMatchInlineSnapshot(`""`);
597
- });
598
-
599
- it("should use --ip command line arg, if provided", async () => {
600
- writeWranglerToml({
601
- main: "index.js",
602
- dev: {
603
- ip: "1.1.1.1",
604
- },
605
- });
606
- fs.writeFileSync("index.js", `export default {};`);
607
- await runWrangler("dev --ip=0.0.0.0");
608
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
609
- expect(std.out).toMatchInlineSnapshot(`""`);
610
- expect(std.warn).toMatchInlineSnapshot(`""`);
611
- expect(std.err).toMatchInlineSnapshot(`""`);
612
- });
613
- });
614
-
615
- describe("port", () => {
616
- it("should default port to 8787 if it is not in use", async () => {
617
- writeWranglerToml({
618
- main: "index.js",
619
- });
620
- fs.writeFileSync("index.js", `export default {};`);
621
- await runWrangler("dev");
622
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8787);
623
- expect(std.out).toMatchInlineSnapshot(`""`);
624
- expect(std.warn).toMatchInlineSnapshot(`""`);
625
- expect(std.err).toMatchInlineSnapshot(`""`);
626
- });
627
-
628
- it("should use to `port` from `wrangler.toml`, if available", async () => {
629
- writeWranglerToml({
630
- main: "index.js",
631
- dev: {
632
- port: 8888,
633
- },
634
- });
635
- fs.writeFileSync("index.js", `export default {};`);
636
- // Mock `getPort()` to resolve to a completely different port.
637
- (getPort as jest.Mock).mockResolvedValue(98765);
638
-
639
- await runWrangler("dev");
640
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8888);
641
- expect(std.out).toMatchInlineSnapshot(`""`);
642
- expect(std.warn).toMatchInlineSnapshot(`""`);
643
- expect(std.err).toMatchInlineSnapshot(`""`);
644
- });
645
-
646
- it("should use --port command line arg, if provided", async () => {
647
- writeWranglerToml({
648
- main: "index.js",
649
- dev: {
650
- port: 8888,
651
- },
652
- });
653
- fs.writeFileSync("index.js", `export default {};`);
654
- // Mock `getPort()` to resolve to a completely different port.
655
- (getPort as jest.Mock).mockResolvedValue(98765);
656
-
657
- await runWrangler("dev --port=9999");
658
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(9999);
659
- expect(std.out).toMatchInlineSnapshot(`""`);
660
- expect(std.warn).toMatchInlineSnapshot(`""`);
661
- expect(std.err).toMatchInlineSnapshot(`""`);
662
- });
663
-
664
- it("should use a different port to the default if it is in use", async () => {
665
- writeWranglerToml({
666
- main: "index.js",
667
- });
668
- fs.writeFileSync("index.js", `export default {};`);
669
- // Mock `getPort()` to resolve to a completely different port.
670
- (getPort as jest.Mock).mockResolvedValue(98765);
671
-
672
- await runWrangler("dev");
673
- expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(98765);
674
- expect(std.out).toMatchInlineSnapshot(`""`);
675
- expect(std.warn).toMatchInlineSnapshot(`""`);
676
- expect(std.err).toMatchInlineSnapshot(`""`);
677
- });
678
- });
679
-
680
- describe("durable_objects", () => {
681
- it("should warn if there are remote Durable Objects, or missing migrations for local Durable Objects", async () => {
682
- writeWranglerToml({
683
- main: "index.js",
684
- durable_objects: {
685
- bindings: [
686
- { name: "NAME_1", class_name: "CLASS_1" },
687
- {
688
- name: "NAME_2",
689
- class_name: "CLASS_2",
690
- script_name: "SCRIPT_A",
691
- },
692
- { name: "NAME_3", class_name: "CLASS_3" },
693
- {
694
- name: "NAME_4",
695
- class_name: "CLASS_4",
696
- script_name: "SCRIPT_B",
697
- },
698
- ],
699
- },
700
- });
701
- fs.writeFileSync("index.js", `export default {};`);
702
- await runWrangler("dev");
703
- expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
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
- `);
712
- expect(std.warn).toMatchInlineSnapshot(`
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.
731
-
732
- Be aware that changes to the data stored in these Durable Objects will be permanent and affect the
733
- live instances.
734
- Remote Durable Objects that are affected:
735
- - {\\"name\\":\\"NAME_2\\",\\"class_name\\":\\"CLASS_2\\",\\"script_name\\":\\"SCRIPT_A\\"}
736
- - {\\"name\\":\\"NAME_4\\",\\"class_name\\":\\"CLASS_4\\",\\"script_name\\":\\"SCRIPT_B\\"}
737
-
738
- "
739
- `);
740
- expect(std.err).toMatchInlineSnapshot(`""`);
741
- });
742
- });
743
-
744
- describe(".dev.vars", () => {
745
- it("should override `vars` bindings from `wrangler.toml` with values in `.dev.vars`", async () => {
746
- fs.writeFileSync("index.js", `export default {};`);
747
-
748
- const localVarsEnvContent = dedent`
531
+ expect(std.out).toMatchInlineSnapshot(`
532
+ "Running custom build: node -e \\"console.log('custom build');\\"
533
+
534
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
535
+ `);
536
+ expect(std.err).toMatchInlineSnapshot(`
537
+ "X [ERROR] The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
538
+
539
+ The \`main\` property in wrangler.toml should point to the file generated by the custom build.
540
+
541
+ "
542
+ `);
543
+ expect(std.warn).toMatchInlineSnapshot(`""`);
544
+ });
545
+ });
546
+
547
+ describe("upstream-protocol", () => {
548
+ it("should default upstream-protocol to `https`", async () => {
549
+ writeWranglerToml({
550
+ main: "index.js",
551
+ });
552
+ fs.writeFileSync("index.js", `export default {};`);
553
+ await runWrangler("dev");
554
+ expect((Dev as jest.Mock).mock.calls[0][0].upstreamProtocol).toEqual(
555
+ "https"
556
+ );
557
+ expect(std.out).toMatchInlineSnapshot(`""`);
558
+ expect(std.warn).toMatchInlineSnapshot(`""`);
559
+ expect(std.err).toMatchInlineSnapshot(`""`);
560
+ });
561
+
562
+ it("should warn if `--upstream-protocol=http` is used", async () => {
563
+ writeWranglerToml({
564
+ main: "index.js",
565
+ });
566
+ fs.writeFileSync("index.js", `export default {};`);
567
+ await runWrangler("dev --upstream-protocol=http");
568
+ expect((Dev as jest.Mock).mock.calls[0][0].upstreamProtocol).toEqual(
569
+ "http"
570
+ );
571
+ expect(std.out).toMatchInlineSnapshot(`""`);
572
+ expect(std.warn).toMatchInlineSnapshot(`
573
+ "▲ [WARNING] Setting upstream-protocol to http is not currently implemented.
574
+
575
+ If this is required in your project, please add your use case to the following issue:
576
+ https://github.com/cloudflare/wrangler2/issues/583.
577
+
578
+ "
579
+ `);
580
+ expect(std.err).toMatchInlineSnapshot(`""`);
581
+ });
582
+ });
583
+
584
+ describe("local-protocol", () => {
585
+ it("should default local-protocol to `http`", async () => {
586
+ writeWranglerToml({
587
+ main: "index.js",
588
+ });
589
+ fs.writeFileSync("index.js", `export default {};`);
590
+ await runWrangler("dev");
591
+ expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual("http");
592
+ expect(std.out).toMatchInlineSnapshot(`""`);
593
+ expect(std.warn).toMatchInlineSnapshot(`""`);
594
+ expect(std.err).toMatchInlineSnapshot(`""`);
595
+ });
596
+
597
+ it("should use `local_protocol` from `wrangler.toml`, if available", async () => {
598
+ writeWranglerToml({
599
+ main: "index.js",
600
+ dev: {
601
+ local_protocol: "https",
602
+ },
603
+ });
604
+ fs.writeFileSync("index.js", `export default {};`);
605
+ await runWrangler("dev");
606
+ expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual(
607
+ "https"
608
+ );
609
+ expect(std.out).toMatchInlineSnapshot(`""`);
610
+ expect(std.warn).toMatchInlineSnapshot(`""`);
611
+ expect(std.err).toMatchInlineSnapshot(`""`);
612
+ });
613
+
614
+ it("should use --local-protocol command line arg, if provided", async () => {
615
+ // Here we show that the command line overrides the wrangler.toml by
616
+ // setting the config to https, and then setting it back to http on the command line.
617
+ writeWranglerToml({
618
+ main: "index.js",
619
+ dev: {
620
+ local_protocol: "https",
621
+ },
622
+ });
623
+ fs.writeFileSync("index.js", `export default {};`);
624
+ await runWrangler("dev --local-protocol=http");
625
+ expect((Dev as jest.Mock).mock.calls[0][0].localProtocol).toEqual("http");
626
+ expect(std.out).toMatchInlineSnapshot(`""`);
627
+ expect(std.warn).toMatchInlineSnapshot(`""`);
628
+ expect(std.err).toMatchInlineSnapshot(`""`);
629
+ });
630
+ });
631
+
632
+ describe("ip", () => {
633
+ it("should default ip to localhost", async () => {
634
+ writeWranglerToml({
635
+ main: "index.js",
636
+ });
637
+ fs.writeFileSync("index.js", `export default {};`);
638
+ await runWrangler("dev");
639
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
640
+ expect(std.out).toMatchInlineSnapshot(`""`);
641
+ expect(std.warn).toMatchInlineSnapshot(`""`);
642
+ expect(std.err).toMatchInlineSnapshot(`""`);
643
+ });
644
+
645
+ it("should use to `ip` from `wrangler.toml`, if available", async () => {
646
+ writeWranglerToml({
647
+ main: "index.js",
648
+ dev: {
649
+ ip: "0.0.0.0",
650
+ },
651
+ });
652
+ fs.writeFileSync("index.js", `export default {};`);
653
+ await runWrangler("dev");
654
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
655
+ expect(std.out).toMatchInlineSnapshot(`""`);
656
+ expect(std.warn).toMatchInlineSnapshot(`""`);
657
+ expect(std.err).toMatchInlineSnapshot(`""`);
658
+ });
659
+
660
+ it("should use --ip command line arg, if provided", async () => {
661
+ writeWranglerToml({
662
+ main: "index.js",
663
+ dev: {
664
+ ip: "1.1.1.1",
665
+ },
666
+ });
667
+ fs.writeFileSync("index.js", `export default {};`);
668
+ await runWrangler("dev --ip=0.0.0.0");
669
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("0.0.0.0");
670
+ expect(std.out).toMatchInlineSnapshot(`""`);
671
+ expect(std.warn).toMatchInlineSnapshot(`""`);
672
+ expect(std.err).toMatchInlineSnapshot(`""`);
673
+ });
674
+ });
675
+
676
+ describe("port", () => {
677
+ it("should default port to 8787 if it is not in use", async () => {
678
+ writeWranglerToml({
679
+ main: "index.js",
680
+ });
681
+ fs.writeFileSync("index.js", `export default {};`);
682
+ await runWrangler("dev");
683
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8787);
684
+ expect(std.out).toMatchInlineSnapshot(`""`);
685
+ expect(std.warn).toMatchInlineSnapshot(`""`);
686
+ expect(std.err).toMatchInlineSnapshot(`""`);
687
+ });
688
+
689
+ it("should use to `port` from `wrangler.toml`, if available", async () => {
690
+ writeWranglerToml({
691
+ main: "index.js",
692
+ dev: {
693
+ port: 8888,
694
+ },
695
+ });
696
+ fs.writeFileSync("index.js", `export default {};`);
697
+ // Mock `getPort()` to resolve to a completely different port.
698
+ (getPort as jest.Mock).mockResolvedValue(98765);
699
+
700
+ await runWrangler("dev");
701
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(8888);
702
+ expect(std.out).toMatchInlineSnapshot(`""`);
703
+ expect(std.warn).toMatchInlineSnapshot(`""`);
704
+ expect(std.err).toMatchInlineSnapshot(`""`);
705
+ });
706
+
707
+ it("should use --port command line arg, if provided", async () => {
708
+ writeWranglerToml({
709
+ main: "index.js",
710
+ dev: {
711
+ port: 8888,
712
+ },
713
+ });
714
+ fs.writeFileSync("index.js", `export default {};`);
715
+ // Mock `getPort()` to resolve to a completely different port.
716
+ (getPort as jest.Mock).mockResolvedValue(98765);
717
+
718
+ await runWrangler("dev --port=9999");
719
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(9999);
720
+ expect(std.out).toMatchInlineSnapshot(`""`);
721
+ expect(std.warn).toMatchInlineSnapshot(`""`);
722
+ expect(std.err).toMatchInlineSnapshot(`""`);
723
+ });
724
+
725
+ it("should use a different port to the default if it is in use", async () => {
726
+ writeWranglerToml({
727
+ main: "index.js",
728
+ });
729
+ fs.writeFileSync("index.js", `export default {};`);
730
+ // Mock `getPort()` to resolve to a completely different port.
731
+ (getPort as jest.Mock).mockResolvedValue(98765);
732
+
733
+ await runWrangler("dev");
734
+ expect((Dev as jest.Mock).mock.calls[0][0].port).toEqual(98765);
735
+ expect(std.out).toMatchInlineSnapshot(`""`);
736
+ expect(std.warn).toMatchInlineSnapshot(`""`);
737
+ expect(std.err).toMatchInlineSnapshot(`""`);
738
+ });
739
+ });
740
+
741
+ describe("durable_objects", () => {
742
+ it("should warn if there are remote Durable Objects, or missing migrations for local Durable Objects", async () => {
743
+ writeWranglerToml({
744
+ main: "index.js",
745
+ durable_objects: {
746
+ bindings: [
747
+ { name: "NAME_1", class_name: "CLASS_1" },
748
+ {
749
+ name: "NAME_2",
750
+ class_name: "CLASS_2",
751
+ script_name: "SCRIPT_A",
752
+ },
753
+ { name: "NAME_3", class_name: "CLASS_3" },
754
+ {
755
+ name: "NAME_4",
756
+ class_name: "CLASS_4",
757
+ script_name: "SCRIPT_B",
758
+ },
759
+ ],
760
+ },
761
+ });
762
+ fs.writeFileSync("index.js", `export default {};`);
763
+ await runWrangler("dev");
764
+ expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
765
+ expect(std.out).toMatchInlineSnapshot(`
766
+ "Your worker has access to the following bindings:
767
+ - Durable Objects:
768
+ - NAME_1: CLASS_1
769
+ - NAME_2: CLASS_2 (defined in SCRIPT_A)
770
+ - NAME_3: CLASS_3
771
+ - NAME_4: CLASS_4 (defined in SCRIPT_B)"
772
+ `);
773
+ expect(std.warn).toMatchInlineSnapshot(`
774
+ "▲ [WARNING] Processing wrangler.toml configuration:
775
+
776
+ - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS_1,
777
+ CLASS_3), but no [migrations] for them. This may not work as expected until you add a [migrations]
778
+ section to your wrangler.toml. Add this configuration to your wrangler.toml:
779
+
780
+ \`\`\`
781
+ [[migrations]]
782
+ tag = \\"v1\\" # Should be unique for each entry
783
+ new_classes = [\\"CLASS_1\\", \\"CLASS_3\\"]
784
+ \`\`\`
785
+
786
+ Refer to
787
+ https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml
788
+ for more details.
789
+
790
+
791
+ ▲ [WARNING] WARNING: You have Durable Object bindings that are not defined locally in the worker being developed.
792
+
793
+ Be aware that changes to the data stored in these Durable Objects will be permanent and affect the
794
+ live instances.
795
+ Remote Durable Objects that are affected:
796
+ - {\\"name\\":\\"NAME_2\\",\\"class_name\\":\\"CLASS_2\\",\\"script_name\\":\\"SCRIPT_A\\"}
797
+ - {\\"name\\":\\"NAME_4\\",\\"class_name\\":\\"CLASS_4\\",\\"script_name\\":\\"SCRIPT_B\\"}
798
+
799
+ "
800
+ `);
801
+ expect(std.err).toMatchInlineSnapshot(`""`);
802
+ });
803
+ });
804
+
805
+ describe(".dev.vars", () => {
806
+ it("should override `vars` bindings from `wrangler.toml` with values in `.dev.vars`", async () => {
807
+ fs.writeFileSync("index.js", `export default {};`);
808
+
809
+ const localVarsEnvContent = dedent`
749
810
  # Preceding comment
750
811
  VAR_1="var #1 value" # End of line comment
751
812
  VAR_3="var #3 value"
@@ -755,256 +816,344 @@ describe("wrangler dev", () => {
755
816
  EMPTY=
756
817
  UNQUOTED= unquoted value
757
818
  `;
758
- fs.writeFileSync(".dev.vars", localVarsEnvContent, "utf8");
759
-
760
- writeWranglerToml({
761
- main: "index.js",
762
- vars: {
763
- VAR_1: "original value 1",
764
- VAR_2: "original value 2", // should not get overridden
765
- VAR_3: "original value 3",
766
- VAR_MULTI_LINE_1: "original multi-line 1",
767
- VAR_MULTI_LINE_2: "original multi-line 2",
768
- EMPTY: "original empty",
769
- UNQUOTED: "original unquoted",
770
- },
771
- });
772
- await runWrangler("dev");
773
- const varBindings: Record<string, unknown> = (Dev as jest.Mock).mock
774
- .calls[0][0].bindings.vars;
775
-
776
- expect(varBindings).toEqual({
777
- VAR_1: "var #1 value",
778
- VAR_2: "original value 2",
779
- VAR_3: "var #3 value",
780
- VAR_MULTI_LINE_1: "A: line 1\nline 2",
781
- VAR_MULTI_LINE_2: "B: line 1\nline 2",
782
- EMPTY: "",
783
- UNQUOTED: "unquoted value", // Note that whitespace is trimmed
784
- });
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
- `);
797
- expect(std.warn).toMatchInlineSnapshot(`""`);
798
- expect(std.err).toMatchInlineSnapshot(`""`);
799
- });
800
- });
801
-
802
- describe("site", () => {
803
- it("should error if --site is used with no value", async () => {
804
- await expect(
805
- runWrangler("dev --site")
806
- ).rejects.toThrowErrorMatchingInlineSnapshot(
807
- `"Not enough arguments following: site"`
808
- );
809
-
810
- expect(std).toMatchInlineSnapshot(`
811
- Object {
812
- "debug": "",
813
- "err": "X [ERROR] Not enough arguments following: site
814
-
815
- ",
816
- "out": "
817
- wrangler dev [script]
818
-
819
- 👂 Start a local server for developing your worker
820
-
821
- Positionals:
822
- script The path to an entry point for your worker [string]
823
-
824
- Flags:
825
- -c, --config Path to .toml configuration file [string]
826
- -h, --help Show help [boolean]
827
- -v, --version Show version number [boolean]
828
-
829
- Options:
830
- --name Name of the worker [string]
831
- --format Choose an entry type [deprecated] [choices: \\"modules\\", \\"service-worker\\"]
832
- -e, --env Perform on a specific environment [string]
833
- --compatibility-date Date to use for compatibility checks [string]
834
- --compatibility-flags, --compatibility-flag Flags to use for compatibility checks [array]
835
- --latest Use the latest version of the worker runtime [boolean] [default: true]
836
- --ip IP address to listen on, defaults to \`localhost\` [string]
837
- --port Port to listen on [number]
838
- --inspector-port Port for devtools to connect to [number]
839
- --routes, --route Routes to upload [array]
840
- --host Host to forward requests to, defaults to the zone of project [string]
841
- --local-protocol Protocol to listen to requests on, defaults to http. [choices: \\"http\\", \\"https\\"]
842
- --experimental-public Static assets to be served [string]
843
- --site Root folder of static assets for Workers Sites [string]
844
- --site-include Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded. [array]
845
- --site-exclude Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded. [array]
846
- --upstream-protocol Protocol to forward requests to host on, defaults to https. [choices: \\"http\\", \\"https\\"]
847
- --jsx-factory The function that is called for each JSX element [string]
848
- --jsx-fragment The function that is called for each JSX fragment [string]
849
- --tsconfig Path to a custom tsconfig.json file [string]
850
- -l, --local Run on my machine [boolean] [default: false]
851
- --minify Minify the script [boolean]
852
- --node-compat Enable node.js compatibility [boolean]
853
- --experimental-enable-local-persistence Enable persistence for this session (only for local mode) [boolean]
854
- --inspect Enable dev tools [deprecated] [boolean]",
855
- "warn": "",
856
- }
857
- `);
858
- });
859
-
860
- it("should error if --experimental-public and --site are used together", async () => {
861
- writeWranglerToml({
862
- main: "./index.js",
863
- });
864
- fs.writeFileSync("index.js", `export default {};`);
865
- await expect(
866
- runWrangler("dev --experimental-public abc --site xyz")
867
- ).rejects.toThrowErrorMatchingInlineSnapshot(
868
- `"Cannot use --experimental-public and a Site configuration together."`
869
- );
870
- });
871
-
872
- it("should error if --experimental-public and config.site are used together", async () => {
873
- writeWranglerToml({
874
- main: "./index.js",
875
- site: {
876
- bucket: "xyz",
877
- },
878
- });
879
- fs.writeFileSync("index.js", `export default {};`);
880
- await expect(
881
- runWrangler("dev --experimental-public abc")
882
- ).rejects.toThrowErrorMatchingInlineSnapshot(
883
- `"Cannot use --experimental-public and a Site configuration together."`
884
- );
885
- });
886
- });
887
-
888
- describe("--inspect", () => {
889
- it("should warn if --inspect is used", async () => {
890
- fs.writeFileSync("index.js", `export default {};`);
891
- await runWrangler("dev index.js --inspect");
892
- expect(std).toMatchInlineSnapshot(`
893
- Object {
894
- "debug": "",
895
- "err": "",
896
- "out": "",
897
- "warn": "▲ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.
898
-
899
- ",
900
- }
901
- `);
902
- });
903
- });
904
-
905
- describe("service bindings", () => {
906
- it("should warn when using service bindings", async () => {
907
- writeWranglerToml({
908
- services: [
909
- { binding: "WorkerA", service: "A" },
910
- { binding: "WorkerB", service: "B", environment: "staging" },
911
- ],
912
- });
913
- fs.writeFileSync("index.js", `export default {};`);
914
- await runWrangler("dev index.js");
915
- expect(std).toMatchInlineSnapshot(`
916
- Object {
917
- "debug": "",
918
- "err": "",
919
- "out": "Your worker has access to the following bindings:
920
- - Services:
921
- - WorkerA: A
922
- - WorkerB: B - staging",
923
- "warn": "▲ [WARNING] Processing wrangler.toml configuration:
924
-
925
- - \\"services\\" fields are experimental and may change or break at any time.
926
-
927
-
928
- ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
929
-
930
- ",
931
- }
932
- `);
933
- });
934
- });
935
-
936
- describe("print bindings", () => {
937
- it("should print bindings", async () => {
938
- writeWranglerToml({
939
- services: [
940
- { binding: "WorkerA", service: "A" },
941
- { binding: "WorkerB", service: "B", environment: "staging" },
942
- ],
943
- });
944
- fs.writeFileSync("index.js", `export default {};`);
945
- await runWrangler("dev index.js");
946
- expect(std).toMatchInlineSnapshot(`
947
- Object {
948
- "debug": "",
949
- "err": "",
950
- "out": "Your worker has access to the following bindings:
951
- - Services:
952
- - WorkerA: A
953
- - WorkerB: B - staging",
954
- "warn": "▲ [WARNING] Processing wrangler.toml configuration:
955
-
956
- - \\"services\\" fields are experimental and may change or break at any time.
957
-
958
-
959
- ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
960
-
961
- ",
962
- }
963
- `);
964
- });
965
-
966
- it("should mask vars that were overriden in .dev.vars", async () => {
967
- writeWranglerToml({
968
- vars: {
969
- variable: 123,
970
- overriden: "original values",
971
- },
972
- });
973
- fs.writeFileSync(
974
- ".dev.vars",
975
- `
819
+ fs.writeFileSync(".dev.vars", localVarsEnvContent, "utf8");
820
+
821
+ writeWranglerToml({
822
+ main: "index.js",
823
+ vars: {
824
+ VAR_1: "original value 1",
825
+ VAR_2: "original value 2", // should not get overridden
826
+ VAR_3: "original value 3",
827
+ VAR_MULTI_LINE_1: "original multi-line 1",
828
+ VAR_MULTI_LINE_2: "original multi-line 2",
829
+ EMPTY: "original empty",
830
+ UNQUOTED: "original unquoted",
831
+ },
832
+ });
833
+ await runWrangler("dev");
834
+ const varBindings: Record<string, unknown> = (Dev as jest.Mock).mock
835
+ .calls[0][0].bindings.vars;
836
+
837
+ expect(varBindings).toEqual({
838
+ VAR_1: "var #1 value",
839
+ VAR_2: "original value 2",
840
+ VAR_3: "var #3 value",
841
+ VAR_MULTI_LINE_1: "A: line 1\nline 2",
842
+ VAR_MULTI_LINE_2: "B: line 1\nline 2",
843
+ EMPTY: "",
844
+ UNQUOTED: "unquoted value", // Note that whitespace is trimmed
845
+ });
846
+ expect(std.out).toMatchInlineSnapshot(`
847
+ "Using vars defined in .dev.vars
848
+ Your worker has access to the following bindings:
849
+ - Vars:
850
+ - VAR_1: \\"(hidden)\\"
851
+ - VAR_2: \\"original value 2\\"
852
+ - VAR_3: \\"(hidden)\\"
853
+ - VAR_MULTI_LINE_1: \\"(hidden)\\"
854
+ - VAR_MULTI_LINE_2: \\"(hidden)\\"
855
+ - EMPTY: \\"(hidden)\\"
856
+ - UNQUOTED: \\"(hidden)\\""
857
+ `);
858
+ expect(std.warn).toMatchInlineSnapshot(`""`);
859
+ expect(std.err).toMatchInlineSnapshot(`""`);
860
+ });
861
+ });
862
+
863
+ describe("serve static assets", () => {
864
+ it("should error if --site is used with no value", async () => {
865
+ await expect(
866
+ runWrangler("dev --site")
867
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
868
+ `"Not enough arguments following: site"`
869
+ );
870
+
871
+ expect(std).toMatchInlineSnapshot(`
872
+ Object {
873
+ "debug": "",
874
+ "err": "X [ERROR] Not enough arguments following: site
875
+
876
+ ",
877
+ "out": "
878
+ wrangler dev [script]
879
+
880
+ 👂 Start a local server for developing your worker
881
+
882
+ Positionals:
883
+ script The path to an entry point for your worker [string]
884
+
885
+ Flags:
886
+ -c, --config Path to .toml configuration file [string]
887
+ -h, --help Show help [boolean]
888
+ -v, --version Show version number [boolean]
889
+
890
+ Options:
891
+ --name Name of the worker [string]
892
+ --no-bundle Skip internal build steps and directly publish script [boolean] [default: false]
893
+ --format Choose an entry type [deprecated] [choices: \\"modules\\", \\"service-worker\\"]
894
+ -e, --env Perform on a specific environment [string]
895
+ --compatibility-date Date to use for compatibility checks [string]
896
+ --compatibility-flags, --compatibility-flag Flags to use for compatibility checks [array]
897
+ --latest Use the latest version of the worker runtime [boolean] [default: true]
898
+ --ip IP address to listen on, defaults to \`localhost\` [string]
899
+ --port Port to listen on [number]
900
+ --inspector-port Port for devtools to connect to [number]
901
+ --routes, --route Routes to upload [array]
902
+ --host Host to forward requests to, defaults to the zone of project [string]
903
+ --local-protocol Protocol to listen to requests on, defaults to http. [choices: \\"http\\", \\"https\\"]
904
+ --local-upstream Host to act as origin in local mode, defaults to dev.host or route [string]
905
+ --assets Static assets to be served [string]
906
+ --site Root folder of static assets for Workers Sites [string]
907
+ --site-include Array of .gitignore-style patterns that match file or directory names from the sites directory. Only matched items will be uploaded. [array]
908
+ --site-exclude Array of .gitignore-style patterns that match file or directory names from the sites directory. Matched items will not be uploaded. [array]
909
+ --upstream-protocol Protocol to forward requests to host on, defaults to https. [choices: \\"http\\", \\"https\\"]
910
+ --jsx-factory The function that is called for each JSX element [string]
911
+ --jsx-fragment The function that is called for each JSX fragment [string]
912
+ --tsconfig Path to a custom tsconfig.json file [string]
913
+ -l, --local Run on my machine [boolean] [default: false]
914
+ --minify Minify the script [boolean]
915
+ --node-compat Enable node.js compatibility [boolean]
916
+ --experimental-enable-local-persistence Enable persistence for this session (only for local mode) [boolean]
917
+ --inspect Enable dev tools [deprecated] [boolean]",
918
+ "warn": "",
919
+ }
920
+ `);
921
+ });
922
+
923
+ it("should error if --assets and --site are used together", async () => {
924
+ writeWranglerToml({
925
+ main: "./index.js",
926
+ });
927
+ fs.writeFileSync("index.js", `export default {};`);
928
+ await expect(
929
+ runWrangler("dev --assets abc --site xyz")
930
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
931
+ `"Cannot use Assets and Workers Sites in the same Worker."`
932
+ );
933
+ });
934
+
935
+ it("should error if --assets and config.site are used together", async () => {
936
+ writeWranglerToml({
937
+ main: "./index.js",
938
+ site: {
939
+ bucket: "xyz",
940
+ },
941
+ });
942
+ fs.writeFileSync("index.js", `export default {};`);
943
+ await expect(
944
+ runWrangler("dev --assets abc")
945
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
946
+ `"Cannot use Assets and Workers Sites in the same Worker."`
947
+ );
948
+ });
949
+
950
+ it("should error if config.assets and --site are used together", async () => {
951
+ writeWranglerToml({
952
+ main: "./index.js",
953
+ assets: "abc",
954
+ });
955
+ fs.writeFileSync("index.js", `export default {};`);
956
+ await expect(
957
+ runWrangler("dev --site xyz")
958
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
959
+ `"Cannot use Assets and Workers Sites in the same Worker."`
960
+ );
961
+ });
962
+
963
+ it("should error if config.assets and config.site are used together", async () => {
964
+ writeWranglerToml({
965
+ main: "./index.js",
966
+ assets: "abc",
967
+ site: {
968
+ bucket: "xyz",
969
+ },
970
+ });
971
+ fs.writeFileSync("index.js", `export default {};`);
972
+ await expect(
973
+ runWrangler("dev --assets abc")
974
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
975
+ `"Cannot use Assets and Workers Sites in the same Worker."`
976
+ );
977
+ });
978
+
979
+ it("should indicate whether Sites is being used", async () => {
980
+ writeWranglerToml({
981
+ main: "index.js",
982
+ });
983
+ fs.writeFileSync("index.js", `export default {};`);
984
+
985
+ await runWrangler("dev");
986
+ expect((Dev as jest.Mock).mock.calls[0][0].isWorkersSite).toEqual(false);
987
+
988
+ await runWrangler("dev --site abc");
989
+ expect((Dev as jest.Mock).mock.calls[1][0].isWorkersSite).toEqual(true);
990
+
991
+ await runWrangler("dev --assets abc");
992
+ expect((Dev as jest.Mock).mock.calls[2][0].isWorkersSite).toEqual(false);
993
+ });
994
+
995
+ it("should warn if --assets is used", async () => {
996
+ writeWranglerToml({
997
+ main: "./index.js",
998
+ });
999
+ fs.writeFileSync("index.js", `export default {};`);
1000
+
1001
+ await runWrangler('dev --assets "./assets"');
1002
+ expect(std).toMatchInlineSnapshot(`
1003
+ Object {
1004
+ "debug": "",
1005
+ "err": "",
1006
+ "out": "",
1007
+ "warn": "▲ [WARNING] The --assets argument is experimental and may change or break at any time
1008
+
1009
+ ",
1010
+ }
1011
+ `);
1012
+ });
1013
+
1014
+ it("should warn if config.assets is used", async () => {
1015
+ writeWranglerToml({
1016
+ main: "./index.js",
1017
+ assets: "./assets",
1018
+ });
1019
+ fs.writeFileSync("index.js", `export default {};`);
1020
+
1021
+ await runWrangler("dev");
1022
+ expect(std).toMatchInlineSnapshot(`
1023
+ Object {
1024
+ "debug": "",
1025
+ "err": "",
1026
+ "out": "",
1027
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
1028
+
1029
+ - \\"assets\\" fields are experimental and may change or break at any time.
1030
+
1031
+ ",
1032
+ }
1033
+ `);
1034
+ });
1035
+ });
1036
+
1037
+ describe("--inspect", () => {
1038
+ it("should warn if --inspect is used", async () => {
1039
+ fs.writeFileSync("index.js", `export default {};`);
1040
+ await runWrangler("dev index.js --inspect");
1041
+ expect(std).toMatchInlineSnapshot(`
1042
+ Object {
1043
+ "debug": "",
1044
+ "err": "",
1045
+ "out": "",
1046
+ "warn": "▲ [WARNING] Passing --inspect is unnecessary, now you can always connect to devtools.
1047
+
1048
+ ",
1049
+ }
1050
+ `);
1051
+ });
1052
+ });
1053
+
1054
+ describe("service bindings", () => {
1055
+ it("should warn when using service bindings", async () => {
1056
+ writeWranglerToml({
1057
+ services: [
1058
+ { binding: "WorkerA", service: "A" },
1059
+ { binding: "WorkerB", service: "B", environment: "staging" },
1060
+ ],
1061
+ });
1062
+ fs.writeFileSync("index.js", `export default {};`);
1063
+ await runWrangler("dev index.js");
1064
+ expect(std).toMatchInlineSnapshot(`
1065
+ Object {
1066
+ "debug": "",
1067
+ "err": "",
1068
+ "out": "Your worker has access to the following bindings:
1069
+ - Services:
1070
+ - WorkerA: A
1071
+ - WorkerB: B - staging",
1072
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
1073
+
1074
+ - \\"services\\" fields are experimental and may change or break at any time.
1075
+
1076
+
1077
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
1078
+
1079
+ ",
1080
+ }
1081
+ `);
1082
+ });
1083
+ });
1084
+
1085
+ describe("print bindings", () => {
1086
+ it("should print bindings", async () => {
1087
+ writeWranglerToml({
1088
+ services: [
1089
+ { binding: "WorkerA", service: "A" },
1090
+ { binding: "WorkerB", service: "B", environment: "staging" },
1091
+ ],
1092
+ });
1093
+ fs.writeFileSync("index.js", `export default {};`);
1094
+ await runWrangler("dev index.js");
1095
+ expect(std).toMatchInlineSnapshot(`
1096
+ Object {
1097
+ "debug": "",
1098
+ "err": "",
1099
+ "out": "Your worker has access to the following bindings:
1100
+ - Services:
1101
+ - WorkerA: A
1102
+ - WorkerB: B - staging",
1103
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
1104
+
1105
+ - \\"services\\" fields are experimental and may change or break at any time.
1106
+
1107
+
1108
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
1109
+
1110
+ ",
1111
+ }
1112
+ `);
1113
+ });
1114
+
1115
+ it("should mask vars that were overriden in .dev.vars", async () => {
1116
+ writeWranglerToml({
1117
+ vars: {
1118
+ variable: 123,
1119
+ overriden: "original values",
1120
+ },
1121
+ });
1122
+ fs.writeFileSync(
1123
+ ".dev.vars",
1124
+ `
976
1125
  SECRET = "A secret"
977
1126
  overriden = "overriden value"
978
1127
  `
979
- );
980
- fs.writeFileSync("index.js", `export default {};`);
981
- await runWrangler("dev index.js");
982
- expect(std).toMatchInlineSnapshot(`
983
- Object {
984
- "debug": "",
985
- "err": "",
986
- "out": "Using vars defined in .dev.vars
987
- Your worker has access to the following bindings:
988
- - Vars:
989
- - variable: \\"123\\"
990
- - overriden: \\"(hidden)\\"
991
- - SECRET: \\"(hidden)\\"",
992
- "warn": "",
993
- }
994
- `);
995
- });
996
- });
1128
+ );
1129
+ fs.writeFileSync("index.js", `export default {};`);
1130
+ await runWrangler("dev index.js");
1131
+ expect(std).toMatchInlineSnapshot(`
1132
+ Object {
1133
+ "debug": "",
1134
+ "err": "",
1135
+ "out": "Using vars defined in .dev.vars
1136
+ Your worker has access to the following bindings:
1137
+ - Vars:
1138
+ - variable: \\"123\\"
1139
+ - overriden: \\"(hidden)\\"
1140
+ - SECRET: \\"(hidden)\\"",
1141
+ "warn": "",
1142
+ }
1143
+ `);
1144
+ });
1145
+ });
997
1146
  });
998
1147
 
999
1148
  function mockGetZones(domain: string, zones: { id: string }[] = []) {
1000
- const removeMock = setMockResponse(
1001
- "/zones",
1002
- "GET",
1003
- (_urlPieces, _init, queryParams) => {
1004
- expect([...queryParams.entries()]).toEqual([["name", domain]]);
1005
- // Because the API URL `/zones` is the same for each request, we can get into a situation where earlier mocks get triggered for later requests. So, we simply clear the mock on every trigger.
1006
- removeMock();
1007
- return zones;
1008
- }
1009
- );
1149
+ const removeMock = setMockResponse(
1150
+ "/zones",
1151
+ "GET",
1152
+ (_urlPieces, _init, queryParams) => {
1153
+ expect([...queryParams.entries()]).toEqual([["name", domain]]);
1154
+ // Because the API URL `/zones` is the same for each request, we can get into a situation where earlier mocks get triggered for later requests. So, we simply clear the mock on every trigger.
1155
+ removeMock();
1156
+ return zones;
1157
+ }
1158
+ );
1010
1159
  }