Skip to content

Commit 1fb134a

Browse files
authored
fix(vscode): suggest again to install the Dart Frog CLI before running a command that requires of Dart Frog CLI if not installed (#870)
1 parent cf62a96 commit 1fb134a

13 files changed

+252
-113
lines changed

extensions/vscode/src/commands/create.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ProgressOptions,
99
OpenDialogOptions,
1010
} from "vscode";
11+
import { isDartFrogCLIInstalled, suggestInstallingDartFrogCLI } from "../utils";
1112

1213
/**
1314
* Creates a new Dart Frog project.
@@ -33,6 +34,12 @@ import {
3334
* @see {@link https://github.com/VeryGoodOpenSource/dart_frog/blob/main/packages/dart_frog_cli/lib/src/commands/create/create.dart Dart Frog CLI `create` command implementation.}
3435
*/
3536
export const create = async (uri: Uri | undefined): Promise<void> => {
37+
if (!isDartFrogCLIInstalled()) {
38+
await suggestInstallingDartFrogCLI(
39+
"Running this command requires Dart Frog CLI to be installed."
40+
);
41+
}
42+
3643
let outputDirectory =
3744
uri === undefined ? await promptForTargetDirectory() : uri.fsPath;
3845

extensions/vscode/src/commands/install-cli.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,15 @@ export const installCLI = async (): Promise<void> => {
2323
* complete.
2424
*/
2525
async function installDartFrogCliVersion(): Promise<void> {
26-
await cp.exec(
27-
`dart pub global activate dart_frog_cli`,
28-
function (error: Error, stdout: string, stderr: string) {
29-
if (error) {
30-
window.showErrorMessage(error.message);
31-
}
26+
try {
27+
await cp.execSync(`dart pub global activate dart_frog_cli`);
28+
} catch (error: any) {
29+
if (error instanceof Error) {
30+
window.showErrorMessage(error.message);
31+
} else {
32+
window.showErrorMessage(
33+
`An error occurred while installing Dart Frog CLI: ${error}`
34+
);
3235
}
33-
);
36+
}
3437
}

extensions/vscode/src/commands/new-middleware.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import {
88
InputBoxOptions,
99
} from "vscode";
1010
import {
11+
isDartFrogCLIInstalled,
1112
nearestDartFrogProject,
1213
normalizeRoutePath,
1314
resolveDartFrogProjectPathFromWorkspace,
15+
suggestInstallingDartFrogCLI,
1416
} from "../utils";
1517

1618
/**
@@ -34,6 +36,12 @@ import {
3436
* @param {Uri | undefined} uri
3537
*/
3638
export const newMiddleware = async (uri: Uri | undefined): Promise<void> => {
39+
if (!isDartFrogCLIInstalled()) {
40+
await suggestInstallingDartFrogCLI(
41+
"Running this command requires Dart Frog CLI to be installed."
42+
);
43+
}
44+
3745
let selectedPath;
3846
if (uri === undefined) {
3947
selectedPath = resolveDartFrogProjectPathFromWorkspace();

extensions/vscode/src/commands/new-route.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import {
88
ProgressOptions,
99
} from "vscode";
1010
import {
11+
isDartFrogCLIInstalled,
1112
nearestDartFrogProject,
1213
normalizeRoutePath,
1314
resolveDartFrogProjectPathFromWorkspace,
15+
suggestInstallingDartFrogCLI,
1416
} from "../utils";
1517

1618
/**
@@ -34,6 +36,12 @@ import {
3436
* @param {Uri | undefined} uri
3537
*/
3638
export const newRoute = async (uri: Uri | undefined): Promise<void> => {
39+
if (!isDartFrogCLIInstalled()) {
40+
await suggestInstallingDartFrogCLI(
41+
"Running this command requires Dart Frog CLI to be installed."
42+
);
43+
}
44+
3745
let selectedPath;
3846
if (uri === undefined) {
3947
selectedPath = resolveDartFrogProjectPathFromWorkspace();

extensions/vscode/src/extension.ts

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
isDartFrogCLIInstalled,
1313
openChangelog,
1414
readLatestDartFrogCLIVersion,
15+
suggestInstallingDartFrogCLI,
1516
} from "./utils";
1617

1718
/**
@@ -27,11 +28,10 @@ import {
2728
*/
2829
export function activate(
2930
context: vscode.ExtensionContext,
30-
suggestInstallingCLI: () => Promise<void> = suggestInstallingDartFrogCLI,
3131
ensureCompatibleCLI: () => Promise<void> = ensureCompatibleDartFrogCLI
3232
): vscode.ExtensionContext {
3333
if (!isDartFrogCLIInstalled()) {
34-
suggestInstallingCLI();
34+
suggestInstallingDartFrogCLI();
3535
} else {
3636
ensureCompatibleCLI();
3737
}
@@ -46,35 +46,6 @@ export function activate(
4646
return context;
4747
}
4848

49-
/**
50-
* Suggests the user to install Dart Frog CLI.
51-
*
52-
* This method should be called upon activation of the extension whenever
53-
* Dart Frog CLI is not installed in the user's system.
54-
*
55-
* It prompts the user to install Dart Frog CLI. This is optional, the user
56-
* can choose to install Dart Frog CLI at a later time but the extension may
57-
* not work as intended until Dart Frog CLI is installed.
58-
*
59-
* @see {@link isDartFrogCLIInstalled}, to check if Dart Frog CLI is installed
60-
*/
61-
export async function suggestInstallingDartFrogCLI(): Promise<void> {
62-
const selection = await vscode.window.showWarningMessage(
63-
"Dart Frog CLI is not installed. Install Dart Frog CLI to use this extension.",
64-
"Install Dart Frog CLI",
65-
"Ignore"
66-
);
67-
switch (selection) {
68-
case "Install Dart Frog CLI":
69-
await installCLI();
70-
break;
71-
case "Ignore":
72-
break;
73-
default:
74-
break;
75-
}
76-
}
77-
7849
/**
7950
* Checks if the version of Dart Frog CLI installed in the user's system is
8051
* compatible with this extension, suggesting to install if it is not.

extensions/vscode/src/test/suite/commands/create.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ suite("create command", () => {
88

99
let vscodeStub: any;
1010
let childProcessStub: any;
11+
let utilsStub: any;
1112
let command: any;
1213

1314
beforeEach(() => {
@@ -22,18 +23,44 @@ suite("create command", () => {
2223
childProcessStub = {
2324
exec: sinon.stub(),
2425
};
26+
utilsStub = {
27+
isDartFrogCLIInstalled: sinon.stub(),
28+
suggestInstallingDartFrogCLI: sinon.stub(),
29+
};
30+
utilsStub.isDartFrogCLIInstalled.returns(true);
2531

2632
command = proxyquire("../../../commands/create", {
2733
vscode: vscodeStub,
2834
// eslint-disable-next-line @typescript-eslint/naming-convention
2935
child_process: childProcessStub,
36+
// eslint-disable-next-line @typescript-eslint/naming-convention
37+
"../utils": utilsStub,
3038
});
3139
});
3240

3341
afterEach(() => {
3442
sinon.restore();
3543
});
3644

45+
test("suggests installing Dart Frog CLI when not installed", async () => {
46+
utilsStub.isDartFrogCLIInstalled.returns(false);
47+
48+
await command.create(targetUri);
49+
50+
sinon.assert.calledWith(
51+
utilsStub.suggestInstallingDartFrogCLI,
52+
"Running this command requires Dart Frog CLI to be installed."
53+
);
54+
});
55+
56+
test("does not suggest installing Dart Frog CLI when installed", async () => {
57+
utilsStub.isDartFrogCLIInstalled.returns(true);
58+
59+
await command.create(targetUri);
60+
61+
sinon.assert.notCalled(utilsStub.suggestInstallingDartFrogCLI);
62+
});
63+
3764
test("project input box is shown with directory name as value", async () => {
3865
await command.create(targetUri);
3966

extensions/vscode/src/test/suite/commands/install-cli.test.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ suite("install-cli command", () => {
2020
},
2121
};
2222
childProcessStub = {
23-
exec: sinon.stub(),
2423
execSync: sinon.stub(),
2524
};
2625
utilsStub = {
@@ -45,10 +44,7 @@ suite("install-cli command", () => {
4544

4645
await command.installCLI();
4746

48-
const wantedCalls = childProcessStub.exec
49-
.getCalls()
50-
.filter((call: any) => call.args[0] === installCommand);
51-
assert.equal(wantedCalls.length, 0);
47+
sinon.assert.notCalled(childProcessStub.execSync);
5248
});
5349

5450
suite("installs Dart Frog CLI", () => {
@@ -62,7 +58,7 @@ suite("install-cli command", () => {
6258
let progressFunction = vscodeStub.window.withProgress.getCall(0).args[1];
6359
await progressFunction();
6460

65-
sinon.assert.calledWith(childProcessStub.exec, installCommand);
61+
sinon.assert.calledWith(childProcessStub.execSync, installCommand);
6662
});
6763

6864
test("shows progress", async () => {
@@ -76,7 +72,7 @@ suite("install-cli command", () => {
7672

7773
test("shows error message on failure", async () => {
7874
const error = new Error("Command failed");
79-
childProcessStub.exec.withArgs(installCommand).yields(error);
75+
childProcessStub.execSync.withArgs(installCommand).throws(error);
8076

8177
await command.installCLI();
8278

@@ -89,5 +85,21 @@ suite("install-cli command", () => {
8985
error.message
9086
);
9187
});
88+
89+
test("shows unknown error message on unknown failure", async () => {
90+
const error = 2;
91+
childProcessStub.execSync.withArgs(installCommand).throws(error);
92+
93+
await command.installCLI();
94+
95+
const progressFunction =
96+
vscodeStub.window.withProgress.getCall(0).args[1];
97+
await progressFunction();
98+
99+
sinon.assert.calledWith(
100+
vscodeStub.window.showErrorMessage,
101+
`An error occurred while installing Dart Frog CLI: ${error}`
102+
);
103+
});
92104
});
93105
});

extensions/vscode/src/test/suite/commands/new-middleware.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@ suite("new-middleware command", () => {
2929
nearestDartFrogProject: sinon.stub(),
3030
normalizeRoutePath: sinon.stub(),
3131
resolveDartFrogProjectPathFromWorkspace: sinon.stub(),
32+
isDartFrogCLIInstalled: sinon.stub(),
33+
suggestInstallingDartFrogCLI: sinon.stub(),
3234
};
35+
utilsStub.isDartFrogCLIInstalled.returns(true);
3336

3437
utilsStub.nearestDartFrogProject
3538
.withArgs(invalidUri.fsPath)
@@ -51,6 +54,25 @@ suite("new-middleware command", () => {
5154
sinon.restore();
5255
});
5356

57+
test("suggests installing Dart Frog CLI when not installed", async () => {
58+
utilsStub.isDartFrogCLIInstalled.returns(false);
59+
60+
await command.newMiddleware(validUri);
61+
62+
sinon.assert.calledWith(
63+
utilsStub.suggestInstallingDartFrogCLI,
64+
"Running this command requires Dart Frog CLI to be installed."
65+
);
66+
});
67+
68+
test("does not suggest installing Dart Frog CLI when installed", async () => {
69+
utilsStub.isDartFrogCLIInstalled.returns(true);
70+
71+
await command.newMiddleware(validUri);
72+
73+
sinon.assert.notCalled(utilsStub.suggestInstallingDartFrogCLI);
74+
});
75+
5476
suite("file open dialog", () => {
5577
test("is shown when Uri is undefined and fails to resolve a path from workspace", async () => {
5678
vscodeStub.window.showOpenDialog.resolves();

extensions/vscode/src/test/suite/commands/new-route.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ suite("new-route command", () => {
3131
nearestDartFrogProject: sinon.stub(),
3232
normalizeRoutePath: sinon.stub(),
3333
resolveDartFrogProjectPathFromWorkspace: sinon.stub(),
34+
isDartFrogCLIInstalled: sinon.stub(),
35+
suggestInstallingDartFrogCLI: sinon.stub(),
3436
};
3537

3638
utilsStub.nearestDartFrogProject
@@ -39,6 +41,8 @@ suite("new-route command", () => {
3941
utilsStub.nearestDartFrogProject
4042
.withArgs(validUri.fsPath)
4143
.returns(validUri.fsPath);
44+
utilsStub.isDartFrogCLIInstalled.returns(true);
45+
utilsStub.suggestInstallingDartFrogCLI.resolves();
4246

4347
command = proxyquire("../../../commands/new-route", {
4448
vscode: vscodeStub,
@@ -53,6 +57,27 @@ suite("new-route command", () => {
5357
sinon.restore();
5458
});
5559

60+
test("suggests installing Dart Frog CLI when not installed", async () => {
61+
utilsStub.isDartFrogCLIInstalled.returns(false);
62+
utilsStub.normalizeRoutePath.returns("/");
63+
64+
await command.newRoute(validUri);
65+
66+
sinon.assert.calledWith(
67+
utilsStub.suggestInstallingDartFrogCLI,
68+
"Running this command requires Dart Frog CLI to be installed."
69+
);
70+
});
71+
72+
test("does not suggest installing Dart Frog CLI when installed", async () => {
73+
utilsStub.isDartFrogCLIInstalled.returns(true);
74+
utilsStub.normalizeRoutePath.returns("/");
75+
76+
await command.newRoute(validUri);
77+
78+
sinon.assert.notCalled(utilsStub.suggestInstallingDartFrogCLI);
79+
});
80+
5681
suite("shows input box to input route path", () => {
5782
test("without suffixing / when not required", async () => {
5883
utilsStub.normalizeRoutePath.returns("/");

0 commit comments

Comments
 (0)