From 952d8e998f95e532dac60660d315c4acaeddfd95 Mon Sep 17 00:00:00 2001 From: weareoutman Date: Wed, 28 Nov 2018 15:57:38 +0800 Subject: [PATCH 1/2] fix: only allow lowercase in package name --- generators/app/index.js | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/generators/app/index.js b/generators/app/index.js index d0c3ff3..df23d88 100644 --- a/generators/app/index.js +++ b/generators/app/index.js @@ -67,7 +67,7 @@ module.exports = class extends Generator { type: 'input', name: 'packageName', message: "What's the name of your package (in kebab-case)?", - validate: value => /^[a-zA-Z]+(-[a-zA-Z0-9]+)*$/.test(value) + validate: value => /^[a-z]+(-[a-z0-9]+)*$/.test(value) } ]) ); @@ -208,33 +208,21 @@ module.exports = class extends Generator { } install() { - if (process.env.NODE_ENV === 'testing') { - return; - } const done = this.async(); let distPath = `${this.props.subPackagePath}/${this.props.packageName}`; - let total = 1; - const decrease = () => { - total -= 1; - if (total <=0) { - done(); - } - }; if (this._isLibrary()) { distPath += '/dist'; - } else { - total += 1; } const childOfYarnLink = this.spawnCommand('yarn', ['link'], { cwd: distPath }); childOfYarnLink.on("close", () => { - decrease(); + if (this._isLibrary()) { + done(); + } else { + const childOfYarn = this.spawnCommand('yarn', [], { cwd: distPath }); + childOfYarn.on("close", () => { + done(); + }); + } }); - - if (!this._isLibrary()) { - const childOfYarn = this.spawnCommand('yarn', [], { cwd: distPath }); - childOfYarn.on("close", () => { - decrease(); - }); - } } }; From 62fd1029b0ca5e91c28ee1b26a9a404c3fa3809a Mon Sep 17 00:00:00 2001 From: weareoutman Date: Wed, 28 Nov 2018 15:58:41 +0800 Subject: [PATCH 2/2] chore: test with stub --- .travis.yml | 4 +++ __tests__/app.js | 80 ++++++++++++++++++++++++++++++++++++++++++++++-- package.json | 1 + yarn.lock | 40 +++++++++++++++++++++--- 4 files changed, 119 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4156fdf..36be284 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,10 @@ language: node_js node_js: - v10 +cache: + yarn: true + directories: + - node_modules install: - yarn script: diff --git a/__tests__/app.js b/__tests__/app.js index 0a9318d..260fd3a 100644 --- a/__tests__/app.js +++ b/__tests__/app.js @@ -1,14 +1,19 @@ 'use strict'; const path = require('path'); +const { EventEmitter } = require('events'); const fs = require('fs-extra'); const assert = require('yeoman-assert'); const helpers = require('yeoman-test'); +const { createSandbox } = require('sinon'); + +const sandbox = createSandbox(); describe('generator-console-package:app:@easyops', () => { const random = Math.random().toString(36).substring(7); const Random = random.substr(0, 1).toUpperCase() + random.substr(1); const packageName = `just-for-test-${random}`; const pascalCaseName = `JustForTest${Random}`; + let mockSpawn; beforeAll(() => { @@ -16,6 +21,16 @@ describe('generator-console-package:app:@easyops', () => { .run(path.join(__dirname, '../generators/app')) .inTmpDir(dir => { fs.copySync(path.join(__dirname, '../generators/app/templates/library/mock'), dir); + fs.writeJsonSync(path.resolve(dir, './package.json'), { name: 'easyops-web-console' }); + }) + .on('ready', gen => { + mockSpawn = sandbox.stub(gen, 'spawnCommand').callsFake(() => { + const spawnEvent = new EventEmitter(); + process.nextTick(() => { + spawnEvent.emit('close'); + }); + return spawnEvent; + }); }) .withPrompts({ scope: '@easyops', @@ -23,6 +38,10 @@ describe('generator-console-package:app:@easyops', () => { }); }); + afterAll(() => { + sandbox.restore(); + }); + it('should create files', () => { assert.file([ // Created files: @@ -81,7 +100,15 @@ describe('generator-console-package:app:@easyops', () => { 'tsconfig.json', `"@easyops/${packageName}": [\n "packages/${packageName}"\n ]` ); - }) + }); + + it('should run `yarn link`', () => { + expect(mockSpawn.calledOnceWithExactly('yarn', ['link'], { + cwd: `packages/${packageName}/dist` + })).toBe(true); + + expect(mockSpawn.callCount).toBe(1); + }); }); describe('generator-console-package:app:@plugin-common', () => { @@ -89,6 +116,7 @@ describe('generator-console-package:app:@plugin-common', () => { const Random = random.substr(0, 1).toUpperCase() + random.substr(1); const packageName = `just-for-test-2-${random}`; const pascalCaseName = `JustForTest2${Random}`; + let mockSpawn; beforeAll(() => { @@ -96,6 +124,16 @@ describe('generator-console-package:app:@plugin-common', () => { .run(path.join(__dirname, '../generators/app')) .inTmpDir(dir => { fs.copySync(path.join(__dirname, '../generators/app/templates/library/mock'), dir); + fs.writeJsonSync(path.resolve(dir, './package.json'), { name: 'console-plugins' }); + }) + .on('ready', gen => { + mockSpawn = sandbox.stub(gen, 'spawnCommand').callsFake(() => { + const spawnEvent = new EventEmitter(); + process.nextTick(() => { + spawnEvent.emit('close'); + }); + return spawnEvent; + }); }) .withPrompts({ scope: '@plugin-common', @@ -103,6 +141,10 @@ describe('generator-console-package:app:@plugin-common', () => { }); }); + afterAll(() => { + sandbox.restore(); + }); + it('should create files', () => { assert.file([ // Created files: @@ -161,7 +203,15 @@ describe('generator-console-package:app:@plugin-common', () => { 'tsconfig.json', `"@plugin-common/${packageName}": [\n "@plugin-common/${packageName}"\n ]` ); - }) + }); + + it('should run `yarn link`', () => { + expect(mockSpawn.calledOnceWithExactly('yarn', ['link'], { + cwd: `@plugin-common/${packageName}/dist` + })).toBe(true); + + expect(mockSpawn.callCount).toBe(1); + }); }); describe('generator-console-package:app:@console-plugin', () => { @@ -169,6 +219,7 @@ describe('generator-console-package:app:@console-plugin', () => { const Random = random.substr(0, 1).toUpperCase() + random.substr(1); const packageName = `just-for-test-3-${random}`; const pascalCaseName = `JustForTest3${Random}`; + let mockSpawn; beforeAll(() => { @@ -177,12 +228,25 @@ describe('generator-console-package:app:@console-plugin', () => { .inTmpDir(dir => { fs.copySync(path.join(__dirname, '../generators/app/templates/library/mock'), dir); }) + .on('ready', gen => { + mockSpawn = sandbox.stub(gen, 'spawnCommand').callsFake(() => { + const spawnEvent = new EventEmitter(); + process.nextTick(() => { + spawnEvent.emit('close'); + }); + return spawnEvent; + }); + }) .withPrompts({ scope: '@console-plugin', packageName }); }); + afterAll(() => { + sandbox.restore(); + }); + it('should create files', () => { assert.file([ // Created files: @@ -218,4 +282,16 @@ describe('generator-console-package:app:@console-plugin', () => { `"${packageName}": {\n "root": "packages/${packageName}/src"` ); }); + + it('should run `yarn link` and `yarn`', () => { + expect(mockSpawn.calledWithExactly('yarn', ['link'], { + cwd: `packages/${packageName}` + })).toBe(true); + + expect(mockSpawn.calledWithExactly('yarn', [], { + cwd: `packages/${packageName}` + })).toBe(true); + + expect(mockSpawn.callCount).toBe(2); + }); }); diff --git a/package.json b/package.json index 2a207df..947973c 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "jest": "23.6.0", "lint-staged": "8.1.0", "prettier": "1.15.2", + "sinon": "^7.1.1", "yeoman-assert": "3.1.1", "yeoman-test": "1.9.1" }, diff --git a/yarn.lock b/yarn.lock index 0bd766d..4e23456 100644 --- a/yarn.lock +++ b/yarn.lock @@ -124,7 +124,14 @@ dependencies: any-observable "^0.3.0" -"@sinonjs/formatio@3.0.0": +"@sinonjs/commons@^1.2.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.3.0.tgz#50a2754016b6f30a994ceda6d9a0a8c36adda849" + integrity sha512-j4ZwhaHmwsCb4DlDOIWnI5YyKDNMoNThsmwEpfHx6a1EpsGZ9qYLxP++LMlmBRjtGptGHFsGItJ768snllFWpA== + dependencies: + type-detect "4.0.8" + +"@sinonjs/formatio@3.0.0", "@sinonjs/formatio@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-3.0.0.tgz#9d282d81030a03a03fa0c5ce31fd8786a4da311a" integrity sha512-vdjoYLDptCgvtJs57ULshak3iJe4NW3sJ3g36xVDGff5AE8P30S6A093EIEPjdi2noGhfuNOEkbxt3J3awFW1w== @@ -145,6 +152,11 @@ dependencies: array-from "^2.1.1" +"@sinonjs/samsam@^2.1.2": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-2.1.2.tgz#16947fce5f57258d01f1688fdc32723093c55d3f" + integrity sha512-ZwTHAlC9akprWDinwEPD4kOuwaYZlyMwVJIANsKNC3QVp0AHB04m7RnB4eqeWfgmxw8MGTzS9uMaw93Z3QcZbw== + abab@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.0.tgz#aba0ab4c5eee2d4c79d3487d85450fb2376ebb0f" @@ -3371,6 +3383,11 @@ lolex@^2.3.2, lolex@^2.4.2: resolved "https://registry.yarnpkg.com/lolex/-/lolex-2.7.5.tgz#113001d56bfc7e02d56e36291cc5c413d1aa0733" integrity sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q== +lolex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-3.0.0.tgz#f04ee1a8aa13f60f1abd7b0e8f4213ec72ec193e" + integrity sha512-hcnW80h3j2lbUfFdMArd5UPA/vxZJ+G8vobd+wg3nVEQA0EigStbYcrG030FJxL6xiDDPEkoMatV9xIh5OecQQ== + loose-envify@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -3674,7 +3691,7 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -nise@^1.3.3: +nise@^1.3.3, nise@^1.4.6: version "1.4.6" resolved "https://registry.yarnpkg.com/nise/-/nise-1.4.6.tgz#76cc3915925056ae6c405dd8ad5d12bde570c19f" integrity sha512-1GedetLKzmqmgwabuMSqPsT7oumdR77SBpDfNNJhADRIeA3LN/2RVqR4fFqwvzhAqcTef6PPCzQwITE/YQ8S8A== @@ -4682,6 +4699,21 @@ sinon@^5.0.7: supports-color "^5.4.0" type-detect "^4.0.8" +sinon@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-7.1.1.tgz#1202f317aa14d93cb9b69ff50b6bd49c0e05ffc9" + integrity sha512-iYagtjLVt1vN3zZY7D8oH7dkjNJEjLjyuzy8daX5+3bbQl8gaohrheB9VfH1O3L6LKuue5WTJvFluHiuZ9y3nQ== + dependencies: + "@sinonjs/commons" "^1.2.0" + "@sinonjs/formatio" "^3.0.0" + "@sinonjs/samsam" "^2.1.2" + diff "^3.5.0" + lodash.get "^4.4.2" + lolex "^3.0.0" + nise "^1.4.6" + supports-color "^5.5.0" + type-detect "^4.0.8" + sisteransi@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" @@ -4963,7 +4995,7 @@ supports-color@^3.1.2: dependencies: has-flag "^1.0.0" -supports-color@^5.3.0, supports-color@^5.4.0: +supports-color@^5.3.0, supports-color@^5.4.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -5156,7 +5188,7 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" -type-detect@^4.0.8: +type-detect@4.0.8, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==