Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/update/notify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function gt(a: number[], b: number[]): boolean {
export function isNewer(latest: string, current: string, channel: Channel): boolean {
if (channel === "latest") {
const l = parseStable(latest);
const c = parseStable(current);
const c = parseStable(current) ?? parsePreview(current)?.slice(0, 3);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Parse multi-component preview identifiers

When the installed build has a supported multi-component prerelease such as 2.8.2-preview.20260731.2, parsePreview() rejects it because its regex permits exactly one numeric component after preview. The release tooling accepts this form, and tests/release-notes.test.ts explicitly exercises same-day suffixes such as .2 and .10; consequently this branch still returns false and the GUI/API reports already_latest even when stable 2.9.1 is available. Parse the core independently of the complete prerelease identifier, or allow all supported numeric components, and cover this form in the update tests.

Useful? React with 👍 / 👎.

if (!l || !c) return false;
return gt(l, c);
}
Expand Down
18 changes: 18 additions & 0 deletions tests/update-job.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,24 @@ describe("GUI update check", () => {
expect(result.canUpdate).toBe(false);
expect(result.reason).toBe("already_latest");
});

test("offers a stable update from an older preview but not the same base", () => {
const olderPreview = checkForUpdate("latest", {
currentVersion: () => "2.8.2-preview.20260731",
detectInstall: () => "npm",
latestVersion: () => "2.9.1",
});
expect(olderPreview.updateAvailable).toBe(true);
expect(olderPreview.canUpdate).toBe(true);

const sameBasePreview = checkForUpdate("latest", {
currentVersion: () => "2.9.1-preview.20260731",
detectInstall: () => "npm",
latestVersion: () => "2.9.1",
});
expect(sameBasePreview.updateAvailable).toBe(false);
expect(sameBasePreview.canUpdate).toBe(false);
});
});

describe("GUI update execution decisions", () => {
Expand Down
4 changes: 4 additions & 0 deletions tests/update-notify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ describe("isNewer — latest channel", () => {
test("prereleases are ignored on the stable channel", () => {
expect(isNewer("2.7.0-preview.1", "2.6.4", "latest")).toBe(false);
});
test("stable releases compare against a preview current by its base version", () => {
expect(isNewer("2.9.1", "2.8.2-preview.20260731", "latest")).toBe(true);
expect(isNewer("2.9.1", "2.9.1-preview.20260731", "latest")).toBe(false);
});
});

describe("isNewer — preview channel", () => {
Expand Down
Loading