Skip to content

Commit f182eaa

Browse files
committed
export functions from dialogs.tsx, pass tests
As mentioned in #124 (comment), it's possible to use regular exports from a module, but still be able to mock their implementations in jest. This PR does so, and passes tests.
1 parent 23543fe commit f182eaa

File tree

3 files changed

+38
-48
lines changed

3 files changed

+38
-48
lines changed

packages/wrangler/src/__tests__/index.test.ts

+30-20
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,39 @@ import * as TOML from "@iarna/toml";
55
import { main } from "../index";
66
import { setMock, unsetAllMocks } from "./mock-cfetch";
77
import { existsSync } from "node:fs";
8-
import { dialogs } from "../dialogs";
8+
import { confirm } from "../dialogs";
99

1010
jest.mock("../cfetch", () => jest.requireActual("./mock-cfetch"));
1111

12+
jest.mock("../dialogs", () => {
13+
return {
14+
// @ts-expect-error typescript doesn't know that jest.requireActual
15+
// returns the 'object' form of the dialogs module
16+
...jest.requireActual("../dialogs"),
17+
confirm: jest.fn().mockName("confirmMock"),
18+
};
19+
});
20+
21+
/**
22+
* Mock the implementation of `confirm()` that will respond with configured results
23+
* for configured confirmation text messages.
24+
*
25+
* If there is a call to `confirm()` that does not match any of the expectations
26+
* then an error is thrown.
27+
*/
28+
function mockConfirm(...expectations: { text: string; result: boolean }[]) {
29+
// @ts-expect-error - we're mocking the implementation of a function
30+
// but typescript doesn't know we've replaced confirm up there
31+
confirm.mockImplementationOnce((text: string) => {
32+
for (const { text: expectedText, result } of expectations) {
33+
if (text === expectedText) {
34+
return result;
35+
}
36+
}
37+
throw new Error(`Unexpected confirmation message: ${text}`);
38+
});
39+
}
40+
1241
async function w(cmd?: string) {
1342
const logSpy = jest.spyOn(console, "log").mockImplementation();
1443
const errorSpy = jest.spyOn(console, "error").mockImplementation();
@@ -222,22 +251,3 @@ describe("wrangler", () => {
222251
});
223252
});
224253
});
225-
226-
/**
227-
* Create a mock version of `confirm()` that will respond with configured results
228-
* for configured confirmation text messages.
229-
*
230-
* If there is a call to `confirm()` that does not match any of the expectations
231-
* then an error is thrown.
232-
*/
233-
function mockConfirm(...expectations: { text: string; result: boolean }[]) {
234-
const mockImplementation = async (text: string) => {
235-
for (const { text: expectedText, result } of expectations) {
236-
if (text === expectedText) {
237-
return result;
238-
}
239-
}
240-
throw new Error(`Unexpected confirmation message: ${text}`);
241-
};
242-
return jest.spyOn(dialogs, "confirm").mockImplementation(mockImplementation);
243-
}

packages/wrangler/src/dialogs.tsx

+2-16
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function Confirm(props: ConfirmProps) {
2323
);
2424
}
2525

26-
function confirm(text: string): Promise<boolean> {
26+
export function confirm(text: string): Promise<boolean> {
2727
return new Promise((resolve) => {
2828
const { unmount } = render(
2929
<Confirm
@@ -61,7 +61,7 @@ function Prompt(props: PromptProps) {
6161
);
6262
}
6363

64-
async function prompt(text: string, type: "text" | "password" = "text") {
64+
export async function prompt(text: string, type: "text" | "password" = "text") {
6565
return new Promise((resolve) => {
6666
const { unmount } = render(
6767
<Prompt
@@ -75,17 +75,3 @@ async function prompt(text: string, type: "text" | "password" = "text") {
7575
);
7676
});
7777
}
78-
79-
// this one feels a little non "standard"
80-
// export async function select(
81-
// title: string,
82-
// choices: { label: string; value: string }[]
83-
// ): Promise<{ label: string; value: string }>{
84-
85-
// }
86-
87-
// Export as an object so that it is easier to mock for testing
88-
export const dialogs = {
89-
confirm,
90-
prompt,
91-
};

packages/wrangler/src/index.tsx

+6-12
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type yargs from "yargs";
88
import { findUp } from "find-up";
99
import TOML from "@iarna/toml";
1010
import type { Config } from "./config";
11-
import { dialogs } from "./dialogs";
11+
import { confirm, prompt } from "./dialogs";
1212
import { version as wranglerVersion } from "../package.json";
1313
import {
1414
login,
@@ -202,7 +202,7 @@ export async function main(argv: string[]): Promise<void> {
202202
const destination = path.join(process.cwd(), "wrangler.toml");
203203
if (fs.existsSync(destination)) {
204204
console.error(`${destination} file already exists!`);
205-
const result = await dialogs.confirm(
205+
const result = await confirm(
206206
"Do you want to continue initializing this project?"
207207
);
208208
if (!result) {
@@ -229,9 +229,7 @@ export async function main(argv: string[]): Promise<void> {
229229

230230
if (!pathToPackageJson) {
231231
if (
232-
await dialogs.confirm(
233-
"No package.json found. Would you like to create one?"
234-
)
232+
await confirm("No package.json found. Would you like to create one?")
235233
) {
236234
await writeFile(
237235
path.join(process.cwd(), "package.json"),
@@ -256,7 +254,7 @@ export async function main(argv: string[]): Promise<void> {
256254
// and make a tsconfig?
257255
let pathToTSConfig = await findUp("tsconfig.json");
258256
if (!pathToTSConfig) {
259-
if (await dialogs.confirm("Would you like to use typescript?")) {
257+
if (await confirm("Would you like to use typescript?")) {
260258
await writeFile(
261259
path.join(process.cwd(), "tsconfig.json"),
262260
JSON.stringify(
@@ -915,7 +913,7 @@ export async function main(argv: string[]): Promise<void> {
915913

916914
// -- snip, end --
917915

918-
const secretValue = await dialogs.prompt(
916+
const secretValue = await prompt(
919917
"Enter a secret value:",
920918
"password"
921919
);
@@ -1015,11 +1013,7 @@ export async function main(argv: string[]): Promise<void> {
10151013

10161014
// -- snip, end --
10171015

1018-
if (
1019-
await dialogs.confirm(
1020-
"Are you sure you want to delete this secret?"
1021-
)
1022-
) {
1016+
if (await confirm("Are you sure you want to delete this secret?")) {
10231017
console.log(
10241018
`Deleting the secret ${args.key} on script ${scriptName}.`
10251019
);

0 commit comments

Comments
 (0)