From eac015d2191b6538e242a86ff0b5c465b792c79f Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 4 Sep 2020 13:07:16 +0200 Subject: [PATCH 01/65] Extract `version.js` into different classes and extend tests phovea/generator-phovea#425 --- generators/clone-repo/index.js | 10 +- generators/workspace/index.js | 65 ++--- test/NpmUtils.test.js | 428 +++++++++++++++++++++++++++++++++ test/PipUtils.test.js | 82 +++++++ test/TestUtils.js | 14 ++ test/init-app-slib.test.js | 6 +- test/init-app.test.js | 6 +- test/init-lib-service.test.js | 6 +- test/init-lib-slib.test.js | 6 +- test/init-lib.test.js | 8 +- test/testUtils.js | 13 - test/utils-version.test.js | 397 ------------------------------ utils/NpmUtils.js | 244 +++++++++++++++++++ utils/PipUtils.js | 76 ++++++ utils/version.js | 296 ----------------------- 15 files changed, 898 insertions(+), 759 deletions(-) create mode 100644 test/NpmUtils.test.js create mode 100644 test/PipUtils.test.js create mode 100644 test/TestUtils.js delete mode 100644 test/testUtils.js delete mode 100644 test/utils-version.test.js create mode 100644 utils/NpmUtils.js create mode 100644 utils/PipUtils.js delete mode 100644 utils/version.js diff --git a/generators/clone-repo/index.js b/generators/clone-repo/index.js index ae89f042..a7fbfaab 100644 --- a/generators/clone-repo/index.js +++ b/generators/clone-repo/index.js @@ -4,7 +4,7 @@ const chalk = require('chalk'); const { simplifyRepoUrl } = require('../../utils/repo'); -const version = require('../../utils/version'); +const NpmUtils = require('../../utils/NpmUtils'); function failed(spawnResult) { return spawnResult.status !== 0; @@ -105,10 +105,10 @@ class Generator extends Base { } _cloneRepo(repoUrl, branch, extras, cloneDirName) { - if (!version.isGitCommit(branch)) { + if (!NpmUtils.isGitCommit(branch)) { // modify branch name, if it is an advance version tag // otherwise just use the branch name as it is - if (version.isAdvancedVersionTag(branch)) { + if (NpmUtils.isAdvancedVersionTag(branch)) { this.log(chalk.white(`found branch with version range`), chalk.green(branch), chalk.white(`for`), chalk.green(repoUrl)); const line = `ls-remote --tags ${repoUrl}`; @@ -122,10 +122,10 @@ class Generator extends Base { } const gitLog = r.stdout.toString(); - const gitVersions = version.extractVersionsFromGitLog(gitLog); + const gitVersions = NpmUtils.extractVersionsFromGitLog(gitLog); this.log(chalk.white(`found the following version tags: `), gitVersions); - const highestVersion = version.findHighestVersion(gitVersions, branch); + const highestVersion = NpmUtils.findHighestVersion(gitVersions, branch); if (!highestVersion) { this.log(chalk.red(`failed to find git version tag for given version range`)); return this._abort(`failed to find git version tag for given version range`); diff --git a/generators/workspace/index.js b/generators/workspace/index.js index 8b77f6c1..842c7a87 100644 --- a/generators/workspace/index.js +++ b/generators/workspace/index.js @@ -10,7 +10,8 @@ const fs = require('fs'); const known = () => require('../../utils/known'); const writeTemplates = require('../../utils').writeTemplates; const patchPackageJSON = require('../../utils').patchPackageJSON; -const {mergeVersions, mergePipVersions} = require('../../utils/version'); +const NpmUtils = require('../../utils/NpmUtils'); +const PipUtils = require('../../utils/PipUtils'); const {parseRequirements} = require('../../utils/pip'); function mergeWith(target, source) { @@ -99,7 +100,7 @@ class Generator extends Base { default: defaultConfig.addWorkspaceRepos, description: 'States whether workspace repos should be part of the dependencies. Set to `true` for local development setup. Otherwise `false` for CI build process.' }); - + } initializing() { @@ -158,14 +159,14 @@ class Generator extends Base { plugins.map((plugin) => { return `./${plugin}/src`; }), - 'extensions': 'html,scss,css', - 'quiet': false, - 'legacyWatch': true, - 'delay': 2500, - 'runOnChangeOnly': true + 'extensions': 'html,scss,css', + 'quiet': false, + 'legacyWatch': true, + 'delay': 2500, + 'runOnChangeOnly': true } }; - const repoDependencies = Object.assign({},...plugins.map((plugin) => ({[plugin]: `./${plugin}`}))); + const repoDependencies = Object.assign({}, ...plugins.map((plugin) => ({[plugin]: `./${plugin}`}))); const integrateMulti = (target, source) => { Object.keys(source || {}).forEach((key) => { @@ -205,7 +206,7 @@ class Generator extends Base { if (this.props.defaultApp) { const workspaceFile = this.fs.readJSON(this.destinationPath('.yo-rc-workspace.json')); devRepos = workspaceFile && workspaceFile.devRepos ? workspaceFile.devRepos : [this.props.defaultApp]; - if(devRepos.indexOf(this.props.defaultApp)<0) devRepos.push(this.props.defaultApp); + if (devRepos.indexOf(this.props.defaultApp) < 0) devRepos.push(this.props.defaultApp); devRepos = devRepos.filter((plugin) => plugins.indexOf(plugin) >= 0); //add dev-repos scripts scripts['dev-repos:compile'] = devRepos.map((repo) => `npm run compile:${repo}`).join(' & '); @@ -215,11 +216,11 @@ class Generator extends Base { //add watch watch['dev-repos:copy'] = { 'patterns': devRepos.map((repo) => `./${repo}/src`), - 'extensions': 'html,scss,css', - 'quiet': false, - 'legacyWatch': true, - 'delay': 2500, - 'runOnChangeOnly': true + 'extensions': 'html,scss,css', + 'quiet': false, + 'legacyWatch': true, + 'delay': 2500, + 'runOnChangeOnly': true }; // enforce that the dependencies of the default app are the last one to have a setup suitable for the default app thus more predictable const pkg = this.fs.readJSON(this.destinationPath(this.props.defaultApp + '/package.json')); @@ -240,10 +241,10 @@ class Generator extends Base { }); Object.keys(dependencies).forEach((key) => { - dependencies[key] = mergeVersions(key, dependencies[key]); + dependencies[key] = NpmUtils.mergeVersions(key, dependencies[key]); }); Object.keys(devDependencies).forEach((key) => { - devDependencies[key] = mergeVersions(key, devDependencies[key]); + devDependencies[key] = NpmUtils.mergeVersions(key, devDependencies[key]); }); // dependencies from package.tmpl.json @@ -253,7 +254,7 @@ class Generator extends Base { // scripts from package.tmpl.json const extraScripts = this.fs.readJSON(this.templatePath('package.tmpl.json')).scripts; - return {plugins, dependencies: Object.assign(Object.assign(dependencies, extraDependencies), this.options.addWorkspaceRepos ? repoDependencies : {}), devDependencies: Object.assign(devDependencies, extraDevDependencies), scripts: Object.assign(scripts, extraScripts), watch, devRepos}; + return {plugins, dependencies: Object.assign(Object.assign(dependencies, extraDependencies), this.options.addWorkspaceRepos ? repoDependencies : {}), devDependencies: Object.assign(devDependencies, extraDevDependencies), scripts: Object.assign(scripts, extraScripts), watch, devRepos}; } _generateServerDependencies(additionalPlugins) { @@ -397,10 +398,10 @@ class Generator extends Base { }); Object.keys(requirements).forEach((key) => { - requirements[key] = mergePipVersions(key, requirements[key]); + requirements[key] = PipUtils.mergePipVersions(key, requirements[key]); }); Object.keys(devRequirements).forEach((key) => { - devRequirements[key] = mergePipVersions(key, devRequirements[key]); + devRequirements[key] = PipUtils.mergePipVersions(key, devRequirements[key]); }); return { @@ -451,17 +452,17 @@ class Generator extends Base { const {plugins, dependencies, devDependencies, scripts, watch, devRepos} = this._generateWebDependencies(this.props.modules); const sdeps = this._generateServerDependencies(this.props.modules); const dockerWebHint = - ' # Uncomment the following lines for testing the web production build\n' + - ' # web:\n' + - ' # build:\n' + - ' # context: ./deploy/web\n' + - ' # dockerfile: deploy/web/Dockerfile\n' + - ' # ports:\n' + - ' # - \'8090:80\'\n' + - ' # volumes:\n' + - ' # - \'./bundles:/usr/share/nginx/html\'\n' + - ' # depends_on:\n' + - ' # - api\n'; + ' # Uncomment the following lines for testing the web production build\n' + + ' # web:\n' + + ' # build:\n' + + ' # context: ./deploy/web\n' + + ' # dockerfile: deploy/web/Dockerfile\n' + + ' # ports:\n' + + ' # - \'8090:80\'\n' + + ' # volumes:\n' + + ' # - \'./bundles:/usr/share/nginx/html\'\n' + + ' # depends_on:\n' + + ' # - api\n'; // save config this.fs.extendJSON(this.destinationPath('.yo-rc-workspace.json'), { @@ -485,8 +486,8 @@ class Generator extends Base { this._patchDockerImages(patch, sdeps.dockerCompose); } { - this.fs.write(this.destinationPath('docker-compose.yml'), yaml.stringify(sdeps.dockerCompose, 100, 2) ); - this.fs.write(this.destinationPath('docker-compose-debug.yml'), yaml.stringify(sdeps.dockerComposeDebug, 100, 2)+ dockerWebHint); + this.fs.write(this.destinationPath('docker-compose.yml'), yaml.stringify(sdeps.dockerCompose, 100, 2)); + this.fs.write(this.destinationPath('docker-compose-debug.yml'), yaml.stringify(sdeps.dockerComposeDebug, 100, 2) + dockerWebHint); } const config = {}; diff --git a/test/NpmUtils.test.js b/test/NpmUtils.test.js new file mode 100644 index 00000000..d214d516 --- /dev/null +++ b/test/NpmUtils.test.js @@ -0,0 +1,428 @@ +'use strict'; +const NpmUtils = require('../utils/NpmUtils'); + + +describe('mergeVersions list of versions with github or gitlab version tags', () => { + + it('returns first correct gitlab tag', () => { + const name = 'target360'; + const versions = [ + 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop', + 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop', + '4.0.0' + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop'); + }); + + it('returns first correct github tag', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#develop', + 'github:phovea/phovea_core#develop', + '5.0.0' + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#develop'); + }); + + it('throws error if versions point to different gitlab branches', () => { + const name = 'target360'; + const versions = [ + 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop', + 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#master', + '4.0.0' + ]; + expect(() => NpmUtils.mergeVersions(name, versions)).toThrow(); + }); + + it('returns correct intersection of github ranges', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + 'github:phovea/phovea_core#semver:^7.0.0', + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^7.0.1'); + }); + + it('throws error if versions contain both github and gitlab', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#master', + ]; + expect(() => NpmUtils.mergeVersions(name, versions)).toThrow(); + }); + + it('throws error if versions are 2 different github versions', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + 'github:phovea/phovea_core#develop', + ]; + expect(() => NpmUtils.mergeVersions(name, versions)).toThrow(); + }); + + it('returns github version if one of the versions is a github semver version bigger than the rest', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + '4.0.0', + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^7.0.1'); + }); + + it('returns correct max github version', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + 'github:phovea/phovea_core#semver:^8.0.0' + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^8.0.0'); + }); + + it('compares github version with npm version', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + '^8.0.0' + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('^8.0.0'); + }); + + it('compares an equal github version with an npm version', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + '^7.0.1' + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^7.0.1'); + }); + + it('compares multiple github and npm versions', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:^7.0.1', + 'github:phovea/phovea_core#semver:^6.0.1', + '^7.0.1', + '^7.0.2' + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('^7.0.2'); + }); + + it('finds the intersection of a git version and npm version', () => { + const name = 'phovea_core'; + const versions = [ + 'github:phovea/phovea_core#semver:~7.0.1', + 'github:phovea/phovea_core#semver:^6.0.1', + '^7.0.1', + ]; + expect(NpmUtils.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:~7.0.1'); + }); +}); + +describe('check isGitCommit()', () => { + it('check `451709494a48af64a8a4876063c244edf41d2643` === true', () => { + expect(NpmUtils.isGitCommit('451709494a48af64a8a4876063c244edf41d2643')).toBeTruthy(); + }); + + it('check `8747a43780e4651542facd7b4feac7bcb8e3778d` === true', () => { + expect(NpmUtils.isGitCommit('8747a43780e4651542facd7b4feac7bcb8e3778d')).toBeTruthy(); + }); + + it('check `develop` === false', () => { + expect(NpmUtils.isGitCommit('develop')).toBeFalsy(); + }); + + it('check `v2.0.0` === false', () => { + expect(NpmUtils.isGitCommit('v2.0.0')).toBeFalsy(); + }); + + it('check `~v2.0.0` === false', () => { + expect(NpmUtils.isGitCommit('~v2.0.0')).toBeFalsy(); + }); + + it('check `^v2.0.0` === false', () => { + expect(NpmUtils.isGitCommit('^v2.0.0')).toBeFalsy(); + }); + + it('check `2.0.0` === false', () => { + expect(NpmUtils.isGitCommit('2.0.0')).toBeFalsy(); + }); + + it('check `~2.0.0` === false', () => { + expect(NpmUtils.isGitCommit('~2.0.0')).toBeFalsy(); + }); + + it('check `^2.0.0` === false', () => { + expect(NpmUtils.isGitCommit('^2.0.0')).toBeFalsy(); + }); +}); + +describe('check isExactVersionTag()', () => { + it('check `develop` === false', () => { + expect(NpmUtils.isExactVersionTag('develop')).toBeFalsy(); + }); + + it('check `v2.0.0` === true', () => { + expect(NpmUtils.isExactVersionTag('v2.0.0')).toBeTruthy(); + }); + + it('check `~v2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('~v2.0.0')).toBeFalsy(); + }); + + it('check `^v2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('^v2.0.0')).toBeFalsy(); + }); + + it('check `2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('2.0.0')).toBeFalsy(); + }); + + it('check `~2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('~2.0.0')).toBeFalsy(); + }); + + it('check `^2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('^2.0.0')).toBeFalsy(); + }); +}); + +describe('check isExactVersionTag()', () => { + it('check `develop` === false', () => { + expect(NpmUtils.isExactVersionTag('develop')).toBeFalsy(); + }); + + it('check `v2.0.0` === true', () => { + expect(NpmUtils.isExactVersionTag('v2.0.0')).toBeTruthy(); + }); + + it('check `~v2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('~v2.0.0')).toBeFalsy(); + }); + + it('check `^v2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('^v2.0.0')).toBeFalsy(); + }); + + it('check `2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('2.0.0')).toBeFalsy(); + }); + + it('check `~2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('~2.0.0')).toBeFalsy(); + }); + + it('check `^2.0.0` === false', () => { + expect(NpmUtils.isExactVersionTag('^2.0.0')).toBeFalsy(); + }); +}); + +describe('check isAdvancedVersionTag()', () => { + it('check `develop` === false', () => { + expect(NpmUtils.isAdvancedVersionTag('develop')).toBeFalsy(); + }); + + it('check `v2.0.0` === false', () => { + expect(NpmUtils.isAdvancedVersionTag('v2.0.0')).toBeFalsy(); + }); + + it('check `~v2.0.0` === true', () => { + expect(NpmUtils.isAdvancedVersionTag('~v2.0.0')).toBeTruthy(); + }); + + it('check `^v2.0.0` === true', () => { + expect(NpmUtils.isAdvancedVersionTag('^v2.0.0')).toBeTruthy(); + }); + + it('check `2.0.0` === false', () => { + expect(NpmUtils.isAdvancedVersionTag('2.0.0')).toBeFalsy(); + }); + + it('check `~2.0.0` === false', () => { + expect(NpmUtils.isAdvancedVersionTag('~2.0.0')).toBeFalsy(); + }); + + it('check `^2.0.0` === false', () => { + expect(NpmUtils.isAdvancedVersionTag('^2.0.0')).toBeFalsy(); + }); +}); + +describe('transform git log to version tags list', () => { + const gitLog = `451709494a48af64a8a4876063c244edf41d2643 refs/tags/caleydo_web + a1d4f93a626d71937bc35b23d3715eaf34cce4a1 refs/tags/v0.0.5 + 921409de073f4329c09a4602622e87d816de266f refs/tags/v0.1.0 + 9815eb1163b212e06b7239a0bf6f97b0fbc2cf0c refs/tags/v1.0.0 + e61c59f8c09e51e0b25f2087ad92789c26d58c11 refs/tags/v1.0.0^{} + 336072e87ec8f6054cead9f64c6830897fb7f076 refs/tags/v2.0.0 + 8747a43780e4651542facd7b4feac7bcb8e3778d refs/tags/v2.0.1 + ebb538469a661dc4a8c5646ca1bb11259f2ba2bb refs/tags/v2.0.1^{} + c073da02dbb1c8185a5d50266f78b9688dd4403a refs/tags/v2.1.0 + 53f68e0768df23b173f59d22ea90f61c478b8450 refs/tags/v2.1.1 + `; + + const versionTags = NpmUtils.extractVersionsFromGitLog(gitLog); + + it('check number of extracted versions', () => { + expect(versionTags.length).toBe(7); + }); + + it('check if tags without `v` are removed', () => { + expect(versionTags.indexOf('caleydo_web')).toBe(-1); + }); + + it('check if tags ending with `^{}` are removed', () => { + expect(versionTags.indexOf('v1.0.0^{}')).toBe(-1); + expect(versionTags.filter((v) => v === 'v1.0.0').length).toBe(1); + }); + + it('find specific version tag in list', () => { + expect(versionTags.indexOf('v0.0.5')).toBe(0); + }); +}); + +describe('check semver.satisfies', () => { + const semver = require('semver'); + + it('check against target version with caret operator', () => { + const targetVersion = '^v2.0.0'; + expect(semver.satisfies('v1.0.0', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.0.0', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.0.1', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.0.2', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.1.0', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.1.1', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.1.2', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.2.0', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.2.1', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.2.2', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v3.0.0', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v3.1.0', targetVersion)).toBeFalsy(); + }); + + it('check target version with tilde operator', () => { + const targetVersion = '~v2.0.0'; + expect(semver.satisfies('v1.0.0', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.0.0', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.0.1', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.0.2', targetVersion)).toBeTruthy(); + expect(semver.satisfies('v2.1.0', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.1.1', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.1.2', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.2.0', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.2.1', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v2.2.2', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v3.0.0', targetVersion)).toBeFalsy(); + expect(semver.satisfies('v3.1.0', targetVersion)).toBeFalsy(); + }); +}); + +describe('semver-intersect works for prerelease ranges', () => { + const {intersect} = require('semver-intersect'); + + it('finds intersection of an array of prerelease ranges', () => { + const versions = ['~4.2.0-alpha.1', '~4.2.0-beta.1',]; + expect(intersect(...versions)).toBe('~4.2.0-beta.1'); + }); +}); + +describe('find highest version from list', () => { + const sourceVersions = [ + 'v0.0.5', + 'v0.1.0', + 'v1.0.0', + 'v2.1.0', // note: out of order to test sorting + 'v2.2.0', // note: out of order to test sorting + 'v2.0.0', + 'v2.0.1', + 'v2.0.2', + 'v2.1.1', + 'v2.1.2', + 'v2.2.1', + 'v2.2.2', + 'v3.0.0', + 'v3.1.0' + ]; + + it('find exact version `v2.0.0`', () => { + const targetVersion = 'v2.0.0'; + expect(NpmUtils.findHighestVersion(sourceVersions, targetVersion)).toBe('v2.0.0'); + }); + + it('find patch version `~v2.0.0`', () => { + const targetVersion = '~v2.0.0'; + expect(NpmUtils.findHighestVersion(sourceVersions, targetVersion)).toBe('v2.0.2'); + }); + + it('find minor version `^v2.0.0`', () => { + const targetVersion = '^v2.0.0'; + expect(NpmUtils.findHighestVersion(sourceVersions, targetVersion)).toBe('v2.2.2'); + }); + + it('find non-existing `v4.0.0`', () => { + const targetVersion = 'v4.0.0'; + expect(NpmUtils.findHighestVersion(sourceVersions, targetVersion)).toBeUndefined(); + }); + + it('find non-existing `^v3.2.0`', () => { + const targetVersion = '^v3.2.0'; + expect(NpmUtils.findHighestVersion(sourceVersions, targetVersion)).toBeUndefined(); + }); +}); + +describe('find max version or range version from list', () => { + + it('works for simple versions arrays', () => { + const versions = ['0.0.5', '0.1.0', '1.0.0', '2.1.0', '2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('2.2.0'); + }); + + it('works for arrays with prerelease versions', () => { + const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '0.1.0', '1.0.0', '2.1.0', '2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('4.2.0-beta.0'); + }); + + it('works for arrays with prerelease and tilde ranges', () => { + const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '0.1.0', '~4.2.0', '2.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('~4.2.0'); + }); + + it('works for arrays with prerelease, tilde and caret ranges', () => { + const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '^4.2.0', '~4.2.0', '2.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('^4.2.0'); + }); + + it('works for `^4.2.0`', () => { + const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '^4.2.0', '~4.2.0', '2.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('^4.2.0'); + }); + + it('works for caret prerelease ranges', () => { + const versions = ['^4.2.0-alpha.1', '^4.2.0-beta.0', '^4.1.0', '2.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('^4.2.0-beta.0'); + }); + + it('works for tilde prerelease ranges', () => { + const versions = ['~4.2.0-alpha.1', '~4.2.0-beta.0', '~4.1.0', '2.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('~4.2.0-beta.0'); + }); + + it('works for tilde and caret prerelease ranges', () => { + const versions = ['~4.2.0-alpha.1', '^4.2.0-rc.0', '~4.2.0-beta.1', '^4.1.0', '2.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('^4.2.0-rc.0'); + }); + + it('works for versions that start with `v`', () => { + const versions = ['~4.2.0-alpha.1', '^4.2.0-rc.0', '~4.2.0-beta.1', '^4.1.0', 'v5.1.0', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('5.1.0'); + }); + + it('works for versions of the format `5.1`', () => { + const versions = ['~4.2.0-alpha.1', '^4.2.0-rc.0', '~4.2.0-beta.1', '^4.1.0', '5.1', '~2.2.0']; + expect(NpmUtils.findMaxVersion(versions)).toBe('5.1.0'); + }); + + it('works if versions are all ranges', () => { + const versions = ['^2.9.0', '~2.8.1']; + expect(NpmUtils.findMaxVersion(versions)).toBe('^2.9.0'); + }); +}); \ No newline at end of file diff --git a/test/PipUtils.test.js b/test/PipUtils.test.js new file mode 100644 index 00000000..c7610af7 --- /dev/null +++ b/test/PipUtils.test.js @@ -0,0 +1,82 @@ +'use strict'; +const PipUtils = require('../utils/PipUtils'); + +describe('find intersection list of pip versions', () => { + const pipPackage = 'alembic'; + it('check for empty list', () => { + const versions = []; + + expect(PipUtils.mergePipVersions(pipPackage, versions)).toBe(''); + }); + + it('check for single exact version', () => { + const versions = ['==3.10.1']; + + expect(PipUtils.mergePipVersions(pipPackage, versions)).toBe('==3.10.1'); + }); + + it('check for list of exact versions', () => { + const versions = ['==3.10.1', '==3.10.2']; + + expect(PipUtils.mergePipVersions(pipPackage, versions)).toBe('==3.10.2'); + }); + + it('check for list of ranged and exact versions', () => { + const versions = ['~=3.10.1', '^=3.10.2']; + + expect(PipUtils.mergePipVersions(pipPackage, versions)).toBe('~=3.10.2'); + }); + + // TODO Refactor to return max without removing the range tags + it('finds max exact version when no intersection exists', () => { + const versions = ['~=3.10.3', '^=3.10.2', '~=3.10.3', '^=4.10.2']; + + expect(PipUtils.mergePipVersions(pipPackage, versions)).toBe('==4.10.2'); + }); +}); + +describe('check PipUtils.toSemver', () => { + + it('version is an empty string', () => { + const version = ''; + expect(PipUtils.toSemVer(version)).toBe(''); + }); + + it('version has `==`', () => { + const version = '==3.4.0'; + expect(PipUtils.toSemVer(version)).toBe('3.4.0'); + }); + + it('version has `~=`', () => { + const version = '~=3.4.0'; + expect(PipUtils.toSemVer(version)).toBe('~3.4.0'); + }); + + it('version has `^=`', () => { + const version = '^=3.4.0'; + expect(PipUtils.toSemVer(version)).toBe('^3.4.0'); + }); +}); + +describe('check PipUtils.toPipVersion', () => { + + it('version is an empty string', () => { + const version = ''; + expect(PipUtils.toPipVersion(version)).toBe(null); + }); + + it('version has no range tag', () => { + const version = '3.4.0'; + expect(PipUtils.toPipVersion(version)).toBe('==3.4.0'); + }); + + it('version has a `~`', () => { + const version = '~3.4.0'; + expect(PipUtils.toPipVersion(version)).toBe('~=3.4.0'); + }); + + it('version has `^`', () => { + const version = '^3.4.0'; + expect(PipUtils.toPipVersion(version)).toBe('^=3.4.0'); + }); +}); \ No newline at end of file diff --git a/test/TestUtils.js b/test/TestUtils.js new file mode 100644 index 00000000..7c1045c2 --- /dev/null +++ b/test/TestUtils.js @@ -0,0 +1,14 @@ +const path = require('path'); + +module.exports = class TestUtils { + /** + * Get the path to the templates of a specific subgenerator. + * @param {string} subgenerator + * @param {string} fileName + * @param {string} type Type of template, plain or processed + */ + static templatePath(subgenerator, fileName, type = '') { + return path.join(__dirname, `../generators/${subgenerator}/templates/${type}/${fileName}`); + } + +}; \ No newline at end of file diff --git a/test/init-app-slib.test.js b/test/init-app-slib.test.js index aefddef5..8d3692e9 100644 --- a/test/init-app-slib.test.js +++ b/test/init-app-slib.test.js @@ -5,7 +5,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const testUtils = require('./testUtils'); +const TestUtils = require('./TestUtils'); /** * Directory name to run the generator */ @@ -42,12 +42,12 @@ describe('generate app-slib plugin with prompt `app: appName` and the rest defau /** * package.tmpl.json template of the _init-web subgenerator */ - const initWebPackage = fse.readJSONSync(testUtils.templatePath('_init-web', 'package.tmpl.json')); + const initWebPackage = fse.readJSONSync(TestUtils.templatePath('_init-web', 'package.tmpl.json')); /** * tsconfig.json template of the _init-web subgenerator */ - const initWebTsConfig = fse.readJSONSync(testUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); + const initWebTsConfig = fse.readJSONSync(TestUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); beforeAll(() => { return helpers diff --git a/test/init-app.test.js b/test/init-app.test.js index 849a8486..26d55b3c 100644 --- a/test/init-app.test.js +++ b/test/init-app.test.js @@ -5,7 +5,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const testUtils = require('./testUtils'); +const TestUtils = require('./TestUtils'); /** * Directory name to run the generator @@ -39,11 +39,11 @@ describe('generate app plugin with prompt `app: appName` and the rest default pr /** * package.tmpl.json template of the _init-web subgenerator */ - const initWebPackage = fse.readJSONSync(testUtils.templatePath('_init-web', 'package.tmpl.json')); + const initWebPackage = fse.readJSONSync(TestUtils.templatePath('_init-web', 'package.tmpl.json')); /** * tsconfig.json template of the _init-web subgenerator */ - const initWebTsConfig = fse.readJSONSync(testUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); + const initWebTsConfig = fse.readJSONSync(TestUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); beforeAll(() => { return helpers diff --git a/test/init-lib-service.test.js b/test/init-lib-service.test.js index bae80e66..902f9556 100644 --- a/test/init-lib-service.test.js +++ b/test/init-lib-service.test.js @@ -5,7 +5,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const testUtils = require('./testUtils'); +const TestUtils = require('./TestUtils'); /** * Directory name to run the generator */ @@ -41,12 +41,12 @@ describe('generate lib-service plugin with default prompt values', () => { /** * package.tmpl.json template of the _init-web subgenerator */ - const initWebPackage = fse.readJSONSync(testUtils.templatePath('_init-web', 'package.tmpl.json')); + const initWebPackage = fse.readJSONSync(TestUtils.templatePath('_init-web', 'package.tmpl.json')); /** * tsconfig.json template of the _init-web subgenerator */ - const initWebTsConfig = fse.readJSONSync(testUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); + const initWebTsConfig = fse.readJSONSync(TestUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); beforeAll(() => { return helpers diff --git a/test/init-lib-slib.test.js b/test/init-lib-slib.test.js index 8d0986cc..e59b5e82 100644 --- a/test/init-lib-slib.test.js +++ b/test/init-lib-slib.test.js @@ -5,7 +5,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const testUtils = require('./testUtils'); +const TestUtils = require('./TestUtils'); /** * Directory name to run the generator */ @@ -41,12 +41,12 @@ describe('generate lib-slib plugin with default prompt values', () => { /** * package.tmpl.json template of the _init-web subgenerator */ - const initWebPackage = fse.readJSONSync(testUtils.templatePath('_init-web', 'package.tmpl.json')); + const initWebPackage = fse.readJSONSync(TestUtils.templatePath('_init-web', 'package.tmpl.json')); /** * tsconfig.json template of the _init-web subgenerator */ - const initWebTsConfig = fse.readJSONSync(testUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); + const initWebTsConfig = fse.readJSONSync(TestUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); beforeAll(() => { return helpers diff --git a/test/init-lib.test.js b/test/init-lib.test.js index a8e5ad0a..fc6e7ed7 100644 --- a/test/init-lib.test.js +++ b/test/init-lib.test.js @@ -5,7 +5,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const testUtils = require('./testUtils'); +const TestUtils = require('./TestUtils'); const {template} = require('lodash'); /** @@ -42,12 +42,12 @@ describe('generate lib plugin with default prompt values', () => { /** * package.tmpl.json template of the _init-web subgenerator */ - const initWebPackage = fse.readJSONSync(testUtils.templatePath('_init-web', 'package.tmpl.json')); + const initWebPackage = fse.readJSONSync(TestUtils.templatePath('_init-web', 'package.tmpl.json')); /** * tsconfig.json template of the _init-web subgenerator */ - const initWebTsConfig = fse.readJSONSync(testUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); + const initWebTsConfig = fse.readJSONSync(TestUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); beforeAll(() => { return helpers @@ -112,7 +112,7 @@ describe('Generate plugin with name `phovea_core`', () => { }); it('generates `phovea_registry.js` with import statement adapted for `phovea_core`', () => { - const phoveaRegistryTmpl = template(fse.readFileSync(testUtils.templatePath('_init-web', 'phovea_registry.js', 'processed')))({name: prompts.name, modules: [], isWeb: () => null}); + const phoveaRegistryTmpl = template(fse.readFileSync(TestUtils.templatePath('_init-web', 'phovea_registry.js', 'processed')))({name: prompts.name, modules: [], isWeb: () => null}); assert.fileContent('phovea_registry.js', phoveaRegistryTmpl); }); }); diff --git a/test/testUtils.js b/test/testUtils.js deleted file mode 100644 index f331dfda..00000000 --- a/test/testUtils.js +++ /dev/null @@ -1,13 +0,0 @@ -const path = require('path'); - -/** - * Get the path to the templates of a specific subgenerator. - * @param {string} subgenerator - * @param {string} fileName - * @param {string} type Type of template, plain or processed - */ -const templatePath = (subgenerator, fileName, type = '') => path.join(__dirname, `../generators/${subgenerator}/templates/${type}/${fileName}`); - -module.exports = { - templatePath -}; diff --git a/test/utils-version.test.js b/test/utils-version.test.js deleted file mode 100644 index f7bebe44..00000000 --- a/test/utils-version.test.js +++ /dev/null @@ -1,397 +0,0 @@ -'use strict'; -const {intersect} = require('semver-intersect'); -const version = require('../utils/version'); - -describe('check isGitCommit()', () => { - it('check `451709494a48af64a8a4876063c244edf41d2643` === true', () => { - expect(version.isGitCommit('451709494a48af64a8a4876063c244edf41d2643')).toBeTruthy(); - }); - - it('check `8747a43780e4651542facd7b4feac7bcb8e3778d` === true', () => { - expect(version.isGitCommit('8747a43780e4651542facd7b4feac7bcb8e3778d')).toBeTruthy(); - }); - - it('check `develop` === false', () => { - expect(version.isGitCommit('develop')).toBeFalsy(); - }); - - it('check `v2.0.0` === false', () => { - expect(version.isGitCommit('v2.0.0')).toBeFalsy(); - }); - - it('check `~v2.0.0` === false', () => { - expect(version.isGitCommit('~v2.0.0')).toBeFalsy(); - }); - - it('check `^v2.0.0` === false', () => { - expect(version.isGitCommit('^v2.0.0')).toBeFalsy(); - }); - - it('check `2.0.0` === false', () => { - expect(version.isGitCommit('2.0.0')).toBeFalsy(); - }); - - it('check `~2.0.0` === false', () => { - expect(version.isGitCommit('~2.0.0')).toBeFalsy(); - }); - - it('check `^2.0.0` === false', () => { - expect(version.isGitCommit('^2.0.0')).toBeFalsy(); - }); -}); - -describe('check isExactVersionTag()', () => { - it('check `develop` === false', () => { - expect(version.isExactVersionTag('develop')).toBeFalsy(); - }); - - it('check `v2.0.0` === true', () => { - expect(version.isExactVersionTag('v2.0.0')).toBeTruthy(); - }); - - it('check `~v2.0.0` === false', () => { - expect(version.isExactVersionTag('~v2.0.0')).toBeFalsy(); - }); - - it('check `^v2.0.0` === false', () => { - expect(version.isExactVersionTag('^v2.0.0')).toBeFalsy(); - }); - - it('check `2.0.0` === false', () => { - expect(version.isExactVersionTag('2.0.0')).toBeFalsy(); - }); - - it('check `~2.0.0` === false', () => { - expect(version.isExactVersionTag('~2.0.0')).toBeFalsy(); - }); - - it('check `^2.0.0` === false', () => { - expect(version.isExactVersionTag('^2.0.0')).toBeFalsy(); - }); -}); - -describe('check isAdvancedVersionTag()', () => { - it('check `develop` === false', () => { - expect(version.isAdvancedVersionTag('develop')).toBeFalsy(); - }); - - it('check `v2.0.0` === false', () => { - expect(version.isAdvancedVersionTag('v2.0.0')).toBeFalsy(); - }); - - it('check `~v2.0.0` === true', () => { - expect(version.isAdvancedVersionTag('~v2.0.0')).toBeTruthy(); - }); - - it('check `^v2.0.0` === true', () => { - expect(version.isAdvancedVersionTag('^v2.0.0')).toBeTruthy(); - }); - - it('check `2.0.0` === false', () => { - expect(version.isAdvancedVersionTag('2.0.0')).toBeFalsy(); - }); - - it('check `~2.0.0` === false', () => { - expect(version.isAdvancedVersionTag('~2.0.0')).toBeFalsy(); - }); - - it('check `^2.0.0` === false', () => { - expect(version.isAdvancedVersionTag('^2.0.0')).toBeFalsy(); - }); -}); - -describe('transform git log to version tags list', () => { - const gitLog = `451709494a48af64a8a4876063c244edf41d2643 refs/tags/caleydo_web - a1d4f93a626d71937bc35b23d3715eaf34cce4a1 refs/tags/v0.0.5 - 921409de073f4329c09a4602622e87d816de266f refs/tags/v0.1.0 - 9815eb1163b212e06b7239a0bf6f97b0fbc2cf0c refs/tags/v1.0.0 - e61c59f8c09e51e0b25f2087ad92789c26d58c11 refs/tags/v1.0.0^{} - 336072e87ec8f6054cead9f64c6830897fb7f076 refs/tags/v2.0.0 - 8747a43780e4651542facd7b4feac7bcb8e3778d refs/tags/v2.0.1 - ebb538469a661dc4a8c5646ca1bb11259f2ba2bb refs/tags/v2.0.1^{} - c073da02dbb1c8185a5d50266f78b9688dd4403a refs/tags/v2.1.0 - 53f68e0768df23b173f59d22ea90f61c478b8450 refs/tags/v2.1.1 - `; - - const versionTags = version.extractVersionsFromGitLog(gitLog); - - it('check number of extracted versions', () => { - expect(versionTags.length).toBe(7); - }); - - it('check if tags without `v` are removed', () => { - expect(versionTags.indexOf('caleydo_web')).toBe(-1); - }); - - it('check if tags ending with `^{}` are removed', () => { - expect(versionTags.indexOf('v1.0.0^{}')).toBe(-1); - expect(versionTags.filter((v) => v === 'v1.0.0').length).toBe(1); - }); - - it('find specific version tag in list', () => { - expect(versionTags.indexOf('v0.0.5')).toBe(0); - }); -}); - -describe('check semver.satisfies', () => { - const semver = require('semver'); - - it('check against target version with caret operator', () => { - const targetVersion = '^v2.0.0'; - expect(semver.satisfies('v1.0.0', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.0.0', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.0.1', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.0.2', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.1.0', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.1.1', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.1.2', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.2.0', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.2.1', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.2.2', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v3.0.0', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v3.1.0', targetVersion)).toBeFalsy(); - }); - - it('check target version with tilde operator', () => { - const targetVersion = '~v2.0.0'; - expect(semver.satisfies('v1.0.0', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.0.0', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.0.1', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.0.2', targetVersion)).toBeTruthy(); - expect(semver.satisfies('v2.1.0', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.1.1', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.1.2', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.2.0', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.2.1', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v2.2.2', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v3.0.0', targetVersion)).toBeFalsy(); - expect(semver.satisfies('v3.1.0', targetVersion)).toBeFalsy(); - }); -}); - -describe('find highest version from list', () => { - const sourceVersions = [ - 'v0.0.5', - 'v0.1.0', - 'v1.0.0', - 'v2.1.0', // note: out of order to test sorting - 'v2.2.0', // note: out of order to test sorting - 'v2.0.0', - 'v2.0.1', - 'v2.0.2', - 'v2.1.1', - 'v2.1.2', - 'v2.2.1', - 'v2.2.2', - 'v3.0.0', - 'v3.1.0' - ]; - - it('find exact version `v2.0.0`', () => { - const targetVersion = 'v2.0.0'; - expect(version.findHighestVersion(sourceVersions, targetVersion)).toBe('v2.0.0'); - }); - - it('find patch version `~v2.0.0`', () => { - const targetVersion = '~v2.0.0'; - expect(version.findHighestVersion(sourceVersions, targetVersion)).toBe('v2.0.2'); - }); - - it('find minor version `^v2.0.0`', () => { - const targetVersion = '^v2.0.0'; - expect(version.findHighestVersion(sourceVersions, targetVersion)).toBe('v2.2.2'); - }); - - it('find non-existing `v4.0.0`', () => { - const targetVersion = 'v4.0.0'; - expect(version.findHighestVersion(sourceVersions, targetVersion)).toBeUndefined(); - }); - - it('find non-existing `^v3.2.0`', () => { - const targetVersion = '^v3.2.0'; - expect(version.findHighestVersion(sourceVersions, targetVersion)).toBeUndefined(); - }); -}); - -describe('find max version or range version from list', () => { - - it('works for simple versions arrays', () => { - const versions = ['0.0.5', '0.1.0', '1.0.0', '2.1.0', '2.2.0']; - expect(version.findMaxVersion(versions)).toBe('2.2.0'); - }); - - it('works for arrays with prerelease versions', () => { - const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '0.1.0', '1.0.0', '2.1.0', '2.2.0']; - expect(version.findMaxVersion(versions)).toBe('4.2.0-beta.0'); - }); - - it('works for arrays with prerelease and tilde ranges', () => { - const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '0.1.0', '~4.2.0', '2.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('~4.2.0'); - }); - - it('works for arrays with prerelease, tilde and caret ranges', () => { - const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '^4.2.0', '~4.2.0', '2.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('^4.2.0'); - }); - - it('works for `^4.2.0`', () => { - const versions = ['4.2.0-alpha.1', '4.2.0-beta.0', '^4.2.0', '~4.2.0', '2.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('^4.2.0'); - }); - - it('works for caret prerelease ranges', () => { - const versions = ['^4.2.0-alpha.1', '^4.2.0-beta.0', '^4.1.0', '2.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('^4.2.0-beta.0'); - }); - - it('works for tilde prerelease ranges', () => { - const versions = ['~4.2.0-alpha.1', '~4.2.0-beta.0', '~4.1.0', '2.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('~4.2.0-beta.0'); - }); - - it('works for tilde and caret prerelease ranges', () => { - const versions = ['~4.2.0-alpha.1', '^4.2.0-rc.0', '~4.2.0-beta.1', '^4.1.0', '2.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('^4.2.0-rc.0'); - }); - - it('works for versions that start with `v`', () => { - const versions = ['~4.2.0-alpha.1', '^4.2.0-rc.0', '~4.2.0-beta.1', '^4.1.0', 'v5.1.0', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('5.1.0'); - }); - - it('works for versions of the format `5.1`', () => { - const versions = ['~4.2.0-alpha.1', '^4.2.0-rc.0', '~4.2.0-beta.1', '^4.1.0', '5.1', '~2.2.0']; - expect(version.findMaxVersion(versions)).toBe('5.1.0'); - }); - - it('works if versions are all ranges', () => { - const versions = ['^2.9.0', '~2.8.1']; - expect(version.findMaxVersion(versions)).toBe('^2.9.0'); - }); -}); - -describe('semver-intersect works for prerelease ranges', () => { - - it('finds intersection of an array of prerelease ranges', () => { - const versions = ['~4.2.0-alpha.1', '~4.2.0-beta.1',]; - expect(intersect(...versions)).toBe('~4.2.0-beta.1'); - }); -}); - -describe('find intersection or max version of github or gitlab version tags', () => { - - it('returns first correct gitlab tag', () => { - const name = 'target360'; - const versions = [ - 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop', - 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop', - '4.0.0' - ]; - expect(version.mergeVersions(name, versions)).toBe('git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop'); - }); - - it('returns first correct githab tag', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#develop', - 'github:phovea/phovea_core#develop', - '5.0.0' - ]; - expect(version.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#develop'); - }); - - it('throws error if versions point to different gitlab branches', () => { - const name = 'target360'; - const versions = [ - 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#dv_develop', - 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#master', - '4.0.0' - ]; - expect(() => version.mergeVersions(name, versions)).toThrow(); - }); - - it('returns correct intersection of github ranges', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - 'github:phovea/phovea_core#semver:^7.0.0', - ]; - expect(version.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^7.0.1'); - }); - - it('throws error if versions contain both github and gitlab', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - 'git+ssh://git@gitlab.customer.com:Target360/plugins/target360#master', - ]; - expect(() => version.mergeVersions(name, versions)).toThrow(); - }); - - it('throws error if versions 2 different github versions', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - 'github:phovea/phovea_core#develop', - ]; - expect(() => version.mergeVersions(name, versions)).toThrow(); - }); - - it('returns github version if one of the versions is a github semver version bigger than the rest', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - '4.0.0', - ]; - expect(version.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^7.0.1'); - }); - - it('returns correct max github version', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - 'github:phovea/phovea_core#semver:^8.0.0' - ]; - expect(version.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^8.0.0'); - }); - - it('compares github version with npm version', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - '^8.0.0' - ]; - expect(version.mergeVersions(name, versions)).toBe('^8.0.0'); - }); - - it('compares an equal github version with an npm version', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - '^7.0.1' - ]; - expect(version.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:^7.0.1'); - }); - - it('compares multiple github and npm versions', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:^7.0.1', - 'github:phovea/phovea_core#semver:^6.0.1', - '^7.0.1', - '^7.0.2' - ]; - expect(version.mergeVersions(name, versions)).toBe('^7.0.2'); - }); - - it('finds the intersection of a git version and npm version', () => { - const name = 'phovea_core'; - const versions = [ - 'github:phovea/phovea_core#semver:~7.0.1', - 'github:phovea/phovea_core#semver:^6.0.1', - '^7.0.1', - ]; - expect(version.mergeVersions(name, versions)).toBe('github:phovea/phovea_core#semver:~7.0.1'); - }); -}); diff --git a/utils/NpmUtils.js b/utils/NpmUtils.js new file mode 100644 index 00000000..e7b75550 --- /dev/null +++ b/utils/NpmUtils.js @@ -0,0 +1,244 @@ +'use strict'; + +const semver = require('semver'); +const chalk = require('chalk'); +const {intersect} = require('semver-intersect'); + + +module.exports = class NpmUtils { + + /** + * Finds the intersection of an array of semver versions. If no intersection exists the maximum version is returned. + * @param {string} name Name of the dependency. + * @param {string[]} versions Array of versions found for the dependency in the different workspace plugins. + */ + static mergeVersions(name, versions, logWarning = true) { + if (versions.some((v) => v === 'latest')) { + throw new Error(chalk.red('Invalid version. Please avoid using version latest in package.json.')); + } + // create set + versions = Array.from(new Set(versions)); + if (versions.length === 1) { + return versions[0]; + } + // filter for github and gitlab version strings + const gitRepos = versions.filter((d) => d.includes('github') || d.includes('gitlab')); + // npm version strings + const noGitRepos = versions.filter((v) => !gitRepos.includes(v)); + + if (gitRepos.length) { + return NpmUtils.mergeGithubVersions(name, gitRepos, noGitRepos); + } + + try { + return intersect(...noGitRepos).toString(); + } catch (e) { + // map to base version, sort descending take first + const max = NpmUtils.findMaxVersion(noGitRepos); + if (logWarning) { + console.warn(`cannot find common intersecting version for ${name} = ${versions.join(', ')}, taking max "${max}" for now`); + } + + return max.toString(); + } + } + + /** + * Extracts git version strings, compares them with the npm versions and returns the intersection or max + * @param {string} name Name of the dependency + * @param {string[]} gitBranches Git version strings, i.e, `github:phovea/phovea_core#semver:~7.0.1` + * @param {string[]} npmVersions Npm version strings, i.e, `^7.0.0` + */ + static mergeGithubVersions(name, gitBranches, npmVersions) { + const versions = Array.from(new Set(gitBranches.map((branch) => branch.split('#')[1]))); + const areSemverVersions = versions.every((version) => version.includes('semver')); + if (areSemverVersions) { + const prefix = gitBranches[0].split('#')[0]; + const parsedSemver = versions.map((version) => version.replace('semver:', '')); + const gitVersion = NpmUtils.mergeVersions(name, parsedSemver, false); + const allVersions = [gitVersion, ...npmVersions]; + const max = NpmUtils.mergeVersions(name, allVersions, false); + const areEqual = (v1, v2) => v1 === NpmUtils.mergeVersions(name, [v1, v2], false); + return areEqual(gitVersion, max) ? `${prefix}#semver:${gitVersion}` : max; + } + + const uniqueGitBranchesCount = versions.length; + if (uniqueGitBranchesCount === 1) { + return gitBranches[0]; + } + + throw new Error(chalk.red(`Versions ${chalk.white(gitBranches.join(', '))} point to different branches, which can lead to workspace errors.\nPlease use the same branch in all versions.`)); + } + + /** + * Finds the max version of an array of versions, i.e., `['1.2.3-alpha.1', '4.0.1-beta.0', '^3.8.0', '~4.0.0', '^2.8.0', '^4.0.0', '4.0.1-rc.0']`. + * Can handle range(caret, tilde) and prerelease versions. + * @param {Array} versions Array of semver versions including range versions. + */ + static findMaxVersion(versions) { + const nonRangeVersions = versions.filter((v) => !NpmUtils.hasRangeVersionTag(v)).map((v) => semver.prerelease(v) ? v : semver.coerce(v).version); // Filter out versions with `~` and `^` + // Sort versions and get max. Method `semver.rcomapre()` fails when you try comparing ranges, i.e., `~2.0.0` + const maxNonRangeVersion = nonRangeVersions.sort(semver.rcompare)[0] || nonRangeVersions[nonRangeVersions.length - 1]; + if (versions.some((v) => NpmUtils.hasRangeVersionTag(v))) { + const maxCaretRange = NpmUtils.findMaxCaretRange(versions); // ['^1.0.0', '^1.2.3']--> '^1.2.3' + const maxTildeRange = NpmUtils.findMaxTildeRange(versions); // ['~1.0.0', '~1.2.5']--> '~1.2.5' + const maxRange = maxCaretRange && maxTildeRange ? NpmUtils.findMaxRange(maxTildeRange, maxCaretRange) : maxTildeRange || maxCaretRange; + return maxNonRangeVersion && semver.gtr(maxNonRangeVersion, maxRange) ? maxNonRangeVersion : maxRange; // check maxNonRangeVersion is greater than all the versions possible in the range. + } + return maxNonRangeVersion; + } + + /** + * Find max between a tilde range and a caret range. + * @param {string} tildeRange , i.e., '~2.0.3' + * @param {string} caretRange , i.e., '^3.5.6' + * @returns {string} Returns a tilde range or a caret range. + */ + static findMaxRange(tildeRange, caretRange) { + const parsedCaretRange = semver.coerce(caretRange); // create a semver object from tag to access `major` and `version` properties + const parsedTildeRange = semver.coerce(tildeRange); + // tilde range can only be greater than caret range when its major is greater, i.e, '~3.5.6' > '^2.9.0' + if (semver.gt(semver.coerce(parsedTildeRange.major), semver.coerce(parsedCaretRange.major))) { + return tildeRange; + } else { // in any other case the caret range is greater (has a greater upper domain) + return caretRange; + } + } + + + /** + * Remove caret or tilde and format version. + * @param {string} range Possible values: `^2.3.4, `~3.0.0`. + * @returns {string} Return a version string without the range tags (tilde, caret). + */ + static removeRangeTag(range) { + return semver.prerelease(semver.minVersion(range)) ? semver.minVersion(range) : semver.coerce(range).version; + } + + /** + * Finds the max caret range of an array of caret ranges. + * @param {string[]} versions Possible values: `['^2.3.4', '^3.0.0']` + * @returns {void | string} Returns the caret range with the highest upper domain or void if there are no caret ranges in the versions array. + */ + static findMaxCaretRange(versions) { + const caretRanges = versions.filter((v) => v.startsWith('^')); + if (caretRanges) { + const parsedTags = caretRanges.map((r) => NpmUtils.removeRangeTag(r)); + const max = parsedTags.sort(semver.rcompare)[0] || caretRanges[caretRanges.length - 1]; + return caretRanges.find((r) => semver.eq(NpmUtils.removeRangeTag(r), max)); + } + } + + /** + * Finds the max tilde range of an array of tilde ranges. + * @param {string[]} versions Possible values: `['~2.3.4', '~3.0.0']` + * @returns {void | string} Returns the tilde range with the highest upper domain or void if there are no tilde ranges in the versions array. + */ + static findMaxTildeRange(versions) { + const tildeRanges = versions.filter((v) => v.startsWith('~')); + if (tildeRanges) { + const parsedTags = tildeRanges.map((r) => NpmUtils.removeRangeTag(r)); + const max = parsedTags.sort(semver.rcompare)[0] || tildeRanges[tildeRanges.length - 1]; + return tildeRanges.find((r) => semver.eq(NpmUtils.removeRangeTag(r), max)); + } + } + + /** + * Check if version is a caret or a tilde range. + * @param {string} version Possible values: `^=2.0.0`, `~3.5.6`, `3.4.5`. + * @returns {boolean} + */ + static hasRangeVersionTag(version) { + return /^[\^~]/gi.test(version); + } + + /** + * Find the highest possible target version from a list of versions. + * The target version can be a range of versions and supports the npm semver syntax. + * + * @param {string[]} sourceVersions List of source versions (e.g., [`2.0.0`, `v2.1.0`, ...]) + * @param {string} targetVersion version or version range supporting the npm semver syntax + * @returns {string|undefined} Returns the highest possible version from the list of source versions + */ + static findHighestVersion(sourceVersions, targetVersion) { + const semver = require('semver'); + + const regex = /^([\^~])/gi; // test if target version starts with ^ or ~ + // shortcut if exact target version is required + if (regex.test(targetVersion) === false) { + return sourceVersions.find((v) => v === targetVersion); + } + + const versions = sourceVersions + .map((version) => { + return { + version, + satisfied: semver.satisfies(version, targetVersion) + }; + }) + .filter((v) => v.satisfied) + .sort((a, b) => b.version.localeCompare(a.version)); // sort version descending + + return (versions[0]) ? versions[0].version : undefined; // first element = highest version + } + + /** + * Checks if a given name is a git commit. + * + * @param {string} name name to check + * @returns {boolean} Returns `true` if name is a git commit. Otherwise returns `false`. + */ + static isGitCommit(name) { + return /^[0-9a-f]+$/gi.test(name); + } + + /** + * Checks if a given name is a version tag that starts with `v`. + * + * @param {string} name name to check + * @returns {boolean} Returns `true` if name is a version tag. Otherwise returns `false`. + */ + static isExactVersionTag(name) { + return /^v\d+.*/gi.test(name); + } + + /** + * Checks if a given name is an advanced version tag supporting npm's version ranges. + * A version tag must start with `^v`, `~v`. + * + * @see https://docs.npmjs.com/misc/semver#advanced-range-syntax + * + * @param {string} name name to check + * @returns {boolean} Returns `true` if name is a version tag. Otherwise returns `false`. + */ + static isAdvancedVersionTag(name) { + return /^[\^~]v/gi.test(name); + } + + /** + * Extract tag names starting with `v` (e.g., `v2.0.1`) from the given git log. + * The git log must have the structure: + * ``` + * refs/tags/ + * ``` + * The output can be generated using the command `git ls-remote --tags ` + * + * @param {string} gitLog Console output with list of git hashes and git tags + * @returns {string[]} Returns an array with tag names starting with `v` + */ + static extractVersionsFromGitLog(gitLog) { + const regex = /refs\/tags\/([v]{1}.*[^}])\n/gm; // capture all tag names starting with `v` + let m; + const versionTags = []; + + while ((m = regex.exec(gitLog)) !== null) { + // This is necessary to avoid infinite loops with zero-width matches + if (m.index === regex.lastIndex) { + regex.lastIndex++; + } + versionTags.push(m[1]); + } + + return versionTags; + } +}; \ No newline at end of file diff --git a/utils/PipUtils.js b/utils/PipUtils.js new file mode 100644 index 00000000..01725ae9 --- /dev/null +++ b/utils/PipUtils.js @@ -0,0 +1,76 @@ +'use strict'; + +const semver = require('semver'); +const {intersect} = require('semver-intersect'); + + +module.exports = class PipUtils { + + /** + * Finds the intersection of an array of pip versions, i.e, `^=2.2.0`. If no intersection exists the maximum version is returned. + * @param {string} name Name of the requirement. + * @param {string[]} versions Array of versions found for the requirement in the different workspace plugins. + * TODO find the correct max version for ranges... + */ + static mergePipVersions(name, versions) { + versions = Array.from(new Set(versions)).filter(Boolean); // unique + not empty entries + if (versions.length === 0) { + return ''; + } + if (versions.length === 1) { + return versions[0]; + } + const gitBranch = versions.find((d) => d.startsWith('@')); + if (gitBranch) { + return gitBranch; + } + + const nodeVersions = versions.map(PipUtils.toSemVer); + // first try to find a good intersection + try { + return PipUtils.toPipVersion(intersect(...nodeVersions).toString()); + } catch (e) { + // map to base version, sort descending take first + const max = PipUtils.toPipVersion(nodeVersions.map(semver.coerce).sort(semver.rcompare)[0]) || versions[versions.length - 1]; + console.warn(`cannot find common intersecting version for ${name} = ${versions.join(', ')}, taking max "${max}" for now`); + return max.toString(); + } + } + + /** + * Transforms a pip to semver version, i.e, `~=2.0.0` --> `~2.0.0` + * @param {string} version + */ + static toSemVer(version) { + if (version.startsWith('~=')) { + return `~${version.slice(2)}`; + } + if (version.startsWith('^=')) { + return `^${version.slice(2)}`; + } + if (version.startsWith('==')) { + return version.slice(2); + } + return version; + } + + /** + * Transforms a semver to pip version, i.e, `2.0.0` --> `==2.0.0` + * @param {string} version + */ + static toPipVersion(version) { + if (!version) { + return null; + } + version = version.toString(); + if (version.startsWith('~')) { + return `~=${version.slice(1)}`; + } + if (version.startsWith('^')) { + return `^=${version.slice(1)}`; + } + // TODO range + // fix + return `==${version}`; + } +}; \ No newline at end of file diff --git a/utils/version.js b/utils/version.js deleted file mode 100644 index 998046e9..00000000 --- a/utils/version.js +++ /dev/null @@ -1,296 +0,0 @@ -'use strict'; - -const semver = require('semver'); -const chalk = require('chalk'); -const { - intersect -} = require('semver-intersect'); - -function mergeVersions(name, versions, logWarning = true) { - if (versions.some((v) => v === 'latest')) { - throw new Error(chalk.red('Invalid version. Please avoid using version latest in package.json.')); - } - // create set - versions = Array.from(new Set(versions)); - if (versions.length === 1) { - return versions[0]; - } - // filter for github and gitlab version strings - const gitRepos = versions.filter((d) => d.includes('github') || d.includes('gitlab')); - // npm version strings - const noGitRepos = versions.filter((v) => !gitRepos.includes(v)); - - if (gitRepos.length) { - return mergeGithubVersions(name, gitRepos, noGitRepos); - } - - try { - return intersect(...noGitRepos).toString(); - } catch (e) { - // map to base version, sort descending take first - const max = findMaxVersion(noGitRepos); - if (logWarning) { - console.warn(`cannot find common intersecting version for ${name} = ${versions.join(', ')}, taking max "${max}" for now`); - } - - return max.toString(); - } -} - -module.exports.mergeVersions = mergeVersions; - - -/** - * Extracts git version strings, compares them with the npm versions and returns the intersection or max - * @param {string} name Name of the dependency - * @param {string[]} gitBranches Git version strings, i.e, `github:phovea/phovea_core#semver:~7.0.1` - * @param {string[]} npmVersions Npm version strings, i.e, `^7.0.0` - */ -function mergeGithubVersions(name, gitBranches, npmVersions) { - const versions = Array.from(new Set(gitBranches.map((branch) => branch.split('#')[1]))); - const areSemverVersions = versions.every((version) => version.includes('semver')); - if (areSemverVersions) { - const prefix = gitBranches[0].split('#')[0]; - const parsedSemver = versions.map((version) => version.replace('semver:', '')); - const gitVersion = mergeVersions(name, parsedSemver, false); - const allVersions = [gitVersion, ...npmVersions]; - const max = mergeVersions(name, allVersions, false); - const areEqual = (v1, v2) => v1 === mergeVersions(name, [v1, v2], false); - return areEqual(gitVersion, max) ? `${prefix}#semver:${gitVersion}` : max; - } - - const uniqueGitBranchesCount = versions.length; - if (uniqueGitBranchesCount === 1) { - return gitBranches[0]; - } - - throw new Error(chalk.red(`Versions ${chalk.white(gitBranches.join(', '))} point to different branches, which can lead to workspace errors.\nPlease use the same branch in all versions.`)); -} - -/** - * Finds the max version of an array of versions, i.e., `['1.2.3-alpha.1', '4.0.1-beta.0', '^3.8.0', '~4.0.0', '^2.8.0', '^4.0.0', '4.0.1-rc.0']`. - * Can handle range(caret, tilde) and prerelease versions. - * @param {Array} versions Array of semver versions including range versions. - */ -function findMaxVersion(versions) { - const nonRangeVersions = versions.filter((v) => !hasRangeVersionTag(v)).map((v) => semver.prerelease(v) ? v : semver.coerce(v).version); // Filter out versions with `~` and `^` - // Sort versions and get max. Method `semver.rcomapre()` fails when you try comparing ranges, i.e., `~2.0.0` - const maxNonRangeVersion = nonRangeVersions.sort(semver.rcompare)[0] || nonRangeVersions[nonRangeVersions.length - 1]; - if (versions.some((v) => hasRangeVersionTag(v))) { - const maxCaretRange = findMaxCaretRange(versions); // ['^1.0.0', '^1.2.3']--> '^1.2.3' - const maxTildeRange = findMaxTildeRange(versions); // ['~1.0.0', '~1.2.5']--> '~1.2.5' - const maxRange = maxCaretRange && maxTildeRange ? findMaxRange(maxTildeRange, maxCaretRange) : maxTildeRange || maxCaretRange; - return maxNonRangeVersion && semver.gtr(maxNonRangeVersion, maxRange) ? maxNonRangeVersion : maxRange; // check maxNonRangeVersion is greater than all the versions possible in the range. - } - return maxNonRangeVersion; -} - -/** - * Find max between a tilde range and a caret range. - * @param {string} tildeRange , i.e., '~2.0.3' - * @param {string} caretRange , i.e., '^3.5.6' - * @returns {string} Returns a tilde range or a caret range. - */ -function findMaxRange(tildeRange, caretRange) { - const parsedCaretRange = semver.coerce(caretRange); // create a semver object from tag to access `major` and `version` properties - const parsedTildeRange = semver.coerce(tildeRange); - // tilde range can only be greater than caret range when its major is greater, i.e, '~3.5.6' > '^2.9.0' - if (semver.gt(semver.coerce(parsedTildeRange.major), semver.coerce(parsedCaretRange.major))) { - return tildeRange; - } else { // in any other case the caret range is greater (has a greater upper domain) - return caretRange; - } -} - -module.exports.findMaxVersion = findMaxVersion; - -/** - * Remove caret or tilde and format version. - * @param {string} range Possible values: `^2.3.4, `~3.0.0`. - * @returns {string} Return a version string without the range tags (tilde, caret). - */ -function removeRangeTag(range) { - return semver.prerelease(semver.minVersion(range)) ? semver.minVersion(range) : semver.coerce(range).version; -} - -/** - * Finds the max caret range of an array of caret ranges. - * @param {string[]} versions Possible values: `['^2.3.4', '^3.0.0']` - * @returns {void | string} Returns the caret range with the highest upper domain or void if there are no caret ranges in the versions array. - */ -function findMaxCaretRange(versions) { - const caretRanges = versions.filter((v) => v.startsWith('^')); - if (caretRanges) { - const parsedTags = caretRanges.map((r) => removeRangeTag(r)); - const max = parsedTags.sort(semver.rcompare)[0] || caretRanges[caretRanges.length - 1]; - return caretRanges.find((r) => semver.eq(removeRangeTag(r), max)); - } -} - -/** - * Finds the max tilde range of an array of tilde ranges. - * @param {string[]} versions Possible values: `['~2.3.4', '~3.0.0']` - * @returns {void | string} Returns the tilde range with the highest upper domain or void if there are no tilde ranges in the versions array. - */ -function findMaxTildeRange(versions) { - const tildeRanges = versions.filter((v) => v.startsWith('~')); - if (tildeRanges) { - const parsedTags = tildeRanges.map((r) => removeRangeTag(r)); - const max = parsedTags.sort(semver.rcompare)[0] || tildeRanges[tildeRanges.length - 1]; - return tildeRanges.find((r) => semver.eq(removeRangeTag(r), max)); - } -} - -/** - * Check if version is a caret or a tilde range. - * @param {string} version Possible values: `^=2.0.0`, `~3.5.6`, `3.4.5`. - * @returns {boolean} - */ -function hasRangeVersionTag(version) { - return /^[\^~]/gi.test(version); -} - -function toSemVer(version) { - if (version.startsWith('~=')) { - return `~${version.slice(2)}`; - } - if (version.startsWith('^=')) { - return `^${version.slice(2)}`; - } - if (version.startsWith('==')) { - return version.slice(2); - } - return version; -} - -function toPipVersion(version) { - if (!version) { - return null; - } - version = version.toString(); - if (version.startsWith('~')) { - return `~=${version.slice(1)}`; - } - if (version.startsWith('^')) { - return `^=${version.slice(1)}`; - } - // TODO range - // fix - return `==${version}`; -} -// -module.exports.mergePipVersions = (name, versions) => { - versions = Array.from(new Set(versions)).filter(Boolean); // unique + not empty entries - if (versions.length === 0) { - return ''; - } - if (versions.length === 1) { - return versions[0]; - } - const gitBranch = versions.find((d) => d.startsWith('@')); - if (gitBranch) { - return gitBranch; - } - - const nodeVersions = versions.map(toSemVer); - // first try to find a good intersection - try { - return toPipVersion(intersect(...nodeVersions).toString()); - } catch (e) { - // map to base version, sort descending take first - const max = toPipVersion(nodeVersions.map(semver.coerce).sort(semver.rcompare)[0]) || versions[versions.length - 1]; - console.warn(`cannot find common intersecting version for ${name} = ${versions.join(', ')}, taking max "${max}" for now`); - return max.toString(); - } -}; - -/** - * Extract tag names starting with `v` (e.g., `v2.0.1`) from the given git log. - * The git log must have the structure: - * ``` - * refs/tags/ - * ``` - * The output can be generated using the command `git ls-remote --tags ` - * - * @param {string} gitLog Console output with list of git hashes and git tags - * @returns {string[]} Returns an array with tag names starting with `v` - */ -module.exports.extractVersionsFromGitLog = (gitLog) => { - const regex = /refs\/tags\/([v]{1}.*[^}])\n/gm; // capture all tag names starting with `v` - let m; - const versionTags = []; - - while ((m = regex.exec(gitLog)) !== null) { - // This is necessary to avoid infinite loops with zero-width matches - if (m.index === regex.lastIndex) { - regex.lastIndex++; - } - versionTags.push(m[1]); - } - - return versionTags; -}; - -/** - * Find the highest possible target version from a list of versions. - * The target version can be a range of versions and supports the npm semver syntax. - * - * @param {string[]} sourceVersions List of source versions (e.g., [`2.0.0`, `v2.1.0`, ...]) - * @param {string} targetVersion version or version range supporting the npm semver syntax - * @returns {string|undefined} Returns the highest possible version from the list of source versions - */ -module.exports.findHighestVersion = (sourceVersions, targetVersion) => { - const semver = require('semver'); - - const regex = /^([\^~])/gi; // test if target version starts with ^ or ~ - // shortcut if exact target version is required - if (regex.test(targetVersion) === false) { - return sourceVersions.find((v) => v === targetVersion); - } - - const versions = sourceVersions - .map((version) => { - return { - version, - satisfied: semver.satisfies(version, targetVersion) - }; - }) - .filter((v) => v.satisfied) - .sort((a, b) => b.version.localeCompare(a.version)); // sort version descending - - return (versions[0]) ? versions[0].version : undefined; // first element = highest version -}; - -/** - * Checks if a given name is an advanced version tag supporting npm's version ranges. - * A version tag must start with `^v`, `~v`. - * - * @see https://docs.npmjs.com/misc/semver#advanced-range-syntax - * - * @param {string} name name to check - * @returns {boolean} Returns `true` if name is a version tag. Otherwise returns `false`. - */ -module.exports.isAdvancedVersionTag = (name) => { - return /^[\^~]v/gi.test(name); -}; - -/** - * Checks if a given name is a version tag that starts with `v`. - * - * @param {string} name name to check - * @returns {boolean} Returns `true` if name is a version tag. Otherwise returns `false`. - */ -module.exports.isExactVersionTag = (name) => { - return /^v\d+.*/gi.test(name); -}; - -/** - * Checks if a given name is a git commit. - * - * @param {string} name name to check - * @returns {boolean} Returns `true` if name is a git commit. Otherwise returns `false`. - */ -module.exports.isGitCommit = (name) => { - return /^[0-9a-f]+$/gi.test(name); -}; - From 3fd9eacae6e1973f9c8c8db8e8358f08bb408f15 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 4 Sep 2020 13:43:29 +0200 Subject: [PATCH 02/65] Write tests for `pip.js` and refactor into a class method phovea/generator-phovea#425 --- generators/_init-python/index.js | 6 ++--- generators/prepare-release/index.js | 6 ++--- generators/workspace/index.js | 5 ++-- test/PipUtils.test.js | 34 +++++++++++++++++++++++++ utils/PipUtils.js | 38 ++++++++++++++++++++++++++++ utils/pip.js | 39 ----------------------------- 6 files changed, 80 insertions(+), 48 deletions(-) delete mode 100644 utils/pip.js diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index c5be5940..edc218a2 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -2,7 +2,7 @@ const _ = require('lodash'); const Base = require('yeoman-generator'); const {writeTemplates, patchPackageJSON, stringifyAble, useDevVersion} = require('../../utils'); -const {parseRequirements} = require('../../utils/pip'); +const PipUtils = require('../../utils/PipUtils'); const fs = require('fs'); const known = () => require('../../utils/known'); @@ -66,8 +66,8 @@ class Generator extends Base { } _generateDependencies(useDevelopDependencies, cwd) { - let requirements = parseRequirements(this.fs.read(this.destinationPath(cwd + 'requirements.txt'), {defaults: ''})); - const dockerPackages = parseRequirements(this.fs.read(this.destinationPath(cwd + 'docker_packages.txt'), {defaults: ''})); + let requirements = PipUtils.parseRequirements(this.fs.read(this.destinationPath(cwd + 'requirements.txt'), {defaults: ''})); + const dockerPackages = PipUtils.parseRequirements(this.fs.read(this.destinationPath(cwd + 'docker_packages.txt'), {defaults: ''})); const concat = (p) => Object.keys(p).map((pi) => pi + p[pi]); // merge dependencies diff --git a/generators/prepare-release/index.js b/generators/prepare-release/index.js index ec144065..1f65db33 100644 --- a/generators/prepare-release/index.js +++ b/generators/prepare-release/index.js @@ -2,7 +2,7 @@ const Base = require('yeoman-generator'); const chalk = require('chalk'); const fs = require('fs-extra'); -const {parseRequirements} = require('../../utils/pip'); +const PipUtils = require('../../utils/PipUtils'); const {toHTTPRepoUrl, toSSHRepoUrl, simplifyRepoUrl} = require('../../utils/repo'); function toBaseName(name) { @@ -222,7 +222,7 @@ class Generator extends Base { if (fs.existsSync(`${ctx.cwd}/requirements.txt`)) { ctx.requirements = {}; - const req = parseRequirements(this.fs.read(`${ctx.cwd}/requirements.txt`)); + const req = PipUtils.parseRequirements(this.fs.read(`${ctx.cwd}/requirements.txt`)); p = Promise.all(Object.keys(req).map((dep) => { if (dependenciesToIgnores.some((d) => dep.includes(d))) { return null; @@ -294,7 +294,7 @@ class Generator extends Base { }); this.fs.writeJSON(`${ctx.cwd}/package.json`, pkg); if (ctx.requirements) { - const req = parseRequirements(this.fs.read(`${ctx.cwd}/requirements.txt`)); + const req = PipUtils.parseRequirements(this.fs.read(`${ctx.cwd}/requirements.txt`)); Object.keys(ctx.requirements).forEach((dep) => { const depVersion = req[dep]; if (depVersion && depVersion !== '') { diff --git a/generators/workspace/index.js b/generators/workspace/index.js index 842c7a87..aa4e25e9 100644 --- a/generators/workspace/index.js +++ b/generators/workspace/index.js @@ -12,7 +12,6 @@ const writeTemplates = require('../../utils').writeTemplates; const patchPackageJSON = require('../../utils').patchPackageJSON; const NpmUtils = require('../../utils/NpmUtils'); const PipUtils = require('../../utils/PipUtils'); -const {parseRequirements} = require('../../utils/pip'); function mergeWith(target, source) { const mergeArrayUnion = (a, b) => Array.isArray(a) ? _.union(a, b) : undefined; @@ -290,8 +289,8 @@ class Generator extends Base { set.add(ri.trim()); }); }; - integrateMulti(requirements, parseRequirements(this.fs.read(this.destinationPath(`${p}/requirements.txt`), {defaults: ''}))); - integrateMulti(devRequirements, parseRequirements(this.fs.read(this.destinationPath(`${p}/requirements_dev.txt`), {defaults: ''}))); + integrateMulti(requirements, PipUtils.parseRequirements(this.fs.read(this.destinationPath(`${p}/requirements.txt`), {defaults: ''}))); + integrateMulti(devRequirements, PipUtils.parseRequirements(this.fs.read(this.destinationPath(`${p}/requirements_dev.txt`), {defaults: ''}))); addAll('docker_packages.txt', dockerPackages); const script = this.fs.read(this.destinationPath(`${p}/docker_script.sh`), {defaults: ''}); diff --git a/test/PipUtils.test.js b/test/PipUtils.test.js index c7610af7..d5a79b6c 100644 --- a/test/PipUtils.test.js +++ b/test/PipUtils.test.js @@ -79,4 +79,38 @@ describe('check PipUtils.toPipVersion', () => { const version = '^3.4.0'; expect(PipUtils.toPipVersion(version)).toBe('^=3.4.0'); }); + +}); + +describe('parse requirements.txt into an object', () => { + + it('returns an empty object if requirements file is null', () => { + const file = null; + expect(PipUtils.parseRequirements(file)).toEqual({}); + }); + + it('returns an empty object if the requirements file contains an string of only whitespace', () => { + const file = ' '; + expect(PipUtils.parseRequirements(file)).toEqual({}); + }); + + it('returns the requirements object', () => { + const file = ` + flake8^=3.7.9 + pep8-naming~=0.9.1 + pytest==5.3.5 + -e git+https://github.com/phovea/phovea_server.git@develop#egg=phovea_server + -e git+https://github.com/datavisyn/tdp_core.git@develop#egg=tdp_core + + + `; + const result = { + "flake8": "^=3.7.9", + "pep8-naming": "~=0.9.1", + "pytest": "==5.3.5", + "-e git+https://github.com/datavisyn/tdp_core.git": "@develop#egg=tdp_core", + "-e git+https://github.com/phovea/phovea_server.git": "@develop#egg=phovea_server" + }; + expect(PipUtils.parseRequirements(file)).toEqual(result); + }); }); \ No newline at end of file diff --git a/utils/PipUtils.js b/utils/PipUtils.js index 01725ae9..e95bcc73 100644 --- a/utils/PipUtils.js +++ b/utils/PipUtils.js @@ -73,4 +73,42 @@ module.exports = class PipUtils { // fix return `==${version}`; } + + /** + * Transform the requirements.txt file from a string to an object with name as key and version as value. + * @param {string} file Requirements.txt file. + */ + static parseRequirements(file) { + if (!file) { + return {}; + } + file = file.trim(); + if (file === '') { + return {}; + } + const versions = {}; + file.split('\n').forEach((line) => { + line = line.trim(); + + if (line.startsWith('-e')) { + // editable special dependency + const branchSeparator = line.indexOf('@'); + const name = line.slice(0, branchSeparator).trim(); + versions[name] = line.slice(branchSeparator).trim(); + return; + } + + if (line.startsWith('#') || line.startsWith('-')) { + return; // skip + } + const versionSeparator = line.search(/[\^~=>!]/); + if (versionSeparator >= 0) { + const name = line.slice(0, versionSeparator).trim(); + versions[name] = line.slice(versionSeparator).trim(); + } else { + versions[line] = ''; + } + }); + return versions; + } }; \ No newline at end of file diff --git a/utils/pip.js b/utils/pip.js deleted file mode 100644 index 290d5dd8..00000000 --- a/utils/pip.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Created by Samuel Gratzl on 05.04.2017. - */ - -function parseRequirements(file) { - if (!file) { - return {}; - } - file = file.trim(); - if (file === '') { - return {}; - } - const versions = {}; - file.split('\n').forEach((line) => { - line = line.trim(); - - if (line.startsWith('-e')) { - // editable special dependency - const branchSeparator = line.indexOf('@'); - const name = line.slice(0, branchSeparator).trim(); - versions[name] = line.slice(branchSeparator).trim(); - return; - } - - if (line.startsWith('#') || line.startsWith('-')) { - return; // skip - } - const versionSeparator = line.search(/[\^~=>!]/); - if (versionSeparator >= 0) { - const name = line.slice(0, versionSeparator).trim(); - versions[name] = line.slice(versionSeparator).trim(); - } else { - versions[line] = ''; - } - }); - return versions; -} - -module.exports.parseRequirements = parseRequirements; From 2beb41ce5fff5962f1e64966191032f3a544a2f9 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 4 Sep 2020 14:45:33 +0200 Subject: [PATCH 03/65] Write tests for `repo.js` and refactor into a Util class phovea/generator-phovea#425 --- generators/clone-repo/index.js | 6 +-- generators/clone/index.js | 4 +- generators/init-product/index.js | 4 +- generators/prepare-release/index.js | 8 +-- generators/setup-workspace/index.js | 18 +++---- test/RepoUtils.test.js | 84 +++++++++++++++++++++++++++++ utils/RepoUtils.js | 68 +++++++++++++++++++++++ utils/repo.js | 49 ----------------- 8 files changed, 169 insertions(+), 72 deletions(-) create mode 100644 test/RepoUtils.test.js create mode 100644 utils/RepoUtils.js delete mode 100644 utils/repo.js diff --git a/generators/clone-repo/index.js b/generators/clone-repo/index.js index a7fbfaab..309377b3 100644 --- a/generators/clone-repo/index.js +++ b/generators/clone-repo/index.js @@ -1,9 +1,7 @@ 'use strict'; const Base = require('yeoman-generator'); const chalk = require('chalk'); -const { - simplifyRepoUrl -} = require('../../utils/repo'); +const RepoUtils = require('../../utils/RepoUtils'); const NpmUtils = require('../../utils/NpmUtils'); function failed(spawnResult) { @@ -145,7 +143,7 @@ class Generator extends Base { return this._spawnOrAbort('git', line.split(/ +/)).then(() => { const line = `checkout ${branch}`; this.log(chalk.white(`checkout commit:`), `git ${line}`); - let repoName = simplifyRepoUrl(repoUrl); + let repoName = RepoUtils.simplifyRepoUrl(repoUrl); repoName = repoName.slice(repoName.lastIndexOf('/') + 1); return this._spawnOrAbort('git', line.split(/ +/), { cwd: `${this.cwd}/${repoName}` diff --git a/generators/clone/index.js b/generators/clone/index.js index cedcc7ce..72bf0db2 100644 --- a/generators/clone/index.js +++ b/generators/clone/index.js @@ -3,10 +3,10 @@ const Base = require('yeoman-generator'); const path = require('path'); const glob = require('glob').sync; const known = require('../../utils/known'); -const {toHTTPRepoUrl, toSSHRepoUrl} = require('../../utils/repo'); +const RepoUtils = require('../../utils/RepoUtils'); function toRepository(plugin, useSSH) { const p = known.plugin.byName(plugin); - return useSSH ? toSSHRepoUrl(p.repository) : toHTTPRepoUrl(p.repository); + return useSSH ? RepoUtils.RtoSSHRepoUrl(p.repository) : RepoUtils.toHTTPRepoUrl(p.repository); } function resolveNeighbors(plugins, useSSH, types, shallow) { diff --git a/generators/init-product/index.js b/generators/init-product/index.js index 659b0551..52ca2f8c 100644 --- a/generators/init-product/index.js +++ b/generators/init-product/index.js @@ -3,7 +3,7 @@ */ const Base = require('yeoman-generator'); const {writeTemplates, patchPackageJSON} = require('../../utils'); -const {simplifyRepoUrl} = require('../../utils/repo'); +const RepoUtils = require('../../utils/RepoUtils'); const chalk = require('chalk'); const fs = require('fs'); @@ -11,7 +11,7 @@ const isRequired = (v) => v.toString().length > 0; function buildPossibleAdditionalPlugins(type) { const toDescription = (d) => ({ - value: {name: d.name, repo: simplifyRepoUrl(d.repository)}, + value: {name: d.name, repo: RepoUtils.simplifyRepoUrl(d.repository)}, name: `${d.name}: ${d.description}`, short: d.name }); diff --git a/generators/prepare-release/index.js b/generators/prepare-release/index.js index 1f65db33..94faea28 100644 --- a/generators/prepare-release/index.js +++ b/generators/prepare-release/index.js @@ -3,7 +3,7 @@ const Base = require('yeoman-generator'); const chalk = require('chalk'); const fs = require('fs-extra'); const PipUtils = require('../../utils/PipUtils'); -const {toHTTPRepoUrl, toSSHRepoUrl, simplifyRepoUrl} = require('../../utils/repo'); +const RepoUtils = require('../../utils/RepoUtils'); function toBaseName(name) { if (name.includes('/')) { @@ -137,7 +137,7 @@ class Generator extends Base { } _cloneRepo(repo, branch, extras) { - const repoUrl = this.cloneSSH ? toSSHRepoUrl(repo) : toHTTPRepoUrl(repo); + const repoUrl = this.cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); const line = `clone -b ${branch}${extras || ''} ${repoUrl}`; this.log(chalk.blue(`clone repository:`), `git ${line}`); return this._spawnOrAbort('git', line.split(' ')); @@ -332,7 +332,7 @@ class Generator extends Base { _createPullRequest(ctx) { const open = require('open'); - const base = simplifyRepoUrl(ctx.repo); + const base = RepoUtils.simplifyRepoUrl(ctx.repo); const url = `https://github.com/${base}/compare/release_${ctx.version}?expand=1`; return open(url, { wait: false @@ -362,7 +362,7 @@ class Generator extends Base { _openReleasePage(ctx) { const open = require('open'); - const base = simplifyRepoUrl(ctx.repo); + const base = RepoUtils.simplifyRepoUrl(ctx.repo); const url = `https://github.com/${base}/releases/tag/v${ctx.version}`; return open(url, { wait: false diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index a4edeeff..3ae8fb1a 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -4,11 +4,7 @@ const chalk = require('chalk'); const fs = require('fs-extra'); const path = require('path'); const yeoman = require('yeoman-environment'); -const { - toHTTPRepoUrl, - toSSHRepoUrl, - simplifyRepoUrl -} = require('../../utils/repo'); +const RepoUtils = require('../../utils/RepoUtils'); function toBaseName(name) { if (name.includes('/')) { @@ -170,14 +166,14 @@ class Generator extends Base { if (failed(r)) { this.log(r.stderr.toString()); return this._abort(`Failed: "${cmd} ${Array.isArray(argline) ? argline.join(' ') : argline}" - status code: ${r.status}`); - } else if(r.stdout) { + } else if (r.stdout) { this.log(r.stdout.toString()); } return Promise.resolve(cmd); } _cloneRepo(repo, branch, extras, dir) { - const repoUrl = this.cloneSSH ? toSSHRepoUrl(repo) : toHTTPRepoUrl(repo); + const repoUrl = this.cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); return this._yo(`clone-repo`, { branch, extras: extras || '', @@ -191,7 +187,7 @@ class Generator extends Base { .then(() => { const phoveaProductJSON = `${this.cwd}/phovea_product.json`; - if(!fs.existsSync(phoveaProductJSON)) { + if (!fs.existsSync(phoveaProductJSON)) { throw new Error('No phovea_product.json file found! Did you enter a valid phovea product repository?'); } @@ -199,11 +195,11 @@ class Generator extends Base { const defaultApp = this.product.find((v) => v.type === 'web'); if (defaultApp) { - const baseRepo = simplifyRepoUrl(defaultApp.repo); + const baseRepo = RepoUtils.simplifyRepoUrl(defaultApp.repo); const defaultAppName = baseRepo.slice(baseRepo.lastIndexOf('/') + 1); this.defaultApp = defaultAppName; const yoWorkspacePath = this.destinationPath(`${this.cwd}/.yo-rc-workspace.json`); - if(!fs.existsSync(yoWorkspacePath)) { + if (!fs.existsSync(yoWorkspacePath)) { fs.writeJsonSync(yoWorkspacePath, { modules: [], defaultApp: defaultAppName, @@ -382,7 +378,7 @@ class Generator extends Base { } end() { - if(this.hasErrors) { + if (this.hasErrors) { return; // skip next steps on errors } diff --git a/test/RepoUtils.test.js b/test/RepoUtils.test.js new file mode 100644 index 00000000..57a37e0e --- /dev/null +++ b/test/RepoUtils.test.js @@ -0,0 +1,84 @@ +'use strict'; +const RepoUtils = require('../utils/RepoUtils'); + +describe('transfroms repo name to an https url', () => { + + it('repo is already an http url', () => { + const repo = 'https://github.com/phovea/phovea_core.git'; + expect(RepoUtils.toHTTPRepoUrl(repo)).toBe(repo); + }); + + it('repo has format `organization/repo`', () => { + const repo = 'phovea/phovea_core'; + expect(RepoUtils.toHTTPRepoUrl(repo)).toBe('https://github.com/phovea/phovea_core.git'); + }); + + it('repo is only the name of the repo', () => { + const repo = 'ordino'; + expect(RepoUtils.toHTTPRepoUrl(repo)).toBe('https://github.com/Caleydo/ordino.git'); + }); + + it('repo is an SSH url', () => { + const repo = 'git@github.com:phovea/phovea_core.git'; + expect(RepoUtils.toHTTPRepoUrl(repo)).toBe('https://github.com/phovea/phovea_core.git'); + }); +}); + +describe('transfroms repo to a SSH url', () => { + + it('repo is already a SSH url', () => { + const repo = 'git@github.com:phovea/phovea_core.git'; + expect(RepoUtils.toSSHRepoUrl(repo)).toBe(repo); + }); + + it('repo is an http url', () => { + const repo = 'http://github.com/phovea/phovea_core.git'; + expect(RepoUtils.toSSHRepoUrl(repo)).toBe('git@github.com:phovea/phovea_core.git'); + }); + + it('repo is an https url', () => { + const repo = 'https://github.com/phovea/phovea_core.git'; + expect(RepoUtils.toSSHRepoUrl(repo)).toBe('git@github.com:phovea/phovea_core.git'); + }); + + it('repo is only the name of the repo', () => { + const repo = 'ordino_public'; + expect(RepoUtils.toSSHRepoUrl(repo)).toBe('git@github.com:Caleydo/ordino_public.git'); + }); +}); + +describe('transfroms a http(s) to a SSH url', () => { + + it('repo is an empty string', () => { + const repo = ''; + expect(RepoUtils.toSSHRepoUrlFromHTTP(repo)).toBe(''); + }); + + it('repo is already a SSH url', () => { + const repo = 'git@github.com:phovea/phovea_core.git'; + expect(RepoUtils.toSSHRepoUrlFromHTTP(repo)).toBe(repo); + }); + + it('repo is an http url', () => { + const repo = 'http://github.com/phovea/phovea_core.git'; + expect(RepoUtils.toSSHRepoUrlFromHTTP(repo)).toBe('git@github.com:phovea/phovea_core.git'); + }); +}); + +describe('extract `organization/repo` from a SSH or an http url', () => { + + it('repo is an empty string', () => { + const repo = ''; + expect(RepoUtils.simplifyRepoUrl(repo)).toBe(''); + }); + + it('repo is a SSH url', () => { + const repo = 'git@github.com:phovea/phovea_core.git'; + expect(RepoUtils.simplifyRepoUrl(repo)).toBe('phovea/phovea_core'); + }); + + it('repo is an http url', () => { + const repo = 'http://github.com/phovea/phovea_core.git'; + expect(RepoUtils.simplifyRepoUrl(repo)).toBe('phovea/phovea_core'); + }); +}); \ No newline at end of file diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js new file mode 100644 index 00000000..320428f7 --- /dev/null +++ b/utils/RepoUtils.js @@ -0,0 +1,68 @@ +module.exports = class RepoUtils { + + /** + * Transforms repo name or SSH url to an https url + * @param {string} repo Repo + */ + static toHTTPRepoUrl(repo) { + if (repo.startsWith('http')) { + return repo; + } + if (repo.startsWith('git@')) { + const m = repo.match(/(https?:\/\/([^/]+)\/|git@(.+):)([\w\d-_/]+)(.git)?/); + return `https://${m[3]}/${m[4]}.git`; + } + if (!repo.includes('/')) { + repo = `Caleydo/${repo}`; + } + return `https://github.com/${repo}.git`; + } + + + /** + * Transforms repo name or http(s) url to an SSH url + * @param {string} repo Repo + */ + static toSSHRepoUrl(repo) { + if (repo.startsWith('git@')) { + return repo; + } + if (repo.startsWith('http')) { + const m = repo.match(/(https?:\/\/([^/]+)\/|git@(.+):)([\w\d-_/]+)(.git)?/); + return `git@${m[2]}:${m[4]}.git`; + } + if (!repo.includes('/')) { + repo = `Caleydo/${repo}`; + } + return `git@github.com:${repo}.git`; + } + + /** + * Transforms repo http(s) url to an SSH url. + * @param {string} repo Repo. + */ + static toSSHRepoUrlFromHTTP(repo) { + if (repo.startsWith('git@')) { + return repo; + } + const m = repo.match(/(https?:\/\/([^/]+)\/|git@(.+):)([\w\d-_/]+)(.git)?/); + if (m) { + return `git@${m[2]}:${m[4]}.git`; + } + return repo; + } + + /** + * Extracts organization and repo names from a SSH or an http url. + * @param {string} repo Repo. + */ + static simplifyRepoUrl(repo) { + // matches http and git urls + const m = repo.match(/(https?:\/\/[^/]+\/|git@.+:)([\w\d-_/]+)(.git)?/); + if (m) { + // just the repo part + return m[2]; + } + return repo; + } +}; diff --git a/utils/repo.js b/utils/repo.js deleted file mode 100644 index 80d8a810..00000000 --- a/utils/repo.js +++ /dev/null @@ -1,49 +0,0 @@ - -module.exports.toHTTPRepoUrl = (repo) => { - if (repo.startsWith('http')) { - return repo; - } - if (repo.startsWith('git@')) { - const m = repo.match(/(https?:\/\/([^/]+)\/|git@(.+):)([\w\d-_/]+)(.git)?/); - return `https://${m[3]}/${m[4]}.git`; - } - if (!repo.includes('/')) { - repo = `Caleydo/${repo}`; - } - return `https://github.com/${repo}.git`; -}; - -module.exports.toSSHRepoUrl = (repo) => { - if (repo.startsWith('git@')) { - return repo; - } - if (repo.startsWith('http')) { - const m = repo.match(/(https?:\/\/([^/]+)\/|git@(.+):)([\w\d-_/]+)(.git)?/); - return `git@${m[2]}:${m[4]}.git`; - } - if (!repo.includes('/')) { - repo = `Caleydo/${repo}`; - } - return `git@github.com:${repo}.git`; -}; - -module.exports.toSSHRepoUrlFromHTTP = (repo) => { - if (repo.startsWith('git@')) { - return repo; - } - const m = repo.match(/(https?:\/\/([^/]+)\/|git@(.+):)([\w\d-_/]+)(.git)?/); - if (m) { - return `git@${m[2]}:${m[4]}.git`; - } - return repo; -}; - -module.exports.simplifyRepoUrl = (repo) => { - // matches http and git urls - const m = repo.match(/(https?:\/\/[^/]+\/|git@.+:)([\w\d-_/]+)(.git)?/); - if (m) { - // just the repo part - return m[2]; - } - return repo; -}; From 5d202f5dabe73613fc19a376b789537be1a469ea Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 10 Sep 2020 13:32:12 +0200 Subject: [PATCH 04/65] Refactor SpawnUtils phovea/generator-phovea#425 --- generators/clone-repo/index.js | 34 +++-------------- generators/setup-workspace/index.js | 41 ++++---------------- utils/SpawnUtils.js | 58 +++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 63 deletions(-) create mode 100644 utils/SpawnUtils.js diff --git a/generators/clone-repo/index.js b/generators/clone-repo/index.js index 309377b3..82404bf4 100644 --- a/generators/clone-repo/index.js +++ b/generators/clone-repo/index.js @@ -3,10 +3,7 @@ const Base = require('yeoman-generator'); const chalk = require('chalk'); const RepoUtils = require('../../utils/RepoUtils'); const NpmUtils = require('../../utils/NpmUtils'); - -function failed(spawnResult) { - return spawnResult.status !== 0; -} +const SpawnUtils = require('../../utils/SpawnUtils'); /** * Clone a given repository and supports version ranges for git tags. @@ -111,9 +108,9 @@ class Generator extends Base { const line = `ls-remote --tags ${repoUrl}`; this.log(chalk.white(`fetching possible version tags:`), `git ${line}`); - const r = this._spawn('git', line.split(/ +/)); + const r = SpawnUtils.spawn('git', line.split(/ +/), this.cwd); - if (failed(r)) { + if (SpawnUtils.failed(r)) { this.log(chalk.red(`failed to fetch list of tags from git repository`), `status code: ${r.status}`); this.log(r.stderr.toString()); return this._abort(`failed to fetch list of tags from git repository - status code: ${r.status}`); @@ -135,12 +132,12 @@ class Generator extends Base { const line = `clone -b ${branch}${extras || ''} ${repoUrl}${cloneDirName}`; this.log(chalk.white(`clone repository:`), `git ${line}`); - return this._spawnOrAbort('git', line.split(/ +/)); + return SpawnUtils.spawnOrAbort('git', line.split(/ +/), this.cwd); } // clone a specific commit const line = `clone ${extras || ''} ${repoUrl}${cloneDirName}`; this.log(chalk.white(`clone repository:`), `git ${line}`); - return this._spawnOrAbort('git', line.split(/ +/)).then(() => { + return this._spawnOrAbort('git', line.split(/ +/), this.cwd).then(() => { const line = `checkout ${branch}`; this.log(chalk.white(`checkout commit:`), `git ${line}`); let repoName = RepoUtils.simplifyRepoUrl(repoUrl); @@ -151,27 +148,6 @@ class Generator extends Base { }); } - _abort(msg) { - return Promise.reject(msg ? msg : 'Step Failed: Aborting'); - } - - _spawn(cmd, argline, cwd) { - const options = cwd === false ? {} : Object.assign({ - cwd: this.cwd, - stdio: ['inherit', 'pipe', 'pipe'] // pipe `stdout` and `stderr` to host process - }, cwd || {}); - return this.spawnCommandSync(cmd, Array.isArray(argline) ? argline : argline.split(' '), options); - } - - _spawnOrAbort(cmd, argline, cwd) { - const r = this._spawn(cmd, argline, cwd); - if (failed(r)) { - this.log(r.stderr.toString()); - return this._abort(`failed: "${cmd} ${Array.isArray(argline) ? argline.join(' ') : argline}" - status code: ${r.status}`); - } - return Promise.resolve(r); - } - } module.exports = Generator; diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index ad847b07..1a7248be 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -5,6 +5,7 @@ const fs = require('fs-extra'); const path = require('path'); const yeoman = require('yeoman-environment'); const RepoUtils = require('../../utils/RepoUtils'); +const SpawnUtils = require('../../utils/SpawnUtils'); function toBaseName(name) { if (name.includes('/')) { @@ -13,9 +14,6 @@ function toBaseName(name) { return `Caleydo/${name}`; } -function failed(spawnResult) { - return spawnResult.status !== 0; -} function toCWD(basename) { let match = basename.match(/.*\/(.*)/)[1]; @@ -147,32 +145,7 @@ class Generator extends Base { }); } - _abort(msg) { - return Promise.reject(msg ? msg : 'Step Failed: Aborting'); - } - - _spawn(cmd, argline, cwd) { - const options = cwd === false ? {} : Object.assign({ - cwd: this.cwd, - stdio: 'inherit' // log output and error of spawned process to host process - }, cwd || {}); - - this.log(`\nRunning: ${cmd} ${argline}\n`); - return this.spawnCommandSync(cmd, Array.isArray(argline) ? argline : argline.split(' '), options); - } - - _spawnOrAbort(cmd, argline, cwd) { - const r = this._spawn(cmd, argline, cwd); - if (failed(r)) { - this.log(r.stderr.toString()); - return this._abort(`Failed: "${cmd} ${Array.isArray(argline) ? argline.join(' ') : argline}" - status code: ${r.status}`); - } else if (r.stdout) { - this.log(r.stdout.toString()); - } - return Promise.resolve(cmd); - } - - _cloneRepo(repo, branch, extras, dir= '') { + _cloneRepo(repo, branch, extras, dir = '') { const repoUrl = this.cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); return this._yo(`clone-repo`, { branch, @@ -195,7 +168,7 @@ class Generator extends Base { */ _copyProductTemplates(templatePath) { const dirs = fs.readdirSync(templatePath).filter(f => fs.statSync(path.join(templatePath, f)).isDirectory()); - dirs.forEach((dir) => fs.copySync(templatePath +'/' + dir, this.destinationPath(this.cwd))); + dirs.forEach((dir) => fs.copySync(templatePath + '/' + dir, this.destinationPath(this.cwd))); } @@ -249,7 +222,7 @@ class Generator extends Base { } const productTemplatesPath = this.destinationPath(`${this.cwd}/templates`); - if (fs.existsSync(productTemplatesPath)){ + if (fs.existsSync(productTemplatesPath)) { this._copyProductTemplates(productTemplatesPath); } } @@ -312,7 +285,7 @@ class Generator extends Base { } return this._mkdir(this.cwd + '/_backup') .then(() => Promise.all(data.map((d) => this._downloadBackupFile(d, this.cwd + '/_backup')))) - .then(this._ifExecutable.bind(this, 'docker-compose', this._spawnOrAbort.bind(this, './docker-backup', 'restore'), 'please execute: "./docker-backup restore" manually')); + .then(this._ifExecutable.bind(this, 'docker-compose', SpawnUtils.spawnOrAbort.bind(this, './docker-backup', 'restore', this.cwd, true), 'please execute: "./docker-backup restore" manually')); } _ifExecutable(cmd, ifExists, extraMessage = '') { @@ -377,14 +350,14 @@ class Generator extends Base { })) .then(this._customizeWorkspace.bind(this)) .then(this._downloadDataFiles.bind(this)) - .then(() => this.options.skip.includes('install') ? null : this._spawnOrAbort('npm', 'install')) + .then(() => this.options.skip.includes('install') ? null : SpawnUtils.spawnOrAbort('npm', 'install', this.cwd, true)) .then(this._downloadBackupFiles.bind(this)) .then(() => { const l = this.fs.read(this.destinationPath(`${this.cwd}/docker-compose.yml`), { defaults: '' }); if (l.trim().length > 0 && !this.options.skip.includes('build')) { - return this._ifExecutable('docker-compose', this._spawnOrAbort.bind(this, 'docker-compose', 'build'), ' please run "docker-compose build" manually"'); + return this._ifExecutable('docker-compose', SpawnUtils.spawnOrAbort.bind(this, 'docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); } return null; }) diff --git a/utils/SpawnUtils.js b/utils/SpawnUtils.js new file mode 100644 index 00000000..3c3c7b8d --- /dev/null +++ b/utils/SpawnUtils.js @@ -0,0 +1,58 @@ +'use strict'; + +const spawnSync = require('child_process').spawnSync; + +module.exports = class SpawnUtils { + + /** + * Execute a shell command - abort if it fails. + * @param {string} cmd Command to execute. + * @param {string | string[]} argline Arguments to execute the command with. + * @param {string} cwd The directory in Which the command should be excecuted. + */ + static spawnOrAbort(cmd, argline, cwd, verbose) { + const result = SpawnUtils.spawn(cmd, argline, cwd, verbose); + const output = result.stdout.toString().trim(); + + if (SpawnUtils.failed(result)) { + console.log(result.stderr.toString()); + return SpawnUtils.abort(`Failed: "${cmd} ${Array.isArray(argline) ? argline.join(' ') : argline}" - status code: ${result.status}`); + + } else if (output) { + console.log(output); + } + + return Promise.resolve(cmd); + } + + /** + * Execute she command + * @param {string} cmd Command to execute. + * @param {string | string[]} argline Arguments to execute the command with. + * @param {string} cwd The directory in Which the command should be excecuted. + */ + static spawn(cmd, argline, cwd, verbose) { + const options = { + ...{cwd: cwd} || {}, + ...verbose ? {stdio: 'inherit'} : {} + }; + + return spawnSync(cmd, Array.isArray(argline) ? argline : argline.split(' '), options); + } + + /** + * Shel command result object + * @param {{}} spawnResult + */ + static failed(spawnResult) { + return spawnResult.status !== 0; + } + + /** + * Reject Promise with error message. + * @param {string} msg Error message to log. + */ + static abort(msg) { + return Promise.reject(msg ? msg : 'Step Failed: Aborting'); + } +}; From 19ead1ed30b34293b30b6a40ec09b687de521e77 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 10 Sep 2020 15:20:46 +0200 Subject: [PATCH 05/65] Remove list-plugins file phovea/generator-phovea#425 --- utils/SpawnUtils.js | 4 ++-- utils/WorkspaceUtils.js | 50 +++++++++++++++++++++++++++++++++++++++ utils/list-plugins.js | 52 ----------------------------------------- 3 files changed, 52 insertions(+), 54 deletions(-) create mode 100644 utils/WorkspaceUtils.js delete mode 100644 utils/list-plugins.js diff --git a/utils/SpawnUtils.js b/utils/SpawnUtils.js index 3c3c7b8d..5e5a0bd4 100644 --- a/utils/SpawnUtils.js +++ b/utils/SpawnUtils.js @@ -26,7 +26,7 @@ module.exports = class SpawnUtils { } /** - * Execute she command + * Execute shell command * @param {string} cmd Command to execute. * @param {string | string[]} argline Arguments to execute the command with. * @param {string} cwd The directory in Which the command should be excecuted. @@ -41,7 +41,7 @@ module.exports = class SpawnUtils { } /** - * Shel command result object + * Shell command result object * @param {{}} spawnResult */ static failed(spawnResult) { diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js new file mode 100644 index 00000000..5ec44531 --- /dev/null +++ b/utils/WorkspaceUtils.js @@ -0,0 +1,50 @@ +const path = require('path'); +const glob = require('glob').sync; +const known = require('../../utils/known'); +const RepoUtils = require('../../utils/RepoUtils'); +const fs = require('fs-extra'); + +module.exports = class WorkspaceUtils { + /** + * Returns a list of all web plugins (i.e., the directory names) for a given workspace directory. + * A valid web plugin must contain a `webpack.config.js` file. Otherwise the directory is ignored. + * + * @param {string} workspaceDirectory Workspace directory used as current work directory (cwd) + * @returns {string[]} List of plugin names + */ + static listWebPlugins(workspaceDirectory) { + const files = glob('*/webpack.config.js', { + cwd: workspaceDirectory + }); + return files.map(path.dirname).sort(); + } + + /** + * Returns a list of all server plugins (i.e., the directory names) for a given workspace directory. + * A valid server plugin must contain a `requirements.txt` file. Otherwise the directory is ignored. + * + * @param {string} workspaceDirectory Workspace directory used as current work directory (cwd) + * @returns {string[]} List of plugin names + */ + static listServerPlugins(workspaceDirectory) { + const files = glob('*/requirements.txt', { + cwd: workspaceDirectory + }); + return files.map(path.dirname).sort(); + } + + /** + * Returns a list of all plugins (i.e., the directory names) for a given workspace directory. + * A valid web plugin must contain a `webpack.config.js` file. + * A valid server plugin must contain a `requirements.txt` file. + * Otherwise the directory is ignored. + * + * @param {string} workspaceDirectory Workspace directory used as current work directory (cwd) + * @returns {string[]} List of plugin names + */ + static listAllPlugins(workspaceDirectory) { + const webPlugins = WorkspaceUtils.listWebPlugins(workspaceDirectory); + const serverPlugins = WorkspaceUtils.listServerPlugins(workspaceDirectory); + return [...new Set([].concat(...webPlugins, ...serverPlugins))].sort(); + } +}; diff --git a/utils/list-plugins.js b/utils/list-plugins.js deleted file mode 100644 index 5bb7b43e..00000000 --- a/utils/list-plugins.js +++ /dev/null @@ -1,52 +0,0 @@ -const path = require('path'); -const glob = require('glob').sync; - -/** - * Returns a list of all web plugins (i.e., the directory names) for a given workspace directory. - * A valid web plugin must contain a `webpack.config.js` file. Otherwise the directory is ignored. - * - * @param {string} workspaceDirectory Workspace directory used as current work directory (cwd) - * @returns {string[]} List of plugin names - */ -function listWebPlugins(workspaceDirectory) { - const files = glob('*/webpack.config.js', { - cwd: workspaceDirectory - }); - return files.map(path.dirname).sort(); -} - -/** - * Returns a list of all server plugins (i.e., the directory names) for a given workspace directory. - * A valid server plugin must contain a `requirements.txt` file. Otherwise the directory is ignored. - * - * @param {string} workspaceDirectory Workspace directory used as current work directory (cwd) - * @returns {string[]} List of plugin names - */ -function listServerPlugins(workspaceDirectory) { - const files = glob('*/requirements.txt', { - cwd: workspaceDirectory - }); - return files.map(path.dirname).sort(); -} - -/** - * Returns a list of all plugins (i.e., the directory names) for a given workspace directory. - * A valid web plugin must contain a `webpack.config.js` file. - * A valid server plugin must contain a `requirements.txt` file. - * Otherwise the directory is ignored. - * - * @param {string} workspaceDirectory Workspace directory used as current work directory (cwd) - * @returns {string[]} List of plugin names - */ -function listAllPlugins(workspaceDirectory) { - const webPlugins = listWebPlugins(workspaceDirectory); - const serverPlugins = listServerPlugins(workspaceDirectory); - return [...new Set([].concat(...webPlugins, ...serverPlugins))].sort(); -} - -module.exports = { - listWebPlugins, - listServerPlugins, - listAllPlugins -}; - From 9666dd834ee6604f381919dd5c30a099bb751800 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 11 Sep 2020 11:35:34 +0200 Subject: [PATCH 06/65] Extend tests and extract functions into util clases phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 37 ++++------------------------- test/RepoUtils.test.js | 31 ++++++++++++++++++++++++ utils/RepoUtils.js | 27 +++++++++++++++++++++ 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index 1a7248be..a3f75969 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -6,34 +6,7 @@ const path = require('path'); const yeoman = require('yeoman-environment'); const RepoUtils = require('../../utils/RepoUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); - -function toBaseName(name) { - if (name.includes('/')) { - return name; - } - return `Caleydo/${name}`; -} - - -function toCWD(basename) { - let match = basename.match(/.*\/(.*)/)[1]; - if (match.endsWith('_product')) { - match = match.slice(0, -8); - } - return match; -} - -function findDefaultApp(product) { - if (!product) { - return null; - } - for (let p of product) { - if (p.type === 'web') { - return p.repo.slice(p.repo.lastIndexOf('/') + 1).replace('.git', ''); - } - } - return null; -} +const WorkspaceUtils = require('../../utils/WorkspaceUtils'); function downloadFileImpl(url, dest) { const http = require(url.startsWith('https') ? 'https' : 'http'); @@ -117,8 +90,8 @@ class Generator extends Base { default: this.options.ssh, when: !this.options.ssh }]).then((props) => { - this.productName = toBaseName(props.productName || this.args[0]); - this.cwd = toCWD(this.productName); + this.productName = RepoUtils.toBaseName(props.productName || this.args[0]); + this.cwd = RepoUtils.toCWD(this.productName); this.cloneSSH = props.cloneSSH || this.options.ssh; }); } @@ -211,7 +184,7 @@ class Generator extends Base { } _customizeWorkspace() { - const defaultApp = findDefaultApp(this.product); + const defaultApp = WorkspaceUtils.findDefaultApp(this.product); if (defaultApp) { this.fs.copyTpl(this.templatePath('start_defaultapp.tmpl.xml'), this.destinationPath(`${this.cwd}/.idea/runConfigurations/start_${defaultApp}.xml`), { defaultApp: defaultApp @@ -345,7 +318,7 @@ class Generator extends Base { }) .then((repos) => Promise.all(repos.map((r) => this._cloneRepo(r.repo, r.branch)))) .then(this._yo.bind(this, 'workspace', { - defaultApp: findDefaultApp(), + defaultApp: WorkspaceUtils.findDefaultApp(), skipNextStepsLog: true // skip "next steps" logs from yo phovea:workspace })) .then(this._customizeWorkspace.bind(this)) diff --git a/test/RepoUtils.test.js b/test/RepoUtils.test.js index 57a37e0e..c15c36d9 100644 --- a/test/RepoUtils.test.js +++ b/test/RepoUtils.test.js @@ -81,4 +81,35 @@ describe('extract `organization/repo` from a SSH or an http url', () => { const repo = 'http://github.com/phovea/phovea_core.git'; expect(RepoUtils.simplifyRepoUrl(repo)).toBe('phovea/phovea_core'); }); +}); + +describe('prefix repo name with organization name`', () => { + + it('repo already contains organization', () => { + const repo = 'Caleydo/ordino'; + expect(RepoUtils.toBaseName(repo)).toBe(repo); + }); + + it('repo does not contain organization', () => { + const repo = 'ordino'; + expect(RepoUtils.toBaseName(repo)).toBe('Caleydo/ordino'); + }); +}); + +describe('extact repo name from string containing `org/repo`', () => { + + it('repo contains org', () => { + const repo = 'Caleydo/ordino'; + expect(RepoUtils.toCWD(repo)).toBe('ordino'); + }); + + it('repo is a product', () => { + const repo = 'Caleydo/ordino_product'; + expect(RepoUtils.toCWD(repo)).toBe('ordino'); + }); + + it('repo does not contain org', () => { + const repo = 'ordino'; + expect(RepoUtils.toCWD(repo)).toBe('ordino'); + }); }); \ No newline at end of file diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js index 320428f7..1e310cdf 100644 --- a/utils/RepoUtils.js +++ b/utils/RepoUtils.js @@ -65,4 +65,31 @@ module.exports = class RepoUtils { } return repo; } + /** + * Checks if repo name includes organization. If not it adds `Caleydo/` prefix. + * @param {string} name Name of the repo. + */ + static toBaseName(name) { + if (name.includes('/')) { + return name; + } + return `Caleydo/${name}`; + } + + /** + * Removes `_product` suffix from name. + * @param {string} basename Repo name optionaly prefixed with the organization name. + */ + static toCWD(basename) { + try { + let match = basename.match(/.*\/(.*)/)[1]; + if (match.endsWith('_product')) { + match = match.slice(0, -8); + } + return match; + + } catch{ + return basename; + } + } }; From ab4ae9bcae82824f82ccb4d55e9070cb4e90adb8 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 11 Sep 2020 12:06:15 +0200 Subject: [PATCH 07/65] Extract mkdir function --- generators/init-app/index.js | 2 +- generators/setup-workspace/index.js | 14 ++++---------- utils/GeneratorUtils.js | 13 +++++++++++++ utils/RepoUtils.js | 4 ++-- utils/index.js | 10 +++++----- 5 files changed, 25 insertions(+), 18 deletions(-) create mode 100644 utils/GeneratorUtils.js diff --git a/generators/init-app/index.js b/generators/init-app/index.js index c83cc486..cadead25 100644 --- a/generators/init-app/index.js +++ b/generators/init-app/index.js @@ -49,7 +49,7 @@ class PluginGenerator extends BasePluginGenerator { writing() { const config = this.config.getAll(); - this._mkdir(config.cwd); + this._createSubDir(config.cwd); this._patchPackageJSON(config, ['main'], null, this.cwd); this._writeTemplates(config, !this.options.noSamples, this.cwd); } diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index a3f75969..03c436e8 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -7,6 +7,7 @@ const yeoman = require('yeoman-environment'); const RepoUtils = require('../../utils/RepoUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); const WorkspaceUtils = require('../../utils/WorkspaceUtils'); +const GeneratorUtils = require('../../utils/GeneratorUtils'); function downloadFileImpl(url, dest) { const http = require(url.startsWith('https') ? 'https' : 'http'); @@ -176,13 +177,6 @@ class Generator extends Base { return this.product; }); } - - _mkdir(dir) { - dir = dir || this.cwd; - this.log('Create directory: ' + dir); - return new Promise((resolve) => fs.ensureDir(dir, resolve)); - } - _customizeWorkspace() { const defaultApp = WorkspaceUtils.findDefaultApp(this.product); if (defaultApp) { @@ -242,7 +236,7 @@ class Generator extends Base { if (data.length === 0) { return Promise.resolve(null); } - return this._mkdir(this.cwd + '/_data') + return GeneratorUtils.mkdir(this.cwd + '/_data') .then(() => Promise.all(data.map((d) => this._downloadDataFile(d, this.cwd + '/_data')))); } @@ -256,7 +250,7 @@ class Generator extends Base { if (data.length === 0) { return Promise.resolve(null); } - return this._mkdir(this.cwd + '/_backup') + return GeneratorUtils.mkdir(this.cwd + '/_backup') .then(() => Promise.all(data.map((d) => this._downloadBackupFile(d, this.cwd + '/_backup')))) .then(this._ifExecutable.bind(this, 'docker-compose', SpawnUtils.spawnOrAbort.bind(this, './docker-backup', 'restore', this.cwd, true), 'please execute: "./docker-backup restore" manually')); } @@ -289,7 +283,7 @@ class Generator extends Base { this.hasErrors = false; return Promise.resolve(1) - .then(this._mkdir.bind(this, null)) + .then(GeneratorUtils.mkdir(this.cwd)) .then(this._getProduct.bind(this)) .then((product) => { const names = new Set(); diff --git a/utils/GeneratorUtils.js b/utils/GeneratorUtils.js new file mode 100644 index 00000000..0e7d103f --- /dev/null +++ b/utils/GeneratorUtils.js @@ -0,0 +1,13 @@ + +const fs = require('fs-extra'); + +module.exports = class GeneratorUtils { + /** + * Creates directory in the given path. + * @param {string} dir Directory + */ + static mkdir(dir) { + console.log('Create directory: ' + dir); + return new Promise((resolve) => fs.ensureDir(dir, resolve)); + } +}; diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js index 1e310cdf..100d7997 100644 --- a/utils/RepoUtils.js +++ b/utils/RepoUtils.js @@ -77,8 +77,8 @@ module.exports = class RepoUtils { } /** - * Removes `_product` suffix from name. - * @param {string} basename Repo name optionaly prefixed with the organization name. + * Extracts repo name and removes `_product` suffix from name. + * @param {string} basename Repo name optionaly prefixed with the organization name, i.e, `Caleydo/ordino`. */ static toCWD(basename) { try { diff --git a/utils/index.js b/utils/index.js index d8739f83..0064cd46 100644 --- a/utils/index.js +++ b/utils/index.js @@ -5,6 +5,7 @@ const path = require('path'); const glob = require('glob').sync; const fs = require('fs-extra'); const chalk = require('chalk'); +const GeneratorUtils = require('./GeneratorUtils'); /** * Modify package.json by passing the configuration @@ -86,7 +87,7 @@ function writeTemplates(config, withSamples, cwd = '') { }); f.forEach((fi) => { const rel = path.relative(base, fi); - if(!initialize_once || !fs.existsSync(this.destinationPath(cwd + dbase + rel))) { + if (!initialize_once || !fs.existsSync(this.destinationPath(cwd + dbase + rel))) { this.fs.copyTpl(fi, this.destinationPath(cwd + dbase + rel), pattern); } }); @@ -171,11 +172,10 @@ class BaseInitPluginGenerator extends Generator { * Initialize the property cwd. * @param {string} dir Directory name. */ - _mkdir(dir) { + _createSubDir(dir) { if (this._isWorkspace() && this.cwd !== dir + '/') { this.cwd = dir + '/'; - this.log('Create directory: ' + dir); - return new Promise((resolve) => fs.ensureDir(dir, resolve)); + GeneratorUtils.mkdir(dir); } } @@ -198,7 +198,7 @@ class BaseInitPluginGenerator extends Generator { writing() { const config = this.config.getAll(); - this._mkdir(config.cwd || config.name); + this._createSubDir(config.cwd || config.name); if (fs.existsSync(this.templatePath('package.tmpl.json'))) { this._patchPackageJSON(config, null, null, this.cwd); } From e160827971c0b4ca62d19f4c9a83894eb15aacb8 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 11 Sep 2020 12:07:04 +0200 Subject: [PATCH 08/65] Create `WorkspaceUtils` phovea/generator-phovea#425 --- test/WorkspaceUtils.test.js | 45 +++++++++++++++++++++++++++++++++++++ utils/WorkspaceUtils.js | 19 +++++++++++++--- 2 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 test/WorkspaceUtils.test.js diff --git a/test/WorkspaceUtils.test.js b/test/WorkspaceUtils.test.js new file mode 100644 index 00000000..b74983c0 --- /dev/null +++ b/test/WorkspaceUtils.test.js @@ -0,0 +1,45 @@ +'use strict'; +const WorkspaceUtils = require('../utils/WorkspaceUtils'); + + +describe('Find default app in product object', () => { + + it('returns null if product is undefined', () => { + const product = undefined; + expect(WorkspaceUtils.findDefaultApp(product)).toBe(null); + }); + + it('returns null if product has no entry type `web`', () => { + const product = [ + { + type: 'api', + label: 'phovea_ui', + repo: 'phovea/phovea_ui', + branch: 'develop', + additional: [] + + }]; + expect(WorkspaceUtils.findDefaultApp(product)).toBe(null); + }); + + it('returns parsed repo name when entry has type `web`', () => { + const product = [ + { + type: 'web', + label: 'ordino', + repo: 'Caleydo/ordino_public', + branch: 'develop', + additional: [] + + }, + { + type: 'api', + label: 'repo', + repo: 'org/repo', + branch: 'develop', + additional: [] + + }]; + expect(WorkspaceUtils.findDefaultApp(product)).toBe('ordino_public'); + }); +}); \ No newline at end of file diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js index 5ec44531..280cb217 100644 --- a/utils/WorkspaceUtils.js +++ b/utils/WorkspaceUtils.js @@ -1,8 +1,5 @@ const path = require('path'); const glob = require('glob').sync; -const known = require('../../utils/known'); -const RepoUtils = require('../../utils/RepoUtils'); -const fs = require('fs-extra'); module.exports = class WorkspaceUtils { /** @@ -47,4 +44,20 @@ module.exports = class WorkspaceUtils { const serverPlugins = WorkspaceUtils.listServerPlugins(workspaceDirectory); return [...new Set([].concat(...webPlugins, ...serverPlugins))].sort(); } + + /** + * Extract default app from `phovea_product.json`. + * @param {Object} product Content of the `phovea_product.json`. + */ + static findDefaultApp(product) { + if (!product) { + return null; + } + for (let p of product) { + if (p.type === 'web') { + return p.repo.slice(p.repo.lastIndexOf('/') + 1).replace('.git', ''); + } + } + return null; + } }; From 9bae930ac07c25f7dd6aecb6975c1c5b1ba00068 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 11 Sep 2020 12:33:30 +0200 Subject: [PATCH 09/65] Refactor useDevVersion phovea/generator-phovea#425 --- generators/_init-python/index.js | 12 +++++++----- generators/_init-web/index.js | 6 ++++-- utils/NpmUtils.js | 7 +++++++ utils/index.js | 11 +---------- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index edc218a2..03611472 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -1,8 +1,9 @@ 'use strict'; const _ = require('lodash'); const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON, stringifyAble, useDevVersion} = require('../../utils'); +const {writeTemplates, patchPackageJSON, stringifyAble} = require('../../utils'); const PipUtils = require('../../utils/PipUtils'); +const NpmUtils = require('../../utils/NpmUtils'); const fs = require('fs'); const known = () => require('../../utils/known'); @@ -78,9 +79,9 @@ class Generator extends Base { modules.filter(known().plugin.isTypeServer).forEach((m) => { const p = known().plugin.byName(m); - // avoid having a requirement twice in two different formats that occurs when in the requirements.txt a requirement is written - // in the format -e git+https://github.com/phovea/phovea_server.git@v2.2.0#egg=phovea_server - // and the incoming format is phovea_server>=5.0.1,<6.0.0 + // avoid having a requirement twice in two different formats that occurs when in the requirements.txt a requirement is written + // in the format -e git+https://github.com/phovea/phovea_server.git@v2.2.0#egg=phovea_server + // and the incoming format is phovea_server>=5.0.1,<6.0.0 if (!useDevelopDependencies) { const devRequirement = Object.keys(p.develop.requirements)[0]; const masterRequirment = Object.keys(p.requirements)[0]; @@ -106,7 +107,8 @@ class Generator extends Base { writing() { const config = this.config.getAll(); this.cwd = this.options.isWorkspace ? (config.cwd || config.name) + '/' : ''; - const deps = this._generateDependencies(useDevVersion.call(this, this.cwd), this.cwd); + const {version} = fs.readFileSync(this.destinationPath(this.cwd + 'packge.json')); + const deps = this._generateDependencies(NpmUtils.useDevVersion(version), this.cwd); patchPackageJSON.call(this, config, ['devDependencies'], null, null, this.cwd); writeTemplates.call(this, config, !this.options.noSamples, this.cwd); diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index f89113f9..34057ad5 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -2,8 +2,9 @@ const _ = require('lodash'); const chalk = require('chalk'); const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON, stringifyAble, useDevVersion} = require('../../utils'); +const {writeTemplates, patchPackageJSON, stringifyAble} = require('../../utils'); const fs = require('fs'); +const NpmUtils = require('../../utils/NpmUtils'); const known = () => require('../../utils/known'); @@ -130,8 +131,9 @@ class Generator extends Base { writing() { const config = this.config.getAll(); this.cwd = this.options.isWorkspace ? (config.app || config.name) + '/' : ''; + const {version} = fs.readFileSync(this.destinationPath(this.cwd + 'packge.json')); patchPackageJSON.call(this, config, [], { - dependencies: this._generateDependencies(useDevVersion.call(this, this.cwd)) + dependencies: this._generateDependencies(NpmUtils.useDevVersion(version)) }, null, this.cwd); this.fs.copy(this.templatePath('_gitignore'), this.destinationPath(this.cwd + '.gitignore')); writeTemplates.call(this, config, null, this.cwd); diff --git a/utils/NpmUtils.js b/utils/NpmUtils.js index e7b75550..9be0bdfa 100644 --- a/utils/NpmUtils.js +++ b/utils/NpmUtils.js @@ -241,4 +241,11 @@ module.exports = class NpmUtils { return versionTags; } + /** + * Checks if version contains `-` thus branch is not master. + * @param {string} version Package.json version + */ + static useDevVersion(version) { + return (version || '').includes('-'); + } }; \ No newline at end of file diff --git a/utils/index.js b/utils/index.js index 0064cd46..beb0338e 100644 --- a/utils/index.js +++ b/utils/index.js @@ -118,14 +118,6 @@ function writeTemplates(config, withSamples, cwd = '') { } } -function useDevVersion(cwd = '') { - const pkg = this.fs.readJSON(this.destinationPath(cwd + 'package.json'), { - version: '1.0.0' - }); - // assumption having a suffix like -SNAPSHOT use the dev version - return (pkg.version || '').includes('-'); -} - class BaseInitPluginGenerator extends Generator { constructor(args, options, basetype) { @@ -265,6 +257,5 @@ module.exports = { BaseHybrid: BaseInitHybridGenerator, patchPackageJSON: patchPackageJSON, writeTemplates: writeTemplates, - stringifyAble: stringifyAble, - useDevVersion: useDevVersion + stringifyAble: stringifyAble }; From d6e60ca5f5ed004e767ec64c7d4753366c4bb9ce Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 08:47:13 +0200 Subject: [PATCH 10/65] Fix spawnOrAbort bug phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 4 ++-- utils/SpawnUtils.js | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index 03c436e8..a2ec66b6 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -252,7 +252,7 @@ class Generator extends Base { } return GeneratorUtils.mkdir(this.cwd + '/_backup') .then(() => Promise.all(data.map((d) => this._downloadBackupFile(d, this.cwd + '/_backup')))) - .then(this._ifExecutable.bind(this, 'docker-compose', SpawnUtils.spawnOrAbort.bind(this, './docker-backup', 'restore', this.cwd, true), 'please execute: "./docker-backup restore" manually')); + .then(this._ifExecutable.bind(this, 'docker-compose', () => SpawnUtils.spawnOrAbort('./docker-backup', 'restore', this.cwd, true), 'please execute: "./docker-backup restore" manually')); } _ifExecutable(cmd, ifExists, extraMessage = '') { @@ -324,7 +324,7 @@ class Generator extends Base { defaults: '' }); if (l.trim().length > 0 && !this.options.skip.includes('build')) { - return this._ifExecutable('docker-compose', SpawnUtils.spawnOrAbort.bind(this, 'docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); + return this._ifExecutable('docker-compose', () => SpawnUtils.spawnOrAbort('docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); } return null; }) diff --git a/utils/SpawnUtils.js b/utils/SpawnUtils.js index 5e5a0bd4..700e6a64 100644 --- a/utils/SpawnUtils.js +++ b/utils/SpawnUtils.js @@ -12,14 +12,13 @@ module.exports = class SpawnUtils { */ static spawnOrAbort(cmd, argline, cwd, verbose) { const result = SpawnUtils.spawn(cmd, argline, cwd, verbose); - const output = result.stdout.toString().trim(); - + const stdout = result.stdout; if (SpawnUtils.failed(result)) { console.log(result.stderr.toString()); return SpawnUtils.abort(`Failed: "${cmd} ${Array.isArray(argline) ? argline.join(' ') : argline}" - status code: ${result.status}`); - } else if (output) { - console.log(output); + } else if (stdout && stdout.toString()) { + console.log(stdout.toString().trim()); } return Promise.resolve(cmd); From 3b13e2816be6d5c96a29c267f338045e2922c75c Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 09:09:35 +0200 Subject: [PATCH 11/65] Extract yo method phovea/generator-phovea#425 --- generators/install/index.js | 24 ++-------------------- generators/setup-workspace/index.js | 30 ++++------------------------ utils/GeneratorUtils.js | 31 +++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 48 deletions(-) diff --git a/generators/install/index.js b/generators/install/index.js index 8f059219..973a7ecb 100644 --- a/generators/install/index.js +++ b/generators/install/index.js @@ -2,6 +2,7 @@ const Base = require('yeoman-generator'); const path = require('path'); const fs = require('fs'); +const GeneratorUtils = require('../../utils/GeneratorUtils'); function toPluginRepo(url, useSSH) { const match = url.match(/(github:)?([\w\d-_]+\/)?([\w\d-_]+)(#.+)?/); @@ -50,27 +51,6 @@ class Generator extends Base { this.composeWith(['phovea:_check-own-version', 'phovea:check-node-version']); } - _yo(generator, options) { - const yeoman = require('yeoman-environment'); - // call yo internally - const env = yeoman.createEnv([], { - cwd: this.cwd - }, this.env.adapter); - env.register(require.resolve('../' + generator), 'phovea:' + generator); - return new Promise((resolve, reject) => { - try { - this.log('running yo phovea:' + generator); - env.run('phovea:' + generator, options || {}, () => { - // wait a second after running yo to commit the files correctly - setTimeout(() => resolve(), 500); - }); - } catch (e) { - console.error('error', e, e.stack); - reject(e); - } - }); - } - default() { this.plugin = this.options.for; @@ -101,7 +81,7 @@ class Generator extends Base { return p; }).filter((n) => Boolean(n)); this.log('updating workspace'); - return this._yo('workspace').then(() => { + return GeneratorUtils.yo('workspace').then(() => { this.log('running npm install'); this.npmInstall(); }); diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index a2ec66b6..a25dbff2 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -97,36 +97,14 @@ class Generator extends Base { }); } - _yo(generator, options, args) { - // call yo internally - const env = yeoman.createEnv([], { - cwd: this.cwd - }, this.env.adapter); - const _args = Array.isArray(args) ? args.join(' ') : args || ''; - return new Promise((resolve, reject) => { - try { - this.log(`Running: yo phovea:${generator} ${_args}`); - env.lookup(() => { - env.run(`phovea:${generator} ${_args}`, options || {}, () => { - // wait a second after running yo to commit the files correctly - setTimeout(() => resolve(), 500); - }); - }); - } catch (e) { - console.error('Error', e, e.stack); - reject(e); - } - }); - } - _cloneRepo(repo, branch, extras, dir = '') { const repoUrl = this.cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); - return this._yo(`clone-repo`, { + return GeneratorUtils.yo(`clone-repo`, { branch, extras: extras || '', dir, cwd: this.cwd - }, repoUrl); // repository URL as argument + }, repoUrl, this.cwd, this.env.adapter); // repository URL as argument } @@ -311,10 +289,10 @@ class Generator extends Base { return repos; }) .then((repos) => Promise.all(repos.map((r) => this._cloneRepo(r.repo, r.branch)))) - .then(this._yo.bind(this, 'workspace', { + .then(() => GeneratorUtils.yo('workspace', { defaultApp: WorkspaceUtils.findDefaultApp(), skipNextStepsLog: true // skip "next steps" logs from yo phovea:workspace - })) + }, null, this.cwd, this.env.adapter)) .then(this._customizeWorkspace.bind(this)) .then(this._downloadDataFiles.bind(this)) .then(() => this.options.skip.includes('install') ? null : SpawnUtils.spawnOrAbort('npm', 'install', this.cwd, true)) diff --git a/utils/GeneratorUtils.js b/utils/GeneratorUtils.js index 0e7d103f..56d4f305 100644 --- a/utils/GeneratorUtils.js +++ b/utils/GeneratorUtils.js @@ -1,5 +1,6 @@ const fs = require('fs-extra'); +const yeoman = require('yeoman-environment'); module.exports = class GeneratorUtils { /** @@ -10,4 +11,34 @@ module.exports = class GeneratorUtils { console.log('Create directory: ' + dir); return new Promise((resolve) => fs.ensureDir(dir, resolve)); } + + /** + * Similar to the composeWith method of the base yeoman generator but it waits shortly till the generator is finished. + * @param {string} generator Generator name, i.e, `init-lib`. + * @param {Object} options Options to call the generator with. + * @param {*} args Arguments to pass to the generator. + * @param {*} cwd The directory to run the generator in. + * @param {*} adapter The current generator adapter. + */ + static yo(generator, options, args, cwd, adapter) { + // call yo internally + const env = yeoman.createEnv([], { + cwd + }, adapter); + const _args = Array.isArray(args) ? args.join(' ') : args || ''; + return new Promise((resolve, reject) => { + try { + console.log(`Running: yo phovea:${generator} ${_args}`); + env.lookup(() => { + env.run(`phovea:${generator} ${_args}`, options || {}, () => { + // wait a second after running yo to commit the files correctly + setTimeout(() => resolve(), 500); + }); + }); + } catch (e) { + console.error('Error', e, e.stack); + reject(e); + } + }); + } }; From 8f5e84cddd403b7da43a2621fab5727a89e95f0f Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 09:11:44 +0200 Subject: [PATCH 12/65] Remove unused import --- generators/setup-workspace/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index a25dbff2..6e93b723 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -3,7 +3,6 @@ const Base = require('yeoman-generator'); const chalk = require('chalk'); const fs = require('fs-extra'); const path = require('path'); -const yeoman = require('yeoman-environment'); const RepoUtils = require('../../utils/RepoUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); const WorkspaceUtils = require('../../utils/WorkspaceUtils'); From 03a4106c4a438fa816aedcbb76fdb121bae17587 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 10:19:48 +0200 Subject: [PATCH 13/65] Fix useDevVersion bug phovea/generator-phovea#425 --- generators/_init-python/index.js | 3 ++- generators/_init-web/index.js | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index 03611472..538bcaff 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -107,7 +107,8 @@ class Generator extends Base { writing() { const config = this.config.getAll(); this.cwd = this.options.isWorkspace ? (config.cwd || config.name) + '/' : ''; - const {version} = fs.readFileSync(this.destinationPath(this.cwd + 'packge.json')); + const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); + console.log(this.cwd, this.destinationPath(this.cwd + 'package.json')) const deps = this._generateDependencies(NpmUtils.useDevVersion(version), this.cwd); patchPackageJSON.call(this, config, ['devDependencies'], null, null, this.cwd); diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 34057ad5..432ee571 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -131,7 +131,8 @@ class Generator extends Base { writing() { const config = this.config.getAll(); this.cwd = this.options.isWorkspace ? (config.app || config.name) + '/' : ''; - const {version} = fs.readFileSync(this.destinationPath(this.cwd + 'packge.json')); + const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); + patchPackageJSON.call(this, config, [], { dependencies: this._generateDependencies(NpmUtils.useDevVersion(version)) }, null, this.cwd); From 841235f4db7e69c9e2269544572d38351cb65cd3 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 11:22:39 +0200 Subject: [PATCH 14/65] Refactor clone repo phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 15 ++------------- utils/WorkspaceUtils.js | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index 6e93b723..5731c60a 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -96,17 +96,6 @@ class Generator extends Base { }); } - _cloneRepo(repo, branch, extras, dir = '') { - const repoUrl = this.cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); - return GeneratorUtils.yo(`clone-repo`, { - branch, - extras: extras || '', - dir, - cwd: this.cwd - }, repoUrl, this.cwd, this.env.adapter); // repository URL as argument - } - - _removeUnnecessaryProductFiles() { fs.unlinkSync(this.cwd + '/.yo-rc.json'); fs.rmdirSync(this.cwd + '/.git', {recursive: true}); // TODO look into git submodules @@ -124,7 +113,7 @@ class Generator extends Base { _getProduct() { - return this._cloneRepo(this.productName, this.options.branch || 'master', null, '.') + return WorkspaceUtils.cloneRepo(this.productName, this.options.branch || 'master', null, '.', this.cwd, this.cloneSSH) .then(() => { this._removeUnnecessaryProductFiles(); @@ -287,7 +276,7 @@ class Generator extends Base { }); return repos; }) - .then((repos) => Promise.all(repos.map((r) => this._cloneRepo(r.repo, r.branch)))) + .then((repos) => Promise.all(repos.map((r) => WorkspaceUtils.cloneRepo(r.repo, r.branch, null, '', this.cwd, this.cloneSSH)))) .then(() => GeneratorUtils.yo('workspace', { defaultApp: WorkspaceUtils.findDefaultApp(), skipNextStepsLog: true // skip "next steps" logs from yo phovea:workspace diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js index 280cb217..8aa9776d 100644 --- a/utils/WorkspaceUtils.js +++ b/utils/WorkspaceUtils.js @@ -1,5 +1,7 @@ const path = require('path'); const glob = require('glob').sync; +const RepoUtils = require('./RepoUtils'); +const GeneratorUtils = require('./GeneratorUtils'); module.exports = class WorkspaceUtils { /** @@ -60,4 +62,24 @@ module.exports = class WorkspaceUtils { } return null; } + +/** + * Calls the clone repo generator with the name of the repo. + * @param {string} repo Repository name. + * @param {string} branch Branch to clone + * @param {*} extras Extra git options + * @param {*} dir Where to clone the repo + * @param {*} cwd Where to run the generator + * @param {*} cloneSSH SSH or HTTP url + */ + static cloneRepo(repo, branch, extras, dir = '', cwd, cloneSSH) { + const repoUrl = cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); + return GeneratorUtils.yo(`clone-repo`, { + branch, + extras: extras || '', + dir, + cwd + }, repoUrl, cwd); // repository URL as argument + } + }; From 28273c5d1b89b13f47166674022b532cb6920262 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 12:03:09 +0200 Subject: [PATCH 15/65] Commenting phovea/generator-phovea#425 --- utils/WorkspaceUtils.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js index 8aa9776d..4b023364 100644 --- a/utils/WorkspaceUtils.js +++ b/utils/WorkspaceUtils.js @@ -67,10 +67,10 @@ module.exports = class WorkspaceUtils { * Calls the clone repo generator with the name of the repo. * @param {string} repo Repository name. * @param {string} branch Branch to clone - * @param {*} extras Extra git options - * @param {*} dir Where to clone the repo - * @param {*} cwd Where to run the generator - * @param {*} cloneSSH SSH or HTTP url + * @param {Object} extras Extra git options + * @param {string} dir Where to clone the repo + * @param {string} cwd Where to run the generator + * @param {boolean} cloneSSH SSH or HTTP url */ static cloneRepo(repo, branch, extras, dir = '', cwd, cloneSSH) { const repoUrl = cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); From df2f068b0b824dbc93de0f75d4ea7f24f0e98b1f Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 12:25:37 +0200 Subject: [PATCH 16/65] Refactor resolveNeighbours --- generators/clone/index.js | 8 ++--- utils/RepoUtils.js | 7 +++++ utils/WorkspaceUtils.js | 63 +++++++++++++++++++++++++++++++++------ 3 files changed, 63 insertions(+), 15 deletions(-) diff --git a/generators/clone/index.js b/generators/clone/index.js index 72bf0db2..36ab9863 100644 --- a/generators/clone/index.js +++ b/generators/clone/index.js @@ -4,10 +4,6 @@ const path = require('path'); const glob = require('glob').sync; const known = require('../../utils/known'); const RepoUtils = require('../../utils/RepoUtils'); -function toRepository(plugin, useSSH) { - const p = known.plugin.byName(plugin); - return useSSH ? RepoUtils.RtoSSHRepoUrl(p.repository) : RepoUtils.toHTTPRepoUrl(p.repository); -} function resolveNeighbors(plugins, useSSH, types, shallow) { let missing = []; @@ -28,7 +24,7 @@ function resolveNeighbors(plugins, useSSH, types, shallow) { while (missing.length > 0) { let next = missing.shift(); - let repo = toRepository(next, useSSH); + let repo = RepoUtils.toRepository(next, useSSH); let args = ['clone', repo]; if (shallow) { args.splice(1, 0, '--depth', '1'); @@ -130,7 +126,7 @@ class Generator extends Base { } writing() { - const repos = this.props.plugins.map((d) => toRepository(d, this.props.cloneSSH)); + const repos = this.props.plugins.map((d) => RepoUtils.toRepository(d, this.props.cloneSSH)); repos.forEach((repo) => { this.log(`git clone ${repo}`); diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js index 100d7997..e85d2aad 100644 --- a/utils/RepoUtils.js +++ b/utils/RepoUtils.js @@ -1,3 +1,5 @@ +const known = require('./known'); + module.exports = class RepoUtils { /** @@ -92,4 +94,9 @@ module.exports = class RepoUtils { return basename; } } + + static toRepository(plugin, useSSH) { + const p = known.plugin.byName(plugin); + return useSSH ? RepoUtils.RtoSSHRepoUrl(p.repository) : RepoUtils.toHTTPRepoUrl(p.repository); + } }; diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js index 4b023364..9ef4282c 100644 --- a/utils/WorkspaceUtils.js +++ b/utils/WorkspaceUtils.js @@ -2,6 +2,8 @@ const path = require('path'); const glob = require('glob').sync; const RepoUtils = require('./RepoUtils'); const GeneratorUtils = require('./GeneratorUtils'); +const known = require('./known'); +const SpawnUtils = require('./SpawnUtils'); module.exports = class WorkspaceUtils { /** @@ -63,15 +65,15 @@ module.exports = class WorkspaceUtils { return null; } -/** - * Calls the clone repo generator with the name of the repo. - * @param {string} repo Repository name. - * @param {string} branch Branch to clone - * @param {Object} extras Extra git options - * @param {string} dir Where to clone the repo - * @param {string} cwd Where to run the generator - * @param {boolean} cloneSSH SSH or HTTP url - */ + /** + * Calls the clone repo generator with the name of the repo. + * @param {string} repo Repository name. + * @param {string} branch Branch to clone + * @param {Object} extras Extra git options + * @param {string} dir Where to clone the repo + * @param {string} cwd Where to run the generator + * @param {boolean} cloneSSH SSH or HTTP url + */ static cloneRepo(repo, branch, extras, dir = '', cwd, cloneSSH) { const repoUrl = cloneSSH ? RepoUtils.toSSHRepoUrl(repo) : RepoUtils.toHTTPRepoUrl(repo); return GeneratorUtils.yo(`clone-repo`, { @@ -82,4 +84,47 @@ module.exports = class WorkspaceUtils { }, repoUrl, cwd); // repository URL as argument } + static resolveNeighbors(plugins, useSSH, types, shallow, destinationPath) { + let missing = []; + const addMissing = (p) => { + const configPath = path.join(destinationPath, p + '.yo-rc.json'); + console.log(configPath); + const config = this.fs.readJSON(configPath, {'generator-phovea': {}})['generator-phovea']; + let modules = [].concat(config.modules || [], config.smodules || []); + console.log(`${p} => ${modules.join(' ')}`); + if (types && types !== 'both') { + // filter to just certain sub types + const filter = types === 'web' ? known.plugin.isTypeWeb : known.plugin.isTypeServer; + modules = modules.filter((m) => known.plugin.isTypeHybrid(m) || filter(m)); + } + missing.push(...modules.filter((m) => plugins.indexOf(m) < 0)); + }; + + plugins.forEach(addMissing); + + while (missing.length > 0) { + let next = missing.shift(); + let repo = RepoUtils.toRepository(next, useSSH); + let args = ['clone', repo]; + if (shallow) { + args.splice(1, 0, '--depth', '1'); + } + console.log(`git clone ${args.join(' ')}`); + SpawnUtils.spaw('git', args, { + cwd: destinationPath + }); + plugins.push(next); + addMissing(next); + } + } + + + static resolveAllNeighbors(useSSH, types, destinationPath) { + const files = glob('*/.yo-rc.json', { + cwd: destinationPath + }); + const plugins = files.map(path.dirname); + return WorkspaceUtils.resolveNeighbors(plugins, useSSH, types, destinationPath); + } + }; From c708b6d74b871473960a2caeeb42d9c9764f04c1 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 12:31:23 +0200 Subject: [PATCH 17/65] Update function calls phovea/generator-phovea#425 --- generators/clone/index.js | 49 +++---------------------------------- generators/resolve/index.js | 2 +- 2 files changed, 4 insertions(+), 47 deletions(-) diff --git a/generators/clone/index.js b/generators/clone/index.js index 36ab9863..39378526 100644 --- a/generators/clone/index.js +++ b/generators/clone/index.js @@ -1,50 +1,9 @@ 'use strict'; const Base = require('yeoman-generator'); -const path = require('path'); -const glob = require('glob').sync; const known = require('../../utils/known'); const RepoUtils = require('../../utils/RepoUtils'); +const WorkspaceUtils = require('../../utils/WorkspaceUtils'); -function resolveNeighbors(plugins, useSSH, types, shallow) { - let missing = []; - const addMissing = (p) => { - this.log(this.destinationPath(p + '/.yo-rc.json')); - const config = this.fs.readJSON(this.destinationPath(p + '/.yo-rc.json'), {'generator-phovea': {}})['generator-phovea']; - let modules = [].concat(config.modules || [], config.smodules || []); - this.log(`${p} => ${modules.join(' ')}`); - if (types && types !== 'both') { - // filter to just certain sub types - const filter = types === 'web' ? known.plugin.isTypeWeb : known.plugin.isTypeServer; - modules = modules.filter((m) => known.plugin.isTypeHybrid(m) || filter(m)); - } - missing.push(...modules.filter((m) => plugins.indexOf(m) < 0)); - }; - - plugins.forEach(addMissing); - - while (missing.length > 0) { - let next = missing.shift(); - let repo = RepoUtils.toRepository(next, useSSH); - let args = ['clone', repo]; - if (shallow) { - args.splice(1, 0, '--depth', '1'); - } - this.log(`git clone ${args.join(' ')}`); - this.spawnCommandSync('git', args, { - cwd: this.destinationPath() - }); - plugins.push(next); - addMissing(next); - } -} - -function resolveAllNeighbors(useSSH, types) { - const files = glob('*/.yo-rc.json', { - cwd: this.destinationPath() - }); - const plugins = files.map(path.dirname); - return resolveNeighbors.call(this, plugins, useSSH, types); -} class Generator extends Base { constructor(args, options) { @@ -135,11 +94,9 @@ class Generator extends Base { }); }); if (this.props.resolve) { - resolveNeighbors.call(this, this.props.plugins, this.props.cloneSSH); + WorkspaceUtils.resolveNeighbors(this.props.plugins, this.props.cloneSSH, null, null, this.destinationPath()); } } } -module.exports = Generator; -module.exports.resolveNeighbors = resolveNeighbors; -module.exports.resolveAllNeighbors = resolveAllNeighbors; +module.exports = Generator; \ No newline at end of file diff --git a/generators/resolve/index.js b/generators/resolve/index.js index f40de609..222e225d 100644 --- a/generators/resolve/index.js +++ b/generators/resolve/index.js @@ -67,7 +67,7 @@ class Generator extends Base { } writing() { - resolveAllNeighbors.call(this, this.props.cloneSSH, this.props.type, this.options.shallow); + resolveAllNeighbors(this.props.cloneSSH, this.props.type, this.options.shallow, this.destinationPath()); } } From 16e04aa4bd7dd920adf077ccd8368a59b1679ce5 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 14:03:16 +0200 Subject: [PATCH 18/65] Test check-node-version generator phovea/generator-phovea#425 --- generators/_init-python/index.js | 1 - test/check-node-version.test.js | 62 ++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 test/check-node-version.test.js diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index 538bcaff..652cd6a9 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -108,7 +108,6 @@ class Generator extends Base { const config = this.config.getAll(); this.cwd = this.options.isWorkspace ? (config.cwd || config.name) + '/' : ''; const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); - console.log(this.cwd, this.destinationPath(this.cwd + 'package.json')) const deps = this._generateDependencies(NpmUtils.useDevVersion(version), this.cwd); patchPackageJSON.call(this, config, ['devDependencies'], null, null, this.cwd); diff --git a/test/check-node-version.test.js b/test/check-node-version.test.js new file mode 100644 index 00000000..9e012ae6 --- /dev/null +++ b/test/check-node-version.test.js @@ -0,0 +1,62 @@ + +'use strict'; +const path = require('path'); +const helpers = require('yeoman-test'); +const fs = require('fs'); +const installedVersions = require('../utils/installedVersions'); +const requiredNodeVersion = fs.readFileSync(path.resolve(__dirname, '../.nvmrc'), 'utf8'); +const requiredNpmVersion = fs.readFileSync(path.resolve(__dirname, '../.npm-version'), 'utf8'); + +jest.mock('check-node-version'); +const check = require('check-node-version'); + +installedVersions.checkRequiredVersion = jest.fn(); + + +const results = { + versions: { + node: { + version: { + version: 12 + }, + }, + npm: { + version: { + version: 18 + } + } + } +}; + +const versions = { + installed: { + node: results.versions.node.version.version, + npm: results.versions.npm.version.version + }, + required: { + node: requiredNodeVersion.replace('\n', ''), + npm: requiredNpmVersion.replace('\n', '') + } + }; + +check.mockImplementation((versions, cb) => cb(false, results)); + +describe('check-node-version', () => { + + beforeAll(() => { + return helpers + .run(path.join(__dirname, '../generators/check-node-version')); + + }); + it('calls function check only once', () => { + expect(check.mock.calls.length).toBe(1); + }); + + it('calls function checkRequiredVersion once', () => { + expect(installedVersions.checkRequiredVersion.mock.calls.length).toBe(1); + }); + + it('calls checkRequiredVersion with correct argument', () => { + expect(installedVersions.checkRequiredVersion.mock.calls[0][0]).toMatchObject(versions); + }); +}); From 894da0fcca4647f6f3a720ac1f906d8413e4bd1f Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 14:20:30 +0200 Subject: [PATCH 19/65] Minor change phovea/generator-phovea#425 --- test/check-node-version.test.js | 58 ++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/test/check-node-version.test.js b/test/check-node-version.test.js index 9e012ae6..ac6742fd 100644 --- a/test/check-node-version.test.js +++ b/test/check-node-version.test.js @@ -9,39 +9,39 @@ const requiredNpmVersion = fs.readFileSync(path.resolve(__dirname, '../.npm-vers jest.mock('check-node-version'); const check = require('check-node-version'); +const {version} = require('punycode'); installedVersions.checkRequiredVersion = jest.fn(); - -const results = { - versions: { - node: { - version: { - version: 12 +describe('check-node-version', () => { + const results = { + versions: { + node: { + version: { + version: 12 + }, }, - }, - npm: { - version: { - version: 18 + npm: { + version: { + version: 18 + } } } - } -}; - -const versions = { - installed: { - node: results.versions.node.version.version, - npm: results.versions.npm.version.version - }, - required: { - node: requiredNodeVersion.replace('\n', ''), - npm: requiredNpmVersion.replace('\n', '') - } - }; - -check.mockImplementation((versions, cb) => cb(false, results)); + }; + + const versions = { + installed: { + node: results.versions.node.version.version, + npm: results.versions.npm.version.version + }, + required: { + node: requiredNodeVersion.replace('\n', ''), + npm: requiredNpmVersion.replace('\n', '') + } + }; + + check.mockImplementation((_, cb) => cb(false, results)); -describe('check-node-version', () => { beforeAll(() => { return helpers @@ -59,4 +59,10 @@ describe('check-node-version', () => { it('calls checkRequiredVersion with correct argument', () => { expect(installedVersions.checkRequiredVersion.mock.calls[0][0]).toMatchObject(versions); }); + + // it('throws error if function check returns an error', () => { + // TODO do not terminate the node process in installedVersions since it also kills the test. Throw an error instead. + // check.mockImplementation((_, cb) => cb(true, null)); + // expect(installedVersions.checkRequiredVersion.mock.calls[0][0]).toMatchObject(versions); + // }); }); From e7cfd95e0ff2188d006444f93ea2ed6aeac18864 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 14:27:21 +0200 Subject: [PATCH 20/65] Remove unused import phovea/generator-phovea#425 --- test/check-node-version.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/check-node-version.test.js b/test/check-node-version.test.js index ac6742fd..d5cfed51 100644 --- a/test/check-node-version.test.js +++ b/test/check-node-version.test.js @@ -9,7 +9,6 @@ const requiredNpmVersion = fs.readFileSync(path.resolve(__dirname, '../.npm-vers jest.mock('check-node-version'); const check = require('check-node-version'); -const {version} = require('punycode'); installedVersions.checkRequiredVersion = jest.fn(); From 1c245ebba216d0dd3db0dadbb0d235c0c987f0ef Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 15 Sep 2020 15:31:12 +0200 Subject: [PATCH 21/65] Test clone-repo generator --- generators/clone-repo/index.js | 8 +++---- test/clone-repo.test.js | 42 ++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 test/clone-repo.test.js diff --git a/generators/clone-repo/index.js b/generators/clone-repo/index.js index 82404bf4..a9cd5de6 100644 --- a/generators/clone-repo/index.js +++ b/generators/clone-repo/index.js @@ -113,7 +113,7 @@ class Generator extends Base { if (SpawnUtils.failed(r)) { this.log(chalk.red(`failed to fetch list of tags from git repository`), `status code: ${r.status}`); this.log(r.stderr.toString()); - return this._abort(`failed to fetch list of tags from git repository - status code: ${r.status}`); + return SpawnUtils.abort(`failed to fetch list of tags from git repository - status code: ${r.status}`); } const gitLog = r.stdout.toString(); @@ -123,7 +123,7 @@ class Generator extends Base { const highestVersion = NpmUtils.findHighestVersion(gitVersions, branch); if (!highestVersion) { this.log(chalk.red(`failed to find git version tag for given version range`)); - return this._abort(`failed to find git version tag for given version range`); + return SpawnUtils.abort(`failed to find git version tag for given version range`); } this.log(chalk.white(`use version tag`), chalk.green(highestVersion), chalk.white(`as branch name`)); @@ -137,12 +137,12 @@ class Generator extends Base { // clone a specific commit const line = `clone ${extras || ''} ${repoUrl}${cloneDirName}`; this.log(chalk.white(`clone repository:`), `git ${line}`); - return this._spawnOrAbort('git', line.split(/ +/), this.cwd).then(() => { + return SpawnUtils.spawnOrAbort('git', line.split(/ +/), this.cwd).then(() => { const line = `checkout ${branch}`; this.log(chalk.white(`checkout commit:`), `git ${line}`); let repoName = RepoUtils.simplifyRepoUrl(repoUrl); repoName = repoName.slice(repoName.lastIndexOf('/') + 1); - return this._spawnOrAbort('git', line.split(/ +/), { + return SpawnUtils.spawnOrAbort('git', line.split(/ +/), { cwd: `${this.cwd}/${repoName}` }); }); diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js new file mode 100644 index 00000000..0734b640 --- /dev/null +++ b/test/clone-repo.test.js @@ -0,0 +1,42 @@ + +'use strict'; +const path = require('path'); +const assert = require('yeoman-assert'); +const helpers = require('yeoman-test'); +const NpmUtils = require('../utils/NpmUtils'); +const SpawnUtils = require('../utils/SpawnUtils'); + +/** + * Subgenerators composed with the `clone-repo` subgenerator. + */ +const GENERATOR_DEPENDENCIES = [ + + '../../generators/_check-own-version', + '../../generators/check-node-version', +]; + +describe('generator clone-repo', () => { + + const repo = 'git@github.com:Caleydo/ordino.git'; + + beforeAll(() => { + // NpmUtils.isGitCommit = jest.fn(); + // NpmUtils.isGitCommit.mockReturnValueOnce(true); + // NpmUtils.isAdvancedVersionTag = jest.fn(); + SpawnUtils.spawnOrAbort = jest.fn(); + + return helpers + .run(path.join(__dirname, '../generators/clone-repo')) + .inDir(path.join(__dirname, 'cloned'), () => null) + .withArguments([repo]) + .withOptions({branch: 'develop'}) + .withGenerators(GENERATOR_DEPENDENCIES); + }); + + it('calls function spawnOrAbort() once with argument `develop`', () => { + expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); + expect(SpawnUtils.spawnOrAbort.mock.calls[0][0]).toBe('git'); + expect(SpawnUtils.spawnOrAbort.mock.calls[0][1]).toStrictEqual(['clone', '-b', 'develop', repo]); + expect(SpawnUtils.spawnOrAbort.mock.calls[0][2]).toBe(undefined); + }); +}); From 18d92129635dbf9cb5a32bb6b7df0e5b0e4472dd Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 16 Sep 2020 09:37:15 +0200 Subject: [PATCH 22/65] Extending tests phovea/generator-phovea#425 --- test/clone-repo.test.js | 174 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 157 insertions(+), 17 deletions(-) diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js index 0734b640..f9a1a203 100644 --- a/test/clone-repo.test.js +++ b/test/clone-repo.test.js @@ -1,9 +1,7 @@ 'use strict'; const path = require('path'); -const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); -const NpmUtils = require('../utils/NpmUtils'); const SpawnUtils = require('../utils/SpawnUtils'); /** @@ -15,28 +13,170 @@ const GENERATOR_DEPENDENCIES = [ '../../generators/check-node-version', ]; -describe('generator clone-repo', () => { +const repo = 'git@github.com:Caleydo/ordino.git'; - const repo = 'git@github.com:Caleydo/ordino.git'; +const cloneRepo = (options) => helpers + .run(path.join(__dirname, '../generators/clone-repo')) + .inDir(path.join(__dirname, 'cloned'), () => null) + .withArguments([repo]) + .withOptions(options) + .withGenerators(GENERATOR_DEPENDENCIES); + +describe('call clone-repo with branch develop', () => { beforeAll(() => { - // NpmUtils.isGitCommit = jest.fn(); - // NpmUtils.isGitCommit.mockReturnValueOnce(true); - // NpmUtils.isAdvancedVersionTag = jest.fn(); SpawnUtils.spawnOrAbort = jest.fn(); - return helpers - .run(path.join(__dirname, '../generators/clone-repo')) - .inDir(path.join(__dirname, 'cloned'), () => null) - .withArguments([repo]) - .withOptions({branch: 'develop'}) - .withGenerators(GENERATOR_DEPENDENCIES); + return cloneRepo({branch: 'develop'}); }); - it('calls function spawnOrAbort() once with argument `develop`', () => { + it('calls function spawnOrAbort() once with the correct argument', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); - expect(SpawnUtils.spawnOrAbort.mock.calls[0][0]).toBe('git'); - expect(SpawnUtils.spawnOrAbort.mock.calls[0][1]).toStrictEqual(['clone', '-b', 'develop', repo]); - expect(SpawnUtils.spawnOrAbort.mock.calls[0][2]).toBe(undefined); + const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; + expect(cmd).toBe('git'); + + const options = SpawnUtils.spawnOrAbort.mock.calls[0][1]; + expect(options).toStrictEqual(['clone', '-b', 'develop', repo]); + + const cwd = SpawnUtils.spawnOrAbort.mock.calls[0][2]; + expect(cwd).toBe(undefined); + }); +}); + +describe('call clone-repo with exact version tag', () => { + + beforeAll(() => { + SpawnUtils.spawnOrAbort = jest.fn(); + return cloneRepo({branch: 'v2.0.0'}); + }); + + it('calls function spawnOrAbort() once with the correct arguments', () => { + expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); + const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; + expect(cmd).toBe('git'); + + const options = SpawnUtils.spawnOrAbort.mock.calls[0][1]; + expect(options).toStrictEqual(['clone', '-b', 'v2.0.0', repo]); + + const cwd = SpawnUtils.spawnOrAbort.mock.calls[0][2]; + expect(cwd).toBe(undefined); + }); +}); + +describe('call clone-repo with an advanced version tag', () => { + + beforeAll(() => { + SpawnUtils.spawnOrAbort = jest.fn(); + SpawnUtils.spawn = jest.fn(); + SpawnUtils.spawn.mockImplementation(() => { + return { + status: 0, + stdout: ` + 336072e87ec8f6054cead9f64c6830897fb7f076 refs/tags/v2.0.0 + 8747a43780e4651542facd7b4feac7bcb8e3778d refs/tags/v2.0.1 + ` + }; + }); + return cloneRepo({branch: '^v2.0.0'}); + }); + + it('calls function spawnOrAbort() once with the the correctly resolved version tag', () => { + expect(SpawnUtils.spawn.mock.calls.length).toBe(1); + const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; + expect(cmd).toBe('git'); + + const options = SpawnUtils.spawnOrAbort.mock.calls[0][1]; + expect(options).toStrictEqual(['clone', '-b', 'v2.0.1', repo]); + + const cwd = SpawnUtils.spawnOrAbort.mock.calls[0][2]; + expect(cwd).toBe(undefined); }); }); + +describe('call clone-repo with an advanced version tag and no remote', () => { + + beforeAll(() => { + SpawnUtils.spawnOrAbort = jest.fn(); + SpawnUtils.abort = jest.fn(); + SpawnUtils.spawn = jest.fn(); + SpawnUtils.spawn.mockImplementation(() => { + return { + status: 1, + stderr: `some error` + }; + }); + return cloneRepo({branch: '^v2.0.0'}); + }); + + it('calls function abort() once and spawnOrAbort() never', () => { + expect(SpawnUtils.abort.mock.calls.length).toBe(1); + const msg = SpawnUtils.abort.mock.calls[0][0]; + expect(msg).toBe('failed to fetch list of tags from git repository - status code: 1'); + + expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(0); + }); +}); + +describe('call clone-repo with an advanced version tag that does not resolve', () => { + + beforeAll(() => { + SpawnUtils.spawnOrAbort = jest.fn(); + SpawnUtils.abort = jest.fn(); + SpawnUtils.spawn = jest.fn(); + SpawnUtils.spawn.mockImplementation(() => { + return { + status: 0, + stdout: ` + 336072e87ec8f6054cead9f64c6830897fb7f076 refs/tags/v2.0.0 + 8747a43780e4651542facd7b4feac7bcb8e3778d refs/tags/v2.0.1 + ` + }; + }); + return cloneRepo({branch: '^v3.0.0'}); + }); + + it('calls function abort() once and spawnOrAbort() never', () => { + expect(SpawnUtils.abort.mock.calls.length).toBe(1); + const msg = SpawnUtils.abort.mock.calls[0][0]; + expect(msg).toBe('failed to find git version tag for given version range'); + + expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(0); + }); +}); + +describe('call clone-repo with a git commit', () => { + + beforeAll(() => { + SpawnUtils.spawnOrAbort = jest.fn(); + SpawnUtils.spawnOrAbort.mockImplementation(() => Promise.resolve()); + return cloneRepo({branch: 'e7cfd95e0ff2188d006444f93ea2ed6aeac18864'}); + }); + + it('calls function spawnOrabort() twice', () => { + expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(2); + + }); + + it('first it clones the develop branch of the repo', () => { + const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; + expect(cmd).toBe('git'); + + const options = SpawnUtils.spawnOrAbort.mock.calls[0][1]; + expect(options).toStrictEqual(['clone', '-b', 'develop', repo]); + + const cwd = SpawnUtils.spawnOrAbort.mock.calls[0][2]; + expect(cwd).toBe(undefined); + + }); + + it('then it checks out the git commit', () => { + const cmd = SpawnUtils.spawnOrAbort.mock.calls[1][0]; + expect(cmd).toBe('git'); + + const options = SpawnUtils.spawnOrAbort.mock.calls[1][1]; + expect(options).toStrictEqual(['clone', '-b', 'e7cfd95e0ff2188d006444f93ea2ed6aeac18864', repo]); + + const cwd = SpawnUtils.spawnOrAbort.mock.calls[1][2]; + expect(cwd).toBe(undefined); + }); +}); \ No newline at end of file From 61268a90588053ff827d0ba3be5a24ff2a63f8d5 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 16 Sep 2020 09:43:21 +0200 Subject: [PATCH 23/65] Code cleanup phovea/generator-phovea#425 --- test/clone-repo.test.js | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js index f9a1a203..9d065eee 100644 --- a/test/clone-repo.test.js +++ b/test/clone-repo.test.js @@ -2,6 +2,7 @@ 'use strict'; const path = require('path'); const helpers = require('yeoman-test'); +const rimraf = require('rimraf'); const SpawnUtils = require('../utils/SpawnUtils'); /** @@ -14,10 +15,11 @@ const GENERATOR_DEPENDENCIES = [ ]; const repo = 'git@github.com:Caleydo/ordino.git'; +const target = 'cloned'; const cloneRepo = (options) => helpers .run(path.join(__dirname, '../generators/clone-repo')) - .inDir(path.join(__dirname, 'cloned'), () => null) + .inDir(path.join(__dirname, target), () => null) .withArguments([repo]) .withOptions(options) .withGenerators(GENERATOR_DEPENDENCIES); @@ -30,6 +32,10 @@ describe('call clone-repo with branch develop', () => { return cloneRepo({branch: 'develop'}); }); + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + it('calls function spawnOrAbort() once with the correct argument', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; @@ -43,13 +49,17 @@ describe('call clone-repo with branch develop', () => { }); }); -describe('call clone-repo with exact version tag', () => { +describe('call clone-repo with an exact version tag', () => { beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); return cloneRepo({branch: 'v2.0.0'}); }); + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + it('calls function spawnOrAbort() once with the correct arguments', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; @@ -80,6 +90,10 @@ describe('call clone-repo with an advanced version tag', () => { return cloneRepo({branch: '^v2.0.0'}); }); + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + it('calls function spawnOrAbort() once with the the correctly resolved version tag', () => { expect(SpawnUtils.spawn.mock.calls.length).toBe(1); const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; @@ -108,6 +122,10 @@ describe('call clone-repo with an advanced version tag and no remote', () => { return cloneRepo({branch: '^v2.0.0'}); }); + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + it('calls function abort() once and spawnOrAbort() never', () => { expect(SpawnUtils.abort.mock.calls.length).toBe(1); const msg = SpawnUtils.abort.mock.calls[0][0]; @@ -117,7 +135,7 @@ describe('call clone-repo with an advanced version tag and no remote', () => { }); }); -describe('call clone-repo with an advanced version tag that does not resolve', () => { +describe('call clone-repo with an advanced version tag that does not resolve to an exact version tag', () => { beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); @@ -135,6 +153,10 @@ describe('call clone-repo with an advanced version tag that does not resolve', ( return cloneRepo({branch: '^v3.0.0'}); }); + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + it('calls function abort() once and spawnOrAbort() never', () => { expect(SpawnUtils.abort.mock.calls.length).toBe(1); const msg = SpawnUtils.abort.mock.calls[0][0]; @@ -146,12 +168,17 @@ describe('call clone-repo with an advanced version tag that does not resolve', ( describe('call clone-repo with a git commit', () => { + beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); SpawnUtils.spawnOrAbort.mockImplementation(() => Promise.resolve()); return cloneRepo({branch: 'e7cfd95e0ff2188d006444f93ea2ed6aeac18864'}); }); + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + it('calls function spawnOrabort() twice', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(2); From fcf51bd79ebc9722ec8653989abbbcff517acf57 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 16 Sep 2020 10:43:35 +0200 Subject: [PATCH 24/65] Further refactoring phovea/generator-phovea#425 --- generators/clone-repo/index.js | 7 ++++--- test/clone-repo.test.js | 30 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/generators/clone-repo/index.js b/generators/clone-repo/index.js index a9cd5de6..338f9a61 100644 --- a/generators/clone-repo/index.js +++ b/generators/clone-repo/index.js @@ -134,17 +134,18 @@ class Generator extends Base { this.log(chalk.white(`clone repository:`), `git ${line}`); return SpawnUtils.spawnOrAbort('git', line.split(/ +/), this.cwd); } + // clone a specific commit const line = `clone ${extras || ''} ${repoUrl}${cloneDirName}`; this.log(chalk.white(`clone repository:`), `git ${line}`); + return SpawnUtils.spawnOrAbort('git', line.split(/ +/), this.cwd).then(() => { const line = `checkout ${branch}`; this.log(chalk.white(`checkout commit:`), `git ${line}`); let repoName = RepoUtils.simplifyRepoUrl(repoUrl); repoName = repoName.slice(repoName.lastIndexOf('/') + 1); - return SpawnUtils.spawnOrAbort('git', line.split(/ +/), { - cwd: `${this.cwd}/${repoName}` - }); + const cwd = this.cwd ? `${this.cwd}/${repoName}` : repoName; + return SpawnUtils.spawnOrAbort('git', line.split(/ +/), cwd); }); } diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js index 9d065eee..6e1de8e7 100644 --- a/test/clone-repo.test.js +++ b/test/clone-repo.test.js @@ -29,12 +29,12 @@ describe('call clone-repo with branch develop', () => { beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); - return cloneRepo({branch: 'develop'}); + return cloneRepo({branch: 'develop', extras: '--depth 1', dir: '.', cwd: 'ordino_workspace'}); }); afterAll(() => { rimraf.sync(path.join(__dirname, target)); - }); + }); it('calls function spawnOrAbort() once with the correct argument', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); @@ -42,10 +42,10 @@ describe('call clone-repo with branch develop', () => { expect(cmd).toBe('git'); const options = SpawnUtils.spawnOrAbort.mock.calls[0][1]; - expect(options).toStrictEqual(['clone', '-b', 'develop', repo]); + expect(options).toStrictEqual(['clone', '-b', 'develop', '--depth', '1', repo, '.']); const cwd = SpawnUtils.spawnOrAbort.mock.calls[0][2]; - expect(cwd).toBe(undefined); + expect(cwd).toBe('ordino_workspace'); }); }); @@ -58,7 +58,7 @@ describe('call clone-repo with an exact version tag', () => { afterAll(() => { rimraf.sync(path.join(__dirname, target)); - }); + }); it('calls function spawnOrAbort() once with the correct arguments', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(1); @@ -92,7 +92,7 @@ describe('call clone-repo with an advanced version tag', () => { afterAll(() => { rimraf.sync(path.join(__dirname, target)); - }); + }); it('calls function spawnOrAbort() once with the the correctly resolved version tag', () => { expect(SpawnUtils.spawn.mock.calls.length).toBe(1); @@ -115,7 +115,7 @@ describe('call clone-repo with an advanced version tag and no remote', () => { SpawnUtils.spawn = jest.fn(); SpawnUtils.spawn.mockImplementation(() => { return { - status: 1, + status: 128, stderr: `some error` }; }); @@ -124,12 +124,12 @@ describe('call clone-repo with an advanced version tag and no remote', () => { afterAll(() => { rimraf.sync(path.join(__dirname, target)); - }); + }); it('calls function abort() once and spawnOrAbort() never', () => { expect(SpawnUtils.abort.mock.calls.length).toBe(1); const msg = SpawnUtils.abort.mock.calls[0][0]; - expect(msg).toBe('failed to fetch list of tags from git repository - status code: 1'); + expect(msg).toBe('failed to fetch list of tags from git repository - status code: 128'); expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(0); }); @@ -155,7 +155,7 @@ describe('call clone-repo with an advanced version tag that does not resolve to afterAll(() => { rimraf.sync(path.join(__dirname, target)); - }); + }); it('calls function abort() once and spawnOrAbort() never', () => { expect(SpawnUtils.abort.mock.calls.length).toBe(1); @@ -177,19 +177,19 @@ describe('call clone-repo with a git commit', () => { afterAll(() => { rimraf.sync(path.join(__dirname, target)); - }); + }); it('calls function spawnOrabort() twice', () => { expect(SpawnUtils.spawnOrAbort.mock.calls.length).toBe(2); }); - it('first it clones the develop branch of the repo', () => { + it('first it clones the the repo', () => { const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; expect(cmd).toBe('git'); const options = SpawnUtils.spawnOrAbort.mock.calls[0][1]; - expect(options).toStrictEqual(['clone', '-b', 'develop', repo]); + expect(options).toStrictEqual(['clone', repo]); const cwd = SpawnUtils.spawnOrAbort.mock.calls[0][2]; expect(cwd).toBe(undefined); @@ -201,9 +201,9 @@ describe('call clone-repo with a git commit', () => { expect(cmd).toBe('git'); const options = SpawnUtils.spawnOrAbort.mock.calls[1][1]; - expect(options).toStrictEqual(['clone', '-b', 'e7cfd95e0ff2188d006444f93ea2ed6aeac18864', repo]); + expect(options).toStrictEqual(['checkout', 'e7cfd95e0ff2188d006444f93ea2ed6aeac18864']); const cwd = SpawnUtils.spawnOrAbort.mock.calls[1][2]; - expect(cwd).toBe(undefined); + expect(cwd).toBe('ordino'); }); }); \ No newline at end of file From eeb8090d3933aa8f7b9313230b96c268a1e802ac Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 16 Sep 2020 14:36:38 +0200 Subject: [PATCH 25/65] Refactor setup-workspace generator and extend tests phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 39 +++-------- test/RepoUtils.test.js | 24 +++++++ test/templates/phovea_product_dummy.json | 88 ++++++++++++++++++++++++ utils/RepoUtils.js | 31 ++++++++- 4 files changed, 151 insertions(+), 31 deletions(-) create mode 100644 test/templates/phovea_product_dummy.json diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index 5731c60a..b0445aa1 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -97,9 +97,13 @@ class Generator extends Base { } _removeUnnecessaryProductFiles() { - fs.unlinkSync(this.cwd + '/.yo-rc.json'); - fs.rmdirSync(this.cwd + '/.git', {recursive: true}); // TODO look into git submodules - fs.renameSync(this.cwd + '/package.json', this.cwd + '/package_product.json'); + try { + fs.unlinkSync(this.cwd + '/.yo-rc.json'); + fs.rmdirSync(this.cwd + '/.git', {recursive: true}); // TODO look into git submodules + fs.renameSync(this.cwd + '/package.json', this.cwd + '/package_product.json'); + } catch (e) { + this.log(e.message); + } } /** @@ -139,10 +143,10 @@ class Generator extends Base { }, {spaces: 2}); } } - - return this.product; + return RepoUtils.parsePhoveaProduct(this.product); }); } + _customizeWorkspace() { const defaultApp = WorkspaceUtils.findDefaultApp(this.product); if (defaultApp) { @@ -251,31 +255,6 @@ class Generator extends Base { return Promise.resolve(1) .then(GeneratorUtils.mkdir(this.cwd)) .then(this._getProduct.bind(this)) - .then((product) => { - const names = new Set(); - const repos = []; - product.forEach((p) => { - const repo = p.repo || 'phovea/' + p.name; - if (!names.has(repo)) { - names.add(repo); - repos.push({ - repo, - branch: p.branch || 'master' - }); - } - (p.additional || []).forEach((pi) => { - const repo = pi.repo || 'phovea/' + pi.name; - if (!names.has(repo)) { - names.add(repo); - repos.push({ - repo, - branch: pi.branch || 'master' - }); - } - }); - }); - return repos; - }) .then((repos) => Promise.all(repos.map((r) => WorkspaceUtils.cloneRepo(r.repo, r.branch, null, '', this.cwd, this.cloneSSH)))) .then(() => GeneratorUtils.yo('workspace', { defaultApp: WorkspaceUtils.findDefaultApp(), diff --git a/test/RepoUtils.test.js b/test/RepoUtils.test.js index c15c36d9..dbbecd9f 100644 --- a/test/RepoUtils.test.js +++ b/test/RepoUtils.test.js @@ -1,5 +1,7 @@ 'use strict'; const RepoUtils = require('../utils/RepoUtils'); +const fs = require('fs-extra'); +const path = require('path'); describe('transfroms repo name to an https url', () => { @@ -112,4 +114,26 @@ describe('extact repo name from string containing `org/repo`', () => { const repo = 'ordino'; expect(RepoUtils.toCWD(repo)).toBe('ordino'); }); +}); + +describe('parse phovea_product.json', () => { + const result = [ + {repo: 'Caleydo/ordino_public', branch: 'develop'}, + {repo: 'phovea/phovea_core', branch: 'develop'}, + {repo: 'phovea/phovea_ui', branch: 'develop'}, + {repo: 'phovea/phovea_clue', branch: 'develop'}, + {repo: 'phovea/phovea_security_flask', branch: 'develop'}, + {repo: 'datavisyn/tdp_core', branch: 'develop'}, + {repo: 'Caleydo/ordino', branch: 'develop'}, + {repo: 'Caleydo/tdp_gene', branch: 'develop'}, + {repo: 'Caleydo/tdp_publicdb', branch: 'develop'}, + {repo: 'phovea/phovea_server', branch: 'develop'}, + {repo: 'phovea/phovea_data_redis', branch: 'develop'}, + {repo: 'phovea/phovea_data_mongo', branch: 'develop'} + ]; + + const dummyProduct = fs.readJSONSync(path.join(__dirname, `templates/phovea_product_dummy.json`)); + it('resulting object has correct structure', () => { + expect(RepoUtils.parsePhoveaProduct(dummyProduct)).toStrictEqual(result); + }); }); \ No newline at end of file diff --git a/test/templates/phovea_product_dummy.json b/test/templates/phovea_product_dummy.json new file mode 100644 index 00000000..fadc7e4c --- /dev/null +++ b/test/templates/phovea_product_dummy.json @@ -0,0 +1,88 @@ +[ + { + "type": "web", + "label": "ordino", + "repo": "Caleydo/ordino_public", + "branch": "develop", + "additional": [ + { + "name": "phovea_core", + "repo": "phovea/phovea_core", + "branch": "develop" + }, + { + "name": "phovea_ui", + "repo": "phovea/phovea_ui", + "branch": "develop" + }, + { + "name": "phovea_clue", + "repo": "phovea/phovea_clue", + "branch": "develop" + }, + { + "name": "phovea_security_flask", + "repo": "phovea/phovea_security_flask", + "branch": "develop" + }, + { + "name": "tdp_core", + "repo": "datavisyn/tdp_core", + "branch": "develop" + }, + { + "name": "ordino", + "repo": "Caleydo/ordino", + "branch": "develop" + }, + { + "name": "tdp_gene", + "repo": "Caleydo/tdp_gene", + "branch": "develop" + }, + { + "name": "tdp_publicdb", + "repo": "Caleydo/tdp_publicdb", + "branch": "develop" + } + ] + }, + { + "type": "api", + "label": "ordino_server", + "repo": "phovea/phovea_server", + "branch": "develop", + "additional": [ + { + "name": "phovea_security_flask", + "repo": "phovea/phovea_security_flask", + "branch": "develop" + }, + { + "name": "phovea_data_redis", + "repo": "phovea/phovea_data_redis", + "branch": "develop" + }, + { + "name": "phovea_data_mongo", + "repo": "phovea/phovea_data_mongo", + "branch": "develop" + }, + { + "name": "phovea_clue", + "repo": "phovea/phovea_clue", + "branch": "develop" + }, + { + "name": "tdp_core", + "repo": "datavisyn/tdp_core", + "branch": "develop" + }, + { + "name": "tdp_publicdb", + "repo": "Caleydo/tdp_publicdb", + "branch": "develop" + } + ] + } + ] \ No newline at end of file diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js index e85d2aad..21f42756 100644 --- a/utils/RepoUtils.js +++ b/utils/RepoUtils.js @@ -90,7 +90,7 @@ module.exports = class RepoUtils { } return match; - } catch{ + } catch { return basename; } } @@ -99,4 +99,33 @@ module.exports = class RepoUtils { const p = known.plugin.byName(plugin); return useSSH ? RepoUtils.RtoSSHRepoUrl(p.repository) : RepoUtils.toHTTPRepoUrl(p.repository); } + /** + * Parses the `phovea_product.json` file and returns an array of objects containing the repo name and branch + * @param {{}} product + */ + static parsePhoveaProduct(product) { + const names = new Set(); + const repos = []; + product.forEach((p) => { + const repo = p.repo || 'phovea/' + p.name; + if (!names.has(repo)) { + names.add(repo); + repos.push({ + repo, + branch: p.branch || 'master' + }); + } + (p.additional || []).forEach((pi) => { + const repo = pi.repo || 'phovea/' + pi.name; + if (!names.has(repo)) { + names.add(repo); + repos.push({ + repo, + branch: pi.branch || 'master' + }); + } + }); + }); + return repos; + } }; From bb27b9ce85958e80ca5d78bff118186a18a9d8b5 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 16 Sep 2020 16:42:37 +0200 Subject: [PATCH 26/65] Extend tests-fix bugs phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 63 ++++++------- test/WorkspaceUtils.test.js | 15 ++- test/setup-workspace.test.js | 139 ++++++++++++++++++++++++++++ utils/WorkspaceUtils.js | 8 +- 4 files changed, 189 insertions(+), 36 deletions(-) create mode 100644 test/setup-workspace.test.js diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index b0445aa1..e21290ef 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -7,6 +7,7 @@ const RepoUtils = require('../../utils/RepoUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); const WorkspaceUtils = require('../../utils/WorkspaceUtils'); const GeneratorUtils = require('../../utils/GeneratorUtils'); +const {findDefaultApp} = require('../../utils/WorkspaceUtils'); function downloadFileImpl(url, dest) { const http = require(url.startsWith('https') ? 'https' : 'http'); @@ -120,33 +121,33 @@ class Generator extends Base { return WorkspaceUtils.cloneRepo(this.productName, this.options.branch || 'master', null, '.', this.cwd, this.cloneSSH) .then(() => { this._removeUnnecessaryProductFiles(); - const phoveaProductJSON = `${this.cwd}/phovea_product.json`; if (!fs.existsSync(phoveaProductJSON)) { throw new Error('No phovea_product.json file found! Did you enter a valid phovea product repository?'); } this.product = fs.readJSONSync(phoveaProductJSON); + const defaultApp = findDefaultApp(this.product); + this.defaultApp = defaultApp.name; - const defaultApp = this.product.find((v) => v.type === 'web'); - if (defaultApp) { - const baseRepo = RepoUtils.simplifyRepoUrl(defaultApp.repo); - const defaultAppName = baseRepo.slice(baseRepo.lastIndexOf('/') + 1); - this.defaultApp = defaultAppName; - const yoWorkspacePath = this.destinationPath(`${this.cwd}/.yo-rc-workspace.json`); - if (!fs.existsSync(yoWorkspacePath)) { - fs.writeJsonSync(yoWorkspacePath, { - modules: [], - defaultApp: defaultAppName, - frontendRepos: defaultApp.additional.map((repo) => repo.name), - devRepos: [defaultAppName] - }, {spaces: 2}); - } - } + this._createYoRcWorkspace(defaultApp); return RepoUtils.parsePhoveaProduct(this.product); }); } + _createYoRcWorkspace(defaultApp) { + const yoWorkspacePath = this.destinationPath(`${this.cwd}/.yo-rc-workspace.json`); + if (!fs.existsSync(yoWorkspacePath && this.defaultApp)) { + const frontendRepos = defaultApp.additional; + fs.writeJsonSync(yoWorkspacePath, { + modules: [], + defaultApp: this.defaultApp, + frontendRepos, + devRepos: [this.defaultApp] + }, {spaces: 2}); + } + } + _customizeWorkspace() { const defaultApp = WorkspaceUtils.findDefaultApp(this.product); if (defaultApp) { @@ -257,22 +258,22 @@ class Generator extends Base { .then(this._getProduct.bind(this)) .then((repos) => Promise.all(repos.map((r) => WorkspaceUtils.cloneRepo(r.repo, r.branch, null, '', this.cwd, this.cloneSSH)))) .then(() => GeneratorUtils.yo('workspace', { - defaultApp: WorkspaceUtils.findDefaultApp(), + defaultApp: this.defaultApp, skipNextStepsLog: true // skip "next steps" logs from yo phovea:workspace }, null, this.cwd, this.env.adapter)) - .then(this._customizeWorkspace.bind(this)) - .then(this._downloadDataFiles.bind(this)) - .then(() => this.options.skip.includes('install') ? null : SpawnUtils.spawnOrAbort('npm', 'install', this.cwd, true)) - .then(this._downloadBackupFiles.bind(this)) - .then(() => { - const l = this.fs.read(this.destinationPath(`${this.cwd}/docker-compose.yml`), { - defaults: '' - }); - if (l.trim().length > 0 && !this.options.skip.includes('build')) { - return this._ifExecutable('docker-compose', () => SpawnUtils.spawnOrAbort('docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); - } - return null; - }) + // .then(this._customizeWorkspace.bind(this)) + // .then(this._downloadDataFiles.bind(this)) + // .then(() => this.options.skip.includes('install') ? null : SpawnUtils.spawnOrAbort('npm', 'install', this.cwd, true)) + // .then(this._downloadBackupFiles.bind(this)) + // .then(() => { + // const l = this.fs.read(this.destinationPath(`${this.cwd}/docker-compose.yml`), { + // defaults: '' + // }); + // if (l.trim().length > 0 && !this.options.skip.includes('build')) { + // return this._ifExecutable('docker-compose', () => SpawnUtils.spawnOrAbort('docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); + // } + // return null; + // }) .catch((msg) => { this.log('\r\n'); this.log(chalk.red(msg)); @@ -280,7 +281,7 @@ class Generator extends Base { }); } - end() { + _end() { if (this.hasErrors) { return; // skip next steps on errors } diff --git a/test/WorkspaceUtils.test.js b/test/WorkspaceUtils.test.js index b74983c0..dbd0a250 100644 --- a/test/WorkspaceUtils.test.js +++ b/test/WorkspaceUtils.test.js @@ -29,7 +29,18 @@ describe('Find default app in product object', () => { label: 'ordino', repo: 'Caleydo/ordino_public', branch: 'develop', - additional: [] + additional: [ + { + "name": "phovea_core", + "repo": "phovea/phovea_core", + "branch": "develop" + }, + { + "name": "phovea_ui", + "repo": "phovea/phovea_ui", + "branch": "develop" + } + ] }, { @@ -40,6 +51,6 @@ describe('Find default app in product object', () => { additional: [] }]; - expect(WorkspaceUtils.findDefaultApp(product)).toBe('ordino_public'); + expect(WorkspaceUtils.findDefaultApp(product)).toMatchObject({name: 'ordino_public', additional: ['phovea_core', 'phovea_ui']}); }); }); \ No newline at end of file diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js new file mode 100644 index 00000000..42c6dc53 --- /dev/null +++ b/test/setup-workspace.test.js @@ -0,0 +1,139 @@ + +'use strict'; +const path = require('path'); +const helpers = require('yeoman-test'); +const rimraf = require('rimraf'); +const GeneratorUtils = require('../utils/GeneratorUtils'); +const WorkspaceUtils = require('../utils/WorkspaceUtils'); +const assert = require('yeoman-assert'); +const fs = require('fs-extra'); +const RepoUtils = require('../utils/RepoUtils'); +const {yo} = require('../utils/GeneratorUtils'); + +/** + * Directory name to run the generator + */ +const target = '../phovea_workpsace'; + +/** + * Sub-generators called with the setup-workspace sub-generator. + */ +const GENERATOR_DEPENDENCIES = [ + '../generators/workspace', + '../generators/_check-own-version', + '../generators/check-node-version', + '../generators/clone-repo', +]; +const product = 'org/dummy_product'; + +const setupWorkspace = () => helpers + .run(path.join(__dirname, '../generators/setup-workspace')) + .inDir(path.join(__dirname, target), () => null) + .withArguments([product]) + .withOptions({ssh: true, branch: 'develop'}) + .withGenerators(GENERATOR_DEPENDENCIES); + + +describe('generator setup-workspace', () => { + const phoveaProduct = fs.readJSONSync(path.join(__dirname, `templates/phovea_product_dummy.json`)); + beforeAll(() => { + WorkspaceUtils.cloneRepo = jest.fn() + .mockImplementationOnce((repo, branch, extras, dir, cwd) => fs.writeJson(cwd + '/phovea_product.json', phoveaProduct)) // first call + .mockImplementation(() => Promise.resolve(null)); // just resolve promise after the firts call + + GeneratorUtils.yo = jest.fn(); + return setupWorkspace(); + }); + + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + + it('calls WorkspaceUtils.cloneRepo(...args) 13 times (1 product + 12 plugins)', () => { + expect(WorkspaceUtils.cloneRepo.mock.calls.length).toBe(13); + }); + + + it('clones product by calling `WorkspaceUtils.cloneRepo(...args)` with the correct args', () => { + const cloneRepoArgs = WorkspaceUtils.cloneRepo.mock.calls; + + const productRepo = cloneRepoArgs[0][0]; + expect(productRepo).toBe(product); + + const branch = cloneRepoArgs[0][1]; + expect(branch).toBe('develop'); + + const extra = cloneRepoArgs[0][2]; + expect(extra).toBe(null); + + const target = cloneRepoArgs[0][3]; + const currentDir = '.'; + expect(target).toBe(currentDir); + + const cwd = cloneRepoArgs[0][4]; + expect(cwd).toBe('dummy'); + + const ssh = cloneRepoArgs[0][5]; + expect(ssh).toBe(true); + }); + + it('clones all plugins by calling `WorkspaceUtils.cloneRepo(...args)` with the correct args', () => { + const cloneRepoArgs = WorkspaceUtils.cloneRepo.mock.calls; + RepoUtils.parsePhoveaProduct(phoveaProduct).forEach((plugin, i) => { + const index = i + 1; // skip the product cloning call + const name = cloneRepoArgs[index][0]; + expect(name).toBe(plugin.repo); + + const branch = cloneRepoArgs[index][1]; + expect(branch).toBe(plugin.branch); + + const extra = cloneRepoArgs[index][2]; + expect(extra).toBe(null); + + const target = cloneRepoArgs[index][3]; + expect(target).toBe(''); + + const cwd = cloneRepoArgs[index][4]; + expect(cwd).toBe('dummy'); + + const ssh = cloneRepoArgs[index][5]; + expect(ssh).toBe(true); + }); + + }); + + it('creates valid `.yo-rc-workspace.json`', () => { + const content = { + 'modules': [], + 'defaultApp': 'ordino_public', + 'frontendRepos': [ + 'phovea_core', + 'phovea_ui', + 'phovea_clue', + 'phovea_security_flask', + 'tdp_core', + 'ordino', + 'tdp_gene', + 'tdp_publicdb' + ], + 'devRepos': [ + 'ordino_public' + ] + }; + + assert.file('dummy/.yo-rc-workspace.json'); + assert.jsonFileContent('dummy/.yo-rc-workspace.json', content); + }); + + it('calls GeneratorUtils.yo(..args) with the correct arguments', () => { + const yoArgs = GeneratorUtils.yo.mock.calls; + expect(yoArgs.length).toBe(1); + const cmd = yoArgs[0][0]; + expect(cmd).toBe('workspace'); + + const options = yoArgs[0][1]; + expect(options).toMatchObject({'defaultApp': 'ordino_public', 'skipNextStepsLog': true}); + }); + + +}); diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js index 9ef4282c..1c71ce4c 100644 --- a/utils/WorkspaceUtils.js +++ b/utils/WorkspaceUtils.js @@ -59,12 +59,14 @@ module.exports = class WorkspaceUtils { } for (let p of product) { if (p.type === 'web') { - return p.repo.slice(p.repo.lastIndexOf('/') + 1).replace('.git', ''); + return { + name: p.repo.slice(p.repo.lastIndexOf('/') + 1).replace('.git', ''), + additional: p.additional.map(({name}) => name) + }; } + return null; } - return null; } - /** * Calls the clone repo generator with the name of the repo. * @param {string} repo Repository name. From b5c4c2316f966e6fad7239a242004fa9fc8b7658 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 17 Sep 2020 08:20:39 +0200 Subject: [PATCH 27/65] Refactor- extend tests phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 46 +++++++++++++++++------------ test/TestUtils.js | 2 +- test/setup-workspace.test.js | 43 +++++++++++++++++++++++++-- 3 files changed, 68 insertions(+), 23 deletions(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index e21290ef..47924a9d 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -149,7 +149,7 @@ class Generator extends Base { } _customizeWorkspace() { - const defaultApp = WorkspaceUtils.findDefaultApp(this.product); + const defaultApp = this.defaultApp; if (defaultApp) { this.fs.copyTpl(this.templatePath('start_defaultapp.tmpl.xml'), this.destinationPath(`${this.cwd}/.idea/runConfigurations/start_${defaultApp}.xml`), { defaultApp: defaultApp @@ -226,6 +226,12 @@ class Generator extends Base { .then(this._ifExecutable.bind(this, 'docker-compose', () => SpawnUtils.spawnOrAbort('./docker-backup', 'restore', this.cwd, true), 'please execute: "./docker-backup restore" manually')); } + /** + * Checks whether a command/cli tool is installed in the current system and executes provided command. + * @param {*} cmd Command to execute + * @param {*} ifExists + * @param {*} extraMessage + */ _ifExecutable(cmd, ifExists, extraMessage = '') { const paths = process.env.PATH.split(path.delimiter); const pathExt = (process.env.PATHEXT || '').split(path.delimiter); @@ -250,6 +256,19 @@ class Generator extends Base { return ifExists(); } + /** + * Runs `docker-compose build` if `docker-compose.yml` exists in the workspace and user has installed `dokcer-compose` cli. + */ + _buildDockerCompose() { + const file = this.fs.read(this.destinationPath(`${this.cwd}/docker-compose.yml`), {defaults: ''}); + const isNotEmpty = file.trim().length > 0; + if (isNotEmpty && !this.options.skip.includes('build')) { + return this._ifExecutable('docker-compose', () => SpawnUtils.spawnOrAbort('docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); + } + + return null; + } + writing() { this.hasErrors = false; @@ -257,23 +276,12 @@ class Generator extends Base { .then(GeneratorUtils.mkdir(this.cwd)) .then(this._getProduct.bind(this)) .then((repos) => Promise.all(repos.map((r) => WorkspaceUtils.cloneRepo(r.repo, r.branch, null, '', this.cwd, this.cloneSSH)))) - .then(() => GeneratorUtils.yo('workspace', { - defaultApp: this.defaultApp, - skipNextStepsLog: true // skip "next steps" logs from yo phovea:workspace - }, null, this.cwd, this.env.adapter)) - // .then(this._customizeWorkspace.bind(this)) - // .then(this._downloadDataFiles.bind(this)) - // .then(() => this.options.skip.includes('install') ? null : SpawnUtils.spawnOrAbort('npm', 'install', this.cwd, true)) - // .then(this._downloadBackupFiles.bind(this)) - // .then(() => { - // const l = this.fs.read(this.destinationPath(`${this.cwd}/docker-compose.yml`), { - // defaults: '' - // }); - // if (l.trim().length > 0 && !this.options.skip.includes('build')) { - // return this._ifExecutable('docker-compose', () => SpawnUtils.spawnOrAbort('docker-compose', 'build', this.cwd, true), ' please run "docker-compose build" manually"'); - // } - // return null; - // }) + .then(() => GeneratorUtils.yo('workspace', {defaultApp: this.defaultApp, skipNextStepsLog: true}, null, this.cwd, this.env.adapter)) + .then(this._customizeWorkspace.bind(this)) + .then(this._downloadDataFiles.bind(this)) + .then(() => this.options.skip.includes('install') ? null : SpawnUtils.spawnOrAbort('npm', 'install', this.cwd, true)) + .then(this._downloadBackupFiles.bind(this)) + .then(this._buildDockerCompose.bind(this)) .catch((msg) => { this.log('\r\n'); this.log(chalk.red(msg)); @@ -281,7 +289,7 @@ class Generator extends Base { }); } - _end() { + end() { if (this.hasErrors) { return; // skip next steps on errors } diff --git a/test/TestUtils.js b/test/TestUtils.js index 7c1045c2..3425edeb 100644 --- a/test/TestUtils.js +++ b/test/TestUtils.js @@ -8,7 +8,7 @@ module.exports = class TestUtils { * @param {string} type Type of template, plain or processed */ static templatePath(subgenerator, fileName, type = '') { - return path.join(__dirname, `../generators/${subgenerator}/templates/${type}/${fileName}`); + return path.join(__dirname, `../generators/${subgenerator}/templates/${type ? type + '/' : ''}${fileName}`); } }; \ No newline at end of file diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js index 42c6dc53..98db4783 100644 --- a/test/setup-workspace.test.js +++ b/test/setup-workspace.test.js @@ -8,7 +8,9 @@ const WorkspaceUtils = require('../utils/WorkspaceUtils'); const assert = require('yeoman-assert'); const fs = require('fs-extra'); const RepoUtils = require('../utils/RepoUtils'); -const {yo} = require('../utils/GeneratorUtils'); +const TestUtils = require('./TestUtils'); +const SpawnUtils = require('../utils/SpawnUtils'); +const {template} = require('lodash'); /** * Directory name to run the generator @@ -38,10 +40,18 @@ describe('generator setup-workspace', () => { const phoveaProduct = fs.readJSONSync(path.join(__dirname, `templates/phovea_product_dummy.json`)); beforeAll(() => { WorkspaceUtils.cloneRepo = jest.fn() - .mockImplementationOnce((repo, branch, extras, dir, cwd) => fs.writeJson(cwd + '/phovea_product.json', phoveaProduct)) // first call + .mockImplementationOnce((repo, branch, extras, dir, cwd) => { + fs.mkdirSync('dummy/templates/api/deploy/api', {recursive: true}); + fs.writeFileSync('dummy/templates/api/deploy/api/Dockerfile', 'dummy_content'); + + fs.mkdirSync('dummy/templates/web/deploy/web', {recursive: true}); + fs.writeFileSync('dummy/templates/web/deploy/web/Dockerfile', 'dummy_content'); + return fs.writeJSON(cwd + '/phovea_product.json', phoveaProduct); + }) // first call .mockImplementation(() => Promise.resolve(null)); // just resolve promise after the firts call GeneratorUtils.yo = jest.fn(); + SpawnUtils.spawnOrAbort = jest.fn(); return setupWorkspace(); }); @@ -125,7 +135,7 @@ describe('generator setup-workspace', () => { assert.jsonFileContent('dummy/.yo-rc-workspace.json', content); }); - it('calls GeneratorUtils.yo(..args) with the correct arguments', () => { + it('calls `yo phovea:workspace` with the correct arguments', () => { const yoArgs = GeneratorUtils.yo.mock.calls; expect(yoArgs.length).toBe(1); const cmd = yoArgs[0][0]; @@ -133,7 +143,34 @@ describe('generator setup-workspace', () => { const options = yoArgs[0][1]; expect(options).toMatchObject({'defaultApp': 'ordino_public', 'skipNextStepsLog': true}); + + const args = yoArgs[0][2]; + expect(args).toBe(null); + + const cwd = yoArgs[0][3]; + expect(cwd).toBe('dummy'); }); + it('copies `.idea` template files', () => { + let fileContent = template(fs.readFileSync(TestUtils.templatePath('setup-workspace', 'start_defaultapp.tmpl.xml')))({defaultApp: 'ordino_public'}); + assert.file('dummy/.idea/runConfigurations/start_ordino_public.xml'); + assert.fileContent('dummy/.idea/runConfigurations/start_ordino_public.xml', fileContent); + + fileContent = template(fs.readFileSync(TestUtils.templatePath('setup-workspace', 'lint_defaultapp.tmpl.xml')))({defaultApp: 'ordino_public'}); + assert.file('dummy/.idea/runConfigurations/lint_ordino_public.xml'); + assert.fileContent('dummy/.idea/runConfigurations/lint_ordino_public.xml', fileContent); + }); + it('copies products\' template files into the workspace', () => { + assert.file('dummy/deploy/api/Dockerfile'); + assert.file('dummy/deploy/web/Dockerfile'); + }); + + it('calls `SpawnUtils.spawnOrAbort(...args)` with correct args', () => { + const [cmd, args, cwd, verbose] = SpawnUtils.spawnOrAbort.mock.calls[0]; + expect(cmd).toBe('npm'); + expect(args).toBe('install'); + expect(cwd).toBe('dummy'); + expect(verbose).toBe(true); + }); }); From 3ffe83fb0d719101c12a3cc8874833e2921b2148 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 17 Sep 2020 08:45:18 +0200 Subject: [PATCH 28/65] Add comments phovea/generator-phovea#425 --- generators/setup-workspace/index.js | 37 +++++++++++++++++++---------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index 47924a9d..630d4437 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -43,7 +43,6 @@ function toDownloadName(url) { } return url.substring(url.lastIndexOf('/') + 1); } - class Generator extends Base { constructor(args, options) { @@ -97,6 +96,9 @@ class Generator extends Base { }); } + /** + * Removes/renames files of the cloned product that conflict with the workspace files. + */ _removeUnnecessaryProductFiles() { try { fs.unlinkSync(this.cwd + '/.yo-rc.json'); @@ -108,15 +110,18 @@ class Generator extends Base { } /** - * Copies the template files of the product in the workspace - * @param {string} templatePath + * Copies/merges the template files of the product into the workspace. + * @param {string} templatePath Path to the template directory of the product. */ _copyProductTemplates(templatePath) { const dirs = fs.readdirSync(templatePath).filter(f => fs.statSync(path.join(templatePath, f)).isDirectory()); dirs.forEach((dir) => fs.copySync(templatePath + '/' + dir, this.destinationPath(this.cwd))); } - + /** + * Clones the product into the workspace and generates the `yo-rc-workspace.json` file. + * @returns The parsed phovea_product.json file. + */ _getProduct() { return WorkspaceUtils.cloneRepo(this.productName, this.options.branch || 'master', null, '.', this.cwd, this.cloneSSH) .then(() => { @@ -135,6 +140,10 @@ class Generator extends Base { }); } + /** + * Generates `yo-rc-workspace.json` file + * @param {string} defaultApp + */ _createYoRcWorkspace(defaultApp) { const yoWorkspacePath = this.destinationPath(`${this.cwd}/.yo-rc-workspace.json`); if (!fs.existsSync(yoWorkspacePath && this.defaultApp)) { @@ -148,14 +157,16 @@ class Generator extends Base { } } + /** + * Copies the generator's and the product's template files into the workspace. + */ _customizeWorkspace() { - const defaultApp = this.defaultApp; - if (defaultApp) { - this.fs.copyTpl(this.templatePath('start_defaultapp.tmpl.xml'), this.destinationPath(`${this.cwd}/.idea/runConfigurations/start_${defaultApp}.xml`), { - defaultApp: defaultApp + if (this.defaultApp) { + this.fs.copyTpl(this.templatePath('start_defaultapp.tmpl.xml'), this.destinationPath(`${this.cwd}/.idea/runConfigurations/start_${this.defaultApp}.xml`), { + defaultApp: this.defaultApp }); - this.fs.copyTpl(this.templatePath('lint_defaultapp.tmpl.xml'), this.destinationPath(`${this.cwd}/.idea/runConfigurations/lint_${defaultApp}.xml`), { - defaultApp: defaultApp + this.fs.copyTpl(this.templatePath('lint_defaultapp.tmpl.xml'), this.destinationPath(`${this.cwd}/.idea/runConfigurations/lint_${this.defaultApp}.xml`), { + defaultApp: this.defaultApp }); } @@ -228,9 +239,9 @@ class Generator extends Base { /** * Checks whether a command/cli tool is installed in the current system and executes provided command. - * @param {*} cmd Command to execute - * @param {*} ifExists - * @param {*} extraMessage + * @param {string} cmd Cmd i.e, `docker-compose`. + * @param {Function} ifExists Spawn this command if the cmd is executable. + * @param {string} extraMessage Message to log if the cmd was not found. */ _ifExecutable(cmd, ifExists, extraMessage = '') { const paths = process.env.PATH.split(path.delimiter); From 20c7c0fd21f7b5a461ea66f5046d9cc11c3ffee2 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 13:25:46 +0200 Subject: [PATCH 29/65] Remove `chalk.default()` since it does not exist phovea/generator-phovea#428 --- generators/_init-web/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 432ee571..7649de43 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -156,9 +156,9 @@ class Generator extends Base { if (fs.existsSync(this.destinationPath(this.cwd + 'phovea.js'))) { this.log('\r\n'); this.log(chalk.red(`ACTION REQUIRED!`)); - this.log(chalk.default(`Please migrate the content of`), chalk.yellow(`phovea.js`), chalk.default(`to`), chalk.yellow(`/src/phovea.ts`) + chalk.default(` now!`)); - this.log(chalk.default(`Afterwards you can remove the`), chalk.yellow(`phovea.js`), chalk.default(`file from this plugin repository.`)); - this.log(chalk.default(`If you do not migrate the content the registered extension points will be unavailable.`)); + this.log(chalk.green(`Please migrate the content of`), chalk.yellow(`phovea.js`), chalk.green(`to`), chalk.yellow(`/src/phovea.ts`) + chalk.green(` now!`)); + this.log(chalk.green(`Afterwards you can remove the`), chalk.yellow(`phovea.js`), chalk.green(`file from this plugin repository.`)); + this.log(chalk.green(`If you do not migrate the content the registered extension points will be unavailable.`)); } } } From 10517bc660aa34f342b4d7c27c1b1e026863ec88 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 13:28:55 +0200 Subject: [PATCH 30/65] Run npm install sync --- generators/_init-web/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 7649de43..b2631d2e 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -5,6 +5,7 @@ const Base = require('yeoman-generator'); const {writeTemplates, patchPackageJSON, stringifyAble} = require('../../utils'); const fs = require('fs'); const NpmUtils = require('../../utils/NpmUtils'); +const SpawnUtils = require('../../utils/SpawnUtils'); const known = () => require('../../utils/known'); @@ -147,8 +148,7 @@ class Generator extends Base { install() { if (this.options.options.install) { - const options = this.cwd ? {cwd: this.cwd} : {}; - this.spawnCommand("npm", ["install"], options); + SpawnUtils.spawn('npm', 'install', this.cwd, true); } } From bbda376c5c6540371388cd0926e416ca867927ab Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 13:29:27 +0200 Subject: [PATCH 31/65] Fix spawn function impl phovea/generator-phovea#428 --- utils/SpawnUtils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/SpawnUtils.js b/utils/SpawnUtils.js index 700e6a64..a185659c 100644 --- a/utils/SpawnUtils.js +++ b/utils/SpawnUtils.js @@ -32,7 +32,7 @@ module.exports = class SpawnUtils { */ static spawn(cmd, argline, cwd, verbose) { const options = { - ...{cwd: cwd} || {}, + ...cwd ? {cwd} : {}, ...verbose ? {stdio: 'inherit'} : {} }; From 6963e17349da14bb5e245341b55391b09d17b25d Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 13:45:16 +0200 Subject: [PATCH 32/65] Rename function `spawn` to `spawnSync` phovea/generator-phovea#428 --- generators/_init-web/index.js | 2 +- generators/clone-repo/index.js | 2 +- test/clone-repo.test.js | 14 +++++++------- utils/SpawnUtils.js | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index b2631d2e..4064e6e1 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -148,7 +148,7 @@ class Generator extends Base { install() { if (this.options.options.install) { - SpawnUtils.spawn('npm', 'install', this.cwd, true); + SpawnUtils.spawnSync('npm', 'install', this.cwd, true); } } diff --git a/generators/clone-repo/index.js b/generators/clone-repo/index.js index 338f9a61..ab76af82 100644 --- a/generators/clone-repo/index.js +++ b/generators/clone-repo/index.js @@ -108,7 +108,7 @@ class Generator extends Base { const line = `ls-remote --tags ${repoUrl}`; this.log(chalk.white(`fetching possible version tags:`), `git ${line}`); - const r = SpawnUtils.spawn('git', line.split(/ +/), this.cwd); + const r = SpawnUtils.spawnSync('git', line.split(/ +/), this.cwd); if (SpawnUtils.failed(r)) { this.log(chalk.red(`failed to fetch list of tags from git repository`), `status code: ${r.status}`); diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js index 6e1de8e7..0359b418 100644 --- a/test/clone-repo.test.js +++ b/test/clone-repo.test.js @@ -77,8 +77,8 @@ describe('call clone-repo with an advanced version tag', () => { beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); - SpawnUtils.spawn = jest.fn(); - SpawnUtils.spawn.mockImplementation(() => { + SpawnUtils.spawnSync = jest.fn(); + SpawnUtils.spawnSync.mockImplementation(() => { return { status: 0, stdout: ` @@ -95,7 +95,7 @@ describe('call clone-repo with an advanced version tag', () => { }); it('calls function spawnOrAbort() once with the the correctly resolved version tag', () => { - expect(SpawnUtils.spawn.mock.calls.length).toBe(1); + expect(SpawnUtils.spawnSync.mock.calls.length).toBe(1); const cmd = SpawnUtils.spawnOrAbort.mock.calls[0][0]; expect(cmd).toBe('git'); @@ -112,8 +112,8 @@ describe('call clone-repo with an advanced version tag and no remote', () => { beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); SpawnUtils.abort = jest.fn(); - SpawnUtils.spawn = jest.fn(); - SpawnUtils.spawn.mockImplementation(() => { + SpawnUtils.spawnSync = jest.fn(); + SpawnUtils.spawnSync.mockImplementation(() => { return { status: 128, stderr: `some error` @@ -140,8 +140,8 @@ describe('call clone-repo with an advanced version tag that does not resolve to beforeAll(() => { SpawnUtils.spawnOrAbort = jest.fn(); SpawnUtils.abort = jest.fn(); - SpawnUtils.spawn = jest.fn(); - SpawnUtils.spawn.mockImplementation(() => { + SpawnUtils.spawnSync = jest.fn(); + SpawnUtils.spawnSync.mockImplementation(() => { return { status: 0, stdout: ` diff --git a/utils/SpawnUtils.js b/utils/SpawnUtils.js index a185659c..94222328 100644 --- a/utils/SpawnUtils.js +++ b/utils/SpawnUtils.js @@ -11,7 +11,7 @@ module.exports = class SpawnUtils { * @param {string} cwd The directory in Which the command should be excecuted. */ static spawnOrAbort(cmd, argline, cwd, verbose) { - const result = SpawnUtils.spawn(cmd, argline, cwd, verbose); + const result = SpawnUtils.spawnSync(cmd, argline, cwd, verbose); const stdout = result.stdout; if (SpawnUtils.failed(result)) { console.log(result.stderr.toString()); @@ -30,7 +30,7 @@ module.exports = class SpawnUtils { * @param {string | string[]} argline Arguments to execute the command with. * @param {string} cwd The directory in Which the command should be excecuted. */ - static spawn(cmd, argline, cwd, verbose) { + static spawnSync(cmd, argline, cwd, verbose) { const options = { ...cwd ? {cwd} : {}, ...verbose ? {stdio: 'inherit'} : {} From 4a4a3df9d92883579a360698c28aee3a7e34a451 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 14:12:44 +0200 Subject: [PATCH 33/65] Extend test of the init-lib sub-generator phovea/generator-phovea#428 --- test/init-lib.test.js | 50 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/test/init-lib.test.js b/test/init-lib.test.js index fc6e7ed7..e5724366 100644 --- a/test/init-lib.test.js +++ b/test/init-lib.test.js @@ -7,6 +7,7 @@ const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); const {template} = require('lodash'); +const SpawnUtils = require('../utils/SpawnUtils'); /** * Directory name to run the generator @@ -36,8 +37,16 @@ const unExpectedFiles = [ 'index.js' ]; +/** + * Run yo phovea:init-lib in dir + */ +const runInitLib = () => helpers + .run(path.join(__dirname, '../generators/init-lib')) + .withGenerators(GENERATOR_DEPENDENCIES) + .inDir(path.join(__dirname, target), () => null); + -describe('generate lib plugin with default prompt values', () => { +describe('Generate lib plugin with default prompt values', () => { /** * package.tmpl.json template of the _init-web subgenerator @@ -50,10 +59,7 @@ describe('generate lib plugin with default prompt values', () => { const initWebTsConfig = fse.readJSONSync(TestUtils.templatePath('_init-web', 'tsconfig.json', 'plain')); beforeAll(() => { - return helpers - .run(path.join(__dirname, '../generators/init-lib')) - .inDir(path.join(__dirname, target), () => null) - .withGenerators(GENERATOR_DEPENDENCIES); + return runInitLib(); }); afterAll(() => { @@ -100,11 +106,7 @@ describe('Generate plugin with name `phovea_core`', () => { }; beforeAll(() => { - return helpers - .run(path.join(__dirname, '../generators/init-lib')) - .inDir(path.join(__dirname, target), () => null) - .withPrompts(prompts) - .withGenerators(GENERATOR_DEPENDENCIES); + return runInitLib().withPrompts(prompts); }); afterAll(() => { @@ -116,3 +118,31 @@ describe('Generate plugin with name `phovea_core`', () => { assert.fileContent('phovea_registry.js', phoveaRegistryTmpl); }); }); + +describe('Test options of yo phovea:init-lib', () => { + + const prompts = { + name: 'phovea_core' + }; + + const options = { + install: true + }; + + beforeAll(() => { + SpawnUtils.spawnSync = jest.fn(); + return runInitLib() + .withPrompts(prompts) + .withOptions(options); + }); + + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + + it('runs npm install', () => { + expect(SpawnUtils.spawnSync.mock.calls.length).toBe(1); + const [cmd, args, cwd, verbose] = SpawnUtils.spawnSync.mock.calls[0]; + expect([cmd, args, cwd, verbose]).toStrictEqual(['npm', 'install', '', true]); + }); +}); \ No newline at end of file From 4fab4225aabe5481114f28fbc4d0bbd4df58b42a Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 15:58:53 +0200 Subject: [PATCH 34/65] Extract and test function `toLibraryAliasMap` phovea/generator-phovea#428 --- generators/_init-hybrid/index.js | 5 ++-- generators/_init-web/index.js | 25 ++-------------- test/RepoUtils.test.js | 51 ++++++++++++++++++++++++++++++++ utils/RepoUtils.js | 31 +++++++++++++++++-- 4 files changed, 85 insertions(+), 27 deletions(-) diff --git a/generators/_init-hybrid/index.js b/generators/_init-hybrid/index.js index 9209b476..0861e145 100644 --- a/generators/_init-hybrid/index.js +++ b/generators/_init-hybrid/index.js @@ -1,7 +1,8 @@ 'use strict'; const Base = require('../../utils').Base; const known = () => require('../../utils/known'); -const {toLibraryAliasMap, toLibraryExternals} = require('../_init-web'); +const {toLibraryExternals} = require('../_init-web'); +const RepoUtils = require('../../utils/RepoUtils'); class Generator extends Base { @@ -31,7 +32,7 @@ class Generator extends Base { this.config.set('modules', props.modules); this.config.set('libraries', props.libraries); } - this.config.set('libraryAliases', toLibraryAliasMap.call(this, this.config.get('modules'), this.config.get('libraries'))); + this.config.set('libraryAliases', RepoUtils.toLibraryAliasMap(this.config.get('modules'), this.config.get('libraries'))); this.config.set('libraryExternals', toLibraryExternals.call(this, this.config.get('modules'), this.config.get('libraries'))); }); } diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 4064e6e1..4d30c3aa 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -6,30 +6,10 @@ const {writeTemplates, patchPackageJSON, stringifyAble} = require('../../utils') const fs = require('fs'); const NpmUtils = require('../../utils/NpmUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); +const RepoUtils = require('../../utils/RepoUtils'); const known = () => require('../../utils/known'); -function toLibraryAliasMap(moduleNames = [], libraryNames = []) { - let r = {}; - moduleNames.forEach((m) => { - const plugin = known().plugin.byName(m); - if (!plugin) { - this.log('cant find plugin: ', m); - return; - } - libraryNames.push(...(plugin.libraries || [])); - }); - libraryNames.forEach((l) => { - const lib = known().lib.byName(l); - if (!lib) { - this.log('cant find library: ', l); - return; - } - _.merge(r, lib.aliases); - }); - return r; -} - function toLibraryExternals(moduleNames = [], libraryNames = []) { let r = []; moduleNames.forEach((m) => { @@ -101,7 +81,7 @@ class Generator extends Base { this.config.set('modules', props.modules); this.config.set('libraries', props.libraries); } - this.config.set('libraryAliases', toLibraryAliasMap.call(this, this.config.get('modules'), this.config.get('libraries'))); + this.config.set('libraryAliases', RepoUtils.toLibraryAliasMap(this.config.get('modules'), this.config.get('libraries'))); this.config.set('libraryExternals', toLibraryExternals.call(this, this.config.get('modules'), this.config.get('libraries'))); }); } @@ -164,5 +144,4 @@ class Generator extends Base { } module.exports = Generator; -module.exports.toLibraryAliasMap = toLibraryAliasMap; module.exports.toLibraryExternals = toLibraryExternals; diff --git a/test/RepoUtils.test.js b/test/RepoUtils.test.js index dbbecd9f..ed79eb60 100644 --- a/test/RepoUtils.test.js +++ b/test/RepoUtils.test.js @@ -136,4 +136,55 @@ describe('parse phovea_product.json', () => { it('resulting object has correct structure', () => { expect(RepoUtils.parsePhoveaProduct(dummyProduct)).toStrictEqual(result); }); +}); + + +describe('test toLibraryAliasMap()', () => { + + const mockedAliases = { + 'd3': "d3/d3", + 'font-awesome': 'fw/font-awesome' + }; + + jest.mock('../utils/known', () => { + return { + plugin: { + byName: () => { + return { + aliases: mockedAliases + }; + } + }, + lib: { + byName: () => { + return { + aliases: mockedAliases + }; + } + } + }; + }); + + + it('finds the correct aliases of the modules and libraries', () => { + const moduleNames = [ + 'phovea_core', + 'phovea_d3', + 'phovea_ui', + 'phovea_importer', + ]; + const libraryNames = [ + 'd3', + 'd3v5', + 'lineupjs', 'font-awesome', + 'bootstrap', 'select2', + 'd3', 'jquery', + ]; + expect(RepoUtils.toLibraryAliasMap(moduleNames, libraryNames)).toMatchObject(mockedAliases); + }); + + it('returns an empty object if no modules or libraries are provided', () => { + + expect(RepoUtils.toLibraryAliasMap([], [])).toMatchObject({}); + }); }); \ No newline at end of file diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js index 21f42756..e4db6196 100644 --- a/utils/RepoUtils.js +++ b/utils/RepoUtils.js @@ -1,4 +1,5 @@ -const known = require('./known'); +const known = () => require('./known'); +const _ = require('lodash'); module.exports = class RepoUtils { @@ -96,7 +97,7 @@ module.exports = class RepoUtils { } static toRepository(plugin, useSSH) { - const p = known.plugin.byName(plugin); + const p = known().plugin.byName(plugin); return useSSH ? RepoUtils.RtoSSHRepoUrl(p.repository) : RepoUtils.toHTTPRepoUrl(p.repository); } /** @@ -128,4 +129,30 @@ module.exports = class RepoUtils { }); return repos; } + + /** + * Finds the aliases of the selected modules and libraries. + * @param {string[]} moduleNames Array of modules, i.e, `['phovea_clue', 'phovea_core']` + * @param {string[]} libraryNames + */ + static toLibraryAliasMap(moduleNames = [], libraryNames = []) { + let r = {}; + moduleNames.forEach((m) => { + const plugin = known().plugin.byName(m); + if (!plugin) { + console.log('cant find plugin: ', m); + return; + } + libraryNames.push(...(plugin.libraries || [])); + }); + libraryNames.forEach((l) => { + const lib = known().lib.byName(l); + if (!lib) { + console.log('cant find library: ', l); + return; + } + _.merge(r, lib.aliases); + }); + return r; + } }; From 5559968f5a31c56feee489b1778a4d80adb82075 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 23 Sep 2020 18:12:27 +0200 Subject: [PATCH 35/65] Extract and test function `toLibraryExternals` phovea/generator-phovea#428 --- generators/_init-hybrid/index.js | 3 +- generators/_init-web/index.js | 27 +-------- test/RepoUtils.test.js | 99 +++++++++++++++++++++++--------- utils/RepoUtils.js | 38 ++++++++++-- 4 files changed, 106 insertions(+), 61 deletions(-) diff --git a/generators/_init-hybrid/index.js b/generators/_init-hybrid/index.js index 0861e145..2887413f 100644 --- a/generators/_init-hybrid/index.js +++ b/generators/_init-hybrid/index.js @@ -1,7 +1,6 @@ 'use strict'; const Base = require('../../utils').Base; const known = () => require('../../utils/known'); -const {toLibraryExternals} = require('../_init-web'); const RepoUtils = require('../../utils/RepoUtils'); class Generator extends Base { @@ -33,7 +32,7 @@ class Generator extends Base { this.config.set('libraries', props.libraries); } this.config.set('libraryAliases', RepoUtils.toLibraryAliasMap(this.config.get('modules'), this.config.get('libraries'))); - this.config.set('libraryExternals', toLibraryExternals.call(this, this.config.get('modules'), this.config.get('libraries'))); + this.config.set('libraryExternals', RepoUtils.toLibraryExternals(this.config.get('modules'), this.config.get('libraries'))); }); } diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 4d30c3aa..00b42b81 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -7,32 +7,8 @@ const fs = require('fs'); const NpmUtils = require('../../utils/NpmUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); const RepoUtils = require('../../utils/RepoUtils'); - const known = () => require('../../utils/known'); -function toLibraryExternals(moduleNames = [], libraryNames = []) { - let r = []; - moduleNames.forEach((m) => { - const plugin = known().plugin.byName(m); - if (!plugin) { - this.log('cant find plugin: ', m); - return; - } - r.push(...(plugin.externals || [])); - libraryNames.push(...(plugin.libraries || [])); - }); - libraryNames.forEach((l) => { - const lib = known().lib.byName(l); - if (!lib) { - this.log('cant find library: ', l); - return; - } - r.push(lib.name); - r.push(...(lib.externals || [])); - }); - return Array.from(new Set(r)); -} - class Generator extends Base { constructor(args, options) { @@ -82,7 +58,7 @@ class Generator extends Base { this.config.set('libraries', props.libraries); } this.config.set('libraryAliases', RepoUtils.toLibraryAliasMap(this.config.get('modules'), this.config.get('libraries'))); - this.config.set('libraryExternals', toLibraryExternals.call(this, this.config.get('modules'), this.config.get('libraries'))); + this.config.set('libraryExternals', RepoUtils.toLibraryExternals(this.config.get('modules'), this.config.get('libraries'))); }); } @@ -144,4 +120,3 @@ class Generator extends Base { } module.exports = Generator; -module.exports.toLibraryExternals = toLibraryExternals; diff --git a/test/RepoUtils.test.js b/test/RepoUtils.test.js index ed79eb60..336c45c4 100644 --- a/test/RepoUtils.test.js +++ b/test/RepoUtils.test.js @@ -2,6 +2,51 @@ const RepoUtils = require('../utils/RepoUtils'); const fs = require('fs-extra'); const path = require('path'); +const known = require('../utils/known'); + +jest.mock('../utils/known', () => { + return { + plugin: { + byName: jest.fn() + }, + lib: { + byName: jest.fn() + } + }; +}); + +const mockedPlugin = { + name: 'phovea_core', + libraries: [ + "d3" + ], + externals: [ + 'bootstrap-sass' + ] +}; + +const mockedLib = { + name: 'font-awesome', + libraries: [ + "jquery", + ], + externals: [ + 'marked' + ], + aliases: { + 'd3': "d3/d3", + 'font-awesome': 'fw/font-awesome' + } + +}; + +known.plugin.byName.mockImplementation(() => { + return mockedPlugin; +}); +known.lib.byName.mockImplementation(() => { + return mockedLib; +}); + describe('transfroms repo name to an https url', () => { @@ -139,33 +184,12 @@ describe('parse phovea_product.json', () => { }); -describe('test toLibraryAliasMap()', () => { - - const mockedAliases = { +describe('test toLibraryAliasMap works as expected', () => { + const aliases = { 'd3': "d3/d3", 'font-awesome': 'fw/font-awesome' }; - jest.mock('../utils/known', () => { - return { - plugin: { - byName: () => { - return { - aliases: mockedAliases - }; - } - }, - lib: { - byName: () => { - return { - aliases: mockedAliases - }; - } - } - }; - }); - - it('finds the correct aliases of the modules and libraries', () => { const moduleNames = [ 'phovea_core', @@ -176,15 +200,34 @@ describe('test toLibraryAliasMap()', () => { const libraryNames = [ 'd3', 'd3v5', - 'lineupjs', 'font-awesome', - 'bootstrap', 'select2', - 'd3', 'jquery', + 'lineupjs', + 'bootstrap', + 'd3', ]; - expect(RepoUtils.toLibraryAliasMap(moduleNames, libraryNames)).toMatchObject(mockedAliases); + expect(RepoUtils.toLibraryAliasMap(moduleNames, libraryNames)).toMatchObject(aliases); }); it('returns an empty object if no modules or libraries are provided', () => { - expect(RepoUtils.toLibraryAliasMap([], [])).toMatchObject({}); }); +}); + +describe('test toLibraryExternals', () => { + + it('finds the correct extrernals of the provided modules and libraries', () => { + const moduleNames = [ + 'phovea_core', + 'phovea_d3', + 'phovea_ui', + 'phovea_importer', + ]; + const libraryNames = [ + 'd3', + 'd3v5', + 'lineupjs', + 'bootstrap', + 'd3', + ]; + expect(RepoUtils.toLibraryExternals(moduleNames, libraryNames)).toStrictEqual(['bootstrap-sass', 'font-awesome', 'marked']); + }); }); \ No newline at end of file diff --git a/utils/RepoUtils.js b/utils/RepoUtils.js index e4db6196..1a9a8138 100644 --- a/utils/RepoUtils.js +++ b/utils/RepoUtils.js @@ -1,4 +1,4 @@ -const known = () => require('./known'); +const known = require('./known'); const _ = require('lodash'); module.exports = class RepoUtils { @@ -97,7 +97,7 @@ module.exports = class RepoUtils { } static toRepository(plugin, useSSH) { - const p = known().plugin.byName(plugin); + const p = known.plugin.byName(plugin); return useSSH ? RepoUtils.RtoSSHRepoUrl(p.repository) : RepoUtils.toHTTPRepoUrl(p.repository); } /** @@ -133,12 +133,12 @@ module.exports = class RepoUtils { /** * Finds the aliases of the selected modules and libraries. * @param {string[]} moduleNames Array of modules, i.e, `['phovea_clue', 'phovea_core']` - * @param {string[]} libraryNames + * @param {string[]} libraryNames Array of libraries, i.e, `['d3', 'font-awesome]` */ static toLibraryAliasMap(moduleNames = [], libraryNames = []) { let r = {}; moduleNames.forEach((m) => { - const plugin = known().plugin.byName(m); + const plugin = known.plugin.byName(m); if (!plugin) { console.log('cant find plugin: ', m); return; @@ -146,7 +146,7 @@ module.exports = class RepoUtils { libraryNames.push(...(plugin.libraries || [])); }); libraryNames.forEach((l) => { - const lib = known().lib.byName(l); + const lib = known.lib.byName(l); if (!lib) { console.log('cant find library: ', l); return; @@ -155,4 +155,32 @@ module.exports = class RepoUtils { }); return r; } + + /** + * Finds the externals of the selected modules and libraries. + * @param {string[]} moduleNames Array of modules, i.e, `['phovea_clue', 'phovea_core']` + * @param {string[]} libraryNames Array of libraries, i.e, `['d3', 'font-awesome]` + */ + static toLibraryExternals(moduleNames = [], libraryNames = []) { + let r = []; + moduleNames.forEach((m) => { + const plugin = known.plugin.byName(m); + if (!plugin) { + console.log('cant find plugin: ', m); + return; + } + r.push(...(plugin.externals || [])); + libraryNames.push(...(plugin.libraries || [])); + }); + libraryNames.forEach((l) => { + const lib = known.lib.byName(l); + if (!lib) { + console.log('cant find library: ', l); + return; + } + r.push(lib.name); + r.push(...(lib.externals || [])); + }); + return Array.from(new Set(r)); + } }; From ff09962131aa358ef2b36965f53a311a8a292ac9 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 24 Sep 2020 09:55:05 +0200 Subject: [PATCH 36/65] Change text color phovea/generator-phovea#425 --- generators/_init-web/index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 00b42b81..1c4bd008 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -58,7 +58,7 @@ class Generator extends Base { this.config.set('libraries', props.libraries); } this.config.set('libraryAliases', RepoUtils.toLibraryAliasMap(this.config.get('modules'), this.config.get('libraries'))); - this.config.set('libraryExternals', RepoUtils.toLibraryExternals(this.config.get('modules'), this.config.get('libraries'))); + this.config.set('libraryExternals', RepoUtils.toLibraryExternals(this.config.get('modules'), this.config.get('libraries'))); }); } @@ -112,9 +112,9 @@ class Generator extends Base { if (fs.existsSync(this.destinationPath(this.cwd + 'phovea.js'))) { this.log('\r\n'); this.log(chalk.red(`ACTION REQUIRED!`)); - this.log(chalk.green(`Please migrate the content of`), chalk.yellow(`phovea.js`), chalk.green(`to`), chalk.yellow(`/src/phovea.ts`) + chalk.green(` now!`)); - this.log(chalk.green(`Afterwards you can remove the`), chalk.yellow(`phovea.js`), chalk.green(`file from this plugin repository.`)); - this.log(chalk.green(`If you do not migrate the content the registered extension points will be unavailable.`)); + this.log(chalk.white(`Please migrate the content of`), chalk.yellow(`phovea.js`), chalk.white(`to`), chalk.yellow(`/src/phovea.ts`) + chalk.white(` now!`)); + this.log(chalk.white(`Afterwards you can remove the`), chalk.yellow(`phovea.js`), chalk.white(`file from this plugin repository.`)); + this.log(chalk.white(`If you do not migrate the content the registered extension points will be unavailable.`)); } } } From c5d32ab503b6225692d5bca0254d5ead8687aa1a Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 24 Sep 2020 10:06:52 +0200 Subject: [PATCH 37/65] Remove jenkins file from product templates phovea/generator-phovea#425 --- .../init-product/templates/plain/Jenkinsfile | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 generators/init-product/templates/plain/Jenkinsfile diff --git a/generators/init-product/templates/plain/Jenkinsfile b/generators/init-product/templates/plain/Jenkinsfile deleted file mode 100644 index 44e97420..00000000 --- a/generators/init-product/templates/plain/Jenkinsfile +++ /dev/null @@ -1,46 +0,0 @@ -node { - stage('Checkout') { - checkout scm - } - - stage('Before Install') { - def nodeHome = tool 'node-v7' - env.PATH="${env.PATH}:${nodeHome}/bin" - def dockerHome = tool 'docker' - env.PATH="${env.PATH}:${dockerHome}/bin" - } - - stage('Install') { - sh 'node -v' - sh 'npm --version' - sh 'docker --version' - sh 'npm install' - } - - stage('Build') { - try { - withCredentials([usernameColonPassword(credentialsId: 'PHOVEA_GITHUB_CREDENTIALS', variable: 'PHOVEA_GITHUB_CREDENTIALS')]) { - docker.withRegistry("https://922145058410.dkr.ecr.eu-central-1.amazonaws.com", "ecr:eu-central-1:PHOVEA_AWS_CREDENTIALS") { - docker.withRegistry("", "PHOVEA_DOCKER_HUB_CREDENTIALS") { - wrap([$class: 'Xvfb']) { - sh 'node build.js --skipTests --skipSaveImage --noDefaultTags --pushExtra=latest --pushTo=922145058410.dkr.ecr.eu-central-1.amazonaws.com/caleydo' - } - } - } - } - currentBuild.result = "SUCCESS" - } catch (e) { - // if any exception occurs, mark the build as failed - currentBuild.result = 'FAILURE' - throw e - } finally { - // always clean up - sh 'npm prune' - sh 'rm node_modules -rf' - } - } - - stage('Post Build') { - archiveArtifacts artifacts: 'build/*' - } -} From b7bf82494de86e9888abfa4e91a97515af62bc57 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 24 Sep 2020 13:51:12 +0200 Subject: [PATCH 38/65] Extract and test function `buildPossibleAdditionalPlugins` phovea/generator-phovea#425 --- generators/init-product/index.js | 15 +------- test/WorkspaceUtils.test.js | 64 +++++++++++++++++++++++++++++++- utils/WorkspaceUtils.js | 15 ++++++++ 3 files changed, 80 insertions(+), 14 deletions(-) diff --git a/generators/init-product/index.js b/generators/init-product/index.js index 52ca2f8c..274ce542 100644 --- a/generators/init-product/index.js +++ b/generators/init-product/index.js @@ -3,23 +3,12 @@ */ const Base = require('yeoman-generator'); const {writeTemplates, patchPackageJSON} = require('../../utils'); -const RepoUtils = require('../../utils/RepoUtils'); +const WorkspaceUtils = require('../../utils/WorkspaceUtils'); const chalk = require('chalk'); const fs = require('fs'); const isRequired = (v) => v.toString().length > 0; -function buildPossibleAdditionalPlugins(type) { - const toDescription = (d) => ({ - value: {name: d.name, repo: RepoUtils.simplifyRepoUrl(d.repository)}, - name: `${d.name}: ${d.description}`, - short: d.name - }); - - const plugins = require('../../utils/known').plugin; - return ((type === 'web' || type === 'static') ? plugins.listWeb : plugins.listServer).map(toDescription); -} - class Generator extends Base { initializing() { @@ -95,7 +84,7 @@ class Generator extends Base { name: 'additional', type: 'checkbox', message: 'additional plugins: ', - choices: (act) => buildPossibleAdditionalPlugins(act.type) + choices: (act) => WorkspaceUtils.buildPossibleAdditionalPlugins(act.type) }, { name: 'custom', type: 'confirm', diff --git a/test/WorkspaceUtils.test.js b/test/WorkspaceUtils.test.js index dbd0a250..de95b901 100644 --- a/test/WorkspaceUtils.test.js +++ b/test/WorkspaceUtils.test.js @@ -1,6 +1,6 @@ 'use strict'; const WorkspaceUtils = require('../utils/WorkspaceUtils'); - +jest.mock('../utils/known'); describe('Find default app in product object', () => { @@ -53,4 +53,66 @@ describe('Find default app in product object', () => { }]; expect(WorkspaceUtils.findDefaultApp(product)).toMatchObject({name: 'ordino_public', additional: ['phovea_core', 'phovea_ui']}); }); +}); + +describe('Test `buildPossibleAdditionalPlugins()`', () => { + + + const known = require('../utils/known'); + known.plugin = { + listWeb: [{ + "name": "phovea_core", + "type": "lib", + "description": "Phovea Core Plugin", + "repository": "https://github.com/phovea/phovea_core.git", + "dependencies": { + "phovea_core": "^4.0.0" + }, + "develop": { + "dependencies": { + "phovea_core": "github:phovea/phovea_core#develop" + } + }, + "libraries": [] + },], + listServer: [{ + "name": "phovea_server", + "type": "service", + "description": "Phovea Server Plugin", + "repository": "https://github.com/phovea/phovea_server.git", + "requirements": { + "phovea_server": ">=5.0.1,<6.0.0" + }, + "develop": { + "requirements": { + "-e git+https://github.com/phovea/phovea_server.git": "@develop#egg=phovea_server" + } + } + }], + }; + it('builds additional web plugins', () => { + + const result = [{ + "name": "phovea_core: Phovea Core Plugin", + "short": "phovea_core", + "value": { + "name": "phovea_core", + "repo": "phovea/phovea_core", + }, + }]; + expect(WorkspaceUtils.buildPossibleAdditionalPlugins('web')).toMatchObject(result); + expect(WorkspaceUtils.buildPossibleAdditionalPlugins('static')).toMatchObject(result); + }); + + it('builds additional python plugins', () => { + const result = [{ + "name": "phovea_server: Phovea Server Plugin", + "short": "phovea_server", + "value": { + "name": "phovea_server", + "repo": "phovea/phovea_server", + }, + }]; + expect(WorkspaceUtils.buildPossibleAdditionalPlugins('python')).toMatchObject(result); + }); }); \ No newline at end of file diff --git a/utils/WorkspaceUtils.js b/utils/WorkspaceUtils.js index 1c71ce4c..01e46141 100644 --- a/utils/WorkspaceUtils.js +++ b/utils/WorkspaceUtils.js @@ -129,4 +129,19 @@ module.exports = class WorkspaceUtils { return WorkspaceUtils.resolveNeighbors(plugins, useSSH, types, destinationPath); } + + /** + * Creates an array of additional plugins depending on the type. + * @param {string} type Type of the plugin. `web, static, python` + */ + static buildPossibleAdditionalPlugins(type) { + const toDescription = (d) => ({ + value: {name: d.name, repo: RepoUtils.simplifyRepoUrl(d.repository)}, + name: `${d.name}: ${d.description}`, + short: d.name + }); + + const plugins = known.plugin; + return ((type === 'web' || type === 'static') ? plugins.listWeb : plugins.listServer).map(toDescription); + } }; From 661bf0bd3dc8f7f3aa54dcf68840b1db0024c107 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 24 Sep 2020 15:01:21 +0200 Subject: [PATCH 39/65] Add test for the init-product generator phovea/generator-phovea#425 --- test/init-product.test.js | 88 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 test/init-product.test.js diff --git a/test/init-product.test.js b/test/init-product.test.js new file mode 100644 index 00000000..ed819989 --- /dev/null +++ b/test/init-product.test.js @@ -0,0 +1,88 @@ + +'use strict'; +const path = require('path'); +const assert = require('yeoman-assert'); +const helpers = require('yeoman-test'); +const rimraf = require('rimraf'); +const fse = require('fs-extra'); +const TestUtils = require('./TestUtils'); +const {template} = require('lodash'); + +/** + * Directory name to run the generator + */ +const target = '../product'; + + +const expectedFiles = [ + '.gitattributes', + 'package.json', + 'build.js', + 'phovea_product.schema.json', + '.circleci/config.yml', + '.gitignore', + 'README.md', + '.editorconfig', + 'ISSUE_TEMPLATE.md', + 'LICENSE' +]; + +/** + * Subgenerators composed with the `init-slib` subgenerator. + */ +const GENERATOR_DEPENDENCIES = [ + '../generators/_node', + '../generators/_check-own-version', + '../generators/check-node-version', +]; + + +describe('generate a product with default prompt values', () => { + + const pluginName = 'wep_app'; + const pkg = JSON.parse(template(JSON.stringify(fse.readJSONSync(TestUtils.templatePath('init-product', 'package.tmpl.json'))))( + {name: pluginName})); + + const config = { + type: 'web', + label: 'Web App', + repo: 'phovea/wep_app', + branch: 'master', + additional: [{ + "name": "phovea_core", + "repo": "phovea/phovea_core", + }, { + "name": "phovea_ui", + "repo": "phovea/phovea_ui", + }] + }; + + beforeAll(() => { + return helpers + .run(path.join(__dirname, '../generators/init-product')) + .inDir(path.join(__dirname, target), () => null) + .withGenerators(GENERATOR_DEPENDENCIES) + .withPrompts({ + ...config, + name: pluginName, + }); + }); + + afterAll(() => { + rimraf.sync(path.join(__dirname, target)); + }); + + it('generates all expected files', () => { + assert.file(expectedFiles); + }); + + it('generates correct `package.json`', () => { + assert.jsonFileContent('package.json', {dependencies: pkg.dependencies}); + assert.jsonFileContent('package.json', {name: 'wep_app'}); + assert.jsonFileContent('package.json', {scripts: pkg.scripts}); + }); + + it('generates `phovea_product.json` with the correct service', () => { + assert.jsonFileContent('phovea_product.json', [config]); + }); +}); \ No newline at end of file From c3a9484051ef41fdaea06ca4ffd30a82bc74e96b Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 24 Sep 2020 15:29:08 +0200 Subject: [PATCH 40/65] Further refactoring phovea/generator-phovea#428 --- test/setup-workspace.test.js | 69 +++++++----------------------------- 1 file changed, 12 insertions(+), 57 deletions(-) diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js index 98db4783..2cf0dcaf 100644 --- a/test/setup-workspace.test.js +++ b/test/setup-workspace.test.js @@ -39,7 +39,9 @@ const setupWorkspace = () => helpers describe('generator setup-workspace', () => { const phoveaProduct = fs.readJSONSync(path.join(__dirname, `templates/phovea_product_dummy.json`)); beforeAll(() => { + // mock the clone-repo function WorkspaceUtils.cloneRepo = jest.fn() + // first call .mockImplementationOnce((repo, branch, extras, dir, cwd) => { fs.mkdirSync('dummy/templates/api/deploy/api', {recursive: true}); fs.writeFileSync('dummy/templates/api/deploy/api/Dockerfile', 'dummy_content'); @@ -47,7 +49,7 @@ describe('generator setup-workspace', () => { fs.mkdirSync('dummy/templates/web/deploy/web', {recursive: true}); fs.writeFileSync('dummy/templates/web/deploy/web/Dockerfile', 'dummy_content'); return fs.writeJSON(cwd + '/phovea_product.json', phoveaProduct); - }) // first call + }) .mockImplementation(() => Promise.resolve(null)); // just resolve promise after the firts call GeneratorUtils.yo = jest.fn(); @@ -63,53 +65,18 @@ describe('generator setup-workspace', () => { expect(WorkspaceUtils.cloneRepo.mock.calls.length).toBe(13); }); - it('clones product by calling `WorkspaceUtils.cloneRepo(...args)` with the correct args', () => { - const cloneRepoArgs = WorkspaceUtils.cloneRepo.mock.calls; - - const productRepo = cloneRepoArgs[0][0]; - expect(productRepo).toBe(product); - - const branch = cloneRepoArgs[0][1]; - expect(branch).toBe('develop'); - - const extra = cloneRepoArgs[0][2]; - expect(extra).toBe(null); - - const target = cloneRepoArgs[0][3]; - const currentDir = '.'; - expect(target).toBe(currentDir); - - const cwd = cloneRepoArgs[0][4]; - expect(cwd).toBe('dummy'); - - const ssh = cloneRepoArgs[0][5]; - expect(ssh).toBe(true); + const [productRepo, branch, extra, target, cwd, ssh] = WorkspaceUtils.cloneRepo.mock.calls[0]; + expect([productRepo, branch, extra, target, cwd, ssh]).toStrictEqual([product, 'develop', null, '.', 'dummy', true]); }); it('clones all plugins by calling `WorkspaceUtils.cloneRepo(...args)` with the correct args', () => { const cloneRepoArgs = WorkspaceUtils.cloneRepo.mock.calls; RepoUtils.parsePhoveaProduct(phoveaProduct).forEach((plugin, i) => { const index = i + 1; // skip the product cloning call - const name = cloneRepoArgs[index][0]; - expect(name).toBe(plugin.repo); - - const branch = cloneRepoArgs[index][1]; - expect(branch).toBe(plugin.branch); - - const extra = cloneRepoArgs[index][2]; - expect(extra).toBe(null); - - const target = cloneRepoArgs[index][3]; - expect(target).toBe(''); - - const cwd = cloneRepoArgs[index][4]; - expect(cwd).toBe('dummy'); - - const ssh = cloneRepoArgs[index][5]; - expect(ssh).toBe(true); + const [name, branch, extra, target, cwd, ssh] = cloneRepoArgs[index]; + expect([name, branch, extra, target, cwd, ssh]).toStrictEqual([plugin.repo, plugin.branch, null, '', 'dummy', true]); }); - }); it('creates valid `.yo-rc-workspace.json`', () => { @@ -136,19 +103,10 @@ describe('generator setup-workspace', () => { }); it('calls `yo phovea:workspace` with the correct arguments', () => { - const yoArgs = GeneratorUtils.yo.mock.calls; - expect(yoArgs.length).toBe(1); - const cmd = yoArgs[0][0]; - expect(cmd).toBe('workspace'); - - const options = yoArgs[0][1]; - expect(options).toMatchObject({'defaultApp': 'ordino_public', 'skipNextStepsLog': true}); - - const args = yoArgs[0][2]; - expect(args).toBe(null); - - const cwd = yoArgs[0][3]; - expect(cwd).toBe('dummy'); + const yoArguments = GeneratorUtils.yo.mock.calls; + expect(yoArguments.length).toBe(1); + const [generator, options, args, cwd] = yoArguments[0]; + expect([generator, options, args, cwd]).toStrictEqual(['workspace', {'defaultApp': 'ordino_public', 'skipNextStepsLog': true}, null, 'dummy']); }); it('copies `.idea` template files', () => { @@ -168,9 +126,6 @@ describe('generator setup-workspace', () => { it('calls `SpawnUtils.spawnOrAbort(...args)` with correct args', () => { const [cmd, args, cwd, verbose] = SpawnUtils.spawnOrAbort.mock.calls[0]; - expect(cmd).toBe('npm'); - expect(args).toBe('install'); - expect(cwd).toBe('dummy'); - expect(verbose).toBe(true); + expect([cmd, args, cwd, verbose]).toStrictEqual(['npm', 'install', 'dummy', true]); }); }); From f8615ded45ef1e7606ae55e754112dfef219c7a6 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 24 Sep 2020 17:12:45 +0200 Subject: [PATCH 41/65] Extract and test `stringifyAble` function phovea/generator-phovea#428 --- generators/_init-python/index.js | 5 +-- generators/_init-web/index.js | 5 +-- generators/add-extension/index.js | 4 +-- test/GeneratorUtils.test.js | 52 +++++++++++++++++++++++++++++++ utils/GeneratorUtils.js | 38 +++++++++++++++++++++- utils/index.js | 28 +---------------- 6 files changed, 98 insertions(+), 34 deletions(-) create mode 100644 test/GeneratorUtils.test.js diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index 652cd6a9..3b748bd9 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -1,9 +1,10 @@ 'use strict'; const _ = require('lodash'); const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON, stringifyAble} = require('../../utils'); +const {writeTemplates, patchPackageJSON} = require('../../utils'); const PipUtils = require('../../utils/PipUtils'); const NpmUtils = require('../../utils/NpmUtils'); +const GeneratorUtils = require('../../utils/GeneratorUtils'); const fs = require('fs'); const known = () => require('../../utils/known'); @@ -118,7 +119,7 @@ class Generator extends Base { // don't overwrite existing registry file if (!fs.existsSync(this.destinationPath(this.cwd + config.name.toLowerCase() + '/__init__.py'))) { - this.fs.copyTpl(this.templatePath('__init__.tmpl.py'), this.destinationPath(this.cwd + config.name.toLowerCase() + '/__init__.py'), stringifyAble(config)); + this.fs.copyTpl(this.templatePath('__init__.tmpl.py'), this.destinationPath(this.cwd + config.name.toLowerCase() + '/__init__.py'), GeneratorUtils.stringifyAble(config)); } this.fs.copy(this.templatePath('_gitignore'), this.destinationPath(this.cwd + '.gitignore')); this.fs.copy(this.templatePath('docs_gitignore'), this.destinationPath(this.cwd + 'docs/.gitignore')); diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 1c4bd008..78b226b1 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -2,11 +2,12 @@ const _ = require('lodash'); const chalk = require('chalk'); const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON, stringifyAble} = require('../../utils'); +const {writeTemplates, patchPackageJSON} = require('../../utils'); const fs = require('fs'); const NpmUtils = require('../../utils/NpmUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); const RepoUtils = require('../../utils/RepoUtils'); +const GeneratorUtils = require('../../utils/GeneratorUtils'); const known = () => require('../../utils/known'); class Generator extends Base { @@ -98,7 +99,7 @@ class Generator extends Base { // do not overwrite existing registry file if (!fs.existsSync(this.destinationPath(this.cwd + 'src/phovea.ts'))) { - this.fs.copyTpl(this.templatePath('phovea.tmpl.ts'), this.destinationPath(this.cwd + 'src/phovea.ts'), stringifyAble(config)); + this.fs.copyTpl(this.templatePath('phovea.tmpl.ts'), this.destinationPath(this.cwd + 'src/phovea.ts'), GeneratorUtils.stringifyAble(config)); } } diff --git a/generators/add-extension/index.js b/generators/add-extension/index.js index d9270cd2..5a179a1e 100644 --- a/generators/add-extension/index.js +++ b/generators/add-extension/index.js @@ -2,11 +2,11 @@ const Base = require('yeoman-generator'); const plugins = require('../../utils/types').plugin; -const stringifyAble = require('../../utils').stringifyAble; const path = require('path'); const fs = require('fs'); const glob = require('glob').sync; const chalk = require('chalk'); +const GeneratorUtils = require('../../utils/GeneratorUtils'); function toJSONFromText(text) { const r = {}; @@ -182,7 +182,7 @@ class Generator extends Base { this._writeConfig(this.cwd, basekey, arr); // inject new extension - const d = stringifyAble(this.new_); + const d = GeneratorUtils.stringifyAble(this.new_); if (this.basetype === 'web') { this._injectWebExtension(d, this.cwd); diff --git a/test/GeneratorUtils.test.js b/test/GeneratorUtils.test.js new file mode 100644 index 00000000..0795953e --- /dev/null +++ b/test/GeneratorUtils.test.js @@ -0,0 +1,52 @@ +'use strict'; +const GeneratorUtils = require('../utils/GeneratorUtils'); + + +describe('Test `stringifyInline()` correctly stringifies object', () => { + + + it('adds 1 space', () => { + const obj = {key1: 'value1', key2: 'value2'}; + const space = ' '; + const result = "{\n 'key1': 'value1',\n 'key2': 'value2'\n }"; + expect(GeneratorUtils.stringifyInline(obj, space)).toBe(result); + }); + + it('adds 2 spaces', () => { + const obj = {key1: 'value1', key2: 'value2'}; + const space = ' '; + const result = "{\n 'key1': 'value1',\n 'key2': 'value2'\n }"; + expect(GeneratorUtils.stringifyInline(obj, space)).toBe(result); + }); + + it('removes double quotes', () => { + const obj = {key1: 'value1', key2: 'value2'}; + const space = ' '; + const result = '{\n "key1": "value1",\n "key2": "value2"\n }'; + expect(GeneratorUtils.stringifyInline(obj, space)).not.toBe(result); + }); +}); + +describe('Test `stringifyAble()`', () => { + const config = { + type: 'slib', + modules: ['phovea_server'], + libraries: [], + sextensions: [], + }; + it('isWeb returns false', () => { + expect(GeneratorUtils.stringifyAble(config).isWeb('phovea_server')).toBe(false); + }); + + it('formats boolean to python boolean', () => { + expect(GeneratorUtils.stringifyAble(config).stringifyPython({key1: true, key2: false}, ' ')).toBe("{\n 'key1': True,\n 'key2': False\n }"); + }); + + it('returns stringify function', () => { + expect(GeneratorUtils.stringifyAble(config).stringify).toBe(GeneratorUtils.stringifyInline); + }); + + it('returns the config', () => { + expect(GeneratorUtils.stringifyAble(config)).toMatchObject(config); + }); +}); \ No newline at end of file diff --git a/utils/GeneratorUtils.js b/utils/GeneratorUtils.js index 56d4f305..8b87efcc 100644 --- a/utils/GeneratorUtils.js +++ b/utils/GeneratorUtils.js @@ -28,7 +28,7 @@ module.exports = class GeneratorUtils { const _args = Array.isArray(args) ? args.join(' ') : args || ''; return new Promise((resolve, reject) => { try { - console.log(`Running: yo phovea:${generator} ${_args}`); + console.log(`Running: yo phovea:${generator} ${_args}`); env.lookup(() => { env.run(`phovea:${generator} ${_args}`, options || {}, () => { // wait a second after running yo to commit the files correctly @@ -41,4 +41,40 @@ module.exports = class GeneratorUtils { } }); } + + /** + * Creates object with custom formatting functions that can be called inside a template file when copying a template. + * @param {{}} config Config file + */ + static stringifyAble(config) { + return Object.assign({ + stringifyPython: (obj, space) => { + let base = GeneratorUtils.stringifyInline(obj, space); + // python different true false + base = base.replace(/: true/g, ': True').replace(/: false/g, ': False'); + return base; + }, + stringify: GeneratorUtils.stringifyInline, + isWeb: (p) => { + const { + plugin + } = require('./known'); + return plugin.isTypeWeb(p); + } + }, config); + } + + /** + * Stringifies object and applies custom formatting. + * @param {{}} obj Object to stringify. + * @param {string} space String containing the spaces to use to fromat stringified object. + */ + static stringifyInline(obj, space) { + let base = JSON.stringify(obj, null, ' '); + // common style + base = base.replace(/"/g, '\''); + // prefix with space + base = base.split('\n').map((l) => space + l).join('\n'); + return base.substring(space.length); // skip the first space + } }; diff --git a/utils/index.js b/utils/index.js index beb0338e..04ef2b0d 100644 --- a/utils/index.js +++ b/utils/index.js @@ -36,32 +36,7 @@ function patchPackageJSON(config, unset, extra, replaceExtra, cwd = '') { this.fs.writeJSON(this.destinationPath(cwd + 'package.json'), pkg); } -function stringifyInline(obj, space) { - let base = JSON.stringify(obj, null, ' '); - // common style - base = base.replace(/"/g, '\''); - // prefix with space - base = base.split('\n').map((l) => space + l).join('\n'); - return base.substring(space.length); // skip the first space -} -function stringifyAble(config) { - return Object.assign({ - stringifyPython: (obj, space) => { - let base = stringifyInline(obj, space); - // python different true false - base = base.replace(/: true/g, ': True').replace(/: false/g, ': False'); - return base; - }, - stringify: stringifyInline, - isWeb: (p) => { - const { - plugin - } = require('./known'); - return plugin.isTypeWeb(p); - } - }, config); -} /** * Copies the template files to the current directory or to a subdirectory if `cwd` is provided. @@ -77,7 +52,7 @@ function writeTemplates(config, withSamples, cwd = '') { } }; - const pattern = stringifyAble(config); + const pattern = GeneratorUtils.stringifyAble(config); const copyTpl = (base, dbase, initialize_once) => { // see https://github.com/SBoudrias/mem-fs-editor/issues/25 @@ -257,5 +232,4 @@ module.exports = { BaseHybrid: BaseInitHybridGenerator, patchPackageJSON: patchPackageJSON, writeTemplates: writeTemplates, - stringifyAble: stringifyAble }; From 716baa61a969cf37be3ff5dacc67bd271d40f767 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 10:02:34 +0200 Subject: [PATCH 42/65] Extract and test `toJSONFromText` function --- generators/add-extension/index.js | 30 +---------------- test/GeneratorUtils.test.js | 45 ++++++++++++++++++++++++++ utils/GeneratorUtils.js | 53 +++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 29 deletions(-) diff --git a/generators/add-extension/index.js b/generators/add-extension/index.js index 5a179a1e..f6f08efc 100644 --- a/generators/add-extension/index.js +++ b/generators/add-extension/index.js @@ -8,34 +8,6 @@ const glob = require('glob').sync; const chalk = require('chalk'); const GeneratorUtils = require('../../utils/GeneratorUtils'); -function toJSONFromText(text) { - const r = {}; - text.split('\n').forEach((line) => { - const trimmedLine = line.trim(); - if (trimmedLine.length === 0) { // ignore empty lines (e.g. new line added by editor) - return; - } - - const splitPoint = trimmedLine.indexOf('='); - const key = trimmedLine.slice(0, splitPoint); - let value = trimmedLine.slice(splitPoint + 1); - value = value.trim(); - if (!isNaN(parseFloat(value))) { - value = parseFloat(value); - } - let obj = r; - const keys = key.trim().split('.'); - keys.slice(0, keys.length - 1).forEach((k) => { - if (!(k in obj)) { - obj[k] = {}; - } - obj = obj[k]; - }); - obj[keys[keys.length - 1]] = value; - }); - return r; -} - /** * The outside key in the `.yo-rc.json` file where the configuration is saved. * Used to manually add key-value pairs to the `.yo-rc.json` file. @@ -170,7 +142,7 @@ class Generator extends Base { type: props.type, id: props.id, module: props.module, - extras: toJSONFromText(props.extras) + extras: GeneratorUtils.toJSONFromText(props.extras) }; }); } diff --git a/test/GeneratorUtils.test.js b/test/GeneratorUtils.test.js index 0795953e..75bf1f06 100644 --- a/test/GeneratorUtils.test.js +++ b/test/GeneratorUtils.test.js @@ -49,4 +49,49 @@ describe('Test `stringifyAble()`', () => { it('returns the config', () => { expect(GeneratorUtils.stringifyAble(config)).toMatchObject(config); }); +}); + +describe('Test `toJSONFromText()`', () => { + it('parses string to object with the correct variable types ', () => { + + const extras = ` + type=lib + isBoolean=true + count=3 + weights=[1, 2, 3] + `; + + const extrasObject = { + type: 'lib', + isBoolean: true, + count: 3, + }; + expect(GeneratorUtils.toJSONFromText(extras)).toMatchObject(extrasObject); + }); + + it('parses dot notation to correct nested object', () => { + const extras = ` + config.name=ordino + config.isServer=false + config.number=5 + `; + + const extrasObject = { + config: { + name: 'ordino', + isServer: false, + number: 5 + } + }; + + expect(GeneratorUtils.toJSONFromText(extras)).toMatchObject(extrasObject); + }); + + it('returns an empty object for non string inputs', () => { + expect(GeneratorUtils.toJSONFromText(null)).toMatchObject({}); + expect(GeneratorUtils.toJSONFromText(undefined)).toMatchObject({}); + expect(GeneratorUtils.toJSONFromText('')).toMatchObject({}); + expect(GeneratorUtils.toJSONFromText(' ')).toMatchObject({}); + expect(GeneratorUtils.toJSONFromText(1)).toMatchObject({}); + }); }); \ No newline at end of file diff --git a/utils/GeneratorUtils.js b/utils/GeneratorUtils.js index 8b87efcc..328adad6 100644 --- a/utils/GeneratorUtils.js +++ b/utils/GeneratorUtils.js @@ -44,6 +44,7 @@ module.exports = class GeneratorUtils { /** * Creates object with custom formatting functions that can be called inside a template file when copying a template. + * * @param {{}} config Config file */ static stringifyAble(config) { @@ -66,6 +67,7 @@ module.exports = class GeneratorUtils { /** * Stringifies object and applies custom formatting. + * * @param {{}} obj Object to stringify. * @param {string} space String containing the spaces to use to fromat stringified object. */ @@ -77,4 +79,55 @@ module.exports = class GeneratorUtils { base = base.split('\n').map((l) => space + l).join('\n'); return base.substring(space.length); // skip the first space } + + /** + * Parses a string of the format `key=value` into an object. + * Nested fields are defined using dot notation. + * + * @param {string} text String to format + * @example + * + * const text = ` + * count=3 + * type.lib=false + * ` + * + * toJSONFromText(text) + * // => {count: 3, type: {lib: false }} + */ + static toJSONFromText(text) { + + const r = {}; + if (typeof text !== 'string') return r; + + text.split('\n').forEach((line) => { + const trimmedLine = line.trim(); + if (trimmedLine.length === 0) { // ignore empty lines (e.g. new line added by editor) + return; + } + + const splitPoint = trimmedLine.indexOf('='); + const key = trimmedLine.slice(0, splitPoint); + let value = trimmedLine.slice(splitPoint + 1); + value = value.trim(); + if (!isNaN(parseFloat(value))) { + value = parseFloat(value); + } + + if (value === 'true' || value === 'false') { + value = JSON.parse(value); + } + + let obj = r; + const keys = key.trim().split('.'); + keys.slice(0, keys.length - 1).forEach((k) => { + if (!(k in obj)) { + obj[k] = {}; + } + obj = obj[k]; + }); + obj[keys[keys.length - 1]] = value; + }); + return r; + } }; From 9608dd8bd24544e06406fb08d80340094e796524 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 10:08:23 +0200 Subject: [PATCH 43/65] Create BasePhoveaGenerator class phovea/generator-phovea#430 --- base/BaseInitHybridGenerator.js | 24 +++ base/BaseInitPluginGenerator.js | 93 +++++++++++ base/BaseInitServerGenerator.js | 25 +++ base/BasePhoveaGenerator.js | 97 +++++++++++ generators/_init-hybrid/index.js | 4 +- generators/_init-python/index.js | 9 +- generators/_init-web/index.js | 9 +- generators/_node/index.js | 7 +- generators/init-app-slib/index.js | 5 +- generators/init-app/index.js | 4 +- generators/init-bundle/index.js | 4 +- generators/init-lib-service/index.js | 4 +- generators/init-lib-slib/index.js | 4 +- generators/init-lib/index.js | 4 +- generators/init-product/index.js | 9 +- generators/init-service/index.js | 5 +- generators/init-slib/index.js | 4 +- generators/workspace/index.js | 10 +- utils/index.js | 235 --------------------------- 19 files changed, 278 insertions(+), 278 deletions(-) create mode 100644 base/BaseInitHybridGenerator.js create mode 100644 base/BaseInitPluginGenerator.js create mode 100644 base/BaseInitServerGenerator.js create mode 100644 base/BasePhoveaGenerator.js delete mode 100644 utils/index.js diff --git a/base/BaseInitHybridGenerator.js b/base/BaseInitHybridGenerator.js new file mode 100644 index 00000000..00b525a9 --- /dev/null +++ b/base/BaseInitHybridGenerator.js @@ -0,0 +1,24 @@ +'use strict'; +const BaseInitPluginGenerator = require("./BaseInitPluginGenerator"); + +class BaseInitHybridGenerator extends BaseInitPluginGenerator { + + constructor(args, options) { + super(args, options, 'hybrid'); + } + + initializing() { + // since just last in the hierarchy used, need to do super calls + super.initializing(); + } + + default() { + return super.default(); + } + + writing() { + return super.writing(); + } +} + +module.exports = BaseInitHybridGenerator; \ No newline at end of file diff --git a/base/BaseInitPluginGenerator.js b/base/BaseInitPluginGenerator.js new file mode 100644 index 00000000..98bcc663 --- /dev/null +++ b/base/BaseInitPluginGenerator.js @@ -0,0 +1,93 @@ +'use strict'; +const path = require('path'); +const fs = require('fs-extra'); +const chalk = require('chalk'); +const GeneratorUtils = require('../utils/GeneratorUtils'); +const BasePhoveaGenerator = require('../base/BasePhoveaGenerator'); + +class BaseInitPluginGenerator extends BasePhoveaGenerator { + + constructor(args, options, basetype) { + super(args, options); + this.type = path.basename(path.dirname(this.resolved)).substring(5); // init-web ... web + this.basetype = basetype || 'web'; + // Make options available + this.option('skipInstall'); + this.option('noSamples'); + this.option('useDefaults'); + this.cwd = ''; + } + + initializing() { + if (this._isInvalidWorkspace()) { + throw new Error(chalk.red('Execution failed, because a ".yo-rc.json" and ".yo-rc-workspace.json" file was found. If this directory is a workspace, please remove the ".yo-rc.json" file and try again.\n')); + } + + this.composeWith(['phovea:_check-own-version', 'phovea:check-node-version']); + + this.config.defaults({ + type: this.type + }); + } + + _isWorkspace() { + return fs.existsSync(this.destinationPath('.yo-rc-workspace.json')); + } + + _hasConfigFile() { + return fs.existsSync(this.destinationPath('.yo-rc.json')); + } + + /** + * If there is both a `.yo-rc-workspace.json` and `.yo-rc.json` file in the current directory + * the workspace is invalid and the generator cannot function properly. + */ + _isInvalidWorkspace() { + return this._isWorkspace() && this._hasConfigFile(); + } + + /** + * Create a subdirectory in the current directory. + * Initialize the property cwd. + * @param {string} dir Directory name. + */ + _createSubDir(dir) { + if (this._isWorkspace() && this.cwd !== dir + '/') { + this.cwd = dir + '/'; + GeneratorUtils.mkdir(dir); + } + } + + readmeAddon() { + const f = this.templatePath('README.partial.md'); + if (fs.existsSync(f)) { + return this.fs.read(f); + } + return ''; + } + + default() { + this.composeWith('phovea:_init-' + this.basetype, { + options: Object.assign({ + readme: this.readmeAddon() + (this.options.readme ? `\n\n${this.options.readme}` : '') + }, this.options), + isWorkspace: this._isWorkspace() // inform the sub generator that the cwd is the workspace to avoid reading prompt default values from the workspace package.json + }); + } + + writing() { + const config = this.config.getAll(); + this._createSubDir(config.cwd || config.name); + if (fs.existsSync(this.templatePath('package.tmpl.json'))) { + this._patchPackageJSON(config, null, null, this.cwd); + } + if (fs.existsSync(this.templatePath('_gitignore'))) { + this.fs.copy(this.templatePath('_gitignore'), this.destinationPath(this.cwd + '.gitignore')); + } + + this._writeTemplates(config, !this.options.noSamples, this.cwd); + + } +} + +module.exports = BaseInitPluginGenerator; \ No newline at end of file diff --git a/base/BaseInitServerGenerator.js b/base/BaseInitServerGenerator.js new file mode 100644 index 00000000..0a313075 --- /dev/null +++ b/base/BaseInitServerGenerator.js @@ -0,0 +1,25 @@ +'use strict'; + +const BaseInitPluginGenerator = require('./BaseInitPluginGenerator'); + +class BaseInitServerGenerator extends BaseInitPluginGenerator { + + constructor(args, options) { + super(args, options, 'python'); + } + + initializing() { + // since just last in the hierarchy used, need to do super calls + super.initializing(); + } + + default() { + return super.default(); + } + + writing() { + return super.writing(); + } +} + +module.exports = BaseInitServerGenerator; \ No newline at end of file diff --git a/base/BasePhoveaGenerator.js b/base/BasePhoveaGenerator.js new file mode 100644 index 00000000..c3c40341 --- /dev/null +++ b/base/BasePhoveaGenerator.js @@ -0,0 +1,97 @@ +'use strict'; +const Generator = require('yeoman-generator'); +const {merge, template} = require('lodash'); +const path = require('path'); +const glob = require('glob').sync; +const fs = require('fs-extra'); +const GeneratorUtils = require('../utils/GeneratorUtils'); + +class BasePhoveaGenerator extends Generator { + + /** + * Modify package.json by passing the configuration. + * + * @param {object} config Current configuration + * @param {*} unset + * @param {*} extra + * @param {*} replaceExtra + * @param {string} cwd The directory from which the generator is being called, i.e., `tdp_core/`. + * If cwd is provided than the `package.json` is going to be written to that subdirectory, otherwise to the current directory. + */ + _patchPackageJSON(config, unset, extra, replaceExtra, cwd = '') { + const pkg = this.fs.readJSON(this.destinationPath(cwd + 'package.json'), {}); + let pkgPatch; + if (fs.existsSync(this.templatePath('package.tmpl.json'))) { + pkgPatch = JSON.parse(template(this.fs.read(this.templatePath('package.tmpl.json')))(config)); + } else { + pkgPatch = {}; + } + merge(pkg, pkgPatch); + if (replaceExtra && extra) { + Object.assign(pkg, extra); + } else { + merge(pkg, extra || {}); + } + + (unset || []).forEach((d) => delete pkg[d]); + + this.fs.writeJSON(this.destinationPath(cwd + 'package.json'), pkg); + } + + /** + * Copies the template files to the current directory or to a subdirectory if `cwd` is provided. + * @param {object} config Current configuration + * @param {*} withSamples + * @param {string} cwd The directory from which the generator is being called, i.e., `tdp_core/`. + * If `cwd` is provided than the `package.json` is going to be written to that subdirectory, otherwise to the current directory. + */ + _writeTemplates(config, withSamples, cwd = '') { + const includeDot = { + globOptions: { + dot: true + } + }; + + const pattern = GeneratorUtils.stringifyAble(config); + + const copyTpl = (base, dbase, initialize_once) => { + // see https://github.com/SBoudrias/mem-fs-editor/issues/25 + // copyTpl doesn't support glob options + const f = glob(base + '/**/*', { + dot: true + }); + f.forEach((fi) => { + const rel = path.relative(base, fi); + if (!initialize_once || !fs.existsSync(this.destinationPath(cwd + dbase + rel))) { + this.fs.copyTpl(fi, this.destinationPath(cwd + dbase + rel), pattern); + } + }); + }; + + const copy = (prefix) => { + if (fs.existsSync(this.templatePath(prefix + 'plain'))) { + this.fs.copy(this.templatePath(prefix + 'plain/**/*'), this.destinationPath(cwd), includeDot); + } + + const plainTemplatePath = this.templatePath(prefix + 'plain_initialize_once'); + if (fs.existsSync(plainTemplatePath)) { + copyTpl(plainTemplatePath, '', true); + } + + copyTpl(this.templatePath(prefix + 'processed'), '', false); + + if (config.name) { + if (fs.existsSync(this.templatePath(prefix + 'pluginname_plain'))) { + this.fs.copy(this.templatePath(prefix + 'pluginname_plain/**/*'), this.destinationPath(cwd + config.name.toLowerCase() + '/'), includeDot); + } + copyTpl(this.templatePath(prefix + 'pluginname_processed'), cwd + config.name.toLowerCase() + '/', false); + } + }; + copy(''); + if (withSamples) { + copy('sample_'); + } + } +} + +module.exports = BasePhoveaGenerator; \ No newline at end of file diff --git a/generators/_init-hybrid/index.js b/generators/_init-hybrid/index.js index 2887413f..6194e2ef 100644 --- a/generators/_init-hybrid/index.js +++ b/generators/_init-hybrid/index.js @@ -1,9 +1,9 @@ 'use strict'; -const Base = require('../../utils').Base; const known = () => require('../../utils/known'); +const BaseInitPluginGenerator = require('../../base/BaseInitPluginGenerator'); const RepoUtils = require('../../utils/RepoUtils'); -class Generator extends Base { +class Generator extends BaseInitPluginGenerator { initializing() { this.config.defaults({ diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index 3b748bd9..397c76e5 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -1,15 +1,14 @@ 'use strict'; const _ = require('lodash'); -const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON} = require('../../utils'); const PipUtils = require('../../utils/PipUtils'); const NpmUtils = require('../../utils/NpmUtils'); const GeneratorUtils = require('../../utils/GeneratorUtils'); const fs = require('fs'); +const BasePhoveaGenerator = require('../../base/BasePhoveaGenerator'); const known = () => require('../../utils/known'); -class Generator extends Base { +class Generator extends BasePhoveaGenerator { constructor(args, options) { super(args, options); @@ -111,8 +110,8 @@ class Generator extends Base { const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); const deps = this._generateDependencies(NpmUtils.useDevVersion(version), this.cwd); - patchPackageJSON.call(this, config, ['devDependencies'], null, null, this.cwd); - writeTemplates.call(this, config, !this.options.noSamples, this.cwd); + this._patchPackageJSON(config, ['devDependencies'], null, null, this.cwd); + this._writeTemplates.call(this, config, !this.options.noSamples, this.cwd); this.fs.write(this.destinationPath(this.cwd + 'requirements.txt'), deps.requirements.join('\n')); this.fs.write(this.destinationPath(this.cwd + 'docker_packages.txt'), deps.dockerPackages.join('\n')); diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 78b226b1..4ab7c0ef 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -1,16 +1,15 @@ 'use strict'; const _ = require('lodash'); const chalk = require('chalk'); -const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON} = require('../../utils'); const fs = require('fs'); const NpmUtils = require('../../utils/NpmUtils'); const SpawnUtils = require('../../utils/SpawnUtils'); const RepoUtils = require('../../utils/RepoUtils'); const GeneratorUtils = require('../../utils/GeneratorUtils'); +const BasePhoveaGenerator = require('../../base/BasePhoveaGenerator'); const known = () => require('../../utils/known'); -class Generator extends Base { +class Generator extends BasePhoveaGenerator { constructor(args, options) { super(args, options); @@ -91,11 +90,11 @@ class Generator extends Base { this.cwd = this.options.isWorkspace ? (config.app || config.name) + '/' : ''; const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); - patchPackageJSON.call(this, config, [], { + this._patchPackageJSON(config, [], { dependencies: this._generateDependencies(NpmUtils.useDevVersion(version)) }, null, this.cwd); this.fs.copy(this.templatePath('_gitignore'), this.destinationPath(this.cwd + '.gitignore')); - writeTemplates.call(this, config, null, this.cwd); + this._writeTemplates.call(this, config, null, this.cwd); // do not overwrite existing registry file if (!fs.existsSync(this.destinationPath(this.cwd + 'src/phovea.ts'))) { diff --git a/generators/_node/index.js b/generators/_node/index.js index 84f6ca61..95bdef70 100644 --- a/generators/_node/index.js +++ b/generators/_node/index.js @@ -1,14 +1,13 @@ 'use strict'; const _ = require('lodash'); const parseAuthor = require('parse-author'); -const Base = require('yeoman-generator'); -const patchPackageJSON = require('../../utils').patchPackageJSON; const originUrl = require('git-remote-origin-url'); const fs = require('fs-extra'); +const BasePhoveaGenerator = require('../../base/BasePhoveaGenerator'); // based on https://github.com/yeoman/generator-node/blob/master/generators/app/index.js -class PackageJSONGenerator extends Base { +class PackageJSONGenerator extends BasePhoveaGenerator { constructor(args, options) { super(args, options); @@ -141,7 +140,7 @@ class PackageJSONGenerator extends Base { } else { config.repository = `https://github.com/${config.githubAccount}/${config.name}.git`; } - patchPackageJSON.call(this, config, null, null, null, this.cwd); + this._patchPackageJSON(config, null, null, null, this.cwd); config.content = this.options.readme || ''; config.longDescription = this.options.longDescription || this.props.description || ''; diff --git a/generators/init-app-slib/index.js b/generators/init-app-slib/index.js index e4737495..dc80b4df 100644 --- a/generators/init-app-slib/index.js +++ b/generators/init-app-slib/index.js @@ -1,7 +1,8 @@ 'use strict'; -const BaseHybrid = require('../../utils').BaseHybrid; -class PluginGenerator extends BaseHybrid { +const BaseInitHybridGenerator = require("../init-lib-service"); + +class PluginGenerator extends BaseInitHybridGenerator { initializing() { super.initializing(); diff --git a/generators/init-app/index.js b/generators/init-app/index.js index cadead25..c57ccaf7 100644 --- a/generators/init-app/index.js +++ b/generators/init-app/index.js @@ -1,8 +1,8 @@ 'use strict'; -const BasePluginGenerator = require('../../utils').Base; +const BaseInitPluginGenerator = require('../../base/BaseInitPluginGenerator'); const chalk = require('chalk'); -class PluginGenerator extends BasePluginGenerator { +class PluginGenerator extends BaseInitPluginGenerator { initializing() { super.initializing(); diff --git a/generators/init-bundle/index.js b/generators/init-bundle/index.js index 70fc429d..5cddcebd 100644 --- a/generators/init-bundle/index.js +++ b/generators/init-bundle/index.js @@ -1,4 +1,4 @@ 'use strict'; -var BasePluginGenerator = require('../../utils').Base; +const BaseInitPluginGenerator = require("../../base/BaseInitPluginGenerator"); -module.exports = BasePluginGenerator; +module.exports = BaseInitPluginGenerator; diff --git a/generators/init-lib-service/index.js b/generators/init-lib-service/index.js index 1d3a52a1..9315f2cb 100644 --- a/generators/init-lib-service/index.js +++ b/generators/init-lib-service/index.js @@ -1,4 +1,4 @@ 'use strict'; -var BaseHybrid = require('../../utils').BaseHybrid; +const BaseInitHybridGenerator = require("../../base/BaseInitHybridGenerator"); -module.exports = BaseHybrid; +module.exports = BaseInitHybridGenerator; diff --git a/generators/init-lib-slib/index.js b/generators/init-lib-slib/index.js index 1d3a52a1..c7ee5dfa 100644 --- a/generators/init-lib-slib/index.js +++ b/generators/init-lib-slib/index.js @@ -1,4 +1,4 @@ 'use strict'; -var BaseHybrid = require('../../utils').BaseHybrid; +const BaseInitHybridGenerator = require('../../base/BaseInitHybridGenerator'); -module.exports = BaseHybrid; +module.exports = BaseInitHybridGenerator; diff --git a/generators/init-lib/index.js b/generators/init-lib/index.js index 4d653310..643c6e0a 100644 --- a/generators/init-lib/index.js +++ b/generators/init-lib/index.js @@ -1,7 +1,7 @@ 'use strict'; -const BasePluginGenerator = require('../../utils').Base; const chalk = require('chalk'); -class PluginGenerator extends BasePluginGenerator { +const BaseInitPluginGenerator = require('../../base/BaseInitPluginGenerator'); +class PluginGenerator extends BaseInitPluginGenerator { initializing() { return super.initializing(); diff --git a/generators/init-product/index.js b/generators/init-product/index.js index 274ce542..a29c0c1e 100644 --- a/generators/init-product/index.js +++ b/generators/init-product/index.js @@ -1,15 +1,14 @@ /** * Created by Samuel Gratzl on 28.11.2016. */ -const Base = require('yeoman-generator'); -const {writeTemplates, patchPackageJSON} = require('../../utils'); const WorkspaceUtils = require('../../utils/WorkspaceUtils'); const chalk = require('chalk'); const fs = require('fs'); +const BasePhoveaGenerator = require('../../base/BasePhoveaGenerator'); const isRequired = (v) => v.toString().length > 0; -class Generator extends Base { +class Generator extends BasePhoveaGenerator { initializing() { if (fs.existsSync(this.destinationPath('.yo-rc-workspace.json'))) { @@ -112,8 +111,8 @@ class Generator extends Base { writing() { const config = this.config.getAll(); - patchPackageJSON.call(this, config); - writeTemplates.call(this, config); + this._patchPackageJSON.call(this, config); + this._writeTemplates.call(this, config); this.fs.copy(this.templatePath('_gitignore'), this.destinationPath('.gitignore')); // don't overwrite existing registry file if (!fs.existsSync(this.destinationPath('phovea_product.json'))) { diff --git a/generators/init-service/index.js b/generators/init-service/index.js index 58c969d1..5e2481f6 100644 --- a/generators/init-service/index.js +++ b/generators/init-service/index.js @@ -1,7 +1,8 @@ 'use strict'; -const BasePluginGenerator = require('../../utils').BasePython; -class Generator extends BasePluginGenerator { +const BaseInitServerGenerator = require("../../base/BaseInitServerGenerator"); + +class Generator extends BaseInitServerGenerator { initializing() { super.initializing(); this.config.defaults({ diff --git a/generators/init-slib/index.js b/generators/init-slib/index.js index dde05c85..0f79f8cc 100644 --- a/generators/init-slib/index.js +++ b/generators/init-slib/index.js @@ -1,8 +1,8 @@ 'use strict'; -const BasePluginGenerator = require('../../utils').BasePython; const fs = require('fs'); +const BaseInitServerGenerator = require('../../base/BaseInitServerGenerator'); -class PluginGenerator extends BasePluginGenerator { +class PluginGenerator extends BaseInitServerGenerator { initializing() { super.initializing(); diff --git a/generators/workspace/index.js b/generators/workspace/index.js index aa4e25e9..8050db6b 100644 --- a/generators/workspace/index.js +++ b/generators/workspace/index.js @@ -1,5 +1,4 @@ 'use strict'; -const Base = require('yeoman-generator'); const path = require('path'); const glob = require('glob').sync; const chalk = require('chalk'); @@ -8,10 +7,9 @@ const _ = require('lodash'); const fs = require('fs'); const known = () => require('../../utils/known'); -const writeTemplates = require('../../utils').writeTemplates; -const patchPackageJSON = require('../../utils').patchPackageJSON; const NpmUtils = require('../../utils/NpmUtils'); const PipUtils = require('../../utils/PipUtils'); +const BasePhoveaGenerator = require('../../base/BasePhoveaGenerator'); function mergeWith(target, source) { const mergeArrayUnion = (a, b) => Array.isArray(a) ? _.union(a, b) : undefined; @@ -42,7 +40,7 @@ function rewriteDockerCompose(compose) { return compose; } -class Generator extends Base { +class Generator extends BasePhoveaGenerator { constructor(args, options) { super(args, options); @@ -498,9 +496,9 @@ class Generator extends Base { config.wsDescription = this.options.wsDescription; config.wsVersion = this.options.wsVersion; - writeTemplates.call(this, config, false); + this._writeTemplates(config, false); // replace the added entries - patchPackageJSON.call(this, config, [], {devDependencies, dependencies, scripts, watch}, true); + this._patchPackageJSON(config, [], {devDependencies, dependencies, scripts, watch}, true); if (!fs.existsSync(this.destinationPath('config.json'))) { this.fs.copy(this.templatePath('config.tmpl.json'), this.destinationPath('config.json')); diff --git a/utils/index.js b/utils/index.js deleted file mode 100644 index 04ef2b0d..00000000 --- a/utils/index.js +++ /dev/null @@ -1,235 +0,0 @@ -'use strict'; -const Generator = require('yeoman-generator'); -const {merge, template} = require('lodash'); -const path = require('path'); -const glob = require('glob').sync; -const fs = require('fs-extra'); -const chalk = require('chalk'); -const GeneratorUtils = require('./GeneratorUtils'); - -/** - * Modify package.json by passing the configuration - * @param {object} config Current configuration - * @param {*} unset - * @param {*} extra - * @param {*} replaceExtra - * @param {string} cwd The directory from which the generator is being called, i.e., `tdp_core/`. - * If cwd is provided than the `package.json` is going to be written to that subdirectory, otherwise to the current directory. - */ -function patchPackageJSON(config, unset, extra, replaceExtra, cwd = '') { - const pkg = this.fs.readJSON(this.destinationPath(cwd + 'package.json'), {}); - let pkgPatch; - if (fs.existsSync(this.templatePath('package.tmpl.json'))) { - pkgPatch = JSON.parse(template(this.fs.read(this.templatePath('package.tmpl.json')))(config)); - } else { - pkgPatch = {}; - } - merge(pkg, pkgPatch); - if (replaceExtra && extra) { - Object.assign(pkg, extra); - } else { - merge(pkg, extra || {}); - } - - (unset || []).forEach((d) => delete pkg[d]); - - this.fs.writeJSON(this.destinationPath(cwd + 'package.json'), pkg); -} - - - -/** - * Copies the template files to the current directory or to a subdirectory if `cwd` is provided. - * @param {object} config Current configuration - * @param {*} withSamples - * @param {string} cwd The directory from which the generator is being called, i.e., `tdp_core/`. - * If `cwd` is provided than the `package.json` is going to be written to that subdirectory, otherwise to the current directory. - */ -function writeTemplates(config, withSamples, cwd = '') { - const includeDot = { - globOptions: { - dot: true - } - }; - - const pattern = GeneratorUtils.stringifyAble(config); - - const copyTpl = (base, dbase, initialize_once) => { - // see https://github.com/SBoudrias/mem-fs-editor/issues/25 - // copyTpl doesn't support glob options - const f = glob(base + '/**/*', { - dot: true - }); - f.forEach((fi) => { - const rel = path.relative(base, fi); - if (!initialize_once || !fs.existsSync(this.destinationPath(cwd + dbase + rel))) { - this.fs.copyTpl(fi, this.destinationPath(cwd + dbase + rel), pattern); - } - }); - }; - - const copy = (prefix) => { - if (fs.existsSync(this.templatePath(prefix + 'plain'))) { - this.fs.copy(this.templatePath(prefix + 'plain/**/*'), this.destinationPath(cwd), includeDot); - } - - const plainTemplatePath = this.templatePath(prefix + 'plain_initialize_once'); - if (fs.existsSync(plainTemplatePath)) { - copyTpl(plainTemplatePath, '', true); - } - - copyTpl(this.templatePath(prefix + 'processed'), '', false); - - if (config.name) { - if (fs.existsSync(this.templatePath(prefix + 'pluginname_plain'))) { - this.fs.copy(this.templatePath(prefix + 'pluginname_plain/**/*'), this.destinationPath(cwd + config.name.toLowerCase() + '/'), includeDot); - } - copyTpl(this.templatePath(prefix + 'pluginname_processed'), cwd + config.name.toLowerCase() + '/', false); - } - }; - copy(''); - if (withSamples) { - copy('sample_'); - } -} - -class BaseInitPluginGenerator extends Generator { - - constructor(args, options, basetype) { - super(args, options); - this.type = path.basename(path.dirname(this.resolved)).substring(5); // init-web ... web - this.basetype = basetype || 'web'; - // Make options available - this.option('skipInstall'); - this.option('noSamples'); - this.option('useDefaults'); - this.cwd = ''; - } - - initializing() { - if (this._isInvalidWorkspace()) { - throw new Error(chalk.red('Execution failed, because a ".yo-rc.json" and ".yo-rc-workspace.json" file was found. If this directory is a workspace, please remove the ".yo-rc.json" file and try again.\n')); - } - - this.composeWith(['phovea:_check-own-version', 'phovea:check-node-version']); - - this.config.defaults({ - type: this.type - }); - } - - _isWorkspace() { - return fs.existsSync(this.destinationPath('.yo-rc-workspace.json')); - } - - _hasConfigFile() { - return fs.existsSync(this.destinationPath('.yo-rc.json')); - } - - /** - * If there is both a `.yo-rc-workspace.json` and `.yo-rc.json` file in the current directory - * the workspace is invalid and the generator cannot function properly. - */ - _isInvalidWorkspace() { - return this._isWorkspace() && this._hasConfigFile(); - } - - /** - * Create a subdirectory in the current directory. - * Initialize the property cwd. - * @param {string} dir Directory name. - */ - _createSubDir(dir) { - if (this._isWorkspace() && this.cwd !== dir + '/') { - this.cwd = dir + '/'; - GeneratorUtils.mkdir(dir); - } - } - - readmeAddon() { - const f = this.templatePath('README.partial.md'); - if (fs.existsSync(f)) { - return this.fs.read(f); - } - return ''; - } - - default() { - this.composeWith('phovea:_init-' + this.basetype, { - options: Object.assign({ - readme: this.readmeAddon() + (this.options.readme ? `\n\n${this.options.readme}` : '') - }, this.options), - isWorkspace: this._isWorkspace() // inform the sub generator that the cwd is the workspace to avoid reading prompt default values from the workspace package.json - }); - } - - writing() { - const config = this.config.getAll(); - this._createSubDir(config.cwd || config.name); - if (fs.existsSync(this.templatePath('package.tmpl.json'))) { - this._patchPackageJSON(config, null, null, this.cwd); - } - if (fs.existsSync(this.templatePath('_gitignore'))) { - this.fs.copy(this.templatePath('_gitignore'), this.destinationPath(this.cwd + '.gitignore')); - } - - this._writeTemplates(config, !this.options.noSamples, this.cwd); - - } - - _patchPackageJSON(config, unset, extra, cwd) { - return patchPackageJSON.call(this, config, unset, extra, null, cwd); - } - - _writeTemplates(config, withSamples, cwd) { - return writeTemplates.call(this, config, withSamples, cwd); - } -} - -class BaseInitServerGenerator extends BaseInitPluginGenerator { - - constructor(args, options) { - super(args, options, 'python'); - } - - initializing() { - // since just last in the hierarchy used, need to do super calls - super.initializing(); - } - - default() { - return super.default(); - } - - writing() { - return super.writing(); - } -} - -class BaseInitHybridGenerator extends BaseInitPluginGenerator { - - constructor(args, options) { - super(args, options, 'hybrid'); - } - - initializing() { - // since just last in the hierarchy used, need to do super calls - super.initializing(); - } - - default() { - return super.default(); - } - - writing() { - return super.writing(); - } -} - -module.exports = { - Base: BaseInitPluginGenerator, - BasePython: BaseInitServerGenerator, - BaseHybrid: BaseInitHybridGenerator, - patchPackageJSON: patchPackageJSON, - writeTemplates: writeTemplates, -}; From 3c8eddad6e01774b5033ce4adbbdba591fa0f94e Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 12:00:34 +0200 Subject: [PATCH 44/65] Use import instead of System.import in phovea.ts phovea/generator-phovea#425 --- generators/add-extension/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/add-extension/index.js b/generators/add-extension/index.js index f6f08efc..e4ddbde4 100644 --- a/generators/add-extension/index.js +++ b/generators/add-extension/index.js @@ -187,7 +187,7 @@ class Generator extends Base { if (fs.existsSync(cwd + 'src/phovea.ts')) { absFile = d.module.startsWith('~') ? d.module.slice(1) : `./${d.module.includes('.') ? d.module.slice(0, d.module.lastIndexOf('.')) : d.module}`; - importFunction = `() => System.import('${absFile}')`; // TODO remove System.import for Typescript case when switching to Webpack 4 (see https://github.com/phovea/generator-phovea/issues/286#issuecomment-566553497) + importFunction = `() => import('${absFile}')`; } else { absFile = d.module.startsWith('~') ? d.module.slice(1) : `./src/${d.module.includes('.') ? d.module.slice(0, d.module.lastIndexOf('.')) : d.module}`; importFunction = `function() { return import('${absFile}'); }`; From bb1b2191841f2a6c56bd6c20478b654f7c2e2138 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 13:23:46 +0200 Subject: [PATCH 45/65] Add tests for the add-extension generator phovea/generator-phovea#425 --- test/add-extension.test.js | 217 +++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 test/add-extension.test.js diff --git a/test/add-extension.test.js b/test/add-extension.test.js new file mode 100644 index 00000000..ef20eeb2 --- /dev/null +++ b/test/add-extension.test.js @@ -0,0 +1,217 @@ + +'use strict'; +const path = require('path'); +const assert = require('yeoman-assert'); +const helpers = require('yeoman-test'); +const rimraf = require('rimraf'); +const fse = require('fs-extra'); +const TestUtils = require('./TestUtils'); +const {template} = require('lodash'); + + +const LIB_GENERATOR_DEPENDENCIES = [ + '../generators/_node', + '../generators/init-lib', + '../generators/_init-web', + '../generators/_check-own-version', + '../generators/check-node-version', +].map((d) => path.join(__dirname, d)); + +const SLIB_GENERATOR_DEPENDENCIES = [ + '../generators/_node', + '../generators/init-slib', + '../generators/_init-python', + '../generators/_check-own-version', + '../generators/check-node-version', +].map((d) => path.join(__dirname, d)); +/** + * Subgenerators composed with the `add-extension` subgenerator. + */ +const GENERATOR_DEPENDENCIES = [ + '../generators/_check-own-version', + '../generators/check-node-version', +].map((d) => path.join(__dirname, d)); + +const LIB_SLIB_GENERATOR_DEPENDENCIES = [ + '../generators/_node', + '../generators/_init-hybrid', + '../generators/init-lib', + '../generators/_init-web', + '../generators/init-slib', + '../generators/_init-python', + '../generators/_check-own-version', + '../generators/check-node-version', +].map((d) => path.join(__dirname, d)); + +describe('add a web extension to a web library', () => { + const tdpViewTmpl = template(fse.readFileSync(TestUtils.templatePath('add-extension', 'tdpView.tmpl.ts')))({moduleName: 'CustomView'}); + + const prompts = { + type: 'tdpView', + id: 'view_id', + module: 'CustomView', + extras: ` + idType=MYIDTYPE + load=true + config.database=MyDB + ` + }; + beforeAll(async () => { + let workingDirectory; + // Initialize a dummy web library + await helpers + .run(path.join(__dirname, '../generators/init-lib')) + .withGenerators(LIB_GENERATOR_DEPENDENCIES) + .inTmpDir((dir) => { + workingDirectory = dir; + }); + + // Run yo phovea:add-extension in the same directory + await helpers + .run(path.join(__dirname, '../generators/add-extension')) + .withGenerators(GENERATOR_DEPENDENCIES) + .inTmpDir(() => { + process.chdir(workingDirectory); + }) + .withPrompts(prompts); + }); + + it('generates module', () => { + assert.file('src/CustomView.ts'); + }); + + it('generated module uses the correct template', () => { + assert.fileContent('src/CustomView.ts', tdpViewTmpl); + }); + + it('registers the view in phovea.ts', () => { + const config = `registry.push('tdpView', 'view_id', () => import('./CustomView'), {\n 'idType': 'MYIDTYPE',\n 'load': true,\n 'config': {\n 'database': 'MyDB'\n }\n });`; + assert.fileContent('src/phovea.ts', config); + }); +}); + +describe('add a python extension to a python plugin', () => { + const prompts = { + type: 'tdp-sql-definition', + id: 'my_id', + module: 'custom', + extras: ` + autoUpgrade=false + ` + }; + beforeAll(async () => { + let workingDirectory; + // Initialize a dummy python library + await helpers + .run(path.join(__dirname, '../generators/init-slib')) + .withGenerators(SLIB_GENERATOR_DEPENDENCIES) + .inTmpDir((dir) => { + workingDirectory = dir; + }) + .withPrompts({name: 'server_plugin'}); + + // Run yo phovea:add-extension in the same directory + await helpers + .run(path.join(__dirname, '../generators/add-extension')) + .withGenerators(GENERATOR_DEPENDENCIES) + .inTmpDir(() => { + process.chdir(workingDirectory); + }) + .withPrompts(prompts); + }); + + it('generates module', () => { + assert.file('server_plugin/custom.py'); + }); + + it('registers extension in __init__.py', () => { + const config = `registry.append('tdp-sql-definition', 'my_id', 'server_plugin.custom', {\n 'autoUpgrade': False\n })`; + assert.fileContent('server_plugin/__init__.py', config); + }); +}); + +describe('add a web extension to a hybrid plugin', () => { + const prompts = { + basetype: 'web', + type: 'tdpScore', + id: 'score_id', + module: 'SingleScore', + }; + beforeAll(async () => { + let workingDirectory; + // Initialize a dummy hybrid plugin + await helpers + .run(path.join(__dirname, '../generators/init-lib-slib')) + .withGenerators(LIB_SLIB_GENERATOR_DEPENDENCIES) + .inTmpDir((dir) => { + workingDirectory = dir; + }) + .withPrompts({name: 'hybrid_plugin'}); + + // Run yo phovea:add-extension in the same directory + await helpers + .run(path.join(__dirname, '../generators/add-extension')) + .withGenerators(GENERATOR_DEPENDENCIES) + .inTmpDir(() => { + process.chdir(workingDirectory); + }) + .withPrompts(prompts); + }); + it('generates score module', () => { + assert.file('src/SingleScore.ts'); + }); + + it('registers the view in phovea.ts', () => { + const config = `registry.push('tdpScore', 'score_id', () => import('./SingleScore'), {});`; + assert.fileContent('src/phovea.ts', config); + }); +}); + +describe('add a web extension from the workspace', () => { + const cwd = process.cwd(); + const libPlugin = 'libPLugin'; + const prompts = { + basetype: 'web', + type: 'tdpScore', + id: 'score_id', + module: 'SingleScore', + plugin: libPlugin + }; + beforeAll(async () => { + let workingDirectory; + // Initialize a dummy hybrid plugin + await helpers + .run(path.join(__dirname, '../generators/init-lib')) + .withGenerators(LIB_GENERATOR_DEPENDENCIES) + .inTmpDir((dir) => { + workingDirectory = dir; + // simulate a workspace + fse.writeFileSync('.yo-rc-workspace.json', ''); + fse.mkdirSync(`./${libPlugin}`); + process.chdir(path.join(dir, libPlugin)); + }) + .withPrompts({name: 'plugin'}); + + // Run yo phovea:add-extension in the same directory + await helpers + .run(path.join(__dirname, '../generators/add-extension')) + .withGenerators(GENERATOR_DEPENDENCIES) + .inTmpDir(() => { + process.chdir(workingDirectory); + }) + .withPrompts(prompts); + }); + + // Switch back the cwd + afterAll(() => { + process.chdir(cwd); + }); + it('generates score module inside the plugin directory', () => { + assert.file(libPlugin + '/src/SingleScore.ts'); + }); + + it('registers the view in phovea.ts inside the plugin directory', () => { + const config = `registry.push('tdpScore', 'score_id', () => import('./SingleScore'), {});`; + assert.fileContent(libPlugin + '/src/phovea.ts', config); + }); +}); \ No newline at end of file From 4ca798fc6e91cf0f7d162e16f948f6a583991ce1 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 14:41:47 +0200 Subject: [PATCH 46/65] Further test refactoring phovea/generator-phovea#425 --- test/add-extension.test.js | 64 ++++++-------------------- test/clone-repo.test.js | 14 ++---- test/generator-dependencies.js | 84 ++++++++++++++++++++++++++++++++++ test/init-app-slib.test.js | 17 +------ test/init-app.test.js | 15 +----- test/init-lib-service.test.js | 18 ++------ test/init-lib-slib.test.js | 17 +------ test/init-lib.test.js | 15 +----- test/init-product.test.js | 13 +----- test/init-service.test.js | 13 +----- test/init-slib.test.js | 13 +----- test/setup-workspace.test.js | 12 +---- test/workspace.test.js | 36 ++------------- 13 files changed, 125 insertions(+), 206 deletions(-) create mode 100644 test/generator-dependencies.js diff --git a/test/add-extension.test.js b/test/add-extension.test.js index ef20eeb2..4496de84 100644 --- a/test/add-extension.test.js +++ b/test/add-extension.test.js @@ -3,45 +3,10 @@ const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); -const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); const {template} = require('lodash'); - - -const LIB_GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/init-lib', - '../generators/_init-web', - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); - -const SLIB_GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/init-slib', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); -/** - * Subgenerators composed with the `add-extension` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); - -const LIB_SLIB_GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_init-hybrid', - '../generators/init-lib', - '../generators/_init-web', - '../generators/init-slib', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); +const dependencies = require('./generator-dependencies'); describe('add a web extension to a web library', () => { const tdpViewTmpl = template(fse.readFileSync(TestUtils.templatePath('add-extension', 'tdpView.tmpl.ts')))({moduleName: 'CustomView'}); @@ -58,18 +23,18 @@ describe('add a web extension to a web library', () => { }; beforeAll(async () => { let workingDirectory; - // Initialize a dummy web library + // initialize a dummy web library await helpers .run(path.join(__dirname, '../generators/init-lib')) - .withGenerators(LIB_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_LIB) .inTmpDir((dir) => { workingDirectory = dir; }); - // Run yo phovea:add-extension in the same directory + // run yo phovea:add-extension in the same directory await helpers .run(path.join(__dirname, '../generators/add-extension')) - .withGenerators(GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.COMMON) .inTmpDir(() => { process.chdir(workingDirectory); }) @@ -104,7 +69,7 @@ describe('add a python extension to a python plugin', () => { // Initialize a dummy python library await helpers .run(path.join(__dirname, '../generators/init-slib')) - .withGenerators(SLIB_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_SLIB) .inTmpDir((dir) => { workingDirectory = dir; }) @@ -113,7 +78,7 @@ describe('add a python extension to a python plugin', () => { // Run yo phovea:add-extension in the same directory await helpers .run(path.join(__dirname, '../generators/add-extension')) - .withGenerators(GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.COMMON) .inTmpDir(() => { process.chdir(workingDirectory); }) @@ -142,7 +107,7 @@ describe('add a web extension to a hybrid plugin', () => { // Initialize a dummy hybrid plugin await helpers .run(path.join(__dirname, '../generators/init-lib-slib')) - .withGenerators(LIB_SLIB_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_LIB_SLIB) .inTmpDir((dir) => { workingDirectory = dir; }) @@ -151,7 +116,7 @@ describe('add a web extension to a hybrid plugin', () => { // Run yo phovea:add-extension in the same directory await helpers .run(path.join(__dirname, '../generators/add-extension')) - .withGenerators(GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.COMMON) .inTmpDir(() => { process.chdir(workingDirectory); }) @@ -161,7 +126,7 @@ describe('add a web extension to a hybrid plugin', () => { assert.file('src/SingleScore.ts'); }); - it('registers the view in phovea.ts', () => { + it('registers the score in phovea.ts', () => { const config = `registry.push('tdpScore', 'score_id', () => import('./SingleScore'), {});`; assert.fileContent('src/phovea.ts', config); }); @@ -179,10 +144,10 @@ describe('add a web extension from the workspace', () => { }; beforeAll(async () => { let workingDirectory; - // Initialize a dummy hybrid plugin + // Initialize a dummy lib plugin await helpers .run(path.join(__dirname, '../generators/init-lib')) - .withGenerators(LIB_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_LIB) .inTmpDir((dir) => { workingDirectory = dir; // simulate a workspace @@ -195,7 +160,7 @@ describe('add a web extension from the workspace', () => { // Run yo phovea:add-extension in the same directory await helpers .run(path.join(__dirname, '../generators/add-extension')) - .withGenerators(GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.COMMON) .inTmpDir(() => { process.chdir(workingDirectory); }) @@ -206,11 +171,12 @@ describe('add a web extension from the workspace', () => { afterAll(() => { process.chdir(cwd); }); + it('generates score module inside the plugin directory', () => { assert.file(libPlugin + '/src/SingleScore.ts'); }); - it('registers the view in phovea.ts inside the plugin directory', () => { + it('registers the score in phovea.ts inside the plugin directory', () => { const config = `registry.push('tdpScore', 'score_id', () => import('./SingleScore'), {});`; assert.fileContent(libPlugin + '/src/phovea.ts', config); }); diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js index 0359b418..56429aab 100644 --- a/test/clone-repo.test.js +++ b/test/clone-repo.test.js @@ -4,25 +4,17 @@ const path = require('path'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const SpawnUtils = require('../utils/SpawnUtils'); - -/** - * Subgenerators composed with the `clone-repo` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - - '../../generators/_check-own-version', - '../../generators/check-node-version', -]; +const dependencies = require('./generator-dependencies'); const repo = 'git@github.com:Caleydo/ordino.git'; -const target = 'cloned'; +const target = '../cloned'; const cloneRepo = (options) => helpers .run(path.join(__dirname, '../generators/clone-repo')) .inDir(path.join(__dirname, target), () => null) .withArguments([repo]) .withOptions(options) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.COMMON); describe('call clone-repo with branch develop', () => { diff --git a/test/generator-dependencies.js b/test/generator-dependencies.js new file mode 100644 index 00000000..b1f85f8f --- /dev/null +++ b/test/generator-dependencies.js @@ -0,0 +1,84 @@ +'use-strict'; +const path = require('path'); + +const toPath = (generator) => path.join(__dirname, '../generators/', generator); + +const COMMON = [ + toPath('_check-own-version'), + toPath('check-node-version'), +]; + +const INIT_LIB = [ + ...COMMON, + toPath('_node'), + toPath('init-lib'), + toPath('_init-web'), +]; + + +const INIT_SLIB = [ + ...COMMON, + toPath('_node'), + toPath('init-slib'), + toPath('_init-python'), +]; + +const INIT_SERVICE = [ + ...COMMON, + toPath('_node'), + toPath('init-service'), + toPath('_init-python'), +]; + + +const INIT_LIB_SLIB = Array.from(new Set([ + ...INIT_LIB, + ...INIT_SLIB, + toPath('_init-hybrid') +])); + +const INIT_LIB_SERVICE = Array.from(new Set([ + ...INIT_LIB, + ...INIT_SERVICE, + toPath('_init-hybrid') +])); + + +const INIT_APP = [ + ...COMMON, + toPath('_node'), + toPath('init-app'), + toPath('_init-web'), +]; + +const INIT_APP_SLIB = [ + ...INIT_APP, + ...INIT_SLIB, + toPath('_init-hybrid') +]; + +const INIT_PRODUCT = [ + ...COMMON, + toPath('_node'), +]; + +const SETUP_WORKSPACE=[ + ...COMMON, + toPath('workspace'), + toPath('clone-repo'), +]; + +const dependencies = { + COMMON, + INIT_LIB, + INIT_SLIB, + INIT_LIB_SLIB, + INIT_APP, + INIT_SERVICE, + INIT_APP_SLIB, + INIT_LIB_SERVICE, + INIT_PRODUCT, + SETUP_WORKSPACE +}; + +module.exports = dependencies; \ No newline at end of file diff --git a/test/init-app-slib.test.js b/test/init-app-slib.test.js index 8d3692e9..0c3a2593 100644 --- a/test/init-app-slib.test.js +++ b/test/init-app-slib.test.js @@ -6,25 +6,12 @@ const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../appslib'; -/** - * Subgenerators composed with the `init-app-slib` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_init-hybrid', - '../generators/_node', - '../generators/init-app', - '../generators/_init-web', - '../generators/init-slib', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - const expectedFiles = [ 'tsd.d.ts', 'jest.config.js', @@ -56,7 +43,7 @@ describe('generate app-slib plugin with prompt `app: appName` and the rest defau .withPrompts({ app: 'appName' }) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.INIT_APP_SLIB); }); afterAll(() => { diff --git a/test/init-app.test.js b/test/init-app.test.js index 26d55b3c..fd83bcc4 100644 --- a/test/init-app.test.js +++ b/test/init-app.test.js @@ -1,4 +1,3 @@ - 'use strict'; const path = require('path'); const assert = require('yeoman-assert'); @@ -6,23 +5,13 @@ const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../app'; -/** - * Subgenerators composed with the `init-app` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/init-lib', - '../generators/_init-web', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - const expectedFiles = [ 'tsd.d.ts', 'jest.config.js', @@ -52,7 +41,7 @@ describe('generate app plugin with prompt `app: appName` and the rest default pr .withPrompts({ app: 'appName' }) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.INIT_APP); }); afterAll(() => { diff --git a/test/init-lib-service.test.js b/test/init-lib-service.test.js index 902f9556..db7e3d30 100644 --- a/test/init-lib-service.test.js +++ b/test/init-lib-service.test.js @@ -6,25 +6,13 @@ const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); +const dependencies = require('./generator-dependencies'); + /** * Directory name to run the generator */ const target = '../libservice'; -/** - * Subgenerators composed with the `init-lib-service` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_init-hybrid', - '../generators/init-lib', - '../generators/_init-web', - '../generators/init-service', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - const expectedFiles = [ 'tsd.d.ts', 'jest.config.js' @@ -52,7 +40,7 @@ describe('generate lib-service plugin with default prompt values', () => { return helpers .run(path.join(__dirname, '../generators/init-lib-service')) .inDir(path.join(__dirname, target), () => null) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.INIT_LIB_SERVICE); }); afterAll(() => { diff --git a/test/init-lib-slib.test.js b/test/init-lib-slib.test.js index e59b5e82..63238385 100644 --- a/test/init-lib-slib.test.js +++ b/test/init-lib-slib.test.js @@ -6,25 +6,12 @@ const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../libslib'; -/** - * Subgenerators composed with the `init-lib-slib` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_init-hybrid', - '../generators/init-lib', - '../generators/_init-web', - '../generators/init-slib', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - const expectedFiles = [ 'tsd.d.ts', 'jest.config.js' @@ -52,7 +39,7 @@ describe('generate lib-slib plugin with default prompt values', () => { return helpers .run(path.join(__dirname, '../generators/init-lib-slib')) .inDir(path.join(__dirname, target), () => null) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.INIT_LIB_SLIB); }); afterAll(() => { diff --git a/test/init-lib.test.js b/test/init-lib.test.js index e5724366..a4bb8541 100644 --- a/test/init-lib.test.js +++ b/test/init-lib.test.js @@ -8,24 +8,13 @@ const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); const {template} = require('lodash'); const SpawnUtils = require('../utils/SpawnUtils'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../lib'; -/** - * Subgenerators composed with the `init-lib` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/init-lib', - '../generators/_init-web', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - - const expectedFiles = [ 'tsd.d.ts', 'jest.config.js' @@ -42,7 +31,7 @@ const unExpectedFiles = [ */ const runInitLib = () => helpers .run(path.join(__dirname, '../generators/init-lib')) - .withGenerators(GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_LIB) .inDir(path.join(__dirname, target), () => null); diff --git a/test/init-product.test.js b/test/init-product.test.js index ed819989..b7916e46 100644 --- a/test/init-product.test.js +++ b/test/init-product.test.js @@ -7,6 +7,7 @@ const rimraf = require('rimraf'); const fse = require('fs-extra'); const TestUtils = require('./TestUtils'); const {template} = require('lodash'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator @@ -27,16 +28,6 @@ const expectedFiles = [ 'LICENSE' ]; -/** - * Subgenerators composed with the `init-slib` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - - describe('generate a product with default prompt values', () => { const pluginName = 'wep_app'; @@ -61,7 +52,7 @@ describe('generate a product with default prompt values', () => { return helpers .run(path.join(__dirname, '../generators/init-product')) .inDir(path.join(__dirname, target), () => null) - .withGenerators(GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_PRODUCT) .withPrompts({ ...config, name: pluginName, diff --git a/test/init-service.test.js b/test/init-service.test.js index bba3c24a..143af6c9 100644 --- a/test/init-service.test.js +++ b/test/init-service.test.js @@ -4,28 +4,19 @@ const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../service'; -/** - * Subgenerators composed with the `init-slib` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - describe('generate service plugin with default prompt values', () => { beforeAll(() => { return helpers .run(path.join(__dirname, '../generators/init-service')) .inDir(path.join(__dirname, target), () => null) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.INIT_SERVICE); }); afterAll(() => { diff --git a/test/init-slib.test.js b/test/init-slib.test.js index d0ae5ed2..b6747f4c 100644 --- a/test/init-slib.test.js +++ b/test/init-slib.test.js @@ -4,21 +4,12 @@ const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../slib'; -/** - * Subgenerators composed with the `init-slib` subgenerator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_init-python', - '../generators/_check-own-version', - '../generators/check-node-version', -]; - describe('generate slib plugin with default prompt values', () => { @@ -26,7 +17,7 @@ describe('generate slib plugin with default prompt values', () => { return helpers .run(path.join(__dirname, '../generators/init-slib')) .inDir(path.join(__dirname, target), () => null) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.INIT_SLIB); }); afterAll(() => { diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js index 2cf0dcaf..8a58c189 100644 --- a/test/setup-workspace.test.js +++ b/test/setup-workspace.test.js @@ -11,21 +11,13 @@ const RepoUtils = require('../utils/RepoUtils'); const TestUtils = require('./TestUtils'); const SpawnUtils = require('../utils/SpawnUtils'); const {template} = require('lodash'); +const dependencies = require('./generator-dependencies'); /** * Directory name to run the generator */ const target = '../phovea_workpsace'; -/** - * Sub-generators called with the setup-workspace sub-generator. - */ -const GENERATOR_DEPENDENCIES = [ - '../generators/workspace', - '../generators/_check-own-version', - '../generators/check-node-version', - '../generators/clone-repo', -]; const product = 'org/dummy_product'; const setupWorkspace = () => helpers @@ -33,7 +25,7 @@ const setupWorkspace = () => helpers .inDir(path.join(__dirname, target), () => null) .withArguments([product]) .withOptions({ssh: true, branch: 'develop'}) - .withGenerators(GENERATOR_DEPENDENCIES); + .withGenerators(dependencies.SETUP_WORKSPACE); describe('generator setup-workspace', () => { diff --git a/test/workspace.test.js b/test/workspace.test.js index e3b8bc73..edd58343 100644 --- a/test/workspace.test.js +++ b/test/workspace.test.js @@ -4,6 +4,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const fse = require('fs-extra'); const {template} = require('lodash'); +const dependencies = require('./generator-dependencies'); /** * Get the path to the templates of a specific subgenerator. @@ -12,35 +13,6 @@ const {template} = require('lodash'); */ const templatePath = (subgenerator, file) => path.join(__dirname, `../generators/${subgenerator}/templates/${file}`); -/** - * Subgenerators composed with the `init-lib` subgenerator. - */ -const LIB_GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/init-lib', - '../generators/_init-web', - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); - -/** - * Subgenerators composed with the `init-app` subgenerator. - */ -const APP_GENERATOR_DEPENDENCIES = [ - '../generators/_node', - '../generators/_init-web', - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); - -/** - * Subgenerators composed with the `workspace` subgenerator. - */ -const WORKSPACE_GENERATOR_DEPENDENCIES = [ - '../generators/_check-own-version', - '../generators/check-node-version', -].map((d) => path.join(__dirname, d)); - const expectedFiles = [ '.idea/misc.xml', '.idea/remote-mappings.xml', @@ -112,7 +84,7 @@ describe('Run yo phovea:init-lib, yo phovea:init-app and yo:phovea:workspace seq // Run yo phovea:init-lib await helpers .run(path.join(__dirname, '../generators/init-lib')) - .withGenerators(LIB_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_LIB) .inTmpDir((dir) => { workingDirectory = dir; fse.mkdirSync(`./${libPlugin}`); @@ -122,7 +94,7 @@ describe('Run yo phovea:init-lib, yo phovea:init-app and yo:phovea:workspace seq // Run yo:phovea:init-app await helpers .run(path.join(__dirname, '../generators/init-app')) - .withGenerators(APP_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.INIT_APP) .withPrompts({ app: 'appName' }) @@ -135,7 +107,7 @@ describe('Run yo phovea:init-lib, yo phovea:init-app and yo:phovea:workspace seq // Run yo phovea:workspace await helpers .run(path.join(__dirname, '../generators/workspace')) - .withGenerators(WORKSPACE_GENERATOR_DEPENDENCIES) + .withGenerators(dependencies.COMMON) .inTmpDir(() => { workspace = workingDirectory.replace('/tmp/', ''); process.chdir(workingDirectory); From f50ec5ceb4b1d409724b1a1395cd2261bc8cbe94 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 14:57:32 +0200 Subject: [PATCH 47/65] Refactor tests phovea/generator-phovea#425 --- test/RepoUtils.test.js | 2 +- test/add-extension.test.js | 4 ++-- test/clone-repo.test.js | 2 +- test/init-app-slib.test.js | 4 ++-- test/init-app.test.js | 4 ++-- test/init-lib-service.test.js | 4 ++-- test/init-lib-slib.test.js | 4 ++-- test/init-lib.test.js | 4 ++-- test/init-product.test.js | 4 ++-- test/init-service.test.js | 2 +- test/init-slib.test.js | 2 +- test/setup-workspace.test.js | 6 +++--- test/{ => test-utils}/TestUtils.js | 3 +-- test/{ => test-utils}/generator-dependencies.js | 2 +- test/{ => test-utils}/templates/phovea_product_dummy.json | 0 test/workspace.test.js | 2 +- 16 files changed, 24 insertions(+), 25 deletions(-) rename test/{ => test-utils}/TestUtils.js (74%) rename test/{ => test-utils}/generator-dependencies.js (93%) rename test/{ => test-utils}/templates/phovea_product_dummy.json (100%) diff --git a/test/RepoUtils.test.js b/test/RepoUtils.test.js index 336c45c4..33a52549 100644 --- a/test/RepoUtils.test.js +++ b/test/RepoUtils.test.js @@ -177,7 +177,7 @@ describe('parse phovea_product.json', () => { {repo: 'phovea/phovea_data_mongo', branch: 'develop'} ]; - const dummyProduct = fs.readJSONSync(path.join(__dirname, `templates/phovea_product_dummy.json`)); + const dummyProduct = fs.readJSONSync(path.join(__dirname, `test-utils/templates/phovea_product_dummy.json`)); it('resulting object has correct structure', () => { expect(RepoUtils.parsePhoveaProduct(dummyProduct)).toStrictEqual(result); }); diff --git a/test/add-extension.test.js b/test/add-extension.test.js index 4496de84..fee3db11 100644 --- a/test/add-extension.test.js +++ b/test/add-extension.test.js @@ -4,9 +4,9 @@ const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); +const TestUtils = require('./test-utils/TestUtils'); const {template} = require('lodash'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); describe('add a web extension to a web library', () => { const tdpViewTmpl = template(fse.readFileSync(TestUtils.templatePath('add-extension', 'tdpView.tmpl.ts')))({moduleName: 'CustomView'}); diff --git a/test/clone-repo.test.js b/test/clone-repo.test.js index 56429aab..b58df091 100644 --- a/test/clone-repo.test.js +++ b/test/clone-repo.test.js @@ -4,7 +4,7 @@ const path = require('path'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const SpawnUtils = require('../utils/SpawnUtils'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); const repo = 'git@github.com:Caleydo/ordino.git'; const target = '../cloned'; diff --git a/test/init-app-slib.test.js b/test/init-app-slib.test.js index 0c3a2593..b5892f5e 100644 --- a/test/init-app-slib.test.js +++ b/test/init-app-slib.test.js @@ -5,8 +5,8 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); -const dependencies = require('./generator-dependencies'); +const TestUtils = require('./test-utils/TestUtils'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator */ diff --git a/test/init-app.test.js b/test/init-app.test.js index fd83bcc4..dcc3d4b1 100644 --- a/test/init-app.test.js +++ b/test/init-app.test.js @@ -4,8 +4,8 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); -const dependencies = require('./generator-dependencies'); +const TestUtils = require('./test-utils/TestUtils'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator diff --git a/test/init-lib-service.test.js b/test/init-lib-service.test.js index db7e3d30..3dbb60ff 100644 --- a/test/init-lib-service.test.js +++ b/test/init-lib-service.test.js @@ -5,8 +5,8 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); -const dependencies = require('./generator-dependencies'); +const TestUtils = require('./test-utils/TestUtils'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator diff --git a/test/init-lib-slib.test.js b/test/init-lib-slib.test.js index 63238385..b4cc79f1 100644 --- a/test/init-lib-slib.test.js +++ b/test/init-lib-slib.test.js @@ -5,8 +5,8 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); -const dependencies = require('./generator-dependencies'); +const TestUtils = require('./test-utils/TestUtils'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator */ diff --git a/test/init-lib.test.js b/test/init-lib.test.js index a4bb8541..8573d353 100644 --- a/test/init-lib.test.js +++ b/test/init-lib.test.js @@ -5,10 +5,10 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); +const TestUtils = require('./test-utils/TestUtils'); const {template} = require('lodash'); const SpawnUtils = require('../utils/SpawnUtils'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator diff --git a/test/init-product.test.js b/test/init-product.test.js index b7916e46..fcb12708 100644 --- a/test/init-product.test.js +++ b/test/init-product.test.js @@ -5,9 +5,9 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); const fse = require('fs-extra'); -const TestUtils = require('./TestUtils'); +const TestUtils = require('./test-utils/TestUtils'); const {template} = require('lodash'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator diff --git a/test/init-service.test.js b/test/init-service.test.js index 143af6c9..0d293df3 100644 --- a/test/init-service.test.js +++ b/test/init-service.test.js @@ -4,7 +4,7 @@ const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator */ diff --git a/test/init-slib.test.js b/test/init-slib.test.js index b6747f4c..aaa9e8e4 100644 --- a/test/init-slib.test.js +++ b/test/init-slib.test.js @@ -4,7 +4,7 @@ const path = require('path'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const rimraf = require('rimraf'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator */ diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js index 8a58c189..f929abf5 100644 --- a/test/setup-workspace.test.js +++ b/test/setup-workspace.test.js @@ -8,10 +8,10 @@ const WorkspaceUtils = require('../utils/WorkspaceUtils'); const assert = require('yeoman-assert'); const fs = require('fs-extra'); const RepoUtils = require('../utils/RepoUtils'); -const TestUtils = require('./TestUtils'); +const TestUtils = require('./test-utils/TestUtils'); const SpawnUtils = require('../utils/SpawnUtils'); const {template} = require('lodash'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Directory name to run the generator @@ -29,7 +29,7 @@ const setupWorkspace = () => helpers describe('generator setup-workspace', () => { - const phoveaProduct = fs.readJSONSync(path.join(__dirname, `templates/phovea_product_dummy.json`)); + const phoveaProduct = fs.readJSONSync(path.join(__dirname, `test-utils/templates/phovea_product_dummy.json`)); beforeAll(() => { // mock the clone-repo function WorkspaceUtils.cloneRepo = jest.fn() diff --git a/test/TestUtils.js b/test/test-utils/TestUtils.js similarity index 74% rename from test/TestUtils.js rename to test/test-utils/TestUtils.js index 3425edeb..26c2bd2b 100644 --- a/test/TestUtils.js +++ b/test/test-utils/TestUtils.js @@ -8,7 +8,6 @@ module.exports = class TestUtils { * @param {string} type Type of template, plain or processed */ static templatePath(subgenerator, fileName, type = '') { - return path.join(__dirname, `../generators/${subgenerator}/templates/${type ? type + '/' : ''}${fileName}`); + return path.join(__dirname, `../../generators/${subgenerator}/templates/${type ? type + '/' : ''}${fileName}`); } - }; \ No newline at end of file diff --git a/test/generator-dependencies.js b/test/test-utils/generator-dependencies.js similarity index 93% rename from test/generator-dependencies.js rename to test/test-utils/generator-dependencies.js index b1f85f8f..f2628f02 100644 --- a/test/generator-dependencies.js +++ b/test/test-utils/generator-dependencies.js @@ -1,7 +1,7 @@ 'use-strict'; const path = require('path'); -const toPath = (generator) => path.join(__dirname, '../generators/', generator); +const toPath = (generator) => path.join(__dirname, '../../generators/', generator); const COMMON = [ toPath('_check-own-version'), diff --git a/test/templates/phovea_product_dummy.json b/test/test-utils/templates/phovea_product_dummy.json similarity index 100% rename from test/templates/phovea_product_dummy.json rename to test/test-utils/templates/phovea_product_dummy.json diff --git a/test/workspace.test.js b/test/workspace.test.js index edd58343..413187b2 100644 --- a/test/workspace.test.js +++ b/test/workspace.test.js @@ -4,7 +4,7 @@ const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); const fse = require('fs-extra'); const {template} = require('lodash'); -const dependencies = require('./generator-dependencies'); +const dependencies = require('./test-utils/generator-dependencies'); /** * Get the path to the templates of a specific subgenerator. From db6be89ed42de3766898a72abac31450973fcbd8 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 15:04:14 +0200 Subject: [PATCH 48/65] Change folder structure of the tests phovea/generator-phovea#425 --- test/{ => utils}/GeneratorUtils.test.js | 3 +-- test/{ => utils}/NpmUtils.test.js | 2 +- test/{ => utils}/PipUtils.test.js | 2 +- test/{ => utils}/RepoUtils.test.js | 8 ++++---- test/{ => utils}/WorkspaceUtils.test.js | 6 +++--- test/{ => utils}/utils-installedVersions.test.js | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) rename test/{ => utils}/GeneratorUtils.test.js (98%) rename test/{ => utils}/NpmUtils.test.js (99%) rename test/{ => utils}/PipUtils.test.js (98%) rename test/{ => utils}/RepoUtils.test.js (96%) rename test/{ => utils}/WorkspaceUtils.test.js (96%) rename test/{ => utils}/utils-installedVersions.test.js (98%) diff --git a/test/GeneratorUtils.test.js b/test/utils/GeneratorUtils.test.js similarity index 98% rename from test/GeneratorUtils.test.js rename to test/utils/GeneratorUtils.test.js index 75bf1f06..c8396f11 100644 --- a/test/GeneratorUtils.test.js +++ b/test/utils/GeneratorUtils.test.js @@ -1,10 +1,9 @@ 'use strict'; -const GeneratorUtils = require('../utils/GeneratorUtils'); +const GeneratorUtils = require('../../utils/GeneratorUtils'); describe('Test `stringifyInline()` correctly stringifies object', () => { - it('adds 1 space', () => { const obj = {key1: 'value1', key2: 'value2'}; const space = ' '; diff --git a/test/NpmUtils.test.js b/test/utils/NpmUtils.test.js similarity index 99% rename from test/NpmUtils.test.js rename to test/utils/NpmUtils.test.js index d214d516..77115171 100644 --- a/test/NpmUtils.test.js +++ b/test/utils/NpmUtils.test.js @@ -1,5 +1,5 @@ 'use strict'; -const NpmUtils = require('../utils/NpmUtils'); +const NpmUtils = require('../../utils/NpmUtils'); describe('mergeVersions list of versions with github or gitlab version tags', () => { diff --git a/test/PipUtils.test.js b/test/utils/PipUtils.test.js similarity index 98% rename from test/PipUtils.test.js rename to test/utils/PipUtils.test.js index d5a79b6c..cf949f82 100644 --- a/test/PipUtils.test.js +++ b/test/utils/PipUtils.test.js @@ -1,5 +1,5 @@ 'use strict'; -const PipUtils = require('../utils/PipUtils'); +const PipUtils = require('../../utils/PipUtils'); describe('find intersection list of pip versions', () => { const pipPackage = 'alembic'; diff --git a/test/RepoUtils.test.js b/test/utils/RepoUtils.test.js similarity index 96% rename from test/RepoUtils.test.js rename to test/utils/RepoUtils.test.js index 33a52549..9e551724 100644 --- a/test/RepoUtils.test.js +++ b/test/utils/RepoUtils.test.js @@ -1,10 +1,10 @@ 'use strict'; -const RepoUtils = require('../utils/RepoUtils'); +const RepoUtils = require('../../utils/RepoUtils'); const fs = require('fs-extra'); const path = require('path'); -const known = require('../utils/known'); +const known = require('../../utils/known'); -jest.mock('../utils/known', () => { +jest.mock('../../utils/known', () => { return { plugin: { byName: jest.fn() @@ -177,7 +177,7 @@ describe('parse phovea_product.json', () => { {repo: 'phovea/phovea_data_mongo', branch: 'develop'} ]; - const dummyProduct = fs.readJSONSync(path.join(__dirname, `test-utils/templates/phovea_product_dummy.json`)); + const dummyProduct = fs.readJSONSync(path.join(__dirname, `../test-utils/templates/phovea_product_dummy.json`)); it('resulting object has correct structure', () => { expect(RepoUtils.parsePhoveaProduct(dummyProduct)).toStrictEqual(result); }); diff --git a/test/WorkspaceUtils.test.js b/test/utils/WorkspaceUtils.test.js similarity index 96% rename from test/WorkspaceUtils.test.js rename to test/utils/WorkspaceUtils.test.js index de95b901..a8aa0b4d 100644 --- a/test/WorkspaceUtils.test.js +++ b/test/utils/WorkspaceUtils.test.js @@ -1,6 +1,6 @@ 'use strict'; -const WorkspaceUtils = require('../utils/WorkspaceUtils'); -jest.mock('../utils/known'); +const WorkspaceUtils = require('../../utils/WorkspaceUtils'); +jest.mock('../../utils/known'); describe('Find default app in product object', () => { @@ -58,7 +58,7 @@ describe('Find default app in product object', () => { describe('Test `buildPossibleAdditionalPlugins()`', () => { - const known = require('../utils/known'); + const known = require('../../utils/known'); known.plugin = { listWeb: [{ "name": "phovea_core", diff --git a/test/utils-installedVersions.test.js b/test/utils/utils-installedVersions.test.js similarity index 98% rename from test/utils-installedVersions.test.js rename to test/utils/utils-installedVersions.test.js index 3f4f068e..3791e026 100644 --- a/test/utils-installedVersions.test.js +++ b/test/utils/utils-installedVersions.test.js @@ -1,5 +1,5 @@ 'use strict'; -const installedVersions = require('../utils/installedVersions'); +const installedVersions = require('../../utils/installedVersions'); describe('installedVersions() behaves as expected', () => { beforeEach(() => { From 8714ae4165b8053e1dab916c38f923dab72e3c32 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 25 Sep 2020 15:10:05 +0200 Subject: [PATCH 49/65] FIx path in tests phovea/generator-phovea#425 --- test/add-extension.test.js | 1 + test/check-node-version.test.js | 1 - test/setup-workspace.test.js | 2 +- test/utils/RepoUtils.test.js | 4 +--- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/test/add-extension.test.js b/test/add-extension.test.js index fee3db11..a1249c8b 100644 --- a/test/add-extension.test.js +++ b/test/add-extension.test.js @@ -21,6 +21,7 @@ describe('add a web extension to a web library', () => { config.database=MyDB ` }; + beforeAll(async () => { let workingDirectory; // initialize a dummy web library diff --git a/test/check-node-version.test.js b/test/check-node-version.test.js index d5cfed51..aab9ad7a 100644 --- a/test/check-node-version.test.js +++ b/test/check-node-version.test.js @@ -41,7 +41,6 @@ describe('check-node-version', () => { check.mockImplementation((_, cb) => cb(false, results)); - beforeAll(() => { return helpers .run(path.join(__dirname, '../generators/check-node-version')); diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js index f929abf5..ff4f76f7 100644 --- a/test/setup-workspace.test.js +++ b/test/setup-workspace.test.js @@ -29,7 +29,7 @@ const setupWorkspace = () => helpers describe('generator setup-workspace', () => { - const phoveaProduct = fs.readJSONSync(path.join(__dirname, `test-utils/templates/phovea_product_dummy.json`)); + const phoveaProduct = require(`./test-utils/templates/phovea_product_dummy.json`); beforeAll(() => { // mock the clone-repo function WorkspaceUtils.cloneRepo = jest.fn() diff --git a/test/utils/RepoUtils.test.js b/test/utils/RepoUtils.test.js index 9e551724..96b3a1f5 100644 --- a/test/utils/RepoUtils.test.js +++ b/test/utils/RepoUtils.test.js @@ -1,7 +1,5 @@ 'use strict'; const RepoUtils = require('../../utils/RepoUtils'); -const fs = require('fs-extra'); -const path = require('path'); const known = require('../../utils/known'); jest.mock('../../utils/known', () => { @@ -177,7 +175,7 @@ describe('parse phovea_product.json', () => { {repo: 'phovea/phovea_data_mongo', branch: 'develop'} ]; - const dummyProduct = fs.readJSONSync(path.join(__dirname, `../test-utils/templates/phovea_product_dummy.json`)); + const dummyProduct = require('../test-utils/templates/phovea_product_dummy.json'); it('resulting object has correct structure', () => { expect(RepoUtils.parsePhoveaProduct(dummyProduct)).toStrictEqual(result); }); From 46276642ce0378ad633766af1c849c414bb3c92a Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 30 Oct 2020 10:52:13 +0100 Subject: [PATCH 50/65] Use single instead of double quotes phovea/generator-phovea#428 --- base/BaseInitHybridGenerator.js | 2 +- generators/init-app-slib/index.js | 2 +- generators/init-bundle/index.js | 2 +- generators/init-lib-service/index.js | 2 +- generators/init-service/index.js | 2 +- test/init-product.test.js | 8 ++-- test/utils/PipUtils.test.js | 10 ++-- test/utils/RepoUtils.test.js | 8 ++-- test/utils/WorkspaceUtils.test.js | 70 ++++++++++++++-------------- 9 files changed, 53 insertions(+), 53 deletions(-) diff --git a/base/BaseInitHybridGenerator.js b/base/BaseInitHybridGenerator.js index 00b525a9..f6f93e30 100644 --- a/base/BaseInitHybridGenerator.js +++ b/base/BaseInitHybridGenerator.js @@ -1,5 +1,5 @@ 'use strict'; -const BaseInitPluginGenerator = require("./BaseInitPluginGenerator"); +const BaseInitPluginGenerator = require('./BaseInitPluginGenerator'); class BaseInitHybridGenerator extends BaseInitPluginGenerator { diff --git a/generators/init-app-slib/index.js b/generators/init-app-slib/index.js index dc80b4df..2868d0d6 100644 --- a/generators/init-app-slib/index.js +++ b/generators/init-app-slib/index.js @@ -1,6 +1,6 @@ 'use strict'; -const BaseInitHybridGenerator = require("../init-lib-service"); +const BaseInitHybridGenerator = require('../init-lib-service'); class PluginGenerator extends BaseInitHybridGenerator { diff --git a/generators/init-bundle/index.js b/generators/init-bundle/index.js index 5cddcebd..8a3100af 100644 --- a/generators/init-bundle/index.js +++ b/generators/init-bundle/index.js @@ -1,4 +1,4 @@ 'use strict'; -const BaseInitPluginGenerator = require("../../base/BaseInitPluginGenerator"); +const BaseInitPluginGenerator = require('../../base/BaseInitPluginGenerator'); module.exports = BaseInitPluginGenerator; diff --git a/generators/init-lib-service/index.js b/generators/init-lib-service/index.js index 9315f2cb..c7ee5dfa 100644 --- a/generators/init-lib-service/index.js +++ b/generators/init-lib-service/index.js @@ -1,4 +1,4 @@ 'use strict'; -const BaseInitHybridGenerator = require("../../base/BaseInitHybridGenerator"); +const BaseInitHybridGenerator = require('../../base/BaseInitHybridGenerator'); module.exports = BaseInitHybridGenerator; diff --git a/generators/init-service/index.js b/generators/init-service/index.js index 5e2481f6..1f050f85 100644 --- a/generators/init-service/index.js +++ b/generators/init-service/index.js @@ -1,6 +1,6 @@ 'use strict'; -const BaseInitServerGenerator = require("../../base/BaseInitServerGenerator"); +const BaseInitServerGenerator = require('../../base/BaseInitServerGenerator'); class Generator extends BaseInitServerGenerator { initializing() { diff --git a/test/init-product.test.js b/test/init-product.test.js index fcb12708..2dafe880 100644 --- a/test/init-product.test.js +++ b/test/init-product.test.js @@ -40,11 +40,11 @@ describe('generate a product with default prompt values', () => { repo: 'phovea/wep_app', branch: 'master', additional: [{ - "name": "phovea_core", - "repo": "phovea/phovea_core", + 'name': 'phovea_core', + 'repo': 'phovea/phovea_core', }, { - "name": "phovea_ui", - "repo": "phovea/phovea_ui", + 'name': 'phovea_ui', + 'repo': 'phovea/phovea_ui', }] }; diff --git a/test/utils/PipUtils.test.js b/test/utils/PipUtils.test.js index cf949f82..698c1b70 100644 --- a/test/utils/PipUtils.test.js +++ b/test/utils/PipUtils.test.js @@ -105,11 +105,11 @@ describe('parse requirements.txt into an object', () => { `; const result = { - "flake8": "^=3.7.9", - "pep8-naming": "~=0.9.1", - "pytest": "==5.3.5", - "-e git+https://github.com/datavisyn/tdp_core.git": "@develop#egg=tdp_core", - "-e git+https://github.com/phovea/phovea_server.git": "@develop#egg=phovea_server" + 'flake8': '^=3.7.9', + 'pep8-naming': '~=0.9.1', + 'pytest': '==5.3.5', + '-e git+https://github.com/datavisyn/tdp_core.git': '@develop#egg=tdp_core', + '-e git+https://github.com/phovea/phovea_server.git': '@develop#egg=phovea_server' }; expect(PipUtils.parseRequirements(file)).toEqual(result); }); diff --git a/test/utils/RepoUtils.test.js b/test/utils/RepoUtils.test.js index 96b3a1f5..9088129d 100644 --- a/test/utils/RepoUtils.test.js +++ b/test/utils/RepoUtils.test.js @@ -16,7 +16,7 @@ jest.mock('../../utils/known', () => { const mockedPlugin = { name: 'phovea_core', libraries: [ - "d3" + 'd3' ], externals: [ 'bootstrap-sass' @@ -26,13 +26,13 @@ const mockedPlugin = { const mockedLib = { name: 'font-awesome', libraries: [ - "jquery", + 'jquery', ], externals: [ 'marked' ], aliases: { - 'd3': "d3/d3", + 'd3': 'd3/d3', 'font-awesome': 'fw/font-awesome' } @@ -184,7 +184,7 @@ describe('parse phovea_product.json', () => { describe('test toLibraryAliasMap works as expected', () => { const aliases = { - 'd3': "d3/d3", + 'd3': 'd3/d3', 'font-awesome': 'fw/font-awesome' }; diff --git a/test/utils/WorkspaceUtils.test.js b/test/utils/WorkspaceUtils.test.js index a8aa0b4d..ebb68535 100644 --- a/test/utils/WorkspaceUtils.test.js +++ b/test/utils/WorkspaceUtils.test.js @@ -31,14 +31,14 @@ describe('Find default app in product object', () => { branch: 'develop', additional: [ { - "name": "phovea_core", - "repo": "phovea/phovea_core", - "branch": "develop" + 'name': 'phovea_core', + 'repo': 'phovea/phovea_core', + 'branch': 'develop' }, { - "name": "phovea_ui", - "repo": "phovea/phovea_ui", - "branch": "develop" + 'name': 'phovea_ui', + 'repo': 'phovea/phovea_ui', + 'branch': 'develop' } ] @@ -61,31 +61,31 @@ describe('Test `buildPossibleAdditionalPlugins()`', () => { const known = require('../../utils/known'); known.plugin = { listWeb: [{ - "name": "phovea_core", - "type": "lib", - "description": "Phovea Core Plugin", - "repository": "https://github.com/phovea/phovea_core.git", - "dependencies": { - "phovea_core": "^4.0.0" + 'name': 'phovea_core', + 'type': 'lib', + 'description': 'Phovea Core Plugin', + 'repository': 'https://github.com/phovea/phovea_core.git', + 'dependencies': { + 'phovea_core': '^4.0.0' }, - "develop": { - "dependencies": { - "phovea_core": "github:phovea/phovea_core#develop" + 'develop': { + 'dependencies': { + 'phovea_core': 'github:phovea/phovea_core#develop' } }, - "libraries": [] + 'libraries': [] },], listServer: [{ - "name": "phovea_server", - "type": "service", - "description": "Phovea Server Plugin", - "repository": "https://github.com/phovea/phovea_server.git", - "requirements": { - "phovea_server": ">=5.0.1,<6.0.0" + 'name': 'phovea_server', + 'type': 'service', + 'description': 'Phovea Server Plugin', + 'repository': 'https://github.com/phovea/phovea_server.git', + 'requirements': { + 'phovea_server': '>=5.0.1,<6.0.0' }, - "develop": { - "requirements": { - "-e git+https://github.com/phovea/phovea_server.git": "@develop#egg=phovea_server" + 'develop': { + 'requirements': { + '-e git+https://github.com/phovea/phovea_server.git': '@develop#egg=phovea_server' } } }], @@ -93,11 +93,11 @@ describe('Test `buildPossibleAdditionalPlugins()`', () => { it('builds additional web plugins', () => { const result = [{ - "name": "phovea_core: Phovea Core Plugin", - "short": "phovea_core", - "value": { - "name": "phovea_core", - "repo": "phovea/phovea_core", + 'name': 'phovea_core: Phovea Core Plugin', + 'short': 'phovea_core', + 'value': { + 'name': 'phovea_core', + 'repo': 'phovea/phovea_core', }, }]; expect(WorkspaceUtils.buildPossibleAdditionalPlugins('web')).toMatchObject(result); @@ -106,11 +106,11 @@ describe('Test `buildPossibleAdditionalPlugins()`', () => { it('builds additional python plugins', () => { const result = [{ - "name": "phovea_server: Phovea Server Plugin", - "short": "phovea_server", - "value": { - "name": "phovea_server", - "repo": "phovea/phovea_server", + 'name': 'phovea_server: Phovea Server Plugin', + 'short': 'phovea_server', + 'value': { + 'name': 'phovea_server', + 'repo': 'phovea/phovea_server', }, }]; expect(WorkspaceUtils.buildPossibleAdditionalPlugins('python')).toMatchObject(result); From e59fa086c407a264d3f19210242019c66a55758d Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 30 Oct 2020 11:55:29 +0100 Subject: [PATCH 51/65] Use enum for basetypes phovea/generator-phovea#428 --- base/BaseInitHybridGenerator.js | 3 ++- base/BaseInitPluginGenerator.js | 3 ++- base/BaseInitServerGenerator.js | 3 ++- base/config.js | 13 +++++++++++++ test/add-extension.test.js | 5 +++-- 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 base/config.js diff --git a/base/BaseInitHybridGenerator.js b/base/BaseInitHybridGenerator.js index f6f93e30..a164d5ea 100644 --- a/base/BaseInitHybridGenerator.js +++ b/base/BaseInitHybridGenerator.js @@ -1,10 +1,11 @@ 'use strict'; const BaseInitPluginGenerator = require('./BaseInitPluginGenerator'); +const {basetype} = require('./config'); class BaseInitHybridGenerator extends BaseInitPluginGenerator { constructor(args, options) { - super(args, options, 'hybrid'); + super(args, options, basetype.HYBRID); } initializing() { diff --git a/base/BaseInitPluginGenerator.js b/base/BaseInitPluginGenerator.js index 98bcc663..a7bd609a 100644 --- a/base/BaseInitPluginGenerator.js +++ b/base/BaseInitPluginGenerator.js @@ -4,13 +4,14 @@ const fs = require('fs-extra'); const chalk = require('chalk'); const GeneratorUtils = require('../utils/GeneratorUtils'); const BasePhoveaGenerator = require('../base/BasePhoveaGenerator'); +const config= require('./config'); class BaseInitPluginGenerator extends BasePhoveaGenerator { constructor(args, options, basetype) { super(args, options); this.type = path.basename(path.dirname(this.resolved)).substring(5); // init-web ... web - this.basetype = basetype || 'web'; + this.basetype = basetype || config.basetype.WEB; // Make options available this.option('skipInstall'); this.option('noSamples'); diff --git a/base/BaseInitServerGenerator.js b/base/BaseInitServerGenerator.js index 0a313075..f384884e 100644 --- a/base/BaseInitServerGenerator.js +++ b/base/BaseInitServerGenerator.js @@ -1,11 +1,12 @@ 'use strict'; const BaseInitPluginGenerator = require('./BaseInitPluginGenerator'); +const {basetype} = require('./config'); class BaseInitServerGenerator extends BaseInitPluginGenerator { constructor(args, options) { - super(args, options, 'python'); + super(args, options, basetype.PYTHON); } initializing() { diff --git a/base/config.js b/base/config.js new file mode 100644 index 00000000..e74de0dc --- /dev/null +++ b/base/config.js @@ -0,0 +1,13 @@ + +/** + * Base classes types each plugin type can belong to. + */ +const basetype = { + PYTHON: 'python', + WEB: 'web', + HYBRID: 'hybrid' +}; + +module.exports = { + basetype +}; diff --git a/test/add-extension.test.js b/test/add-extension.test.js index a1249c8b..7f5305cd 100644 --- a/test/add-extension.test.js +++ b/test/add-extension.test.js @@ -7,6 +7,7 @@ const fse = require('fs-extra'); const TestUtils = require('./test-utils/TestUtils'); const {template} = require('lodash'); const dependencies = require('./test-utils/generator-dependencies'); +const {basetype} = require('../base/config'); describe('add a web extension to a web library', () => { const tdpViewTmpl = template(fse.readFileSync(TestUtils.templatePath('add-extension', 'tdpView.tmpl.ts')))({moduleName: 'CustomView'}); @@ -98,7 +99,7 @@ describe('add a python extension to a python plugin', () => { describe('add a web extension to a hybrid plugin', () => { const prompts = { - basetype: 'web', + basetype: basetype.WEB, type: 'tdpScore', id: 'score_id', module: 'SingleScore', @@ -137,7 +138,7 @@ describe('add a web extension from the workspace', () => { const cwd = process.cwd(); const libPlugin = 'libPLugin'; const prompts = { - basetype: 'web', + basetype: basetype.WEB, type: 'tdpScore', id: 'score_id', module: 'SingleScore', From f22f93da4e0b717e2075e10307cb32300e5d71a7 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Fri, 30 Oct 2020 12:10:35 +0100 Subject: [PATCH 52/65] Format --- base/BaseInitPluginGenerator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/BaseInitPluginGenerator.js b/base/BaseInitPluginGenerator.js index a7bd609a..cfdac9ed 100644 --- a/base/BaseInitPluginGenerator.js +++ b/base/BaseInitPluginGenerator.js @@ -4,7 +4,7 @@ const fs = require('fs-extra'); const chalk = require('chalk'); const GeneratorUtils = require('../utils/GeneratorUtils'); const BasePhoveaGenerator = require('../base/BasePhoveaGenerator'); -const config= require('./config'); +const config = require('./config'); class BaseInitPluginGenerator extends BasePhoveaGenerator { From e459909f2c342c031790d54c179f53c1a09e982d Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 26 Nov 2020 09:26:02 +0100 Subject: [PATCH 53/65] Do not log error twice --- utils/SpawnUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/SpawnUtils.js b/utils/SpawnUtils.js index 94222328..43f561ce 100644 --- a/utils/SpawnUtils.js +++ b/utils/SpawnUtils.js @@ -14,7 +14,6 @@ module.exports = class SpawnUtils { const result = SpawnUtils.spawnSync(cmd, argline, cwd, verbose); const stdout = result.stdout; if (SpawnUtils.failed(result)) { - console.log(result.stderr.toString()); return SpawnUtils.abort(`Failed: "${cmd} ${Array.isArray(argline) ? argline.join(' ') : argline}" - status code: ${result.status}`); } else if (stdout && stdout.toString()) { From 0d3305a11d0715ffa8d848d4fbc54ea177e7ceb5 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 26 Nov 2020 09:44:28 +0100 Subject: [PATCH 54/65] Extend tests --- test/init-app-slib.test.js | 4 ++++ test/init-app.test.js | 4 ++++ test/init-lib-service.test.js | 4 ++++ test/init-lib-slib.test.js | 4 ++++ test/init-lib.test.js | 4 ++++ test/init-product.test.js | 4 ++++ test/init-service.test.js | 4 ++++ test/init-slib.test.js | 4 ++++ 8 files changed, 32 insertions(+) diff --git a/test/init-app-slib.test.js b/test/init-app-slib.test.js index b5892f5e..20422af2 100644 --- a/test/init-app-slib.test.js +++ b/test/init-app-slib.test.js @@ -71,6 +71,10 @@ describe('generate app-slib plugin with prompt `app: appName` and the rest defau assert.jsonFileContent('tsconfig.json', initWebTsConfig); }); + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'app-slib'}}); + }); + it('generates no `tsconfig_dev.json`', () => { assert.noFile('tsconfig_dev.json'); }); diff --git a/test/init-app.test.js b/test/init-app.test.js index dcc3d4b1..cb63c153 100644 --- a/test/init-app.test.js +++ b/test/init-app.test.js @@ -68,6 +68,10 @@ describe('generate app plugin with prompt `app: appName` and the rest default pr assert.jsonFileContent('tsconfig.json', initWebTsConfig); }); + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'app'}}); + }); + it('generates no `tsconfig_dev.json`', () => { assert.noFile('tsconfig_dev.json'); }); diff --git a/test/init-lib-service.test.js b/test/init-lib-service.test.js index 3dbb60ff..d6d114a7 100644 --- a/test/init-lib-service.test.js +++ b/test/init-lib-service.test.js @@ -67,6 +67,10 @@ describe('generate lib-service plugin with default prompt values', () => { assert.jsonFileContent('tsconfig.json', initWebTsConfig); }); + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'lib-service'}}); + }); + it('generates no `tsconfig_dev.json`', () => { assert.noFile('tsconfig_dev.json'); }); diff --git a/test/init-lib-slib.test.js b/test/init-lib-slib.test.js index b4cc79f1..1b2dce33 100644 --- a/test/init-lib-slib.test.js +++ b/test/init-lib-slib.test.js @@ -66,6 +66,10 @@ describe('generate lib-slib plugin with default prompt values', () => { assert.jsonFileContent('tsconfig.json', initWebTsConfig); }); + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'lib-slib'}}); + }); + it('generates no `tsconfig_dev.json`', () => { assert.noFile('tsconfig_dev.json'); }); diff --git a/test/init-lib.test.js b/test/init-lib.test.js index 8573d353..59943a91 100644 --- a/test/init-lib.test.js +++ b/test/init-lib.test.js @@ -75,6 +75,10 @@ describe('Generate lib plugin with default prompt values', () => { assert.jsonFileContent('tsconfig.json', initWebTsConfig); }); + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'lib'}}); + }); + it('generates no `tsconfig_dev.json`', () => { assert.noFile('tsconfig_dev.json'); }); diff --git a/test/init-product.test.js b/test/init-product.test.js index 2dafe880..c794355d 100644 --- a/test/init-product.test.js +++ b/test/init-product.test.js @@ -76,4 +76,8 @@ describe('generate a product with default prompt values', () => { it('generates `phovea_product.json` with the correct service', () => { assert.jsonFileContent('phovea_product.json', [config]); }); + + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'product'}}); + }); }); \ No newline at end of file diff --git a/test/init-service.test.js b/test/init-service.test.js index 0d293df3..fa203e34 100644 --- a/test/init-service.test.js +++ b/test/init-service.test.js @@ -26,4 +26,8 @@ describe('generate service plugin with default prompt values', () => { it('generates `package.json` with no devDependencies', () => { assert.jsonFileContent('package.json', {devDependencies: undefined}); }); + + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'service'}}); + }); }); diff --git a/test/init-slib.test.js b/test/init-slib.test.js index aaa9e8e4..00c4995b 100644 --- a/test/init-slib.test.js +++ b/test/init-slib.test.js @@ -35,4 +35,8 @@ describe('generate slib plugin with default prompt values', () => { it('generates `package.json` with a no `types`', () => { assert.jsonFileContent('package.json', {types: undefined}); }); + + it('generates `.yo-rc.json` with correct type', () => { + assert.jsonFileContent('.yo-rc.json', {"generator-phovea": {type: 'slib'}}); + }); }); From 6f3502877ebeaaf50d8922e263aae894e46a9ef1 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 26 Nov 2020 11:30:25 +0100 Subject: [PATCH 55/65] Minor fix --- generators/setup-workspace/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/generators/setup-workspace/index.js b/generators/setup-workspace/index.js index 630d4437..7272aa17 100644 --- a/generators/setup-workspace/index.js +++ b/generators/setup-workspace/index.js @@ -100,13 +100,12 @@ class Generator extends Base { * Removes/renames files of the cloned product that conflict with the workspace files. */ _removeUnnecessaryProductFiles() { - try { + if (fs.existsSync(this.cwd + '/.yo-rc.json')) { fs.unlinkSync(this.cwd + '/.yo-rc.json'); - fs.rmdirSync(this.cwd + '/.git', {recursive: true}); // TODO look into git submodules - fs.renameSync(this.cwd + '/package.json', this.cwd + '/package_product.json'); - } catch (e) { - this.log(e.message); } + + fs.rmdirSync(this.cwd + '/.git', { recursive: true }); // TODO look into git submodules + fs.renameSync(this.cwd + '/package.json', this.cwd + '/package_product.json'); } /** From 58351967bd12e7e2befd9692796a6c1e9717f97e Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 26 Nov 2020 12:09:41 +0100 Subject: [PATCH 56/65] Fix test --- test/setup-workspace.test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/test/setup-workspace.test.js b/test/setup-workspace.test.js index ff4f76f7..9ab45e65 100644 --- a/test/setup-workspace.test.js +++ b/test/setup-workspace.test.js @@ -40,6 +40,7 @@ describe('generator setup-workspace', () => { fs.mkdirSync('dummy/templates/web/deploy/web', {recursive: true}); fs.writeFileSync('dummy/templates/web/deploy/web/Dockerfile', 'dummy_content'); + fs.writeJSON(cwd + '/package.json', {}); return fs.writeJSON(cwd + '/phovea_product.json', phoveaProduct); }) .mockImplementation(() => Promise.resolve(null)); // just resolve promise after the firts call From 9772d5d9a6f77456fbc277e5ec8e4e853a5f686f Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 26 Nov 2020 14:54:22 +0100 Subject: [PATCH 57/65] Remove cwd from config --- base/BaseInitPluginGenerator.js | 2 +- generators/init-app/index.js | 3 +-- generators/init-service/index.js | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/base/BaseInitPluginGenerator.js b/base/BaseInitPluginGenerator.js index cfdac9ed..261d06a0 100644 --- a/base/BaseInitPluginGenerator.js +++ b/base/BaseInitPluginGenerator.js @@ -78,7 +78,7 @@ class BaseInitPluginGenerator extends BasePhoveaGenerator { writing() { const config = this.config.getAll(); - this._createSubDir(config.cwd || config.name); + this._createSubDir(config.name); if (fs.existsSync(this.templatePath('package.tmpl.json'))) { this._patchPackageJSON(config, null, null, this.cwd); } diff --git a/generators/init-app/index.js b/generators/init-app/index.js index c57ccaf7..58b18e84 100644 --- a/generators/init-app/index.js +++ b/generators/init-app/index.js @@ -39,7 +39,6 @@ class PluginGenerator extends BaseInitPluginGenerator { }]).then((props) => { this.config.set('app', props.app); this.config.set('clientOnly', props.clientOnly); - this.config.set('cwd', props.app); }); } @@ -49,7 +48,7 @@ class PluginGenerator extends BaseInitPluginGenerator { writing() { const config = this.config.getAll(); - this._createSubDir(config.cwd); + this._createSubDir(config.app); this._patchPackageJSON(config, ['main'], null, this.cwd); this._writeTemplates(config, !this.options.noSamples, this.cwd); } diff --git a/generators/init-service/index.js b/generators/init-service/index.js index 1f050f85..82ac211d 100644 --- a/generators/init-service/index.js +++ b/generators/init-service/index.js @@ -21,7 +21,6 @@ class Generator extends BaseInitServerGenerator { default: this.config.get('serviceName') }]).then(({serviceName}) => { this.config.set('serviceName', serviceName); - this.config.set('cwd', serviceName); }); } From 819c6f80467bdcfcf2b498d3d2b54b626ba98a88 Mon Sep 17 00:00:00 2001 From: anita-steiner Date: Mon, 30 Nov 2020 06:54:23 +0100 Subject: [PATCH 58/65] add space --- generators/_init-web/templates/plain/tsconfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/_init-web/templates/plain/tsconfig.json b/generators/_init-web/templates/plain/tsconfig.json index d147b214..e7bc9b2d 100644 --- a/generators/_init-web/templates/plain/tsconfig.json +++ b/generators/_init-web/templates/plain/tsconfig.json @@ -16,7 +16,7 @@ "esModuleInterop": false, "resolveJsonModule": true, "allowSyntheticDefaultImports": true, - "preserveWatchOutput":true + "preserveWatchOutput": true }, "include": [ "src/**/*.ts", From 36bd182ab6faf67de0eba350a80dd9b41042babb Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Mon, 30 Nov 2020 11:39:12 +0100 Subject: [PATCH 59/65] Copy templates in correct subdir --- base/BaseInitPluginGenerator.js | 2 +- base/BasePhoveaGenerator.js | 2 +- generators/_init-python/index.js | 2 +- generators/_init-web/index.js | 2 +- generators/_node/index.js | 2 +- generators/init-slib/index.js | 7 +++++-- utils/GeneratorUtils.js | 1 - 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/base/BaseInitPluginGenerator.js b/base/BaseInitPluginGenerator.js index 261d06a0..12e02fa8 100644 --- a/base/BaseInitPluginGenerator.js +++ b/base/BaseInitPluginGenerator.js @@ -78,7 +78,7 @@ class BaseInitPluginGenerator extends BasePhoveaGenerator { writing() { const config = this.config.getAll(); - this._createSubDir(config.name); + this._createSubDir(config.app || config.serviceName || config.name); if (fs.existsSync(this.templatePath('package.tmpl.json'))) { this._patchPackageJSON(config, null, null, this.cwd); } diff --git a/base/BasePhoveaGenerator.js b/base/BasePhoveaGenerator.js index c3c40341..05c32f53 100644 --- a/base/BasePhoveaGenerator.js +++ b/base/BasePhoveaGenerator.js @@ -84,7 +84,7 @@ class BasePhoveaGenerator extends Generator { if (fs.existsSync(this.templatePath(prefix + 'pluginname_plain'))) { this.fs.copy(this.templatePath(prefix + 'pluginname_plain/**/*'), this.destinationPath(cwd + config.name.toLowerCase() + '/'), includeDot); } - copyTpl(this.templatePath(prefix + 'pluginname_processed'), cwd + config.name.toLowerCase() + '/', false); + copyTpl(this.templatePath(prefix + 'pluginname_processed'), config.name.toLowerCase() + '/', false); } }; copy(''); diff --git a/generators/_init-python/index.js b/generators/_init-python/index.js index 397c76e5..b0de8053 100644 --- a/generators/_init-python/index.js +++ b/generators/_init-python/index.js @@ -106,7 +106,7 @@ class Generator extends BasePhoveaGenerator { } writing() { const config = this.config.getAll(); - this.cwd = this.options.isWorkspace ? (config.cwd || config.name) + '/' : ''; + this.cwd = this.options.isWorkspace ? (config.app || config.serviceName || config.name) + '/' : ''; const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); const deps = this._generateDependencies(NpmUtils.useDevVersion(version), this.cwd); diff --git a/generators/_init-web/index.js b/generators/_init-web/index.js index 4ab7c0ef..9c9ed19a 100644 --- a/generators/_init-web/index.js +++ b/generators/_init-web/index.js @@ -87,7 +87,7 @@ class Generator extends BasePhoveaGenerator { writing() { const config = this.config.getAll(); - this.cwd = this.options.isWorkspace ? (config.app || config.name) + '/' : ''; + this.cwd = this.options.isWorkspace ? (config.app || config.serviceName|| config.name) + '/' : ''; const {version} = this.fs.readJSON(this.destinationPath(this.cwd + 'package.json'), {version: '1.0.0'}); this._patchPackageJSON(config, [], { diff --git a/generators/_node/index.js b/generators/_node/index.js index 95bdef70..a5192294 100644 --- a/generators/_node/index.js +++ b/generators/_node/index.js @@ -134,7 +134,7 @@ class PackageJSONGenerator extends BasePhoveaGenerator { writing() { const config = _.extend({}, this.props, this.config.getAll()); - this.cwd = this.isWorkspace ? (config.cwd || config.name) + '/' : ''; // use config.cwd for init-app or init-service generators and config.name for the rest. + this.cwd = this.isWorkspace ? (config.app || config.serviceName || config.name) + '/' : ''; if (this.originUrl) { config.repository = this.originUrl; } else { diff --git a/generators/init-slib/index.js b/generators/init-slib/index.js index 0f79f8cc..29b50749 100644 --- a/generators/init-slib/index.js +++ b/generators/init-slib/index.js @@ -14,8 +14,11 @@ class PluginGenerator extends BaseInitServerGenerator { writing() { super.writing(); - if (!fs.existsSync(this.destinationPath(this.config.get('name') + '/config.json'))) { - this.fs.writeJSON(this.destinationPath(this.config.get('name') + '/config.json'), {}); + const config = this.config.getAll(); + const cwd = this.destinationPath(this._isWorkspace() ? (config.app || config.serviceName || config.name) + '/' + config.name : config.name); + if (!fs.existsSync(cwd + '/config.json')) { + this._createSubDir(cwd); + this.fs.writeJSON(cwd + '/config.json', {}); } } } diff --git a/utils/GeneratorUtils.js b/utils/GeneratorUtils.js index 328adad6..11d1af2f 100644 --- a/utils/GeneratorUtils.js +++ b/utils/GeneratorUtils.js @@ -8,7 +8,6 @@ module.exports = class GeneratorUtils { * @param {string} dir Directory */ static mkdir(dir) { - console.log('Create directory: ' + dir); return new Promise((resolve) => fs.ensureDir(dir, resolve)); } From a1e2b95ee769909005f1c1ce30c7b766b4a6e588 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Mon, 30 Nov 2020 14:00:39 +0100 Subject: [PATCH 60/65] Ignore emty dir when copying templates --- base/BasePhoveaGenerator.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/BasePhoveaGenerator.js b/base/BasePhoveaGenerator.js index 05c32f53..fac15df6 100644 --- a/base/BasePhoveaGenerator.js +++ b/base/BasePhoveaGenerator.js @@ -58,7 +58,8 @@ class BasePhoveaGenerator extends Generator { // see https://github.com/SBoudrias/mem-fs-editor/issues/25 // copyTpl doesn't support glob options const f = glob(base + '/**/*', { - dot: true + dot: true, + nodir: true }); f.forEach((fi) => { const rel = path.relative(base, fi); From c319308403a5f6ac8d89467dac44831984fb80b9 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Mon, 30 Nov 2020 14:01:57 +0100 Subject: [PATCH 61/65] Extend test --- test/init-app.test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/init-app.test.js b/test/init-app.test.js index cb63c153..0aaa33dd 100644 --- a/test/init-app.test.js +++ b/test/init-app.test.js @@ -20,7 +20,8 @@ const expectedFiles = [ const unExpectedFiles = [ 'webpack.config.js', - 'tests.webpack.js' + 'tests.webpack.js', + 'src/index.template' ]; describe('generate app plugin with prompt `app: appName` and the rest default prompt values', () => { From cb230f9273aa49a3cf785d74928c49ff0b1b2ba2 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Mon, 30 Nov 2020 14:27:25 +0100 Subject: [PATCH 62/65] Transform dir name to lowercase --- generators/init-slib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generators/init-slib/index.js b/generators/init-slib/index.js index 29b50749..158aaeef 100644 --- a/generators/init-slib/index.js +++ b/generators/init-slib/index.js @@ -15,7 +15,7 @@ class PluginGenerator extends BaseInitServerGenerator { writing() { super.writing(); const config = this.config.getAll(); - const cwd = this.destinationPath(this._isWorkspace() ? (config.app || config.serviceName || config.name) + '/' + config.name : config.name); + const cwd = this.destinationPath(this._isWorkspace() ? (config.app || config.serviceName || config.name) + '/' + config.name.toLowerCase() : config.name); if (!fs.existsSync(cwd + '/config.json')) { this._createSubDir(cwd); this.fs.writeJSON(cwd + '/config.json', {}); From 8eb906f1ab6d90577cb59289dde8a44ae374ad12 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Tue, 1 Dec 2020 14:20:12 +0100 Subject: [PATCH 63/65] Fix cwd bug --- base/BaseInitPluginGenerator.js | 11 ++++++----- generators/init-app/index.js | 6 +++--- generators/init-slib/index.js | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/base/BaseInitPluginGenerator.js b/base/BaseInitPluginGenerator.js index 12e02fa8..794bd20e 100644 --- a/base/BaseInitPluginGenerator.js +++ b/base/BaseInitPluginGenerator.js @@ -52,11 +52,12 @@ class BaseInitPluginGenerator extends BasePhoveaGenerator { * Initialize the property cwd. * @param {string} dir Directory name. */ - _createSubDir(dir) { + async _createSubDir(dir) { if (this._isWorkspace() && this.cwd !== dir + '/') { this.cwd = dir + '/'; - GeneratorUtils.mkdir(dir); + return GeneratorUtils.mkdir(dir); } + return Promise.resolve(); } readmeAddon() { @@ -76,11 +77,11 @@ class BaseInitPluginGenerator extends BasePhoveaGenerator { }); } - writing() { + async writing() { const config = this.config.getAll(); - this._createSubDir(config.app || config.serviceName || config.name); + await this._createSubDir(config.app || config.serviceName || config.name); if (fs.existsSync(this.templatePath('package.tmpl.json'))) { - this._patchPackageJSON(config, null, null, this.cwd); + this._patchPackageJSON(config, null, null, null, this.cwd); } if (fs.existsSync(this.templatePath('_gitignore'))) { this.fs.copy(this.templatePath('_gitignore'), this.destinationPath(this.cwd + '.gitignore')); diff --git a/generators/init-app/index.js b/generators/init-app/index.js index 58b18e84..5a6b53dd 100644 --- a/generators/init-app/index.js +++ b/generators/init-app/index.js @@ -46,10 +46,10 @@ class PluginGenerator extends BaseInitPluginGenerator { super.default(); } - writing() { + async writing() { const config = this.config.getAll(); - this._createSubDir(config.app); - this._patchPackageJSON(config, ['main'], null, this.cwd); + await this._createSubDir(config.app); + this._patchPackageJSON(config, ['main'], null, null, this.cwd); this._writeTemplates(config, !this.options.noSamples, this.cwd); } diff --git a/generators/init-slib/index.js b/generators/init-slib/index.js index 158aaeef..529d768d 100644 --- a/generators/init-slib/index.js +++ b/generators/init-slib/index.js @@ -12,12 +12,12 @@ class PluginGenerator extends BaseInitServerGenerator { return super.default(); } - writing() { - super.writing(); + async writing() { + await super.writing(); const config = this.config.getAll(); const cwd = this.destinationPath(this._isWorkspace() ? (config.app || config.serviceName || config.name) + '/' + config.name.toLowerCase() : config.name); if (!fs.existsSync(cwd + '/config.json')) { - this._createSubDir(cwd); + await this._createSubDir(cwd); this.fs.writeJSON(cwd + '/config.json', {}); } } From 585a58a5d9e8a43eb98932013369fe646ffb8748 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Wed, 2 Dec 2020 13:20:32 +0100 Subject: [PATCH 64/65] Remove buildInfo.js from web plugins --- .../_init-web/templates/plain/buildInfo.js | 170 ------------------ 1 file changed, 170 deletions(-) delete mode 100644 generators/_init-web/templates/plain/buildInfo.js diff --git a/generators/_init-web/templates/plain/buildInfo.js b/generators/_init-web/templates/plain/buildInfo.js deleted file mode 100644 index b9bb0042..00000000 --- a/generators/_init-web/templates/plain/buildInfo.js +++ /dev/null @@ -1,170 +0,0 @@ -/** - * Created by sam on 13.11.2016. - */ - -const spawnSync = require('child_process').spawnSync; -const path = require('path'); -const resolve = path.resolve; -const fs = require('fs'); - -function dependencyGraph(cwd) { - const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm'; - const r = spawnSync(npm, ['ls', '--prod', '--json'], { - cwd: cwd - }); - if (!r.stdout) { - console.error(cwd, r.error); - return {}; - } - return JSON.parse(r.stdout.toString()); -} - -function gitHead(cwd) { - if (!fs.existsSync(cwd + '/.git')) { - return null; - } - const r = spawnSync('git', ['rev-parse', '--verify', 'HEAD'], { - cwd: cwd - }); - if (!r.stdout) { - console.error(cwd, r.error); - return {}; - } - return r.stdout.toString().trim(); -} - -function resolveModules() { - const reg = fs.readFileSync('../phovea_registry.js').toString(); - const regex = /^import '(.*)\/phovea_registry.js'/gm; - const modules = []; - let r; - while ((r = regex.exec(reg)) !== null) { - modules.push(r[1]); - } - return modules; -} - -function cleanupDependency(d) { - return d; -} - -function resolveWorkspace() { - const workspaceDeps = dependencyGraph('..').dependencies; - const modules = new Set(resolveModules()); - - let deps = null; - const resolveModule = (m) => { - const pkg = JSON.parse(fs.readFileSync(`../${m}/package.json`).toString()); - const head = gitHead('../' + m); - const repo = pkg.repository.url; - return { - name: pkg.name, - version: pkg.version, - resolved: head ? `${repo.endsWith('.git') ? repo.slice(0, repo.length - 4) : repo}/commit/${head}` : pkg.version, - dependencies: deps(pkg.dependencies) - }; - }; - deps = (deps) => { - const r = {}; - Object.keys(deps).forEach((d) => { - if (d in workspaceDeps) { - r[d] = cleanupDependency(workspaceDeps[d]); - delete workspaceDeps[d]; - } else if (modules.has(d)) { - modules.delete(d); - r[d] = resolveModule(d); - } else { - r[d] = '-> link'; - } - }); - return r; - }; - - // self = - const root = path.basename(process.cwd()); - modules.delete(root); - const base = resolveModule(root); - base.extraDependencies = {}; - while (modules.size > 0) { - let m = Array.from(modules.keys())[0]; - modules.delete(m); - base.extraDependencies[m] = resolveModule(m); - } - return base; -} - -function resolveSingle() { - const self = dependencyGraph('.'); - const pkg = require(`./package.json`); - const head = gitHead('.'); - const deps = {}; - Object.keys(self.dependencies || {}).forEach((d) => { - deps[d] = cleanupDependency(self.dependencies[d]); - }); - return { - name: self.name, - version: pkg.version, - resolved: head ? `${pkg.repository.url}#${head}` : pkg.version, - dependencies: deps, - extraDependencies: {} - }; -} - -function generate() { - const isWorkspaceContext = fs.existsSync('../phovea_registry.js'); - if (isWorkspaceContext) { - return resolveWorkspace(); - } - return resolveSingle(); -} - -const IS_WINDOWS = process.platform === 'win32'; - -function tmpdir() { - if (IS_WINDOWS) { - return process.env.TEMP || process.env.TMP || - (process.env.SystemRoot || process.env.windir) + '\\temp'; - } - return process.env.TMPDIR || process.env.TMP || process.env.TEMP || '/tmp'; -} - -function resolveScreenshot() { - const f = resolve(__dirname, 'media/screenshot.png'); - if (!fs.existsSync(f)) { - return null; - } - const buffer = Buffer.from(fs.readFileSync(f)).toString('base64'); - return `data:image/png;base64,${buffer}`; -} - -function metaData(pkg) { - pkg = pkg || require(`./package.json`); - return { - name: pkg.name, - displayName: pkg.displayName, - version: pkg.version, - repository: pkg.repository.url, - homepage: pkg.homepage, - description: pkg.description, - screenshot: resolveScreenshot() - }; -} - -module.exports.metaData = metaData; -module.exports.metaDataTmpFile = function (pkg) { - const s = metaData(pkg); - const file = `${tmpdir()}/metaData${Math.random().toString(36).slice(-8)}.txt`; - fs.writeFileSync(file, JSON.stringify(s, null, ' ')); - return file; -}; -module.exports.generate = generate; -module.exports.tmpFile = function () { - const s = generate(); - const file = `${tmpdir()}/buildInfo${Math.random().toString(36).slice(-8)}.txt`; - fs.writeFileSync(file, JSON.stringify(s, null, ' ')); - return file; -}; - -if (require.main === module) { - fs.writeFile('deps.json', JSON.stringify(generate(), null, ' ')); -} From 3e46731c8c3a5b461267d61d2f8aa5bed049f992 Mon Sep 17 00:00:00 2001 From: oltionchampari Date: Thu, 3 Dec 2020 12:43:21 +0100 Subject: [PATCH 65/65] Add base directory to package.json files --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 080fdfd7..e8014f93 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ }, "main": "generators/app/index.js", "files": [ + "base/", "generators/", "utils/", "knownPhoveaPlugins.json",