diff --git a/package.json b/package.json index 7e0dd028..1ed7c368 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "antd": "3.26.7", "markdown-to-jsx": "6.10.3", "query-string": "6.10.1", + "ramda": "^0.26.1", "react": "16.12.0", "react-content-loader": "4.3.4", "react-diff-view": "2.4.1", @@ -51,4 +52,4 @@ "last 1 safari version" ] } -} \ No newline at end of file +} diff --git a/src/components/common/VersionSelector.js b/src/components/common/VersionSelector.js index b93544ec..3ed8115b 100644 --- a/src/components/common/VersionSelector.js +++ b/src/components/common/VersionSelector.js @@ -3,6 +3,8 @@ import styled from 'styled-components' import { Button, Popover } from 'antd' import semver from 'semver/preload' import queryString from 'query-string' +import * as R from 'ramda' + import { RELEASES_URL } from '../../utils' import { Select } from './' @@ -108,23 +110,78 @@ const getReleasedVersionsWithCandidates = ({ }) } -const getReleasedVersions = ({ releasedVersions, minVersion, maxVersion }) => { - const latestMajorReleaseVersion = getLatestMajorReleaseVersion( - releasedVersions - ) +export const isRC = release => release.includes('rc') + +export const filterReleases = ( + releases, + { + showRCs = 'all', + minVersion, + minVersionExcluding, + maxVersion, + maxVersionExcluding + } // defaults should be whatever will return the same results as the input +) => { + let filteredReleases = releases + + switch (showRCs) { + case 'all': + // show all rcs + break + case 'latest': { + // show only latest version's rcs + let latestRelease = filteredReleases[0] + let earliestLatestReleaseIndex = R.findIndex( + release => + semver.compare( + semver.coerce(release), + semver.coerce(latestRelease) + ) !== 0 + )(filteredReleases) + + let [latest, rest] = R.splitAt( + earliestLatestReleaseIndex, + filteredReleases + ) + rest = R.reject(isRC)(rest) + filteredReleases = R.concat(latest, rest) + break + } + case 'none': + // don't show any rcs + filteredReleases = R.reject(isRC)(filteredReleases) + break + default: + break + } + + if (maxVersion !== undefined) { + // drop all versions later than `maxVersion` + filteredReleases = R.dropWhile( + release => semver.compare(release, maxVersion) > 0 + )(filteredReleases) + } + if (maxVersionExcluding !== undefined) { + // drop all versions later or equal to `maxVersionExcluding` + filteredReleases = R.dropWhile( + release => semver.compare(release, maxVersionExcluding) >= 0 + )(filteredReleases) + } - const isVersionAReleaseAndOfLatest = version => - version.includes('rc') && - semver.valid(semver.coerce(version)) === latestMajorReleaseVersion + if (minVersion !== undefined) { + // take all versions later or equal to `minVersion` + filteredReleases = R.takeWhile( + release => semver.compare(release, minVersion) >= 0 + )(filteredReleases) + } + if (minVersionExcluding !== undefined) { + // take all versions later than `minVersionExcluding` + filteredReleases = R.takeWhile( + release => semver.compare(release, minVersionExcluding) > 0 + )(filteredReleases) + } - return releasedVersions.filter( - releasedVersion => - releasedVersion.length > 0 && - ((maxVersion && semver.lt(releasedVersion, maxVersion)) || - (minVersion && - semver.gt(releasedVersion, minVersion) && - !isVersionAReleaseAndOfLatest(releasedVersion))) - ) + return filteredReleases } // Finds the first minor release (which in react-native is the major) when compared to another version @@ -216,16 +273,10 @@ const VersionSelector = ({ showDiff, showReleaseCandidates }) => { }) setFromVersionList( - getReleasedVersions({ - releasedVersions: sanitizedVersions, - maxVersion: toVersionToBeSet - }) + filterReleases(sanitizedVersions, { maxVersion: toVersionToBeSet }) ) setToVersionList( - getReleasedVersions({ - releasedVersions: sanitizedVersions, - minVersion: fromVersionToBeSet - }) + filterReleases(sanitizedVersions, { minVersion: fromVersionToBeSet }) ) setLocalFromVersion(fromVersionToBeSet) @@ -251,16 +302,10 @@ const VersionSelector = ({ showDiff, showReleaseCandidates }) => { } setFromVersionList( - getReleasedVersions({ - releasedVersions: allVersions, - maxVersion: localToVersion - }) + filterReleases(allVersions, { maxVersion: localToVersion }) ) setToVersionList( - getReleasedVersions({ - releasedVersions: allVersions, - minVersion: localFromVersion - }) + filterReleases(allVersions, { minVersion: localFromVersion }) ) }, [ isLoading, diff --git a/src/components/common/VersionSelector.test.js b/src/components/common/VersionSelector.test.js new file mode 100644 index 00000000..46daa1da --- /dev/null +++ b/src/components/common/VersionSelector.test.js @@ -0,0 +1,101 @@ +import R from 'ramda' + +import { filterReleases, isRC } from './VersionSelector' + +describe('rc checker', () => { + it('should detect rc releases correctly', () => { + expect(isRC('0.62.0')).toBe(false) + expect(isRC('0.62.0-rc.0')).toBe(true) + }) +}) + +const releases = [ + '0.63.2-rc.1', + '0.63.2-rc.0', + '0.63.1', + '0.63.0', + '0.62.4', + '0.62.4-rc.1', + '0.62.4-rc.0', + '0.62.3', + '0.62.1', + '0.62.0', + '0.62.0-rc.1', + '0.61.3' +] +const releasesNoRCs = R.reject(isRC)(releases) +// console.log(releasesNoRCs) +const releasesNoRCsWithLatestReleaseRCs = [ + '0.63.2-rc.1', + '0.63.2-rc.0', + ...releasesNoRCs +] + +describe('release filtering', () => { + it('should return the correct releases', () => { + // expect(filterReleases(releasesWithRCs)).toBe(releasesWithRCs) + expect(filterReleases(releases, {})).toEqual(releases) + + expect(filterReleases(releases, { showRCs: 'all' })).toEqual(releases) + expect(filterReleases(releases, { showRCs: 'none' })).toEqual(releasesNoRCs) + expect(filterReleases(releases, { showRCs: 'latest' })).toEqual( + releasesNoRCsWithLatestReleaseRCs + ) + + expect(filterReleases(releases, { maxVersion: '0.62.4' })).toEqual([ + '0.62.4', + '0.62.4-rc.1', + '0.62.4-rc.0', + '0.62.3', + '0.62.1', + '0.62.0', + '0.62.0-rc.1', + '0.61.3' + ]) + expect( + filterReleases(releases, { maxVersionExcluding: '0.62.4' }) + ).toEqual([ + '0.62.4-rc.1', + '0.62.4-rc.0', + '0.62.3', + '0.62.1', + '0.62.0', + '0.62.0-rc.1', + '0.61.3' + ]) + + expect(filterReleases(releases, { minVersion: '0.62.1' })).toEqual([ + '0.63.2-rc.1', + '0.63.2-rc.0', + '0.63.1', + '0.63.0', + '0.62.4', + '0.62.4-rc.1', + '0.62.4-rc.0', + '0.62.3', + '0.62.1' + ]) + expect( + filterReleases(releases, { minVersionExcluding: '0.62.1' }) + ).toEqual([ + '0.63.2-rc.1', + '0.63.2-rc.0', + '0.63.1', + '0.63.0', + '0.62.4', + '0.62.4-rc.1', + '0.62.4-rc.0', + '0.62.3' + ]) + + expect( + filterReleases(releases, { minVersion: '0.62.1', maxVersion: '0.62.4' }) + ).toEqual(['0.62.4', '0.62.4-rc.1', '0.62.4-rc.0', '0.62.3', '0.62.1']) + expect( + filterReleases(releases, { + minVersionExcluding: '0.62.1', + maxVersionExcluding: '0.62.4' + }) + ).toEqual(['0.62.4-rc.1', '0.62.4-rc.0', '0.62.3']) + }) +}) diff --git a/yarn.lock b/yarn.lock index 5d5d7554..f8fda5be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8662,6 +8662,11 @@ raf@^3.4.0, raf@^3.4.1: dependencies: performance-now "^2.1.0" +ramda@^0.26.1: + version "0.26.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06" + integrity sha512-hLWjpy7EnsDBb0p+Z3B7rPi3GDeRG5ZtiI33kJhTt+ORCd38AbAIjB/9zRIUoeTbE/AVX5ZkU7m6bznsvrf8eQ== + randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"