wrangler 2.0.7 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@ npx wrangler init my-worker
24
24
  # try it out
25
25
  cd my-worker && npm run start
26
26
  # and then publish it
27
- npm run publish
27
+ npm run deploy
28
28
  ```
29
29
 
30
30
  ## Installation:
package/bin/wrangler.js CHANGED
@@ -1,6 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  const { spawn } = require("child_process");
3
- const { join } = require("path");
3
+ const path = require("path");
4
+ const fs = require("fs");
5
+ const os = require("os");
4
6
  const semiver = require("semiver");
5
7
 
6
8
  const MIN_NODE_VERSION = "16.7.0";
@@ -25,13 +27,23 @@ Consider using a Node.js version manager such as https://volta.sh/ or https://gi
25
27
  // TODO:
26
28
  // - should we log a warning here?
27
29
  // - maybe we can generate a certificate that concatenates with ours?
28
- // - is there a security concern/should we cleanup after we exit?
29
30
  //
30
31
  // I do think it'll be rare that someone wants to add a cert AND
31
32
  // use cloudflare WARP, but let's wait till the situation actually
32
33
  // arises before we do anything about it
33
34
  } else {
34
- pathToCACerts = join(__dirname, "../Cloudflare_CA.pem");
35
+ const osTempDir = os.tmpdir();
36
+ const certDir = path.join(osTempDir, "wrangler-cert");
37
+ const certPath = path.join(certDir, "Cloudflare_CA.pem");
38
+ // copy cert to the system temp dir if needed
39
+ if (!fs.existsSync(certPath)) {
40
+ fs.mkdirSync(certDir, { recursive: true });
41
+ fs.writeFileSync(
42
+ certPath,
43
+ fs.readFileSync(path.join(__dirname, "../Cloudflare_CA.pem"), "utf-8")
44
+ );
45
+ }
46
+ pathToCACerts = certPath;
35
47
  }
36
48
 
37
49
  wranglerProcess = spawn(
@@ -43,7 +55,7 @@ Consider using a Node.js version manager such as https://volta.sh/ or https://gi
43
55
  "--no-warnings",
44
56
  "--experimental-vm-modules",
45
57
  ...process.execArgv,
46
- join(__dirname, "../wrangler-dist/cli.js"),
58
+ path.join(__dirname, "../wrangler-dist/cli.js"),
47
59
  ...process.argv.slice(2),
48
60
  ],
49
61
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wrangler",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "author": "wrangler@cloudflare.com",
5
5
  "description": "Command-line interface for all things Cloudflare Workers",
6
6
  "bin": {
@@ -40,7 +40,7 @@
40
40
  "@esbuild-plugins/node-modules-polyfill": "^0.1.4",
41
41
  "blake3-wasm": "^2.1.5",
42
42
  "esbuild": "0.14.34",
43
- "miniflare": "2.4.0",
43
+ "miniflare": "^2.5.0",
44
44
  "nanoid": "^3.3.3",
45
45
  "path-to-regexp": "^6.2.0",
46
46
  "selfsigned": "^2.0.1",
@@ -61,6 +61,8 @@ describe("normalizeAndValidateConfig()", () => {
61
61
  data_blobs: undefined,
62
62
  workers_dev: undefined,
63
63
  zone_id: undefined,
64
+ minify: undefined,
65
+ node_compat: undefined,
64
66
  });
65
67
  expect(diagnostics.hasErrors()).toBe(false);
66
68
  expect(diagnostics.hasWarnings()).toBe(false);
@@ -163,68 +165,110 @@ describe("normalizeAndValidateConfig()", () => {
163
165
  `);
164
166
  });
165
167
 
