Skip to content

Commit 17a1b3b

Browse files
committed
Add tests for askQuestion function and refactor main function for better error handling
1 parent 2aee9c0 commit 17a1b3b

File tree

2 files changed

+53
-7
lines changed

2 files changed

+53
-7
lines changed

lib/src/index.test.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { describe, it, expect, vi } from "vitest";
2+
import readline from "readline";
3+
import { execSync } from "child_process";
4+
import { askQuestion } from ".";
5+
6+
vi.mock("child_process");
7+
8+
describe("askQuestion", () => {
9+
it("resolves with user input", async () => {
10+
const mockInterface = {
11+
question: vi.fn((_q: string, cb: (ans: string) => void) => cb("my-app")),
12+
close: vi.fn(),
13+
} as unknown as readline.Interface;
14+
15+
vi.spyOn(readline, "createInterface").mockReturnValue(mockInterface);
16+
17+
const answer = await askQuestion("Project name?");
18+
expect(answer).toBe("my-app");
19+
});
20+
21+
it("resolves with empty string if input is empty", async () => {
22+
const mockInterface = {
23+
question: vi.fn((_q: string, cb: (ans: string) => void) => cb("")),
24+
close: vi.fn(),
25+
} as unknown as readline.Interface;
26+
27+
vi.spyOn(readline, "createInterface").mockReturnValue(mockInterface);
28+
29+
const answer = await askQuestion("Project name?");
30+
expect(answer).toBe("");
31+
});
32+
});
33+
34+
describe("error handling", () => {
35+
it("handles execSync errors gracefully", () => {
36+
(execSync as unknown as ReturnType<typeof vi.fn>).mockImplementation(() => {
37+
throw new Error("mock failure");
38+
});
39+
40+
try {
41+
execSync("pnpm dlx create-turbo");
42+
} catch (err: any) {
43+
expect(err.message).toContain("mock failure");
44+
}
45+
});
46+
});

lib/src/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import readline from "readline";
2020

2121
const DEFAULT_NAME = "react18-tools-turborepo-template";
2222

23-
function askQuestion(query: string): Promise<string> {
23+
export const askQuestion = (query: string): Promise<string> => {
2424
const rl = readline.createInterface({
2525
input: process.stdin,
2626
output: process.stdout,
@@ -31,9 +31,9 @@ function askQuestion(query: string): Promise<string> {
3131
resolve(ans);
3232
}),
3333
);
34-
}
34+
};
3535

36-
async function main(): Promise<void> {
36+
const main = async (): Promise<void> => {
3737
let projectName = process.argv[2];
3838

3939
if (!projectName) {
@@ -51,13 +51,13 @@ async function main(): Promise<void> {
5151
execSync(cmd, { stdio: "inherit" });
5252
} catch (err: any) {
5353
console.error("❌ Error while running create-turbo:", err.message);
54-
process.exit(1);
54+
return;
5555
}
5656

5757
// Step 2: Verify directory exists
5858
if (!existsSync(projectDir)) {
5959
console.error(`❌ Expected directory not found: ${projectDir}`);
60-
process.exit(1);
60+
return;
6161
}
6262

6363
// Step 3: Run rebrand
@@ -69,10 +69,10 @@ async function main(): Promise<void> {
6969
});
7070
} catch (err: any) {
7171
console.error("❌ Rebrand step failed:", err.message);
72-
process.exit(1);
72+
return;
7373
}
7474

7575
console.log(`\n✅ Done! Your project is ready in: ${projectDir}\n`);
76-
}
76+
};
7777

7878
main();

0 commit comments

Comments
 (0)