import * as express from 'express'; import { createServer, Server } from 'http'; import { shuffle } from 'lodash'; import { join } from 'path'; import { bindNodeCallback, Observable, UnaryFunction } from 'rxjs'; import { map, mapTo, mergeMap, shareReplay } from 'rxjs/operators'; import * as serveStatic from 'serve-static'; import { getMatchingVersion, getPackageJson, parseReference } from '../src/utils/semver.utils'; import { getAssetBaseDir } from './utils/test.utils'; describe('semver.utils', () => { const time = { '0.1.398': '2017-09-14T16:12:02.531Z', '0.1.399': '2017-09-14T16:21:48.501Z', '1.0.408': '2017-09-15T13:05:16.167Z', '1.0.410': '2017-09-15T15:48:54.371Z', '1.0.418': '2017-09-19T07:58:50.961Z', '1.0.422': '2017-09-19T10:23:58.552Z', '1.0.423': '2017-09-19T12:18:51.759Z', '1.0.427': '2017-09-19T15:23:26.994Z', '1.0.435': '2017-09-20T10:12:11.325Z', '1.0.442': '2017-09-22T07:52:57.665Z', '1.0.458': '2017-09-26T15:12:47.544Z', '1.0.461': '2017-09-27T08:16:02.174Z', '1.0.475': '2017-09-30T20:43:51.248Z', '1.0.490': '2017-10-05T15:32:13.548Z', '1.0.506': '2017-10-10T09:00:01.528Z', '1.0.508': '2017-10-10T19:42:35.232Z', '1.0.655': '2017-11-13T13:39:15.047Z', '1.0.656': '2017-11-13T15:05:16.468Z', '1.0.659': '2017-11-14T10:31:08.234Z', '1.0.661': '2017-11-14T15:00:23.979Z', '1.0.681': '2017-11-20T08:51:33.225Z', '1.0.722': '2017-11-30T15:24:29.311Z', '1.0.771': '2018-01-16T07:53:42.244Z', '1.0.830': '2018-01-16T16:26:59.031Z', '1.0.903': '2018-02-07T07:52:25.093Z', '5.0.104': '2018-02-28T12:27:08.883Z', '5.0.105': '2018-02-28T14:22:23.989Z', '5.0.107': '2018-02-28T14:53:36.876Z', '5.0.108': '2018-03-02T18:15:11.204Z', '5.0.139': '2018-03-08T20:45:48.822Z', '5.0.207': '2018-03-20T16:29:29.233Z', '5.0.210': '2018-03-21T19:11:18.251Z', '5.0.211': '2018-03-21T19:51:30.304Z', '5.0.212': '2018-03-21T21:26:35.533Z', '4.0.7': '2018-03-22T09:00:35.328Z', '5.0.216': '2018-03-22T09:29:22.653Z', '5.0.217': '2018-03-22T10:44:59.003Z', '5.0.226': '2018-03-23T15:53:52.430Z', '5.0.233': '2018-03-25T15:38:22.666Z', '5.0.238': '2018-03-26T20:29:33.750Z', '5.0.240': '2018-03-27T12:04:25.214Z', '5.0.254': '2018-04-04T07:10:23.662Z', '5.0.258': '2018-04-04T09:21:02.049Z', '5.0.265': '2018-04-06T13:44:30.172Z', '5.0.269': '2018-04-10T09:59:53.260Z' }; it('should download the package version', () => { // ramp up dev server const app = express(); app.use(serveStatic(join(getAssetBaseDir(), 'test', 'npm-registry'), { index: 'index.json' })); const server = createServer(app); const startServer: UnaryFunction> = bindNodeCallback(server.listen.bind(server)); const rxServer: Observable = startServer(0).pipe( mapTo(server), shareReplay() ); const opCloseServer = () => bindNodeCallback(server.close.bind(server))(); // parse the version const parsedRef = parseReference('ibm-wch-sdk-cli@^5.0.0'); // get const rxPkg = rxServer.pipe( map(server => server.address().port), mergeMap(port => getPackageJson(`http://localhost:${port}/`, parsedRef)) ); // check the result return rxPkg.pipe(map(pkg => { expect(pkg).toBeDefined(); expect(pkg.version).toBe('5.0.269'); }), mergeMap(opCloseServer)) .toPromise(); }); it('should decode semver ranges', () => { // non namespaced expect(parseReference('ibm-wch-sdk-cli')).toEqual({ name: 'ibm-wch-sdk-cli', escapedName: 'ibm-wch-sdk-cli', spec: '*' }); expect(parseReference('ibm-wch-sdk-cli@^5.0.0')).toEqual({ name: 'ibm-wch-sdk-cli', escapedName: 'ibm-wch-sdk-cli', spec: '^5.0.0' }); expect(parseReference('ibm-wch-sdk-cli@*')).toEqual({ name: 'ibm-wch-sdk-cli', escapedName: 'ibm-wch-sdk-cli', spec: '*' }); expect(parseReference('ibm-wch-sdk-cli@latest')).toEqual({ name: 'ibm-wch-sdk-cli', escapedName: 'ibm-wch-sdk-cli', spec: '*' }); // namespaced expect(parseReference('@ibm-wch-sdk/cli')).toEqual({ name: '@ibm-wch-sdk/cli', escapedName: '@ibm-wch-sdk%2fcli', spec: '*' }); expect(parseReference('@ibm-wch-sdk/cli@^5.0.0')).toEqual({ name: '@ibm-wch-sdk/cli', escapedName: '@ibm-wch-sdk%2fcli', spec: '^5.0.0' }); expect(parseReference('@ibm-wch-sdk/cli@*')).toEqual({ name: '@ibm-wch-sdk/cli', escapedName: '@ibm-wch-sdk%2fcli', spec: '*' }); expect(parseReference('@ibm-wch-sdk/cli@latest')).toEqual({ name: '@ibm-wch-sdk/cli', escapedName: '@ibm-wch-sdk%2fcli', spec: '*' }); }); it('should match a version range', () => { const versions = shuffle(Object.keys(time)); expect(getMatchingVersion(versions, '^5.0.0')).toEqual('5.0.269'); expect(getMatchingVersion(versions, '*')).toEqual('5.0.269'); expect(getMatchingVersion(versions, '>= 4 < 5')).toEqual('4.0.7'); }); });