166
- it("should override `migrations` config defaults with provided values", () => {
167
- const expectedConfig: RawConfig = {
168
- migrations: [
169
- {
170
- tag: "TAG",
171
- new_classes: ["CLASS_1", "CLASS_2"],
172
- renamed_classes: [
173
- {
174
- from: "FROM_CLASS",
175
- to: "TO_CLASS",
176
- },
177
- ],
178
- deleted_classes: ["CLASS_3", "CLASS_4"],
179
- },
180
- ],
181
- };
168
+ describe("migrations", () => {
169
+ it("should override `migrations` config defaults with provided values", () => {
170
+ const expectedConfig: RawConfig = {
171
+ migrations: [
172
+ {
173
+ tag: "TAG",
174
+ new_classes: ["CLASS_1", "CLASS_2"],
175
+ renamed_classes: [
176
+ {
177
+ from: "FROM_CLASS",
178
+ to: "TO_CLASS",
179
+ },
180
+ ],
181
+ deleted_classes: ["CLASS_3", "CLASS_4"],
182
+ },
183
+ ],
184
+ };
182
185
 
183
- const { config, diagnostics } = normalizeAndValidateConfig(
184
- expectedConfig,
185
- undefined,
186
- { env: undefined }
187
- );
186
+ const { config, diagnostics } = normalizeAndValidateConfig(
187
+ expectedConfig,
188
+ undefined,
189
+ { env: undefined }
190
+ );
188
191
 
189
- expect(config).toEqual(expect.objectContaining(expectedConfig));
190
- expect(diagnostics.hasErrors()).toBe(false);
191
- expect(diagnostics.hasWarnings()).toBe(false);
192
- });
192
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
193
+ expect(diagnostics.hasErrors()).toBe(false);
194
+ expect(diagnostics.hasWarnings()).toBe(false);
195
+ });
193
196
 
194
- it("should error on invalid `migrations` values", () => {
195
- const expectedConfig = {
196
- migrations: [
197
- {
198
- tag: 111,
199
- new_classes: [222, 333],
200
- renamed_classes: [
201
- {
202
- from: 444,
203
- to: 555,
204
- },
205
- ],
206
- deleted_classes: [666, 777],
207
- },
208
- ],
209
- };
197
+ it("should error on invalid `migrations` values", () => {
198
+ const expectedConfig = {
199
+ migrations: [
200
+ {
201
+ tag: 111,
202
+ new_classes: [222, 333],
203
+ renamed_classes: [
204
+ {
205
+ from: 444,
206
+ to: 555,
207
+ },
208
+ ],
209
+ deleted_classes: [666, 777],
210
+ },
211
+ ],
212
+ };
210
213
 
211
- const { config, diagnostics } = normalizeAndValidateConfig(
212
- expectedConfig as unknown as RawConfig,
213
- undefined,
214
- { env: undefined }
215
- );
214
+ const { config, diagnostics } = normalizeAndValidateConfig(
215
+ expectedConfig as unknown as RawConfig,
216
+ undefined,
217
+ { env: undefined }
218
+ );
216
219
 
217
- expect(config).toEqual(expect.objectContaining(expectedConfig));
218
- expect(diagnostics.hasWarnings()).toBe(false);
219
- expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
220
- "Processing wrangler configuration:
221
- - Expected \\"migrations[0].tag\\" to be of type string but got 111.
222
- - Expected \\"migrations[0].new_classes.[0]\\" to be of type string but got 222.
223
- - Expected \\"migrations[0].new_classes.[1]\\" to be of type string but got 333.
224
- - Expected \\"migrations[0].renamed_classes\\" to be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
225
- - Expected \\"migrations[0].deleted_classes.[0]\\" to be of type string but got 666.
226
- - Expected \\"migrations[0].deleted_classes.[1]\\" to be of type string but got 777."
227
- `);
220
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
221
+ expect(diagnostics.hasWarnings()).toBe(false);
222
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
223
+ "Processing wrangler configuration:
224
+ - Expected \\"migrations[0].tag\\" to be of type string but got 111.
225
+ - Expected \\"migrations[0].new_classes.[0]\\" to be of type string but got 222.
226
+ - Expected \\"migrations[0].new_classes.[1]\\" to be of type string but got 333.
227
+ - Expected \\"migrations[0].renamed_classes\\" to be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":444,\\"to\\":555}].
228
+ - Expected \\"migrations[0].deleted_classes.[0]\\" to be of type string but got 666.
229
+ - Expected \\"migrations[0].deleted_classes.[1]\\" to be of type string but got 777."
230
+ `);
231
+ });
232
+
233
+ it("should warn/error on unexpected fields on `migrations`", async () => {
234
+ const expectedConfig = {
235
+ migrations: [
236
+ {
237
+ tag: "TAG",
238
+ new_classes: ["CLASS_1", "CLASS_2"],
239
+ renamed_classes: [
240
+ {
241
+ from: "FROM_CLASS",
242
+ to: "TO_CLASS",
243
+ },
244
+ {
245
+ a: "something",
246
+ b: "someone",
247
+ },
248
+ ],
249
+ deleted_classes: ["CLASS_3", "CLASS_4"],
250
+ unrecognized_field: "FOO",
251
+ },
252
+ ],
253
+ };
254
+
255
+ const { config, diagnostics } = normalizeAndValidateConfig(
256
+ expectedConfig as unknown as RawConfig,
257
+ undefined,
258
+ { env: undefined }
259
+ );
260
+
261
+ expect(config).toEqual(expect.objectContaining(expectedConfig));
262
+ expect(diagnostics.hasErrors()).toBe(true);
263
+ expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
264
+ "Processing wrangler configuration:
265
+ - Unexpected fields found in migrations field: \\"unrecognized_field\\""
266
+ `);
267
+ expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
268
+ "Processing wrangler configuration:
269
+ - Expected \\"migrations[0].renamed_classes\\" to be an array of \\"{from: string, to: string}\\" objects but got [{\\"from\\":\\"FROM_CLASS\\",\\"to\\":\\"TO_CLASS\\"},{\\"a\\":\\"something\\",\\"b\\":\\"someone\\"}]."
270
+ `);
271
+ });
228
272
  });
