From 8ea6225810145ad4801e995ceb100559f8ac3bfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 23 Sep 2019 13:09:52 +0200 Subject: [PATCH 1/6] refactor(cli): extract `createPropertyTemplateData` helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- packages/cli/generators/model/index.js | 57 ++------------- .../generators/model/property-definition.js | 73 +++++++++++++++++++ 2 files changed, 80 insertions(+), 50 deletions(-) create mode 100644 packages/cli/generators/model/property-definition.js diff --git a/packages/cli/generators/model/index.js b/packages/cli/generators/model/index.js index db2f5e1a291a..6619910119e1 100644 --- a/packages/cli/generators/model/index.js +++ b/packages/cli/generators/model/index.js @@ -14,6 +14,8 @@ const utils = require('../../lib/utils'); const chalk = require('chalk'); const path = require('path'); +const {createPropertyTemplateData} = require('./property-definition'); + const PROMPT_BASE_MODEL_CLASS = 'Please select the model base class'; const ERROR_NO_MODELS_FOUND = 'Model was not found in'; @@ -476,56 +478,11 @@ module.exports = class ModelGenerator extends ArtifactGenerator { this.artifactInfo.modelBaseClass, ); - // Set up types for Templating - const TS_TYPES = ['string', 'number', 'object', 'boolean', 'any']; - const NON_TS_TYPES = ['geopoint', 'date']; - Object.values(this.artifactInfo.properties).forEach(val => { - // Default tsType is the type property - val.tsType = val.type; - - // Override tsType based on certain type values - if (val.type === 'array') { - if (TS_TYPES.includes(val.itemType)) { - val.tsType = `${val.itemType}[]`; - } else if (val.type === 'buffer') { - val.tsType = 'Buffer[]'; - } else { - val.tsType = 'string[]'; - } - } else if (val.type === 'buffer') { - val.tsType = 'Buffer'; - } - - if (NON_TS_TYPES.includes(val.tsType)) { - val.tsType = 'string'; - } - - if ( - val.defaultValue && - NON_TS_TYPES.concat(['string', 'any']).includes(val.type) - ) { - val.defaultValue = `'${val.defaultValue}'`; - } - - // Convert Type to include '' for template - val.type = `'${val.type}'`; - if (val.itemType) { - val.itemType = `'${val.itemType}'`; - } - - // If required is false, we can delete it as that's the default assumption - // for this field if not present. This helps to avoid polluting the - // decorator with redundant properties. - if (!val.required) { - delete val.required; - } - - // We only care about marking the `id` field as `id` and not fields that - // are not the id so if this is false we delete it similar to `required`. - if (!val.id) { - delete val.id; - } - }); + const propDefs = this.artifactInfo.properties; + this.artifactInfo.properties = {}; + for (const key in propDefs) { + this.artifactInfo.properties = createPropertyTemplateData(propDefs[key]); + } if (this.artifactInfo.modelSettings) { this.artifactInfo.modelSettings = utils.stringifyModelSettings( diff --git a/packages/cli/generators/model/property-definition.js b/packages/cli/generators/model/property-definition.js new file mode 100644 index 000000000000..bddfaa3456cf --- /dev/null +++ b/packages/cli/generators/model/property-definition.js @@ -0,0 +1,73 @@ +// Copyright IBM Corp. 2019. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; + +const TS_TYPES = ['string', 'number', 'object', 'boolean', 'any']; +const NON_TS_TYPES = ['geopoint', 'date']; +const BUILTIN_TYPES = [...TS_TYPES, ...NON_TS_TYPES]; + +module.exports = { + createPropertyTemplateData, + BUILTIN_TYPES, +}; + +/** + * Convert property definition in LB4 style to data needed by model template + * @param {object} val The property definition + * @returns {object} Data for model-property template + */ +function createPropertyTemplateData(val) { + // shallow clone the object - don't modify original data! + val = {...val}; + + // Default tsType is the type property + val.tsType = val.type; + + // Override tsType based on certain type values + if (val.type === 'array') { + if (TS_TYPES.includes(val.itemType)) { + val.tsType = `${val.itemType}[]`; + } else if (val.type === 'buffer') { + val.tsType = 'Buffer[]'; + } else { + val.tsType = 'string[]'; + } + } else if (val.type === 'buffer') { + val.tsType = 'Buffer'; + } + + if (NON_TS_TYPES.includes(val.tsType)) { + val.tsType = 'string'; + } + + if ( + val.defaultValue && + NON_TS_TYPES.concat(['string', 'any']).includes(val.type) + ) { + val.defaultValue = `'${val.defaultValue}'`; + } + + // Convert Type to include '' for template + val.type = `'${val.type}'`; + if (val.itemType) { + val.itemType = `'${val.itemType}'`; + } + + // If required is false, we can delete it as that's the default assumption + // for this field if not present. This helps to avoid polluting the + // decorator with redundant properties. + if (!val.required) { + delete val.required; + } + + // We only care about marking the `id` field as `id` and not fields that + // are not the id so if this is false we delete it similar to `required`. + if (!val.id) { + delete val.id; + } + + return val; +} From 68ce1cb387996f11f402aa8e81bbba18a47acf9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 23 Sep 2019 13:11:23 +0200 Subject: [PATCH 2/6] refactor(cli): extract helper `logNamingIssues` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- packages/cli/lib/artifact-generator.js | 13 +------------ packages/cli/lib/utils.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/packages/cli/lib/artifact-generator.js b/packages/cli/lib/artifact-generator.js index 28c272c85251..488d5abf370b 100644 --- a/packages/cli/lib/artifact-generator.js +++ b/packages/cli/lib/artifact-generator.js @@ -69,18 +69,7 @@ module.exports = class ArtifactGenerator extends BaseGenerator { * remind user the input might get changed if it contains _ or accented char **/ promptWarningMsgForName() { - if (this.artifactInfo.name.includes('_')) { - this.log( - chalk.red('>>> ') + - `Underscores _ in the class name will get removed: ${this.artifactInfo.name}`, - ); - } - if (this.artifactInfo.name.match(/[\u00C0-\u024F\u1E00-\u1EFF]/)) { - this.log( - chalk.red('>>> ') + - `Accented chars in the class name will get replaced: ${this.artifactInfo.name}`, - ); - } + utils.logNamingIssues(this.artifactInfo.name, this.log.bind(this)); } /** diff --git a/packages/cli/lib/utils.js b/packages/cli/lib/utils.js index fc4e441a12bf..e8411b3a8a05 100644 --- a/packages/cli/lib/utils.js +++ b/packages/cli/lib/utils.js @@ -5,6 +5,7 @@ 'use strict'; +const chalk = require('chalk'); const debug = require('../lib/debug')('utils'); const fs = require('fs'); const path = require('path'); @@ -103,6 +104,21 @@ exports.validateClassName = function(name) { return util.format('Class name is invalid: %s', name); }; +exports.logNamingIssues = function(name, log) { + if (name.includes('_')) { + log( + chalk.red('>>> ') + + `Underscores _ in the class name will get removed: ${name}`, + ); + } + if (name.match(/[\u00C0-\u024F\u1E00-\u1EFF]/)) { + log( + chalk.red('>>> ') + + `Accented chars in the class name will get replaced: ${name}`, + ); + } +}; + /** * Validate project directory to not exist */ From 76ef477b42fb4020e9877e276e1a820d64c6312b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 23 Sep 2019 13:12:03 +0200 Subject: [PATCH 3/6] refactor(cli): extract helper `logClassCreation` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- packages/cli/lib/artifact-generator.js | 9 +-------- packages/cli/lib/utils.js | 11 +++++++++++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/cli/lib/artifact-generator.js b/packages/cli/lib/artifact-generator.js index 488d5abf370b..bd5ad38a5a84 100644 --- a/packages/cli/lib/artifact-generator.js +++ b/packages/cli/lib/artifact-generator.js @@ -79,14 +79,7 @@ module.exports = class ArtifactGenerator extends BaseGenerator { * >> Model MyModel will be created in src/models/my-model.model.ts **/ promptClassFileName(type, typePlural, name) { - this.log( - `${utils.toClassName(type)} ${chalk.yellow( - name, - )} will be created in src/${typePlural}/${chalk.yellow( - utils.toFileName(name) + '.' + `${type}.ts`, - )}`, - ); - this.log(); + utils.logClassCreation(type, typePlural, name, this.log.bind(this)); } scaffold() { diff --git a/packages/cli/lib/utils.js b/packages/cli/lib/utils.js index e8411b3a8a05..9cdf1403228f 100644 --- a/packages/cli/lib/utils.js +++ b/packages/cli/lib/utils.js @@ -119,6 +119,17 @@ exports.logNamingIssues = function(name, log) { } }; +exports.logClassCreation = function(type, typePlural, name, log) { + log( + `${exports.toClassName(type)} ${chalk.yellow( + name, + )} will be created in src/${typePlural}/${chalk.yellow( + exports.toFileName(name) + '.' + `${type}.ts`, + )}`, + ); + log(); +}; + /** * Validate project directory to not exist */ From 3f19253b998651d992e2f56d41a938bc1d249fc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 23 Sep 2019 13:14:59 +0200 Subject: [PATCH 4/6] test(cli): extract test suite for checking loopback project directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .../integration/lib/artifact-generator.js | 80 +---------------- .../lib/check-loopback-project.suite.js | 90 +++++++++++++++++++ 2 files changed, 92 insertions(+), 78 deletions(-) create mode 100644 packages/cli/test/integration/lib/check-loopback-project.suite.js diff --git a/packages/cli/test/integration/lib/artifact-generator.js b/packages/cli/test/integration/lib/artifact-generator.js index dd8950e2795d..96b2f51f7390 100644 --- a/packages/cli/test/integration/lib/artifact-generator.js +++ b/packages/cli/test/integration/lib/artifact-generator.js @@ -6,9 +6,8 @@ 'use strict'; const assert = require('yeoman-assert'); const sinon = require('sinon'); -const chalk = require('chalk'); const testUtils = require('../../test-utils'); -const fs = require('mem-fs-editor').create(require('mem-fs').create()); +const suiteCheckLoopBackProject = require('./check-loopback-project.suite'); module.exports = function(artiGenerator) { return function() { @@ -57,82 +56,7 @@ module.exports = function(artiGenerator) { }); }); - describe('checkLoopBackProject', () => { - let gen; - - beforeEach(() => { - gen = testUtils.testSetUpGen(artiGenerator); - gen.fs.readJSON = sinon.stub(fs, 'readJSON'); - }); - - afterEach(() => { - if (gen) gen.fs.readJSON.restore(); - }); - - testCheckLoopBack( - 'throws an error if no package.json is present', - undefined, - /No package.json found/, - ); - - testCheckLoopBack( - 'throws an error if "@loopback/core" is not a dependency', - {dependencies: {}}, - /No `@loopback\/core` package found/, - ); - - testCheckLoopBack( - 'throws an error if dependencies have incompatible versions', - { - dependencies: { - '@loopback/context': '^0.0.0', - '@loopback/core': '^0.0.0', - }, - }, - /Incompatible dependencies/, - ); - - testCheckLoopBack( - 'allows */x/X for version range', - { - devDependencies: {'@types/node': '*'}, - dependencies: { - '@loopback/context': 'x.x', - '@loopback/core': 'X.*', - }, - }, - // No expected error here - ); - - it('passes if "@loopback/core" is a dependency', async () => { - await gen.checkLoopBackProject(); - }); - - function testCheckLoopBack(testName, obj, expected) { - it(testName, async () => { - let logs = []; - gen.log = function(...args) { - logs = logs.concat(args); - }; - gen.prompt = async () => ({ - ignoreIncompatibleDependencies: false, - }); - gen.fs.readJSON.returns(obj); - await gen.checkLoopBackProject(); - if (!expected) { - assert(gen.exitGeneration == null); - return; - } - assert(gen.exitGeneration instanceof Error); - assert(gen.exitGeneration.message.match(expected)); - gen.end(); - assert.equal( - logs[logs.length - 1], - chalk.red('Generation is aborted:', gen.exitGeneration), - ); - }); - } - }); + suiteCheckLoopBackProject(artiGenerator); describe('promptArtifactName', () => { let gen; diff --git a/packages/cli/test/integration/lib/check-loopback-project.suite.js b/packages/cli/test/integration/lib/check-loopback-project.suite.js new file mode 100644 index 000000000000..bec7cbd96b9c --- /dev/null +++ b/packages/cli/test/integration/lib/check-loopback-project.suite.js @@ -0,0 +1,90 @@ +// Copyright IBM Corp. 2019. All Rights Reserved. +// Node module: @loopback/cli +// This file is licensed under the MIT License. +// License text available at https://opensource.org/licenses/MIT + +'use strict'; +const assert = require('yeoman-assert'); +const sinon = require('sinon'); +const chalk = require('chalk'); +const testUtils = require('../../test-utils'); +const fs = require('mem-fs-editor').create(require('mem-fs').create()); + +module.exports = function suiteCheckLoopBackProject(generator) { + describe('checkLoopBackProject', () => { + let gen; + + beforeEach(() => { + gen = testUtils.testSetUpGen(generator); + gen.fs.readJSON = sinon.stub(fs, 'readJSON'); + }); + + afterEach(() => { + if (gen) gen.fs.readJSON.restore(); + }); + + testCheckLoopBack( + 'throws an error if no package.json is present', + undefined, + /No package.json found/, + ); + + testCheckLoopBack( + 'throws an error if "@loopback/core" is not a dependency', + {dependencies: {}}, + /No `@loopback\/core` package found/, + ); + + testCheckLoopBack( + 'throws an error if dependencies have incompatible versions', + { + dependencies: { + '@loopback/context': '^0.0.0', + '@loopback/core': '^0.0.0', + }, + }, + /Incompatible dependencies/, + ); + + testCheckLoopBack( + 'allows */x/X for version range', + { + devDependencies: {'@types/node': '*'}, + dependencies: { + '@loopback/context': 'x.x', + '@loopback/core': 'X.*', + }, + }, + // No expected error here + ); + + it('passes if "@loopback/core" is a dependency', async () => { + await gen.checkLoopBackProject(); + }); + + function testCheckLoopBack(testName, obj, expected) { + it(testName, async () => { + let logs = []; + gen.log = function(...args) { + logs = logs.concat(args); + }; + gen.prompt = async () => ({ + ignoreIncompatibleDependencies: false, + }); + gen.fs.readJSON.returns(obj); + await gen.checkLoopBackProject(); + if (!expected) { + assert(gen.exitGeneration == null); + return; + } + assert(gen.exitGeneration instanceof Error); + assert(gen.exitGeneration.message.match(expected)); + gen.end(); + assert.equal( + logs[logs.length - 1], + chalk.red('Generation is aborted:', gen.exitGeneration), + ); + }); + } + }); +}; From f6374046a5f29427d9fcf795939872093d7445e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 23 Sep 2019 13:16:21 +0200 Subject: [PATCH 5/6] refactor(cli): move helpers from ArtifactGenerator to BaseGenerator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce two new helpers to be used in generators not inheriting form `ArtifactGenerator`: - `_isGenerationSuccessful` to detect whether all target files were successfully created or modified. - `_updateIndexFile` to add a single entry to a given `index.ts` file Signed-off-by: Miroslav Bajtoš --- packages/cli/lib/artifact-generator.js | 27 ++-------------------- packages/cli/lib/base-generator.js | 31 ++++++++++++++++++++++++++ packages/cli/lib/update-index.js | 2 +- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/packages/cli/lib/artifact-generator.js b/packages/cli/lib/artifact-generator.js index bd5ad38a5a84..f4945ace67e2 100644 --- a/packages/cli/lib/artifact-generator.js +++ b/packages/cli/lib/artifact-generator.js @@ -7,7 +7,6 @@ const BaseGenerator = require('./base-generator'); const debug = require('./debug')('artifact-generator'); const utils = require('./utils'); -const updateIndex = require('./update-index'); const path = require('path'); const chalk = require('chalk'); @@ -103,16 +102,7 @@ module.exports = class ArtifactGenerator extends BaseGenerator { return; } - // Check all files being generated to ensure they succeeded - const generationStatus = !!Object.entries( - this.conflicter.generationStatus, - ).find(([key, val]) => { - // If a file was modified, update the indexes and say stuff about it - return val !== 'skip' && val !== 'identical'; - }); - debug(`Generation status: ${generationStatus}`); - - if (generationStatus) { + if (this._isGenerationSuccessful()) { await this._updateIndexFiles(); const classes = this.artifactInfo.name @@ -171,20 +161,7 @@ module.exports = class ArtifactGenerator extends BaseGenerator { } for (const idx of this.artifactInfo.indexesToBeUpdated) { - await updateIndex(idx.dir, idx.file); - // Output for users - const updateDirRelPath = path.relative( - this.artifactInfo.relPath, - idx.dir, - ); - - const outPath = path.join( - this.artifactInfo.relPath, - updateDirRelPath, - 'index.ts', - ); - - this.log(chalk.green(' update'), `${outPath}`); + await this._updateIndexFile(idx.dir, idx.file); } } }; diff --git a/packages/cli/lib/base-generator.js b/packages/cli/lib/base-generator.js index 679581358e01..44b69caee182 100644 --- a/packages/cli/lib/base-generator.js +++ b/packages/cli/lib/base-generator.js @@ -12,6 +12,7 @@ const path = require('path'); const fs = require('fs'); const debug = require('./debug')('base-generator'); const semver = require('semver'); +const updateIndex = require('./update-index'); /** * Base Generator for LoopBack 4 @@ -444,4 +445,34 @@ module.exports = class BaseGenerator extends Generator { } await this._runLintFix(); } + + // Check all files being generated to ensure they succeeded + _isGenerationSuccessful() { + const generationStatus = !!Object.entries( + this.conflicter.generationStatus, + ).find(([key, val]) => { + // If a file was modified, update the indexes and say stuff about it + return val !== 'skip' && val !== 'identical'; + }); + debug(`Generation status: ${generationStatus}`); + return generationStatus; + } + + async _updateIndexFile(dir, file) { + await updateIndex(dir, file); + + // Output for users + const updateDirRelPath = path.relative( + this.artifactInfo.relPath, + this.artifactInfo.outDir, + ); + + const outPath = path.join( + this.artifactInfo.relPath, + updateDirRelPath, + 'index.ts', + ); + + this.log(chalk.green(' update'), `${outPath}`); + } }; diff --git a/packages/cli/lib/update-index.js b/packages/cli/lib/update-index.js index 71f563497aa4..865587372d0b 100644 --- a/packages/cli/lib/update-index.js +++ b/packages/cli/lib/update-index.js @@ -17,7 +17,7 @@ const exists = util.promisify(fs.exists); * @param {*} file The new file to be exported from index.ts */ module.exports = async function(dir, file) { - debug(`Updating index ${path.join(dir, file)}`); + debug(`Updating index with ${path.join(dir, file)}`); const indexFile = path.join(dir, 'index.ts'); if (!file.endsWith('.ts')) { throw new Error(`${file} must be a TypeScript (.ts) file`); From e524742c33c47414a9334a391353c84d4400517b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Mon, 23 Sep 2019 13:18:58 +0200 Subject: [PATCH 6/6] test(cli): improve BaseGenerator test suite to support required args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Miroslav Bajtoš --- .../test/integration/lib/base-generator.js | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/packages/cli/test/integration/lib/base-generator.js b/packages/cli/test/integration/lib/base-generator.js index 4a76e18ff2aa..18dffa1b8bc8 100644 --- a/packages/cli/test/integration/lib/base-generator.js +++ b/packages/cli/test/integration/lib/base-generator.js @@ -11,12 +11,14 @@ const path = require('path'); const mockStdin = require('mock-stdin'); const process = require('process'); -module.exports = function(generator) { +module.exports = function(generator, env = {}) { + if (!env.args) env = {...env, args: []}; + return function() { describe('usage', () => { it('prints lb4', () => { process.chdir(path.resolve(__dirname, '..', '..', '..')); - const gen = testUtils.testSetUpGen(generator); + const gen = testUtils.testSetUpGen(generator, env); const helpText = gen.help(); assert(helpText.match(/lb4 /)); assert(!helpText.match(/loopback4:/)); @@ -25,17 +27,17 @@ module.exports = function(generator) { describe('exit', () => { it('does nothing if false is passed', () => { - const gen = testUtils.testSetUpGen(generator); + const gen = testUtils.testSetUpGen(generator, env); gen.exit(false); assert(gen.exitGeneration === undefined); }); it('sets "exitGeneration" to true if called with no argument', () => { - const gen = testUtils.testSetUpGen(generator); + const gen = testUtils.testSetUpGen(generator, env); gen.exit(); assert(gen.exitGeneration === true); }); it('sets "exitGeneration" to the error passed to itself', () => { - const gen = testUtils.testSetUpGen(generator); + const gen = testUtils.testSetUpGen(generator, env); gen.exit(new Error('oh no')); assert(gen.exitGeneration instanceof Error); assert.equal(gen.exitGeneration.message, 'oh no'); @@ -51,7 +53,8 @@ module.exports = function(generator) { it('accepts --config', async () => { const jsonFile = path.join(__dirname, 'base-config.json'); const gen = testUtils.testSetUpGen(generator, { - args: ['--config', jsonFile], + ...env, + args: ['--config', jsonFile, ...env.args], }); await gen.setOptions(); assert.equal(gen.options['config'], jsonFile); @@ -61,7 +64,8 @@ module.exports = function(generator) { it('options from json file do not override', async () => { const jsonFile = path.join(__dirname, 'base-config.json'); const gen = testUtils.testSetUpGen(generator, { - args: ['--name', 'abc', '--config', jsonFile], + ...env, + args: ['--name', 'abc', '--config', jsonFile, ...env.args], }); await gen.setOptions(); assert.equal(gen.options['config'], jsonFile); @@ -71,7 +75,12 @@ module.exports = function(generator) { it('fails fast if --config has invalid value', async () => { const gen = testUtils.testSetUpGen(generator, { - args: ['--config', path.join(__dirname, 'base-config-invalid.json')], + ...env, + args: [ + '--config', + path.join(__dirname, 'base-config-invalid.json'), + ...env.args, + ], }); await gen.setOptions(); assert(gen.exitGeneration instanceof Error); @@ -91,7 +100,8 @@ module.exports = function(generator) { it('accepts --config', async () => { const gen = testUtils.testSetUpGen(generator, { - args: ['--config', jsonValue], + ...env, + args: ['--config', jsonValue, ...env.args], }); await gen.setOptions(); assert.equal(gen.options['config'], jsonValue); @@ -100,7 +110,8 @@ module.exports = function(generator) { it('options from json file do not override', async () => { const gen = testUtils.testSetUpGen(generator, { - args: ['--name', 'abc', '--config', jsonValue], + ...env, + args: ['--name', 'abc', '--config', jsonValue, ...env.args], }); await gen.setOptions(); assert.equal(gen.options['config'], jsonValue); @@ -110,7 +121,8 @@ module.exports = function(generator) { it('fails fast if --config has invalid value', async () => { const gen = testUtils.testSetUpGen(generator, { - args: ['--config', invalidJsonValue], + ...env, + args: ['--config', invalidJsonValue, ...env.args], }); await gen.setOptions(); assert(gen.exitGeneration instanceof Error); @@ -134,7 +146,8 @@ module.exports = function(generator) { it('accepts --config stdin', () => { const gen = testUtils.testSetUpGen(generator, { - args: ['--config', 'stdin'], + ...env, + args: ['--config', 'stdin', ...env.args], }); const promise = gen.setOptions(); assert.equal(gen.options['config'], 'stdin'); @@ -151,7 +164,8 @@ module.exports = function(generator) { it('reports invalid json from stdin', () => { const gen = testUtils.testSetUpGen(generator, { - args: ['--config', 'stdin'], + ...env, + args: ['--config', 'stdin', ...env.args], }); const promise = gen.setOptions(); assert.equal(gen.options['config'], 'stdin');