diff --git a/src/update/notify.ts b/src/update/notify.ts index 6a6ad98631..60441b1e3a 100644 --- a/src/update/notify.ts +++ b/src/update/notify.ts @@ -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); if (!l || !c) return false; return gt(l, c); } diff --git a/tests/update-job.test.ts b/tests/update-job.test.ts index d7ac75c166..93c393220b 100644 --- a/tests/update-job.test.ts +++ b/tests/update-job.test.ts @@ -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", () => { diff --git a/tests/update-notify.test.ts b/tests/update-notify.test.ts index 39377032d1..a6f200cd51 100644 --- a/tests/update-notify.test.ts +++ b/tests/update-notify.test.ts @@ -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", () => {