229
273
 
230
274
  describe("site", () => {
@@ -662,6 +706,8 @@ describe("normalizeAndValidateConfig()", () => {
662
706
  },
663
707
  ],
664
708
  },
709
+ minify: true,
710
+ node_compat: true,
665
711
  };
666
712
 
667
713
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -678,7 +724,15 @@ describe("normalizeAndValidateConfig()", () => {
678
724
  "Processing wrangler configuration:
679
725
  - \\"unsafe\\" fields are experimental and may change or break at any time.
680
726
  - \\"services\\" fields are experimental and may change or break at any time.
681
- - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS1), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details."
727
+ - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS1), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Add this configuration to your wrangler.toml:
728
+
729
+ \`\`\`
730
+ [[migrations]]
731
+ tag = \\"v1\\" # Should be unique for each entry
732
+ new_classes = [\\"CLASS1\\"]
733
+ \`\`\`
734
+
735
+ Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details."
682
736
  `);
683
737
  });
684
738
 
@@ -721,6 +775,8 @@ describe("normalizeAndValidateConfig()", () => {
721
775
  cwd: 1555,
722
776
  watch_dir: 1666,
723
777
  },
778
+ minify: "INVALID",
779
+ node_compat: "INVALID",
724
780
  } as unknown as RawEnvironment;
725
781
 
