From 03227e65cfbce63aac05fb57bb9949e03e8c2a97 Mon Sep 17 00:00:00 2001 From: Peter Bacon Darwin Date: Fri, 6 Oct 2017 14:48:37 +0100 Subject: [PATCH] build(aio): example-boilerplate is no longer responsible for yarn install (#19511) The tooling for boilerplate was also running `yarn install` on the examples' shared folder. But since this is handled by `ng-packages-installer` this commit refactors the tools so that the boilerplate no longer does this anymore. PR Close #19511 --- aio/package.json | 6 +-- aio/tools/examples/example-boilerplate.js | 22 +++------ .../examples/example-boilerplate.spec.js | 47 ++++--------------- aio/tools/examples/run-example-e2e.js | 18 +++---- 4 files changed, 28 insertions(+), 65 deletions(-) diff --git a/aio/package.json b/aio/package.json index d3b37848a0..b77126051e 100644 --- a/aio/package.json +++ b/aio/package.json @@ -20,10 +20,10 @@ "pree2e": "yarn check-env && yarn ~~update-webdriver", "e2e": "ng e2e --no-webdriver-update", "presetup": "yarn ~~check-env && yarn install && yarn boilerplate:remove", - "setup": "yarn aio-use-npm && yarn boilerplate:add", - "postsetup": "yarn build-ie-polyfills && yarn generate-plunkers && yarn generate-zips && yarn docs", + "setup": "yarn aio-use-npm && yarn example-use-npm", + "postsetup": "yarn boilerplate:add && yarn build-ie-polyfills && yarn generate-plunkers && yarn generate-zips && yarn docs", "presetup-local": "yarn presetup", - "setup-local": "yarn aio-use-local && yarn boilerplate:add --local", + "setup-local": "yarn aio-use-local && yarn example-use-local", "postsetup-local": "yarn postsetup", "pretest-pwa-score-localhost": "yarn build", "test-pwa-score-localhost": "concurrently --kill-others --success first \"http-server dist -p 4200 --silent\" \"yarn test-pwa-score http://localhost:4200 90\"", diff --git a/aio/tools/examples/example-boilerplate.js b/aio/tools/examples/example-boilerplate.js index 8ba07cc107..9eb300c561 100644 --- a/aio/tools/examples/example-boilerplate.js +++ b/aio/tools/examples/example-boilerplate.js @@ -50,18 +50,18 @@ const EXAMPLE_CONFIG_FILENAME = 'example-config.json'; class ExampleBoilerPlate { /** * Add boilerplate files to all the examples - * - * @param useLocal if true then overwrite the Angular library files with locally built ones */ - add(useLocal) { - // Install the shared `node_modules/` (if necessary overwrite Angular packages from npm with local ones). - this.installNodeModules(SHARED_PATH, useLocal); - + add() { // Get all the examples folders, indicated by those that contain a `example-config.json` file const exampleFolders = this.getFoldersContaining(EXAMPLES_BASE_PATH, EXAMPLE_CONFIG_FILENAME, 'node_modules'); exampleFolders.forEach(exampleFolder => { const exampleConfig = this.loadJsonFile(path.resolve(exampleFolder, EXAMPLE_CONFIG_FILENAME)); + if (!fs.existsSync(SHARED_NODE_MODULES_PATH)) { + throw new Error(`The shared node_modules folder for the examples (${SHARED_NODE_MODULES_PATH}) is missing.\n` + + `Perhaps you need to run "yarn example-use-npm" or "yarn example-use-local" to install the dependencies?`); + } + // Link the node modules - requires admin access (on Windows) because it adds symlinks const destinationNodeModules = path.resolve(exampleFolder, 'node_modules'); fs.ensureSymlinkSync(SHARED_NODE_MODULES_PATH, destinationNodeModules); @@ -87,20 +87,12 @@ class ExampleBoilerPlate { main() { yargs .usage('$0 [args]') - .command('add [--local]', 'add the boilerplate to each example', - { local: { describe: 'Use the locally built Angular libraries, rather than ones from npm.' } }, - argv => this.add(argv.local)) + .command('add', 'add the boilerplate to each example', () => this.add()) .command('remove', 'remove the boilerplate from each example', () => this.remove()) .demandCommand(1, 'Please supply a command from the list above') .argv; } - installNodeModules(basePath, useLocal) { - const tool = 'node tools/ng-packages-installer'; - const command = useLocal ? 'overwrite' : 'restore'; - shelljs.exec([tool, command, basePath, '--debug'].join(' ')); - } - getFoldersContaining(basePath, filename, ignore) { const pattern = path.resolve(basePath, '**', filename); const ignorePattern = path.resolve(basePath, '**', ignore, '**'); diff --git a/aio/tools/examples/example-boilerplate.spec.js b/aio/tools/examples/example-boilerplate.spec.js index f9f2b5aa79..c6868258f9 100644 --- a/aio/tools/examples/example-boilerplate.spec.js +++ b/aio/tools/examples/example-boilerplate.spec.js @@ -18,27 +18,12 @@ describe('example-boilerplate tool', () => { beforeEach(() => { spyOn(fs, 'ensureSymlinkSync'); + spyOn(fs, 'existsSync').and.returnValue(true); spyOn(exampleBoilerPlate, 'copyFile'); spyOn(exampleBoilerPlate, 'getFoldersContaining').and.returnValue(exampleFolders); - spyOn(exampleBoilerPlate, 'installNodeModules'); spyOn(exampleBoilerPlate, 'loadJsonFile').and.returnValue({}); }); - it('should install the npm dependencies into `sharedDir` (and pass the `useLocal` argument through)', () => { - exampleBoilerPlate.add(); - expect(exampleBoilerPlate.installNodeModules).toHaveBeenCalledWith(sharedDir, undefined); - - exampleBoilerPlate.installNodeModules.calls.reset(); - - exampleBoilerPlate.add(true); - expect(exampleBoilerPlate.installNodeModules).toHaveBeenCalledWith(sharedDir, true); - - exampleBoilerPlate.installNodeModules.calls.reset(); - - exampleBoilerPlate.add(false); - expect(exampleBoilerPlate.installNodeModules).toHaveBeenCalledWith(sharedDir, false); - }); - it('should process all the example folders', () => { const examplesDir = path.resolve(__dirname, '../../content/examples'); exampleBoilerPlate.add(); @@ -53,6 +38,14 @@ describe('example-boilerplate tool', () => { expect(fs.ensureSymlinkSync).toHaveBeenCalledWith(sharedNodeModulesDir, path.resolve('c/d/node_modules')); }); + it('should error if the node_modules folder is missing', () => { + fs.existsSync.and.returnValue(false); + expect(() => exampleBoilerPlate.add()).toThrowError( + `The shared node_modules folder for the examples (${sharedNodeModulesDir}) is missing.\n` + + `Perhaps you need to run "yarn example-use-npm" or "yarn example-use-local" to install the dependencies?`); + expect(fs.ensureSymlinkSync).not.toHaveBeenCalled(); + }); + it('should copy all the source boilerplate files for systemjs', () => { const boilerplateDir = path.resolve(sharedDir, 'boilerplate'); exampleBoilerPlate.loadJsonFile.and.callFake(filePath => filePath.indexOf('a/b') !== -1 ? { projectType: 'systemjs' } : {}) @@ -95,28 +88,6 @@ describe('example-boilerplate tool', () => { }); }); - describe('installNodeModules', () => { - beforeEach(() => { - spyOn(shelljs, 'exec'); - }); - - it('should overwrite the Angular packages if `useLocal` is true', () => { - exampleBoilerPlate.installNodeModules('some/base/path', true); - expect(shelljs.exec).toHaveBeenCalledWith('node tools/ng-packages-installer overwrite some/base/path --debug'); - expect(shelljs.exec.calls.count()).toEqual(1); - }); - - it('should restore the Angular packages if `useLocal` is not true', () => { - exampleBoilerPlate.installNodeModules('some/base/path1'); - expect(shelljs.exec).toHaveBeenCalledWith('node tools/ng-packages-installer restore some/base/path1 --debug'); - - exampleBoilerPlate.installNodeModules('some/base/path2', false); - expect(shelljs.exec).toHaveBeenCalledWith('node tools/ng-packages-installer restore some/base/path2 --debug'); - - expect(shelljs.exec.calls.count()).toEqual(2); - }); - }); - describe('getFoldersContaining', () => { it('should use glob.sync', () => { spyOn(glob, 'sync').and.returnValue(['a/b/config.json', 'c/d/config.json']); diff --git a/aio/tools/examples/run-example-e2e.js b/aio/tools/examples/run-example-e2e.js index 509d791681..e9a096b18e 100644 --- a/aio/tools/examples/run-example-e2e.js +++ b/aio/tools/examples/run-example-e2e.js @@ -4,6 +4,9 @@ const argv = require('yargs').argv; const globby = require('globby'); const xSpawn = require('cross-spawn'); const treeKill = require('tree-kill'); +const shelljs = require('shelljs'); + +shelljs.set('-e'); const AIO_PATH = path.join(__dirname, '../../'); const SHARED_PATH = path.join(__dirname, '/shared'); @@ -42,21 +45,18 @@ const IGNORED_EXAMPLES = [ // temporary ignores * e.g. --shard=1/3 // the second of every three specs: 1, 4, 7, etc */ function runE2e() { - let promise = Promise.resolve(); if (argv.setup) { // Run setup. - console.log('runE2e: copy boilerplate'); - const spawnInfo = spawnExt('yarn', ['boilerplate:add', argv.local ? '--local' : ''], { cwd: AIO_PATH }); - promise = spawnInfo.promise - .then(() => { - console.log('runE2e: update webdriver'); - return spawnExt('yarn', ['webdriver:update'], { cwd: SHARED_PATH }).promise; - }); + console.log('runE2e: setup boilerplate'); + const installPackagesCommand = `example-use-${argv.local ? 'local' : 'npm'}`; + const addBoilerplateCommand = 'boilerplate:add'; + shelljs.exec(`yarn ${installPackagesCommand}`, { cwd: AIO_PATH }); + shelljs.exec(`yarn ${addBoilerplateCommand}`, { cwd: AIO_PATH }); } const outputFile = path.join(AIO_PATH, './protractor-results.txt'); - return promise + return Promise.resolve() .then(() => findAndRunE2eTests(argv.filter, outputFile, argv.shard)) .then((status) => { reportStatus(status, outputFile);