diff --git a/src/components/TemurinDownloadTable/index.tsx b/src/components/TemurinDownloadTable/index.tsx index ef56f2de9..55a06747e 100644 --- a/src/components/TemurinDownloadTable/index.tsx +++ b/src/components/TemurinDownloadTable/index.tsx @@ -29,7 +29,7 @@ const TemurinDownloadTable = ({results}) => { {results ? ( - results.sort((pkg1, pkg2) => pkg2.release_date - pkg1.release_date).map( + results.map( (pkg, i): string | JSX.Element => pkg && ( diff --git a/src/hooks/__tests__/__snapshots__/fetchTemurinReleases.test.tsx.snap b/src/hooks/__tests__/__snapshots__/fetchTemurinReleases.test.tsx.snap index 4d1229f90..3ddb5f2ab 100644 --- a/src/hooks/__tests__/__snapshots__/fetchTemurinReleases.test.tsx.snap +++ b/src/hooks/__tests__/__snapshots__/fetchTemurinReleases.test.tsx.snap @@ -69,3 +69,129 @@ exports[`loadLatestAssets > source image is processed correctly 1`] = ` }, ] `; + +exports[`loadLatestAssets > verify that releases are well sorted 1`] = ` +[ + { + "architecture": "aarch64", + "binaries": [ + { + "checksum": "checksum_mock", + "extension": ".tar.gz", + "installer_checksum": "installer_checksum_mock", + "installer_extension": ".msi", + "installer_link": "https://installer_link_mock/", + "installer_size": 0, + "link": "https://link_mock/", + "size": 0, + "type": "JDK", + }, + ], + "os": "os_mock", + "platform_name": "os_mock-aarch64", + "release_date": 2020-01-01T00:00:00.000Z, + "release_link": "https://release_link_mock/", + "release_name": "release_name_mock", + }, + { + "architecture": "ppc64le", + "binaries": [ + { + "checksum": "checksum_mock", + "extension": ".tar.gz", + "installer_checksum": "installer_checksum_mock", + "installer_extension": ".msi", + "installer_link": "https://installer_link_mock/", + "installer_size": 0, + "link": "https://link_mock/", + "size": 0, + "type": "JDK", + }, + ], + "os": "os_mock", + "platform_name": "os_mock-ppc64le", + "release_date": 2020-01-01T00:00:00.000Z, + "release_link": "https://release_link_mock/", + "release_name": "release_name_mock", + }, + { + "architecture": "x64", + "binaries": [ + { + "checksum": "checksum_mock", + "extension": ".tar.gz", + "installer_checksum": "installer_checksum_mock", + "installer_extension": ".msi", + "installer_link": "https://installer_link_mock/", + "installer_size": 0, + "link": "https://link_mock/", + "size": 0, + "type": "JDK", + }, + ], + "os": "os_mock", + "platform_name": "os_mock-x64", + "release_date": 2020-01-01T00:00:00.000Z, + "release_link": "https://release_link_mock/", + "release_name": "release_name_mock", + }, + { + "architecture": "x32", + "binaries": [ + { + "checksum": "checksum_mock", + "extension": ".tar.gz", + "installer_checksum": "installer_checksum_mock", + "installer_extension": ".msi", + "installer_link": "https://installer_link_mock/", + "installer_size": 0, + "link": "https://link_mock/", + "size": 0, + "type": "JDK", + }, + ], + "os": "os_mock", + "platform_name": "os_mock-x32", + "release_date": 2020-01-01T00:00:00.000Z, + "release_link": "https://release_link_mock/", + "release_name": "release_name_mock", + }, +] +`; + +exports[`loadLatestAssets > verify update the release date if this asset is newer 1`] = ` +[ + { + "architecture": "arch_mock", + "binaries": [ + { + "checksum": "checksum_mock", + "extension": ".tar.gz", + "installer_checksum": "installer_checksum_mock", + "installer_extension": ".msi", + "installer_link": "https://installer_link_mock/", + "installer_size": 0, + "link": "https://link_mock/", + "size": 0, + "type": "JDK", + }, + { + "checksum": "checksum_mock", + "extension": ".tar.gz", + "installer_checksum": "installer_checksum_mock", + "installer_extension": ".msi", + "installer_link": "https://installer_link_mock/", + "installer_size": 0, + "link": "https://link_mock/", + "size": 0, + "type": "JDK", + }, + ], + "os": "os_mock", + "platform_name": "os_mock-arch_mock", + "release_date": 2020-01-02T00:00:00.000Z, + "release_link": "https://release_link_mock/", + "release_name": "release_name_mock", + }, +] +`; diff --git a/src/hooks/__tests__/fetchTemurinReleases.test.tsx b/src/hooks/__tests__/fetchTemurinReleases.test.tsx index c359d81d2..3b89c5b24 100644 --- a/src/hooks/__tests__/fetchTemurinReleases.test.tsx +++ b/src/hooks/__tests__/fetchTemurinReleases.test.tsx @@ -53,6 +53,43 @@ describe('loadLatestAssets', () => { }); }); + it('verify update the release date if this asset is newer', async() => { + const r1 = createMockTemurinReleaseAPI(true, 'jdk'); + const r2 = createMockTemurinReleaseAPI(true, 'jdk'); + r2.binary.updated_at.setDate(r2.binary.updated_at.getDate() + 1); + + mockResponse = [r1, r2] + + mock.onGet().reply(200, mockResponse); + + renderHook(async() => { + await loadLatestAssets(8, 'linux', 'x64', 'jdk').then((data) => { + expect(data).toMatchSnapshot() + }) + }); + }); + + it('verify that releases are well sorted', async() => { + const r1 = createMockTemurinReleaseAPI(true, 'jdk'); + r1.binary.architecture = 'x32'; + const r2 = createMockTemurinReleaseAPI(true, 'jdk'); + r2.binary.architecture = 'x64'; + const r3 = createMockTemurinReleaseAPI(true, 'jdk'); + r3.binary.architecture = 'aarch64'; + const r4 = createMockTemurinReleaseAPI(true, 'jdk'); + r4.binary.architecture = 'ppc64le'; + + mockResponse = [r1, r2, r3, r4] + + mock.onGet().reply(200, mockResponse); + + renderHook(async() => { + await loadLatestAssets(8, 'linux', 'x64', 'jdk').then((data) => { + expect(data).toMatchSnapshot() + }) + }); + }); + it('pkgsFound to be empty on error', async() => { mock.onGet().reply(500); diff --git a/src/hooks/fetchTemurinReleases.tsx b/src/hooks/fetchTemurinReleases.tsx index a9f1f8fdb..762ebe516 100644 --- a/src/hooks/fetchTemurinReleases.tsx +++ b/src/hooks/fetchTemurinReleases.tsx @@ -4,6 +4,12 @@ import axios from 'axios'; const baseUrl = 'https://api.adoptium.net/v3'; +Date.prototype.withoutTime = function () { + var d = new Date(this); + d.setHours(0, 0, 0, 0); + return d; +}; + export async function loadLatestAssets( version: number, os: string, @@ -11,6 +17,7 @@ export async function loadLatestAssets( packageType: string ): Promise { let url = new URL(`${baseUrl}/assets/latest/${version}/hotspot?`); + if (os !== 'any') { url.searchParams.append('os', os); } @@ -18,38 +25,36 @@ export async function loadLatestAssets( url.searchParams.append('architecture', architecture); } - let pkgsFound: TemurinRelease[] = [] + // NOTE: Do not filter the query by 'image_type' because we need to have 'sources + // to display the Release Notes and source download (cf src/components/TemurinDownloadTable/index.tsx) - await axios.get(url.toString()) + let pkgsFound: TemurinRelease[] = await axios.get(url.toString()) .then(function (response) { - let data = response.data; - - // Filter JDK/JRE if necessary - if (packageType === 'jdk') { - data = data.filter((pkg: TemurinRelease) => pkg.binary.image_type !== 'jre'); - } else if (packageType === 'jre') { - data = data.filter((pkg: TemurinRelease) => pkg.binary.image_type !== 'jdk'); - } - - for (let pkg of data) { - pkgsFound.push(pkg); - } + return response.data; }) .catch(function (error) { - pkgsFound = [] + return [] }); + // Filter JDK/JRE if necessary + if (packageType === 'jdk') { + pkgsFound = pkgsFound.filter((pkg: TemurinRelease) => pkg.binary.image_type !== 'jre'); + } else if (packageType === 'jre') { + pkgsFound = pkgsFound.filter((pkg: TemurinRelease) => pkg.binary.image_type !== 'jdk'); + } + return renderReleases(pkgsFound); } function renderReleases(pkgs: Array): ReleaseAsset[] { let releases: ReleaseAsset[] = [] + pkgs.forEach((releaseAsset: TemurinRelease) => { const platform = `${releaseAsset.binary.os}-${releaseAsset.binary.architecture}` // Skip this asset if it's not a binary type we're interested in displaying const binary_type = releaseAsset.binary.image_type.toUpperCase(); - if (binary_type == 'SOURCES') { + if (binary_type === 'SOURCES') { releases['source'] = releaseAsset; } if (!['INSTALLER', 'JDK', 'JRE'].includes(binary_type)) { @@ -67,6 +72,12 @@ function renderReleases(pkgs: Array): ReleaseAsset[] { release_date: new Date(releaseAsset.binary.updated_at), binaries: [] }; + } else { + // update the release date if this asset is newer + const rabua = new Date(releaseAsset.binary.updated_at); + if (release.release_date < rabua) { + release.release_date = rabua; + } } let binary_constructor: Binary = { @@ -91,11 +102,30 @@ function renderReleases(pkgs: Array): ReleaseAsset[] { if (release.binaries.length === 1) { releases.push(release); } - - releases.forEach((release) => { - release.binaries.sort((binaryA, binaryB) => binaryA.type > binaryB.type ? 1 : binaryA.type < binaryB.type ? -1 : 0); - }); }) + + // well sort releases + releases.sort((pkg1: ReleaseAsset, pkg2: ReleaseAsset) => { + // order by date DESC + let comparison = pkg2.release_date.withoutTime() - pkg1.release_date.withoutTime(); + if (comparison === 0) { + // for the same date, sort by OS ASC + comparison = pkg1.os.localeCompare(pkg2.os); + if (comparison === 0) { + // for the same OS, sort by architecture ASC + const arch1 = pkg1.architecture === 'x32' ? 'x86' : pkg1.architecture + const arch2 = pkg2.architecture === 'x32' ? 'x86' : pkg2.architecture + comparison = arch1.localeCompare(arch2); + } + } + return comparison; + }); + + // sort binaries inside releases + releases.forEach((release) => { + release.binaries.sort((binaryA, binaryB) => binaryA.type > binaryB.type ? 1 : binaryA.type < binaryB.type ? -1 : 0); + }); + return releases }