From e188e472f1507acf2aa51bb52b302c5cbac29cab Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Fri, 20 May 2016 19:07:01 -0700 Subject: [PATCH] docs(e2e-tests): improve gulp e2e tasks and fix samples that were failing --- gulpfile.js | 109 ++++++++++++------ .../ts/app/countdown-timer.component.ts | 10 +- .../cb-component-relative-paths/e2e-spec.js | 49 ++++---- .../cb-dependency-injection/ts/app/main.ts | 2 +- public/docs/_examples/karma-test-shim.js | 2 +- .../server-communication/ts/app/main.ts | 2 +- public/docs/_examples/systemjs.config.js | 2 +- .../docs/_examples/systemjs.config.plunker.js | 2 +- public/docs/_examples/toh-6/ts/app/main.ts | 2 +- public/docs/_examples/wallaby.js | 2 +- .../cookbook/component-relative-paths.jade | 2 +- 11 files changed, 113 insertions(+), 71 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 448f9afb48..73778bb19e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -86,21 +86,46 @@ var _exampleBoilerplateFiles = [ var _exampleDartWebBoilerPlateFiles = ['styles.css']; -// --filter may be passed in to filter/select _example app subdir names -// i.e. gulp run-e2e-tests --filter=foo ; would select all example apps with -// 'foo' in their folder names. +/** + * Run Protractor End-to-End Tests for Doc Samples + * + * Flags + * --filter to filter/select _example app subdir names + * e.g. gulp run-e2e-tests --filter=foo // all example apps with 'foo' in their folder names. + * + * --fast by-passes the npm install and webdriver update + * Use it for repeated test runs (but not the FIRST run) + * e.g. gulp run-e2e-tests --fast + * + * --lang to filter by code language + * e.g. gulp run-e2e-tests --lang=ts // only TypeScript apps + * default is (ts|js) + * all means (ts|js|dart) + */ gulp.task('run-e2e-tests', function() { - var spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PATH}); - return spawnInfo.promise.then(function() { - copyExampleBoilerplate(); - var exePath = path.join(process.cwd(), "./node_modules/.bin/"); - spawnInfo = spawnExt('webdriver-manager', ['update'], {cwd: exePath}); - return spawnInfo.promise; - }).then(function() { + + var exePath = path.join(process.cwd(), "./node_modules/.bin/"); + + var promise; + if (argv.fast) { + // fast; skip all setup + promise = Promise.resolve(true); + } else { + // Not 'fast'; do full setup + var spawnInfo = spawnExt('npm', ['install'], { cwd: EXAMPLES_PATH}); + promise = spawnInfo.promise.then(function() { + copyExampleBoilerplate(); + spawnInfo = spawnExt('webdriver-manager', ['update'], {cwd: exePath}); + return spawnInfo.promise; + }); + } + + promise.then(function() { return findAndRunE2eTests(argv.filter); }).then(function(status) { reportStatus(status); - }).fail(function(e) { + }).catch(function(e) { + gutil.log(e); return e; }); }); @@ -114,10 +139,13 @@ function findAndRunE2eTests(filter) { var startTime = new Date().getTime(); // create an output file with header. var outputFile = path.join(process.cwd(), 'protractor-results.txt'); - var header = "Protractor example results for " + lang + " on " + (new Date()).toLocaleString() + "\n\n"; - if (filter) { - header += ' Filter: ' + filter.toString() + '\n\n'; - } + + var header = `Doc Sample Protractor Results for ${lang} on ${new Date().toLocaleString()}\n`; + header += argv.fast ? + ' Fast Mode (--fast): no npm install, webdriver update, or boilerplate copy\n' : + ' Slow Mode: npm install, webdriver update, and boilerplate copy\n'; + header += ` Filter: ${filter ? filter : 'All tests'}\n\n`; + fs.writeFileSync(outputFile, header); // create an array of combos where each @@ -175,25 +203,32 @@ function runE2eTsTests(appDir, protractorConfigFilename, outputFile) { } function runProtractor(prepPromise, appDir, appRunSpawnInfo, protractorConfigFilename, outputFile) { - return prepPromise.then(function (data) { - // start protractor - var pcFilename = path.resolve(protractorConfigFilename); // need to resolve because we are going to be running from a different dir - var exePath = path.join(process.cwd(), "./node_modules/.bin/"); - var spawnInfo = spawnExt('protractor', - [ pcFilename, '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: exePath }); - return spawnInfo.promise; - }).then(function(data) { - // kill the app now that protractor has completed. - // Ugh... proc.kill does not work properly on windows with child processes. - // appRun.proc.kill(); - treeKill(appRunSpawnInfo.proc.pid); - return !data; - }).fail(function(err) { - // Ugh... proc.kill does not work properly on windows with child processes. - // appRun.proc.kill(); - treeKill(appRunSpawnInfo.proc.pid); - return false; - }); + return prepPromise + .catch(function(){ + var emsg = `AppDir failed during compile: ${appDir}\n\n`; + gutil.log(emsg); + fs.appendFileSync(outputFile, emsg); + return Promise.reject(emsg); + }) + .then(function (data) { + // start protractor + var pcFilename = path.resolve(protractorConfigFilename); // need to resolve because we are going to be running from a different dir + var exePath = path.join(process.cwd(), "./node_modules/.bin/"); + var spawnInfo = spawnExt('protractor', + [ pcFilename, '--params.appDir=' + appDir, '--params.outputFile=' + outputFile], { cwd: exePath }); + return spawnInfo.promise + }) + .then( + function() { return finish(true);}, + function() { return finish(false);} + ) + + function finish(ok){ + // Ugh... proc.kill does not work properly on windows with child processes. + // appRun.proc.kill(); + treeKill(appRunSpawnInfo.proc.pid); + return ok; + } } // start the server in appDir/build/web; then run protractor with the specified @@ -252,9 +287,11 @@ function spawnExt(command, args, options) { proc.stderr.on('data', function (data) { gutil.log(data.toString()); }); - proc.on('close', function (data) { + proc.on('close', function (returnCode) { gutil.log('completed: ' + descr); - deferred.resolve(data); + // Many tasks (e.g., tsc) complete but are actually errors; + // Confirm return code is zero. + returnCode === 0 ? deferred.resolve(0) : deferred.reject(returnCode); }); proc.on('error', function (data) { gutil.log('completed with error:' + descr); diff --git a/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts b/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts index 83f5751d5b..262ed6f832 100644 --- a/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts +++ b/public/docs/_examples/cb-component-communication/ts/app/countdown-timer.component.ts @@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; @Component({ - selector:'countdown-timer', + selector: 'countdown-timer', template: '

{{message}}

' }) export class CountdownTimerComponent implements OnInit, OnDestroy { @@ -24,12 +24,12 @@ export class CountdownTimerComponent implements OnInit, OnDestroy { private countDown() { this.clearTimer(); - this.intervalId = setInterval(()=>{ + this.intervalId = window.setInterval(() => { this.seconds -= 1; - if (this.seconds == 0) { - this.message = "Blast off!"; + if (this.seconds === 0) { + this.message = 'Blast off!'; } else { - if (this.seconds < 0) { this.seconds = 10;} // reset + if (this.seconds < 0) { this.seconds = 10; } // reset this.message = `T-${this.seconds} seconds and counting`; } }, 1000); diff --git a/public/docs/_examples/cb-component-relative-paths/e2e-spec.js b/public/docs/_examples/cb-component-relative-paths/e2e-spec.js index 52516f4d4b..6646bd0b4f 100644 --- a/public/docs/_examples/cb-component-relative-paths/e2e-spec.js +++ b/public/docs/_examples/cb-component-relative-paths/e2e-spec.js @@ -1,27 +1,32 @@ -// gulp run-e2e-tests --filter=cb-set-document-title -describe('Set Document Title', function () { +describe('Cookbook: component-relative paths', function () { - beforeAll(function () { - browser.get(''); - }); - - it('should set the document title', function () { - - var titles = [ - 'Good morning!', - 'Good afternoon!', - 'Good evening!' - ]; - - element.all( by.css( 'ul li a' ) ).each( - function iterator( element, i ) { - - element.click(); - expect( browser.getTitle() ).toEqual( titles[ i ] ); - - } - ); + function getPageStruct() { + return { + title: element( by.tagName( 'h1' )), + absComp: element( by.css( 'absolute-path div' ) ), + relComp: element( by.css( 'relative-path div' ) ) + } + } + var page; + beforeAll(function () { + browser.get(''); + page = getPageStruct(); }); + it('should display title of the sample', function () { + expect(element(by.tagName('h1')).getText()).toContain('Paths'); + }); + + it('should have absolute-path element', function () { + expect(page.absComp.isPresent()).toBe(true, 'no element'); + }); + + it('should display the absolute path text', function () { + expect(page.absComp.getText()).toContain('Absolute'); + }); + + it('should display the component-relative path text', function () { + expect(page.relComp.getText()).toContain('Component-relative'); + }); }); diff --git a/public/docs/_examples/cb-dependency-injection/ts/app/main.ts b/public/docs/_examples/cb-dependency-injection/ts/app/main.ts index 508177e81b..595971625e 100644 --- a/public/docs/_examples/cb-dependency-injection/ts/app/main.ts +++ b/public/docs/_examples/cb-dependency-injection/ts/app/main.ts @@ -8,7 +8,7 @@ import { LocationStrategy, import { HeroData } from './hero-data'; import { InMemoryBackendService, - SEED_DATA } from 'angular2-in-memory-web-api/core'; + SEED_DATA } from 'angular2-in-memory-web-api'; import { AppComponent } from './app.component'; diff --git a/public/docs/_examples/karma-test-shim.js b/public/docs/_examples/karma-test-shim.js index 4d1e76371d..bc8cf372f3 100644 --- a/public/docs/_examples/karma-test-shim.js +++ b/public/docs/_examples/karma-test-shim.js @@ -38,7 +38,7 @@ var map = { var packages = { 'app': { main: 'main.js', defaultExtension: 'js' }, 'rxjs': { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { defaultExtension: 'js' }, + 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, }; var ngPackageNames = [ diff --git a/public/docs/_examples/server-communication/ts/app/main.ts b/public/docs/_examples/server-communication/ts/app/main.ts index 870548bd32..ceae9a4825 100644 --- a/public/docs/_examples/server-communication/ts/app/main.ts +++ b/public/docs/_examples/server-communication/ts/app/main.ts @@ -5,7 +5,7 @@ import { provide } from '@angular/core'; import { XHRBackend } from '@angular/http'; import { InMemoryBackendService, - SEED_DATA } from 'angular2-in-memory-web-api/core'; + SEED_DATA } from 'angular2-in-memory-web-api'; import { HeroData } from './hero-data'; // The usual bootstrapping imports diff --git a/public/docs/_examples/systemjs.config.js b/public/docs/_examples/systemjs.config.js index dc5c1484b6..56d5f61e5f 100644 --- a/public/docs/_examples/systemjs.config.js +++ b/public/docs/_examples/systemjs.config.js @@ -17,7 +17,7 @@ var packages = { 'app': { main: 'main.js', defaultExtension: 'js' }, 'rxjs': { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { defaultExtension: 'js' }, + 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, }; var ngPackageNames = [ diff --git a/public/docs/_examples/systemjs.config.plunker.js b/public/docs/_examples/systemjs.config.plunker.js index 29a93a07c4..9e13e14edb 100644 --- a/public/docs/_examples/systemjs.config.plunker.js +++ b/public/docs/_examples/systemjs.config.plunker.js @@ -22,7 +22,7 @@ var packages = { 'app': { main: 'main.ts', defaultExtension: 'ts' }, 'rxjs': { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { defaultExtension: 'js' }, + 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, }; var ngPackageNames = [ diff --git a/public/docs/_examples/toh-6/ts/app/main.ts b/public/docs/_examples/toh-6/ts/app/main.ts index 08caa81826..be838f0855 100644 --- a/public/docs/_examples/toh-6/ts/app/main.ts +++ b/public/docs/_examples/toh-6/ts/app/main.ts @@ -4,7 +4,7 @@ import { provide } from '@angular/core'; import { XHRBackend } from '@angular/http'; -import { InMemoryBackendService, SEED_DATA } from 'angular2-in-memory-web-api/core'; +import { InMemoryBackendService, SEED_DATA } from 'angular2-in-memory-web-api'; import { InMemoryDataService } from './in-memory-data.service'; // The usual bootstrapping imports diff --git a/public/docs/_examples/wallaby.js b/public/docs/_examples/wallaby.js index 7a5f259aca..2648c2c3aa 100644 --- a/public/docs/_examples/wallaby.js +++ b/public/docs/_examples/wallaby.js @@ -84,7 +84,7 @@ module.exports = function () { var packages = { 'app': { main: 'main.js', defaultExtension: 'js' }, 'rxjs': { defaultExtension: 'js' }, - 'angular2-in-memory-web-api': { defaultExtension: 'js' }, + 'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' }, }; var ngPackageNames = [ diff --git a/public/docs/ts/latest/cookbook/component-relative-paths.jade b/public/docs/ts/latest/cookbook/component-relative-paths.jade index 6266730f92..66f90c1ffd 100644 --- a/public/docs/ts/latest/cookbook/component-relative-paths.jade +++ b/public/docs/ts/latest/cookbook/component-relative-paths.jade @@ -84,7 +84,7 @@ include ../_util-fns cb-component-relative-paths/ts/app/some.component.css, cb-component-relative-paths/ts/app/app.component.ts`, null, - `app/some.component.ts, app/some.html, app/some.component.css, app/app.component.ts`) + `app/some.component.ts, app/some.component.html, app/some.component.css, app/app.component.ts`) a#why-default .l-main-section