fix(updates): compare prerelease versions correctly (#1220)
Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
This commit is contained in:
committed by
GitHub
co-authored by
Isaac Sanchez
parent
eb3f0e7f72
commit
0cfa37932e
@@ -655,16 +655,35 @@ export async function getLatestVersion() {
|
||||
/**
|
||||
* Compare semver-like version strings.
|
||||
*/
|
||||
function parseVersionForComparison(value) {
|
||||
const normalized = String(value || '').replace(/^v/, '').split('+')[0];
|
||||
const prereleaseIndex = normalized.indexOf('-');
|
||||
const core = prereleaseIndex >= 0 ? normalized.slice(0, prereleaseIndex) : normalized;
|
||||
const parts = core.split('.').map((part) => {
|
||||
const parsed = Number.parseInt(part || '0', 10);
|
||||
return Number.isFinite(parsed) ? parsed : 0;
|
||||
});
|
||||
|
||||
return {
|
||||
parts,
|
||||
prerelease: prereleaseIndex >= 0,
|
||||
};
|
||||
}
|
||||
|
||||
function compareVersions(left, right) {
|
||||
const a = String(left || '').replace(/^v/, '').split('.').map((part) => Number.parseInt(part || '0', 10));
|
||||
const b = String(right || '').replace(/^v/, '').split('.').map((part) => Number.parseInt(part || '0', 10));
|
||||
const length = Math.max(a.length, b.length);
|
||||
const a = parseVersionForComparison(left);
|
||||
const b = parseVersionForComparison(right);
|
||||
const length = Math.max(a.parts.length, b.parts.length);
|
||||
|
||||
for (let index = 0; index < length; index += 1) {
|
||||
const diff = (a[index] || 0) - (b[index] || 0);
|
||||
const diff = (a.parts[index] || 0) - (b.parts[index] || 0);
|
||||
if (diff !== 0) return diff;
|
||||
}
|
||||
|
||||
if (a.prerelease !== b.prerelease) {
|
||||
return a.prerelease ? -1 : 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,14 +34,16 @@ function createFetchMock() {
|
||||
|
||||
describe('checkForUpdates', () => {
|
||||
let fetchMock;
|
||||
let originalFetch;
|
||||
|
||||
beforeEach(() => {
|
||||
fetchMock = createFetchMock();
|
||||
vi.stubGlobal('fetch', fetchMock);
|
||||
originalFetch = globalThis.fetch;
|
||||
globalThis.fetch = fetchMock;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
globalThis.fetch = originalFetch;
|
||||
});
|
||||
|
||||
// --- Scenario: API says update available, npm confirms ---
|
||||
@@ -98,6 +100,21 @@ describe('checkForUpdates', () => {
|
||||
expect(result.available).toBe(false);
|
||||
});
|
||||
|
||||
it('returns available=false when npm only has a prerelease of the current version', async () => {
|
||||
fetchMock
|
||||
.when('api.openchamber.dev', Promise.reject(new Error('Network error')))
|
||||
.when('registry.npmjs.org', {
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
'dist-tags': { latest: '1.10.0-beta.1' },
|
||||
}),
|
||||
});
|
||||
|
||||
const result = await checkForUpdates({ currentVersion: '1.10.0' });
|
||||
|
||||
expect(result.available).toBe(false);
|
||||
});
|
||||
|
||||
it('does not cross-check desktop update claims against npm', async () => {
|
||||
fetchMock
|
||||
.when('api.openchamber.dev', {
|
||||
|
||||
Reference in New Issue
Block a user