Skip to content

Commit 14a651c

Browse files
authored
feat(vscode): add changelog button to warning message (#822)
1 parent 9e8a351 commit 14a651c

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed

extensions/vscode/src/extension.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
readDartFrogCLIVersion,
1111
isCompatibleDartFrogCLIVersion,
1212
isDartFrogCLIInstalled,
13+
openChangelog,
14+
readLatestDartFrogCLIVersion,
1315
} from "./utils";
1416

1517
/**
@@ -105,15 +107,24 @@ export async function ensureCompatibleDartFrogCLI(): Promise<void> {
105107
return;
106108
}
107109

110+
const latestVersion = readLatestDartFrogCLIVersion();
111+
if (!latestVersion) {
112+
return;
113+
}
114+
108115
const selection = await vscode.window.showWarningMessage(
109116
`Dart Frog CLI version ${version} is not compatible with this extension.`,
110117
"Update Dart Frog CLI",
118+
"Changelog",
111119
"Ignore"
112120
);
113121
switch (selection) {
114122
case "Update Dart Frog CLI":
115123
updateCLI();
116124
break;
125+
case "Changelog":
126+
openChangelog(latestVersion);
127+
break;
117128
case "Ignore":
118129
break;
119130
default:

extensions/vscode/src/test/suite/extension.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,11 +222,16 @@ suite("ensureCompatibleDartFrogCLI", () => {
222222
window: {
223223
showWarningMessage: sinon.stub(),
224224
},
225+
commands: {
226+
executeCommand: sinon.stub(),
227+
},
225228
};
226229

227230
utilsStub = {
228231
readDartFrogCLIVersion: sinon.stub(),
229232
isCompatibleDartFrogCLIVersion: sinon.stub(),
233+
readLatestDartFrogCLIVersion: sinon.stub(),
234+
openChangelog: sinon.stub(),
230235
};
231236
commandsStub = {
232237
updateCLI: sinon.stub(),
@@ -262,12 +267,23 @@ suite("ensureCompatibleDartFrogCLI", () => {
262267
sinon.assert.notCalled(vscodeStub.window.showWarningMessage);
263268
});
264269

270+
test("does not show warning when latest version cannot be retrieved", async () => {
271+
utilsStub.readDartFrogCLIVersion.returns("1.0.0");
272+
utilsStub.isCompatibleDartFrogCLIVersion.returns(false);
273+
utilsStub.readLatestDartFrogCLIVersion.returns(undefined);
274+
275+
await extension.ensureCompatibleDartFrogCLI();
276+
277+
sinon.assert.notCalled(vscodeStub.window.showWarningMessage);
278+
});
279+
265280
suite("incompatible CLI", () => {
266281
const version = "0.0.0";
267282

268283
beforeEach(() => {
269284
utilsStub.readDartFrogCLIVersion.returns(version);
270285
utilsStub.isCompatibleDartFrogCLIVersion.returns(false);
286+
utilsStub.readLatestDartFrogCLIVersion.returns(version);
271287
});
272288

273289
afterEach(() => {
@@ -281,6 +297,7 @@ suite("ensureCompatibleDartFrogCLI", () => {
281297
vscodeStub.window.showWarningMessage,
282298
`Dart Frog CLI version ${version} is not compatible with this extension.`,
283299
"Update Dart Frog CLI",
300+
"Changelog",
284301
"Ignore"
285302
);
286303
});
@@ -293,6 +310,15 @@ suite("ensureCompatibleDartFrogCLI", () => {
293310
sinon.assert.calledOnce(commandsStub.updateCLI);
294311
});
295312

313+
test("opens changelog when selected", async () => {
314+
vscodeStub.window.showWarningMessage.returns("Changelog");
315+
316+
await extension.ensureCompatibleDartFrogCLI();
317+
318+
sinon.assert.calledOnceWithExactly(utilsStub.openChangelog, version);
319+
sinon.assert.notCalled(commandsStub.updateCLI);
320+
});
321+
296322
test("does not update CLI when ignored", async () => {
297323
vscodeStub.window.showWarningMessage.returns("Ignore");
298324

extensions/vscode/src/test/suite/utils/cli-version.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,59 @@ suite("readDartFrogCLIVersion", () => {
6060
});
6161
});
6262

63+
suite("readLatestDartFrogCLIVersion", () => {
64+
let cpStub: any;
65+
let cliVersion: any;
66+
67+
beforeEach(() => {
68+
cpStub = {
69+
execSync: sinon.stub(),
70+
};
71+
72+
cliVersion = proxyquire("../../../utils/cli-version", {
73+
// eslint-disable-next-line @typescript-eslint/naming-convention
74+
child_process: cpStub,
75+
});
76+
});
77+
78+
afterEach(() => {
79+
sinon.restore();
80+
});
81+
82+
suite("returns the latest version of Dart Frog CLI", () => {
83+
test("when on latest version", () => {
84+
const dartFrogVersionCommandResult = "0.3.9\n";
85+
const encodedDartFrogVersionCommandResult = new TextEncoder().encode(
86+
dartFrogVersionCommandResult
87+
);
88+
cpStub.execSync.returns(encodedDartFrogVersionCommandResult);
89+
90+
assert.strictEqual(cliVersion.readLatestDartFrogCLIVersion(), "0.3.9");
91+
});
92+
93+
test("when new version is available", () => {
94+
const dartFrogVersionCommandResult = `0.3.7
95+
96+
Update available! 0.3.7 → 0.3.9
97+
Changelog: \u001b]8;;https://github.com/verygoodopensource/dart_frog/releases/tag/dart_frog_cli-v0.3.9\u001b\\https://github.com/verygoodopensource/dart_frog/releases/tag/dart_frog_cli-v0.3.9\u001b]8;;\u001b\\
98+
Run dart_frog update to update
99+
`;
100+
const encodedDartFrogVersionCommandResult = new TextEncoder().encode(
101+
dartFrogVersionCommandResult
102+
);
103+
cpStub.execSync.returns(encodedDartFrogVersionCommandResult);
104+
105+
assert.strictEqual(cliVersion.readLatestDartFrogCLIVersion(), "0.3.9");
106+
});
107+
});
108+
109+
test("returns undefined if Dart Frog CLI is not installed", () => {
110+
cpStub.execSync.throws();
111+
112+
assert.strictEqual(cliVersion.readLatestDartFrogCLIVersion(), undefined);
113+
});
114+
});
115+
63116
suite("isCompatibleDartFrogCLIVersion", () => {
64117
let cliVersion: any;
65118

@@ -89,3 +142,42 @@ suite("isCompatibleDartFrogCLIVersion", () => {
89142
);
90143
});
91144
});
145+
146+
suite("openChangelog", () => {
147+
let vscodeStub: any;
148+
let cliVersion: any;
149+
150+
beforeEach(() => {
151+
vscodeStub = {
152+
commands: {
153+
executeCommand: sinon.stub(),
154+
},
155+
// eslint-disable-next-line @typescript-eslint/naming-convention
156+
Uri: {
157+
parse: sinon.stub(),
158+
},
159+
};
160+
161+
cliVersion = proxyquire("../../../utils/cli-version", {
162+
vscode: vscodeStub,
163+
});
164+
});
165+
166+
afterEach(() => {
167+
sinon.restore();
168+
});
169+
170+
test("triggers vscode.open command with correct url", async () => {
171+
const version = "0.0.0";
172+
const url = "https://github.com";
173+
vscodeStub.Uri.parse.returns(url);
174+
175+
await cliVersion.openChangelog(version);
176+
177+
sinon.assert.calledOnceWithExactly(
178+
vscodeStub.commands.executeCommand,
179+
"vscode.open",
180+
url
181+
);
182+
});
183+
});

extensions/vscode/src/utils/cli-version.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as vscode from "vscode";
12
const cp = require("child_process");
23
const semver = require("semver");
34

@@ -23,6 +24,26 @@ export function readDartFrogCLIVersion(): String | undefined {
2324
}
2425
}
2526

27+
/**
28+
* Collects the latest available version of Dart Frog CLI.
29+
*
30+
* @returns {String | undefined} The latest available semantic version of
31+
* Dart Frog CLI, or undefined if Dart Frog CLI is not installed.
32+
*/
33+
export function readLatestDartFrogCLIVersion(): String | undefined {
34+
try {
35+
const result = cp.execSync(`dart_frog --version`);
36+
const decodedResult = new TextDecoder().decode(result);
37+
const lines = decodedResult.split("\n");
38+
if (lines.length <= 2) {
39+
return lines.at(0);
40+
}
41+
return lines.at(2)?.split(" ").at(-1);
42+
} catch (error) {
43+
return undefined;
44+
}
45+
}
46+
2647
/**
2748
* Checks if the version of Dart Frog CLI installed in the user's system is
2849
* compatible with this extension.
@@ -46,3 +67,18 @@ export function isCompatibleDartFrogCLIVersion(version: String): Boolean {
4667
export function isDartFrogCLIInstalled(): boolean {
4768
return readDartFrogCLIVersion() !== undefined;
4869
}
70+
71+
/**
72+
* Opens the changelog for the specified version in a browser.
73+
*
74+
* @param {String} version The semantic version of Dart Frog CLI which changelog
75+
* is requested to open.
76+
*/
77+
export async function openChangelog(version: String): Promise<void> {
78+
vscode.commands.executeCommand(
79+
"vscode.open",
80+
vscode.Uri.parse(
81+
`https://github.com/verygoodopensource/dart_frog/releases/tag/dart_frog_cli-v${version}`
82+
)
83+
);
84+
}

0 commit comments

Comments
 (0)