726
782
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -783,7 +839,9 @@ describe("normalizeAndValidateConfig()", () => {
783
839
  - Expected \\"tsconfig\\" to be of type string but got true.
784
840
  - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
785
841
  - Expected \\"main\\" to be of type string but got 1333.
786
- - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
842
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\".
843
+ - Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
844
+ - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\"."
787
845
  `);
788
846
  });
789
847
 
@@ -1157,12 +1215,9 @@ describe("normalizeAndValidateConfig()", () => {
1157
1215
  durable_objects: { bindings: expect.anything },
1158
1216
  })
1159
1217
  );
1160
- expect(diagnostics.hasWarnings()).toBe(true);
1218
+ expect(diagnostics.hasWarnings()).toBe(false);
1219
+
1161
1220
  expect(diagnostics.hasErrors()).toBe(true);
1162
- expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
1163
- "Processing wrangler configuration:
1164
- - In wrangler.toml, you have configured [durable_objects] exported by this Worker ((unnamed), (unnamed), 1666, SomeClass, 1883), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details."
1165
- `);
1166
1221
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1167
1222
  "Processing wrangler configuration:
1168
1223
 
@@ -1912,6 +1967,8 @@ describe("normalizeAndValidateConfig()", () => {
1912
1967
  cwd: "CWD",
1913
1968
  watch_dir: "WATCH_DIR",
1914
1969
  },
1970
+ minify: true,
1971
+ node_compat: true,
1915
1972
  };
1916
1973
 
1917
1974
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -1952,6 +2009,8 @@ describe("normalizeAndValidateConfig()", () => {
1952
2009
  cwd: "ENV_CWD",
1953
2010
  watch_dir: "ENV_WATCH_DIR",
1954
2011
  },
2012
+ minify: false,
2013
+ node_compat: false,
1955
2014
  };
1956
2015
  const rawConfig: RawConfig = {
1957
2016
  name: "mock-name",
@@ -1971,6 +2030,8 @@ describe("normalizeAndValidateConfig()", () => {
1971
2030
  cwd: "CWD",
1972
2031
  watch_dir: "WATCH_DIR",
1973
2032
  },
2033
+ minify: true,
2034
+ node_compat: true,
1974
2035
  env: {
1975
2036
  ENV1: rawEnv,
1976
2037
  },
@@ -2221,6 +2282,8 @@ describe("normalizeAndValidateConfig()", () => {
2221
2282
  cwd: 1555,
2222
2283
  watch_dir: 1666,
2223
2284
  },
2285
+ minify: "INVALID",
2286
+ node_compat: "INVALID",
2224
2287
  } as unknown as RawEnvironment;
2225
2288
 
2226
2289
  const { config, diagnostics } = normalizeAndValidateConfig(
@@ -2253,7 +2316,9 @@ describe("normalizeAndValidateConfig()", () => {
2253
2316
  - Expected \\"tsconfig\\" to be of type string but got 123.
2254
2317
  - Expected \\"name\\" to be of type string, alphanumeric and lowercase with dashes only but got 111.
2255
2318
  - Expected \\"main\\" to be of type string but got 1333.
2256
- - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\"."
2319
+ - Expected \\"usage_model\\" field to be one of [\\"bundled\\",\\"unbound\\"] but got \\"INVALID\\".
2320
+ - Expected \\"minify\\" to be of type boolean but got \\"INVALID\\".
2321
+ - Expected \\"node_compat\\" to be of type boolean but got \\"INVALID\\"."
2257
2322
  `);
2258
2323
  });
2259
2324
 
@@ -2474,12 +2539,8 @@ describe("normalizeAndValidateConfig()", () => {
2474
2539
  durable_objects: { bindings: expect.anything },
2475
2540
  })
2476
2541
  );
2477
- expect(diagnostics.hasWarnings()).toBe(true);
2542
+ expect(diagnostics.hasWarnings()).toBe(false);
2478
2543
  expect(diagnostics.hasErrors()).toBe(true);
2479
- expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
2480
- "Processing wrangler configuration:
2481
- - In wrangler.toml, you have configured [durable_objects] exported by this Worker ((unnamed), (unnamed), 1666), but no [migrations] for them. This may not work as expected until you add a [migrations] section to your wrangler.toml. Refer to https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml for more details."
2482
- `);
2483
2544
  expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
2484
2545
  "Processing wrangler configuration:
2485
2546
 
@@ -83,7 +83,7 @@ describe("wrangler dev", () => {
83
83
 
84
84
  expect(std.out).toMatchInlineSnapshot(`
85
85
  "
86
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
86
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
87
87
  `);
88
88
  expect(std.err).toMatchInlineSnapshot(`
89
89
  "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.
@@ -467,7 +467,7 @@ describe("wrangler dev", () => {
467
467
  expect(std.out).toMatchInlineSnapshot(`
468
468
  "Running custom build: node -e \\"console.log('custom build');\\"
469
469
 
470
- If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new."
470
+ If you think this is a bug then please create an issue at https://github.com/cloudflare/wrangler2/issues/new/choose"
471
471
  `);
472
472
  expect(std.err).toMatchInlineSnapshot(`
473
473
  "X [ERROR] The expected output file at \\"index.js\\" was not found after running custom build: node -e \\"console.log('custom build');\\".
@@ -698,13 +698,28 @@ describe("wrangler dev", () => {
698
698
  fs.writeFileSync("index.js", `export default {};`);
699
699
  await runWrangler("dev");
700
700
  expect((Dev as jest.Mock).mock.calls[0][0].ip).toEqual("localhost");
701
- expect(std.out).toMatchInlineSnapshot(`""`);
701
+ expect(std.out).toMatchInlineSnapshot(`
702
+ "Your worker has access to the following bindings:
703
+ - Durable Objects:
704
+ - NAME_1: CLASS_1
705
+ - NAME_2: CLASS_2 (defined in SCRIPT_A)
706
+ - NAME_3: CLASS_3
707
+ - NAME_4: CLASS_4 (defined in SCRIPT_B)"
708
+ `);
702
709
  expect(std.warn).toMatchInlineSnapshot(`
703
710
  "▲ [WARNING] Processing wrangler.toml configuration:
704
711
 
705
712
  - In wrangler.toml, you have configured [durable_objects] exported by this Worker (CLASS_1,
706
713
  CLASS_3), but no [migrations] for them. This may not work as expected until you add a [migrations]
707
- section to your wrangler.toml. Refer to
714
+ section to your wrangler.toml. Add this configuration to your wrangler.toml:
715
+
716
+ \`\`\`
717
+ [[migrations]]
718
+ tag = \\"v1\\" # Should be unique for each entry
719
+ new_classes = [\\"CLASS_1\\", \\"CLASS_3\\"]
720
+ \`\`\`
721
+
722
+ Refer to
708
723
  https://developers.cloudflare.com/workers/learning/using-durable-objects/#durable-object-migrations-in-wranglertoml
709
724
  for more details.
710
725
 
@@ -764,9 +779,18 @@ describe("wrangler dev", () => {
764
779
  EMPTY: "",
765
780
  UNQUOTED: "unquoted value", // Note that whitespace is trimmed
766
781
  });
767
- expect(std.out).toMatchInlineSnapshot(
768
- `"Using vars defined in .dev.vars"`
769
- );
782
+ expect(std.out).toMatchInlineSnapshot(`
783
+ "Using vars defined in .dev.vars
784
+ Your worker has access to the following bindings:
785
+ - Vars:
786
+ - VAR_1: \\"(hidden)\\"
787
+ - VAR_2: \\"original value 2\\"
788
+ - VAR_3: \\"(hidden)\\"
789
+ - VAR_MULTI_LINE_1: \\"(hidden)\\"
790
+ - VAR_MULTI_LINE_2: \\"(hidden)\\"
791
+ - EMPTY: \\"(hidden)\\"
792
+ - UNQUOTED: \\"(hidden)\\""
793
+ `);
770
794
  expect(std.warn).toMatchInlineSnapshot(`""`);
771
795
  expect(std.err).toMatchInlineSnapshot(`""`);
772
796
  });
@@ -862,7 +886,10 @@ describe("wrangler dev", () => {
862
886
  Object {
863
887
  "debug": "",
864
888
  "err": "",
865
- "out": "",
889
+ "out": "Your worker has access to the following bindings:
890
+ - Services:
891
+ - WorkerA: A
892
+ - WorkerB: B - staging",
866
893
  "warn": "▲ [WARNING] Processing wrangler.toml configuration:
867
894
 
868
895
  - \\"services\\" fields are experimental and may change or break at any time.
@@ -875,6 +902,68 @@ describe("wrangler dev", () => {
875
902
  `);
876
903
  });
877
904
  });
905
+
906
+ describe("print bindings", () => {
907
+ it("should print bindings", async () => {
908
+ writeWranglerToml({
909
+ services: [
910
+ { binding: "WorkerA", service: "A" },
911
+ { binding: "WorkerB", service: "B", environment: "staging" },
912
+ ],
913
+ });
914
+ fs.writeFileSync("index.js", `export default {};`);
915
+ await runWrangler("dev index.js");
916
+ expect(std).toMatchInlineSnapshot(`
917
+ Object {
918
+ "debug": "",
919
+ "err": "",
920
+ "out": "Your worker has access to the following bindings:
921
+ - Services:
922
+ - WorkerA: A
923
+ - WorkerB: B - staging",
924
+ "warn": "▲ [WARNING] Processing wrangler.toml configuration:
925
+
926
+ - \\"services\\" fields are experimental and may change or break at any time.
927
+
928
+
929
+ ▲ [WARNING] This worker is bound to live services: WorkerA (A), WorkerB (B@staging)
930
+
931
+ ",
932
+ }
933
+ `);
934
+ });
935
+
936
+ it("should mask vars that were overriden in .dev.vars", async () => {
937
+ writeWranglerToml({
938
+ vars: {
939
+ variable: 123,
940
+ overriden: "original values",
941
+ },
942
+ });
943
+ fs.writeFileSync(
944
+ ".dev.vars",
945
+ `
946
+ SECRET = "A secret"
947
+ overriden = "overriden value"
948
+ `
949
+ );
950
+ fs.writeFileSync("index.js", `export default {};`);
951
+ await runWrangler("dev index.js");
952
+ expect(std).toMatchInlineSnapshot(`
953
+ Object {
954
+ "debug": "",
955
+ "err": "",
956
+ "out": "Using vars defined in .dev.vars
957
+ Your worker has access to the following bindings:
958
+ - Vars:
959
+ - variable: \\"123\\"
960
+ - overriden: \\"(hidden)\\"
961
+ - SECRET: \\"(hidden)\\"",
962
+ "warn": "",
963
+ }
964
+ `);
965
+ });
966
+ });
878
967
  });
879
968
 
880
969
  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
+ }