diff --git a/src/utils/get-chromium-tags.ts b/src/utils/get-chromium-tags.ts index 238820e..0d494cf 100644 --- a/src/utils/get-chromium-tags.ts +++ b/src/utils/get-chromium-tags.ts @@ -1,3 +1,5 @@ +import { compareChromiumVersions } from './compare-chromium-versions.js'; + type ReleaseType = 'Extended' | 'Stable' | 'Beta' | 'Dev' | 'Canary'; export type ReleaseParams = { @@ -30,5 +32,10 @@ export async function getChromiumReleases({ throw new Error(`Failed to fetch Chromium releases: ${response.status}`); } const releases = (await response.json()) as Release[]; - return releases.sort((a, b) => a.time - b.time).map((r) => r.version); + // Order by version rather than release time: channels (Extended, Stable, + // Beta, ...) and platforms within a milestone ship on their own schedules, + // so the most recently released entry is not necessarily the newest version. + return releases + .sort((a, b) => compareChromiumVersions(a.version, b.version)) + .map((r) => r.version); } diff --git a/tests/utils/get-chromium-tags.spec.ts b/tests/utils/get-chromium-tags.spec.ts new file mode 100644 index 0000000..312b11f --- /dev/null +++ b/tests/utils/get-chromium-tags.spec.ts @@ -0,0 +1,92 @@ +import nock from 'nock'; +import { afterEach, describe, expect, it } from 'vitest'; + +import { getChromiumReleases, Release } from '../../src/utils/get-chromium-tags.js'; + +describe('getChromiumReleases', () => { + afterEach(() => { + nock.cleanAll(); + }); + + function mockReleases(releases: Partial[]) { + return nock('https://chromiumdash.appspot.com') + .get('/fetch_releases') + .query(true) + .reply(200, releases); + } + + it('orders releases by version rather than by release time', async () => { + // An Extended release can go out after a Stable or Beta release in the + // same milestone while still carrying an older version. + mockReleases([ + { + channel: 'Extended', + platform: 'Windows', + milestone: 156, + time: 4000, + version: '156.0.8078.13', + }, + { + channel: 'Stable', + platform: 'Windows', + milestone: 156, + time: 3000, + version: '156.0.8078.12', + }, + { + channel: 'Beta', + platform: 'Windows', + milestone: 156, + time: 2000, + version: '156.0.8078.17', + }, + { channel: 'Beta', platform: 'Mac', milestone: 156, time: 1000, version: '156.0.8078.4' }, + ]); + + const releases = await getChromiumReleases({ milestone: 156 }); + + expect(releases).toEqual(['156.0.8078.4', '156.0.8078.12', '156.0.8078.13', '156.0.8078.17']); + expect(releases[releases.length - 1]).toEqual('156.0.8078.17'); + }); + + it('compares version components numerically', async () => { + mockReleases([ + { channel: 'Stable', platform: 'Linux', milestone: 156, time: 2000, version: '156.0.8078.9' }, + { + channel: 'Stable', + platform: 'Linux', + milestone: 156, + time: 1000, + version: '156.0.8078.10', + }, + ]); + + await expect(getChromiumReleases({ milestone: 156 })).resolves.toEqual([ + '156.0.8078.9', + '156.0.8078.10', + ]); + }); + + it('passes the channel and milestone filters to chromiumdash', async () => { + const scope = nock('https://chromiumdash.appspot.com') + .get('/fetch_releases') + .query({ + platform: 'Win32,Windows,Linux,Mac', + num: '10', + channel: 'Canary', + milestone: '157', + }) + .reply(200, []); + + await expect(getChromiumReleases({ channel: 'Canary', milestone: 157 })).resolves.toEqual([]); + expect(scope.isDone()).toBe(true); + }); + + it('throws when chromiumdash responds with an error', async () => { + nock('https://chromiumdash.appspot.com').get('/fetch_releases').query(true).reply(500); + + await expect(getChromiumReleases({ milestone: 156 })).rejects.toThrow( + 'Failed to fetch Chromium releases: 500', + ); + }); +});