From bfd5f27525f8ee2418cdab814321fb6649bab704 Mon Sep 17 00:00:00 2001 From: Filipe Silva Date: Thu, 13 Apr 2017 22:35:13 +0100 Subject: [PATCH] feat(aio): add e2e (#15976) PR Close #15976 --- .travis.yml | 2 + aio/.gitignore | 1 + aio/content/examples/.gitignore | 2 + .../cb-aot-compiler/tsconfig-aot.json | 5 +- .../examples/cb-form-validation/e2e-spec.ts | 3 +- .../cb-i18n/src/systemjs-text-plugin.js | 14 + aio/content/examples/forms/e2e-spec.ts | 3 +- .../examples/lifecycle-hooks/e2e-spec.ts | 7 +- aio/content/examples/router/e2e-spec.ts | 4 +- aio/content/examples/toh-6/copy-dist-files.js | 12 + .../examples/toh-pt6/tsconfig-aot.json | 2 +- .../examples/universal/tsconfig-aot.json | 2 +- .../examples/upgrade-module/e2e-spec.ts | 5 +- .../upgrade-phonecat-1-typescript/e2e-spec.ts | 6 +- .../tsconfig.json | 2 +- .../app/phone-list/phone-list.component.ts | 2 +- .../upgrade-phonecat-2-hybrid/e2e-spec.ts | 5 +- .../systemjs.config.1.js | 8 +- .../tsconfig-aot.json | 2 +- .../upgrade-phonecat-2-hybrid/tsconfig.json | 2 +- .../phone-detail/phone-detail.component.ts | 2 +- .../app/phone-list/phone-list.component.ts | 2 +- .../upgrade-phonecat-3-router/e2e-spec.ts | 5 +- .../systemjs.config.1.js | 8 +- .../tsconfig-aot.json | 2 +- .../upgrade-phonecat-3-router/tsconfig.json | 2 +- .../upgrade-phonecat-4-final/tsconfig.json | 2 +- aio/package.json | 8 +- aio/tools/examples/run-example-e2e.js | 245 ++++++++++++++++++ .../shared/boilerplate/src/tsconfig.json | 2 +- aio/tools/examples/shared/package.json | 2 +- .../examples/shared/protractor-helpers.ts | 35 --- .../examples/shared/protractor.config.js | 23 +- aio/tools/examples/shared/tsconfig.json | 7 +- aio/tools/examples/shared/yarn.lock | 123 ++++++--- aio/yarn.lock | 45 +++- scripts/ci/install.sh | 6 +- scripts/ci/test-aio-e2e.sh | 25 ++ scripts/ci/test-aio.sh | 2 - scripts/ci/test.sh | 3 + 40 files changed, 500 insertions(+), 138 deletions(-) create mode 100644 aio/content/examples/cb-i18n/src/systemjs-text-plugin.js create mode 100644 aio/content/examples/toh-6/copy-dist-files.js create mode 100644 aio/tools/examples/run-example-e2e.js delete mode 100644 aio/tools/examples/shared/protractor-helpers.ts create mode 100755 scripts/ci/test-aio-e2e.sh diff --git a/.travis.yml b/.travis.yml index 82afb15d56..a1ce89891f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,12 +48,14 @@ env: - CI_MODE=browserstack_optional - CI_MODE=docs_test - CI_MODE=aio + - CI_MODE=aio_e2e matrix: fast_finish: true allow_failures: - env: "CI_MODE=saucelabs_optional" - env: "CI_MODE=browserstack_optional" + - env: "CI_MODE=aio_e2e" before_install: # source the env.sh script so that the exported variables are available to other scripts later on diff --git a/aio/.gitignore b/aio/.gitignore index 268ac3aa39..49e9231363 100644 --- a/aio/.gitignore +++ b/aio/.gitignore @@ -38,6 +38,7 @@ yarn-error.log # e2e /e2e/*.js /e2e/*.map +protractor-results*.txt # System Files .DS_Store diff --git a/aio/content/examples/.gitignore b/aio/content/examples/.gitignore index 4352bbcdf1..d9657e8848 100644 --- a/aio/content/examples/.gitignore +++ b/aio/content/examples/.gitignore @@ -36,9 +36,11 @@ dist/ *.3.js.map !systemjs.config.*.js !karma-test-shim.*.js +!copy-dist-files.js # AngularJS files !**/*.ajs.js +**/app/**/*.ajs.js # aot **/*.ngfactory.ts diff --git a/aio/content/examples/cb-aot-compiler/tsconfig-aot.json b/aio/content/examples/cb-aot-compiler/tsconfig-aot.json index d0a3d00ad4..ea56eb7067 100644 --- a/aio/content/examples/cb-aot-compiler/tsconfig-aot.json +++ b/aio/content/examples/cb-aot-compiler/tsconfig-aot.json @@ -8,7 +8,10 @@ "experimentalDecorators": true, "lib": ["es2015", "dom"], "noImplicitAny": true, - "suppressImplicitAnyIndexErrors": true + "suppressImplicitAnyIndexErrors": true, + "typeRoots": [ + "./node_modules/@types/" + ] }, "files": [ diff --git a/aio/content/examples/cb-form-validation/e2e-spec.ts b/aio/content/examples/cb-form-validation/e2e-spec.ts index 8ffc01e250..1e9788956a 100644 --- a/aio/content/examples/cb-form-validation/e2e-spec.ts +++ b/aio/content/examples/cb-form-validation/e2e-spec.ts @@ -1,10 +1,9 @@ 'use strict'; // necessary for node! import { browser, element, by, protractor, ElementFinder, ElementArrayFinder } from 'protractor'; -import { appLang, describeIf } from '../protractor-helpers'; // THESE TESTS ARE INCOMPLETE -describeIf(appLang.appIsTs || appLang.appIsJs, 'Form Validation Tests', function () { +describe('Form Validation Tests', function () { beforeAll(function () { browser.get(''); diff --git a/aio/content/examples/cb-i18n/src/systemjs-text-plugin.js b/aio/content/examples/cb-i18n/src/systemjs-text-plugin.js new file mode 100644 index 0000000000..581f87db1a --- /dev/null +++ b/aio/content/examples/cb-i18n/src/systemjs-text-plugin.js @@ -0,0 +1,14 @@ +// #docregion +/* + SystemJS Text plugin from + https://github.com/systemjs/plugin-text/blob/master/text.js +*/ +exports.translate = function (load) { + if (this.builder && this.transpiler) { + load.metadata.format = 'esm'; + return 'exp' + 'ort var __useDefault = true; exp' + 'ort default ' + JSON.stringify(load.source) + ';'; + } + + load.metadata.format = 'amd'; + return 'def' + 'ine(function() {\nreturn ' + JSON.stringify(load.source) + ';\n});'; +} diff --git a/aio/content/examples/forms/e2e-spec.ts b/aio/content/examples/forms/e2e-spec.ts index 2afd370103..d3d3cff970 100644 --- a/aio/content/examples/forms/e2e-spec.ts +++ b/aio/content/examples/forms/e2e-spec.ts @@ -1,7 +1,6 @@ import { browser, element, by } from 'protractor'; -import { appLang, describeIf } from '../protractor-helpers'; -describeIf(appLang.appIsTs || appLang.appIsJs, 'Forms Tests', function () { +describe('Forms Tests', function () { beforeEach(function () { browser.get(''); diff --git a/aio/content/examples/lifecycle-hooks/e2e-spec.ts b/aio/content/examples/lifecycle-hooks/e2e-spec.ts index 8e9acb1c76..003f8f68f2 100644 --- a/aio/content/examples/lifecycle-hooks/e2e-spec.ts +++ b/aio/content/examples/lifecycle-hooks/e2e-spec.ts @@ -1,4 +1,4 @@ -'use strict'; // necessary for es6 output in node +'use strict'; // necessary for es6 output in node import { browser, element, by } from 'protractor'; @@ -101,7 +101,10 @@ describe('Lifecycle hooks', function () { expect(commentEle.getText()).toContain('long name'); return logEles.count(); }).then(function(count: number) { - expect(logCount + 7).toEqual(count, '7 additional log messages should have been added'); + expect(logCount + 7).toBeGreaterThan(count - 3, + '7 additional log messages should have been added'); + expect(logCount + 7).toBeLessThan(count + 3, + '7 additional log messages should have been added'); logCount = count; return buttonEle.click(); }).then(function() { diff --git a/aio/content/examples/router/e2e-spec.ts b/aio/content/examples/router/e2e-spec.ts index 2e9c6bafeb..e7a882f83c 100644 --- a/aio/content/examples/router/e2e-spec.ts +++ b/aio/content/examples/router/e2e-spec.ts @@ -151,11 +151,11 @@ describe('Router', () => { await buttonEle.click(); crisisEle = page.crisisList.get(index); if (save) { - expect(crisisEle.getText()).toEqual(crisisText + '-foo'); + expect(crisisEle.getText()).toContain(crisisText + '-foo'); } else { await browser.wait(EC.alertIsPresent(), 4000); await browser.switchTo().alert().accept(); - expect(crisisEle.getText()).toEqual(crisisText); + expect(crisisEle.getText()).toContain(crisisText); } } diff --git a/aio/content/examples/toh-6/copy-dist-files.js b/aio/content/examples/toh-6/copy-dist-files.js new file mode 100644 index 0000000000..080864e99c --- /dev/null +++ b/aio/content/examples/toh-6/copy-dist-files.js @@ -0,0 +1,12 @@ +// #docregion +var fs = require('fs'); +var resources = [ + 'node_modules/core-js/client/shim.min.js', + 'node_modules/zone.js/dist/zone.min.js', + 'src/styles.css' +]; +resources.map(function(f) { + var path = f.split('/'); + var t = 'aot/' + path[path.length-1]; + fs.createReadStream(f).pipe(fs.createWriteStream(t)); +}); diff --git a/aio/content/examples/toh-pt6/tsconfig-aot.json b/aio/content/examples/toh-pt6/tsconfig-aot.json index fe1e6df520..2a88388860 100644 --- a/aio/content/examples/toh-pt6/tsconfig-aot.json +++ b/aio/content/examples/toh-pt6/tsconfig-aot.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, diff --git a/aio/content/examples/universal/tsconfig-aot.json b/aio/content/examples/universal/tsconfig-aot.json index 023bf2fb68..fd4632d05f 100644 --- a/aio/content/examples/universal/tsconfig-aot.json +++ b/aio/content/examples/universal/tsconfig-aot.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "node_modules/@types/" + "./node_modules/@types/" ] }, diff --git a/aio/content/examples/upgrade-module/e2e-spec.ts b/aio/content/examples/upgrade-module/e2e-spec.ts index 0c45fb78b8..257e53d2cc 100644 --- a/aio/content/examples/upgrade-module/e2e-spec.ts +++ b/aio/content/examples/upgrade-module/e2e-spec.ts @@ -1,12 +1,13 @@ 'use strict'; // necessary for es6 output in node import { browser, element, by } from 'protractor'; -import { setProtractorToHybridMode } from '../protractor-helpers'; describe('Upgrade Tests', function () { beforeAll(function () { - setProtractorToHybridMode(); + // Set protractor to hybrid mode. + browser.rootEl = 'body'; + browser.ng12Hybrid = true; }); describe('AngularJS Auto-bootstrap', function() { diff --git a/aio/content/examples/upgrade-phonecat-1-typescript/e2e-spec.ts b/aio/content/examples/upgrade-phonecat-1-typescript/e2e-spec.ts index 4598a7f6dc..ec98b44eb5 100644 --- a/aio/content/examples/upgrade-phonecat-1-typescript/e2e-spec.ts +++ b/aio/content/examples/upgrade-phonecat-1-typescript/e2e-spec.ts @@ -1,7 +1,6 @@ -'use strict'; // necessary for es6 output in node +'use strict'; // necessary for es6 output in node import { browser, element, by, ElementFinder } from 'protractor'; -import { setProtractorToNg1Mode } from '../protractor-helpers'; // Angular E2E Testing Guide: // https://docs.angularjs.org/guide/e2e-testing @@ -10,7 +9,8 @@ describe('PhoneCat Application', function() { beforeAll(function() { browser.baseUrl = 'http://localhost:8080/app/'; - setProtractorToNg1Mode(); + // protractor.config.js is set to ng2 mode by default, so we must manually change it + browser.rootEl = 'body'; }); it('should redirect `index.html` to `index.html#!/phones', function() { diff --git a/aio/content/examples/upgrade-phonecat-1-typescript/tsconfig.json b/aio/content/examples/upgrade-phonecat-1-typescript/tsconfig.json index be11d1eb49..8444d2ddea 100644 --- a/aio/content/examples/upgrade-phonecat-1-typescript/tsconfig.json +++ b/aio/content/examples/upgrade-phonecat-1-typescript/tsconfig.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, "compileOnSave": true, diff --git a/aio/content/examples/upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts b/aio/content/examples/upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts index 1f51c6faa2..453df46d25 100644 --- a/aio/content/examples/upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts +++ b/aio/content/examples/upgrade-phonecat-2-hybrid/app/phone-list/phone-list.component.ts @@ -11,7 +11,7 @@ import { Phone, PhoneData } from '../core/phone/phone.service'; // #docregion downgrade-component @Component({ selector: 'phone-list', - templateUrl: 'phone-list.template.html' + templateUrl: './phone-list.template.html' }) export class PhoneListComponent { // #enddocregion downgrade-component diff --git a/aio/content/examples/upgrade-phonecat-2-hybrid/e2e-spec.ts b/aio/content/examples/upgrade-phonecat-2-hybrid/e2e-spec.ts index 2ec8e37977..c0669774b9 100644 --- a/aio/content/examples/upgrade-phonecat-2-hybrid/e2e-spec.ts +++ b/aio/content/examples/upgrade-phonecat-2-hybrid/e2e-spec.ts @@ -1,7 +1,6 @@ 'use strict'; // necessary for es6 output in node import { browser, element, by } from 'protractor'; -import { setProtractorToHybridMode } from '../protractor-helpers'; // Angular E2E Testing Guide: // https://docs.angularjs.org/guide/e2e-testing @@ -9,7 +8,9 @@ import { setProtractorToHybridMode } from '../protractor-helpers'; describe('PhoneCat Application', function() { beforeAll(function () { - setProtractorToHybridMode(); + // Set protractor to hybrid mode. + browser.rootEl = 'body'; + browser.ng12Hybrid = true; }); it('should redirect `index.html` to `index.html#!/phones', function() { diff --git a/aio/content/examples/upgrade-phonecat-2-hybrid/systemjs.config.1.js b/aio/content/examples/upgrade-phonecat-2-hybrid/systemjs.config.1.js index 8197c44a89..199067dc0a 100644 --- a/aio/content/examples/upgrade-phonecat-2-hybrid/systemjs.config.1.js +++ b/aio/content/examples/upgrade-phonecat-2-hybrid/systemjs.config.1.js @@ -10,6 +10,7 @@ 'npm:': '/node_modules/' }, map: { + 'ng-loader': '../src/systemjs-angular-loader.js', app: '/app', // #enddocregion paths // angular bundles @@ -36,7 +37,12 @@ packages: { 'app': { main: './main.js', - defaultExtension: 'js' + defaultExtension: 'js', + meta: { + './*.js': { + loader: 'ng-loader' + } + } }, rxjs: { defaultExtension: 'js' diff --git a/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig-aot.json b/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig-aot.json index 58f9de3309..91807a25a9 100644 --- a/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig-aot.json +++ b/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig-aot.json @@ -11,7 +11,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, diff --git a/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig.json b/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig.json index f267800f14..bdf16643ce 100644 --- a/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig.json +++ b/aio/content/examples/upgrade-phonecat-2-hybrid/tsconfig.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, "compileOnSave": true, diff --git a/aio/content/examples/upgrade-phonecat-3-router/app/phone-detail/phone-detail.component.ts b/aio/content/examples/upgrade-phonecat-3-router/app/phone-detail/phone-detail.component.ts index 32a3d40790..e9e666ceef 100644 --- a/aio/content/examples/upgrade-phonecat-3-router/app/phone-detail/phone-detail.component.ts +++ b/aio/content/examples/upgrade-phonecat-3-router/app/phone-detail/phone-detail.component.ts @@ -8,7 +8,7 @@ import { Phone, PhoneData } from '../core/phone/phone.service'; import { RouteParams } from '../ajs-upgraded-providers'; @Component({ - templateUrl: 'phone-detail.template.html', + templateUrl: './phone-detail.template.html', }) export class PhoneDetailComponent { phone: PhoneData; diff --git a/aio/content/examples/upgrade-phonecat-3-router/app/phone-list/phone-list.component.ts b/aio/content/examples/upgrade-phonecat-3-router/app/phone-list/phone-list.component.ts index 40f522bec8..e730024952 100644 --- a/aio/content/examples/upgrade-phonecat-3-router/app/phone-list/phone-list.component.ts +++ b/aio/content/examples/upgrade-phonecat-3-router/app/phone-list/phone-list.component.ts @@ -6,7 +6,7 @@ import { Component } from '@angular/core'; import { Phone, PhoneData } from '../core/phone/phone.service'; @Component({ - templateUrl: 'phone-list.template.html' + templateUrl: './phone-list.template.html' }) export class PhoneListComponent { phones: PhoneData[]; diff --git a/aio/content/examples/upgrade-phonecat-3-router/e2e-spec.ts b/aio/content/examples/upgrade-phonecat-3-router/e2e-spec.ts index 2ec8e37977..c0669774b9 100644 --- a/aio/content/examples/upgrade-phonecat-3-router/e2e-spec.ts +++ b/aio/content/examples/upgrade-phonecat-3-router/e2e-spec.ts @@ -1,7 +1,6 @@ 'use strict'; // necessary for es6 output in node import { browser, element, by } from 'protractor'; -import { setProtractorToHybridMode } from '../protractor-helpers'; // Angular E2E Testing Guide: // https://docs.angularjs.org/guide/e2e-testing @@ -9,7 +8,9 @@ import { setProtractorToHybridMode } from '../protractor-helpers'; describe('PhoneCat Application', function() { beforeAll(function () { - setProtractorToHybridMode(); + // Set protractor to hybrid mode. + browser.rootEl = 'body'; + browser.ng12Hybrid = true; }); it('should redirect `index.html` to `index.html#!/phones', function() { diff --git a/aio/content/examples/upgrade-phonecat-3-router/systemjs.config.1.js b/aio/content/examples/upgrade-phonecat-3-router/systemjs.config.1.js index b801d42bad..82dd2d3890 100644 --- a/aio/content/examples/upgrade-phonecat-3-router/systemjs.config.1.js +++ b/aio/content/examples/upgrade-phonecat-3-router/systemjs.config.1.js @@ -10,6 +10,7 @@ 'npm:': '/node_modules/' }, map: { + 'ng-loader': '../src/systemjs-angular-loader.js', app: '/app', // #enddocregion paths // angular bundles @@ -34,7 +35,12 @@ packages: { 'app': { main: './main.js', - defaultExtension: 'js' + defaultExtension: 'js', + meta: { + './*.js': { + loader: 'ng-loader' + } + } }, rxjs: { defaultExtension: 'js' diff --git a/aio/content/examples/upgrade-phonecat-3-router/tsconfig-aot.json b/aio/content/examples/upgrade-phonecat-3-router/tsconfig-aot.json index 58f9de3309..91807a25a9 100644 --- a/aio/content/examples/upgrade-phonecat-3-router/tsconfig-aot.json +++ b/aio/content/examples/upgrade-phonecat-3-router/tsconfig-aot.json @@ -11,7 +11,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, diff --git a/aio/content/examples/upgrade-phonecat-3-router/tsconfig.json b/aio/content/examples/upgrade-phonecat-3-router/tsconfig.json index f267800f14..bdf16643ce 100644 --- a/aio/content/examples/upgrade-phonecat-3-router/tsconfig.json +++ b/aio/content/examples/upgrade-phonecat-3-router/tsconfig.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, "compileOnSave": true, diff --git a/aio/content/examples/upgrade-phonecat-4-final/tsconfig.json b/aio/content/examples/upgrade-phonecat-4-final/tsconfig.json index f267800f14..bdf16643ce 100644 --- a/aio/content/examples/upgrade-phonecat-4-final/tsconfig.json +++ b/aio/content/examples/upgrade-phonecat-4-final/tsconfig.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../node_modules/@types/" + "./node_modules/@types/" ] }, "compileOnSave": true, diff --git a/aio/package.json b/aio/package.json index f560a34c89..2036c0ca9c 100644 --- a/aio/package.json +++ b/aio/package.json @@ -17,6 +17,7 @@ "pretest-pwa-score-local": "yarn build", "test-pwa-score-local": "concurrently --kill-others --success first \"http-server dist -p 4200 --silent\" \"yarn test-pwa-score -- http://localhost:4200 90\"", "test-pwa-score": "node scripts/test-pwa-score", + "example-e2e": "node ./tools/examples/run-example-e2e", "deploy-preview": "scripts/deploy-preview.sh", "deploy-staging": "scripts/deploy-staging.sh", "check-env": "node ../tools/check-environment.js", @@ -58,13 +59,14 @@ "canonical-path": "^0.0.2", "codelyzer": "~2.0.0", "concurrently": "^3.4.0", + "cross-spawn": "^5.1.0", "dgeni": "^0.4.7", "dgeni-packages": "0.17.0", "entities": "^1.1.1", "eslint": "^3.19.0", "eslint-plugin-jasmine": "^2.2.0", "firebase-tools": "^3.2.1", - "fs-extra": "^2.1.1", + "fs-extra": "^2.1.2", "globby": "^6.1.0", "html": "^1.0.0", "http-server": "^0.9.0", @@ -87,10 +89,12 @@ "rho": "https://github.com/petebacondarwin/rho#master", "rimraf": "^2.6.1", "shelljs": "^0.7.7", + "tree-kill": "^1.1.0", "ts-node": "~2.0.0", "tslint": "~4.5.0", "typescript": "2.2.0", "vrsource-tslint-rules": "^4.0.1", - "watchr": "^3.0.1" + "watchr": "^3.0.1", + "yargs": "^7.0.2" } } diff --git a/aio/tools/examples/run-example-e2e.js b/aio/tools/examples/run-example-e2e.js new file mode 100644 index 0000000000..e11310218a --- /dev/null +++ b/aio/tools/examples/run-example-e2e.js @@ -0,0 +1,245 @@ +const path = require('path'); +const fs = require('fs-extra'); +const argv = require('yargs').argv; +const globby = require('globby'); +const xSpawn = require('cross-spawn'); +const treeKill = require('tree-kill'); + +const AIO_PATH = path.join(__dirname, '../../'); +const SHARED_PATH = path.join(__dirname, '/shared'); +const EXAMPLES_PATH = path.join(AIO_PATH, './content/examples/'); +const PROTRACTOR_CONFIG_FILENAME = path.join(__dirname, './shared/protractor.config.js'); +const SPEC_FILENAME = 'e2e-spec.ts'; +const EXAMPLE_CONFIG_FILENAME = 'example-config.json'; +const IGNORED_EXAMPLES = [ + 'cb-ts-to-js/' +]; + +/** + * Run Protractor End-to-End Tests for Doc Samples + * + * Flags + * --filter to filter/select _example app subdir names + * e.g. --filter=foo // all example apps with 'foo' in their folder names. + * + * --setup run yarn install, copy boilerplate and update webdriver + * e.g. --setup + */ +function runE2e() { + let promise = Promise.resolve(); + if (argv.setup) { + // Run setup. + console.log('runE2e: copy boilerplate'); + const spawnInfo = spawnExt('yarn', ['boilerplate:add'], { cwd: AIO_PATH }); + promise = spawnInfo.promise + .then(() => { + console.log('runE2e: update webdriver'); + return spawnExt('yarn', ['webdriver:update'], { cwd: SHARED_PATH }).promise; + }); + }; + + const outputFile = path.join(AIO_PATH, './protractor-results.txt'); + + return promise + .then(() => findAndRunE2eTests(argv.filter, outputFile)) + .then((status) => { + reportStatus(status, outputFile); + if (status.failed.length > 0) { + return Promise.reject('Some test suites failed'); + } + }).catch(function (e) { + console.log(e); + process.exitCode = 1; + }); +} + +// Finds all of the *e2e-spec.tests under the examples folder along with the corresponding apps +// that they should run under. Then run each app/spec collection sequentially. +function findAndRunE2eTests(filter, outputFile) { + // create an output file with header. + const startTime = new Date().getTime(); + let header = `Doc Sample Protractor Results on ${new Date().toLocaleString()}\n`; + header += ` Filter: ${filter ? filter : 'All tests'}\n\n`; + fs.writeFileSync(outputFile, header); + + // Run the tests sequentially. + const status = { passed: [], failed: [] }; + return getE2eSpecPaths(EXAMPLES_PATH, filter) + .then(e2eSpecPaths => e2eSpecPaths.reduce((promise, specPath) => { + return promise.then(() => { + const examplePath = path.dirname(specPath); + return runE2eTests(examplePath, outputFile).then((ok) => { + const arr = ok ? status.passed : status.failed; + arr.push(examplePath); + }); + }); + }, Promise.resolve())) + .then(function () { + const stopTime = new Date().getTime(); + status.elapsedTime = (stopTime - startTime) / 1000; + return status; + }); +} + +// Start the example in appDir; then run protractor with the specified +// fileName; then shut down the example. +// All protractor output is appended to the outputFile. +function runE2eTests(appDir, outputFile) { + + const config = loadExampleConfig(appDir); + + const appBuildSpawnInfo = spawnExt('yarn', [config.build], { cwd: appDir }); + const appRunSpawnInfo = spawnExt('yarn', [config.run, '--', '-s'], { cwd: appDir }, true); + + let run = runProtractor(appBuildSpawnInfo.promise, appDir, appRunSpawnInfo, outputFile); + + if (fs.existsSync(appDir + '/aot/index.html')) { + run = run.then((ok) => ok && runProtractorAoT(appDir, outputFile)); + } + return run; +} + +function runProtractor(prepPromise, appDir, appRunSpawnInfo, outputFile) { + const specFilename = path.resolve(`${appDir}/${SPEC_FILENAME}`); + return prepPromise + .catch(function () { + const emsg = `Application at ${appDir} failed to transpile.\n\n`; + console.log(emsg); + fs.appendFileSync(outputFile, emsg); + return Promise.reject(emsg); + }) + .then(function (data) { + let transpileError = false; + + // Start protractor. + + const spawnInfo = spawnExt('yarn', ['protractor', '--', + PROTRACTOR_CONFIG_FILENAME, + `--specs=${specFilename}`, + '--params.appDir=' + appDir, + '--params.outputFile=' + outputFile + ], { cwd: SHARED_PATH }); + + spawnInfo.proc.stderr.on('data', function (data) { + transpileError = transpileError || /npm ERR! Exit status 100/.test(data.toString()); + }); + return spawnInfo.promise.catch(function (err) { + if (transpileError) { + const emsg = `${specFilename} failed to transpile.\n\n`; + console.log(emsg); + fs.appendFileSync(outputFile, emsg); + } + return Promise.reject(emsg); + }); + }) + .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; + } +} + +// Run e2e tests over the AOT build for projects that examples it. +function runProtractorAoT(appDir, outputFile) { + fs.appendFileSync(outputFile, '++ AoT version ++\n'); + const aotBuildSpawnInfo = spawnExt('yarn', ['build:aot'], { cwd: appDir }); + let promise = aotBuildSpawnInfo.promise; + + const copyFileCmd = 'copy-dist-files.js'; + if (fs.existsSync(appDir + '/' + copyFileCmd)) { + promise = promise.then(() => spawnExt('node', [copyFileCmd], { cwd: appDir }).promise); + } + const aotRunSpawnInfo = spawnExt('yarn', ['serve:aot'], { cwd: appDir }, true); + return runProtractor(promise, appDir, aotRunSpawnInfo, outputFile); +} + +// Report final status. +function reportStatus(status, outputFile) { + let log = ['']; + log.push('Suites passed:'); + status.passed.forEach(function (val) { + log.push(' ' + val); + }); + + if (status.failed.length == 0) { + log.push('All tests passed'); + } else { + log.push('Suites failed:'); + status.failed.forEach(function (val) { + log.push(' ' + val); + }); + } + log.push('\nElapsed time: ' + status.elapsedTime + ' seconds'); + log = log.join('\n'); + console.log(log); + fs.appendFileSync(outputFile, log); +} + +// Returns both a promise and the spawned process so that it can be killed if needed. +function spawnExt(command, args, options, ignoreClose = false) { + let proc; + const promise = new Promise((resolve, reject) => { + let descr = command + " " + args.join(' '); + console.log('running: ' + descr); + try { + proc = xSpawn.spawn(command, args, options); + } catch (e) { + console.log(e); + reject(e); + return { proc: null, promise }; + } + proc.stdout.on('data', function (data) { + process.stdout.write(data.toString()); + }); + proc.stderr.on('data', function (data) { + process.stdout.write(data.toString()); + }); + proc.on('close', function (returnCode) { + console.log(`completed: ${descr} \n`); + // Many tasks (e.g., tsc) complete but are actually errors; + // Confirm return code is zero. + returnCode === 0 || ignoreClose ? resolve(0) : reject(returnCode); + }); + proc.on('error', function (data) { + console.log(`completed with error: ${descr} \n`); + console.log(data.toString()); + reject(data); + }); + }); + return { proc, promise }; +} + +// Find all e2e specs in a given example folder. +function getE2eSpecPaths(basePath, filter) { + // Only get spec file at the example root. + const e2eSpecGlob = `${filter ? `*${filter}*` : '*'}/${SPEC_FILENAME}`; + return globby(e2eSpecGlob, { cwd: basePath, nodir: true }) + .then(paths => paths + .filter(file => IGNORED_EXAMPLES.some(ignored => !file.startsWith(ignored))) + .map(file => path.join(basePath, file)) + ); +} + +// Load configuration for an example. +function loadExampleConfig(exampleFolder) { + // Default config. + let config = { + build: 'build', + run: 'serve:e2e' + }; + + try { + const exampleConfig = fs.readJsonSync(`${exampleFolder}/${EXAMPLE_CONFIG_FILENAME}`); + Object.assign(config, exampleConfig); + } catch (e) { } + + return config; +} + +runE2e(); diff --git a/aio/tools/examples/shared/boilerplate/src/tsconfig.json b/aio/tools/examples/shared/boilerplate/src/tsconfig.json index 05839ec2ff..1a6e599592 100644 --- a/aio/tools/examples/shared/boilerplate/src/tsconfig.json +++ b/aio/tools/examples/shared/boilerplate/src/tsconfig.json @@ -10,7 +10,7 @@ "noImplicitAny": true, "suppressImplicitAnyIndexErrors": true, "typeRoots": [ - "../../../node_modules/@types/" + "../node_modules/@types/" ] }, "compileOnSave": true, diff --git a/aio/tools/examples/shared/package.json b/aio/tools/examples/shared/package.json index 41dc5e5b56..661364764c 100644 --- a/aio/tools/examples/shared/package.json +++ b/aio/tools/examples/shared/package.json @@ -69,7 +69,7 @@ "lodash": "^4.16.2", "null-loader": "^0.1.1", "phantomjs-prebuilt": "^2.1.7", - "protractor": "~4.0.14", + "protractor": "~5.1.0", "raw-loader": "^0.5.1", "rimraf": "^2.5.4", "rollup": "^0.41.6", diff --git a/aio/tools/examples/shared/protractor-helpers.ts b/aio/tools/examples/shared/protractor-helpers.ts deleted file mode 100644 index 61af74ba30..0000000000 --- a/aio/tools/examples/shared/protractor-helpers.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { browser } from 'protractor'; - -export var appLang = { - appIsTs: false, - appIsJs: false, - appIsDart: false, - appIsUnknown: false -}; - -export function describeIf(cond: boolean, name: string, func: () => void): void { - if (cond) { - describe(name, func); - } else { - xdescribe(name, func); - } -} - -export function itIf(cond: boolean, name: string, func: (done: DoneFn) => void): void { - if (cond) { - it(name, func); - } else { - xit(name, func); - } -} - -// protractor.config.js is set to ng2 mode by default, so we must manually -// change it for upgradeAdapter tests -export function setProtractorToNg1Mode(): void { - browser.rootEl = 'body'; -} - -export function setProtractorToHybridMode() { - setProtractorToNg1Mode(); - browser.ng12Hybrid = true; -} diff --git a/aio/tools/examples/shared/protractor.config.js b/aio/tools/examples/shared/protractor.config.js index 92b5e1fda5..b5c090e2df 100644 --- a/aio/tools/examples/shared/protractor.config.js +++ b/aio/tools/examples/shared/protractor.config.js @@ -20,7 +20,11 @@ exports.config = { // Capabilities to be passed to the webdriver instance. capabilities: { - 'browserName': 'chrome' + 'browserName': 'chrome', + // For Travis + chromeOptions: { + binary: process.env.CHROME_BIN + } }, // Framework to use. Jasmine is recommended. @@ -43,22 +47,7 @@ exports.config = { // debugging // console.log('browser.params:' + JSON.stringify(browser.params)); - var protractorHelpers = require('./protractor-helpers.ts'); - var appDir = browser.params.appDir; - if (appDir) { - if (appDir.match('/ts') != null) { - protractorHelpers.appLang.appIsTs = true; - } else if (appDir.match('/js') != null) { - protractorHelpers.appLang.appIsJs = true; - } else if (appDir.match('/dart') != null) { - protractorHelpers.appLang.appIsDart = true; - } else { - protractorHelpers.appLang.appIsUnknown = true; - } - } else { - protractorHelpers.appLang.appIsUnknown = true; - } jasmine.getEnv().addReporter(new Reporter( browser.params )); }, @@ -79,7 +68,7 @@ exports.config = { // See http://jasmine.github.io/2.1/custom_reporter.html function Reporter(options) { - var _defaultOutputFile = path.resolve(process.cwd(), "../../../", 'protractor-results.txt'); + var _defaultOutputFile = path.resolve(__dirname, '../../protractor-results.txt'); options.outputFile = options.outputFile || _defaultOutputFile; var _root = { appDir: options.appDir, suites: [] }; diff --git a/aio/tools/examples/shared/tsconfig.json b/aio/tools/examples/shared/tsconfig.json index 51ea56dc7f..b564f9cb9f 100644 --- a/aio/tools/examples/shared/tsconfig.json +++ b/aio/tools/examples/shared/tsconfig.json @@ -1,5 +1,5 @@ // this tsconfig is used for protractor tests -// see _boilerplate/tsconfig.json for the tsconfig used in examples +// see boilerplate/tsconfig.json for the tsconfig used in examples { "compilerOptions": { "target": "es6", @@ -15,10 +15,7 @@ "node_modules/@types" ] }, - "files": [ - "protractor-helpers.ts" - ], "include": [ - "*/e2e-spec.ts" + "../../../content/examples/*/e2e-spec.ts" ] } diff --git a/aio/tools/examples/shared/yarn.lock b/aio/tools/examples/shared/yarn.lock index fc1bcc0f75..88b1dc1d2a 100644 --- a/aio/tools/examples/shared/yarn.lock +++ b/aio/tools/examples/shared/yarn.lock @@ -183,7 +183,7 @@ dependencies: "@types/jquery" "*" -"@types/jasmine@2.5.36", "@types/jasmine@^2.5.36": +"@types/jasmine@2.5.36": version "2.5.36" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.36.tgz#6d804b79a57e9380d766a2680e9362c17d9556d2" @@ -199,9 +199,9 @@ version "0.0.32" resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5" -"@types/selenium-webdriver@2.53.37": - version "2.53.37" - resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-2.53.37.tgz#34f743c20e53ae7100ede90870fde554df2447f8" +"@types/selenium-webdriver@^2.53.35", "@types/selenium-webdriver@~2.53.39": + version "2.53.42" + resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-2.53.42.tgz#74cb77fb6052edaff2a8984ddafd88d419f25cac" abbrev@1: version "1.1.0" @@ -244,7 +244,7 @@ adm-zip@0.4.4: version "0.4.4" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.4.tgz#a61ed5ae6905c3aea58b3a657d25033091052736" -adm-zip@0.4.7, adm-zip@^0.4.7: +adm-zip@^0.4.7: version "0.4.7" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" @@ -1035,6 +1035,12 @@ block-stream@*: dependencies: inherits "~2.0.0" +blocking-proxy@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/blocking-proxy/-/blocking-proxy-0.0.5.tgz#462905e0dcfbea970f41aa37223dda9c07b1912b" + dependencies: + minimist "^1.2.0" + bluebird@^3.3.0, bluebird@^3.4.7: version "3.5.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" @@ -2629,7 +2635,7 @@ glob@^3.2.11: inherits "2" minimatch "0.3" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@~7.1.1: +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@~7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -3257,7 +3263,19 @@ jasmine-core@~2.4.0, jasmine-core@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.4.1.tgz#6f83ab3a0f16951722ce07d206c773d57cc838be" -jasmine@2.4.1, jasmine@~2.4.1: +jasmine-core@~2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.5.2.tgz#6f61bd79061e27f43e6f9355e44b3c6cab6ff297" + +jasmine@^2.5.3: + version "2.5.3" + resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.5.3.tgz#5441f254e1fc2269deb1dfd93e0e57d565ff4d22" + dependencies: + exit "^0.1.2" + glob "^7.0.6" + jasmine-core "~2.5.2" + +jasmine@~2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.4.1.tgz#9016dda453213d27ac6d43dc4ea97315a189085e" dependencies: @@ -3265,9 +3283,9 @@ jasmine@2.4.1, jasmine@~2.4.1: glob "^3.2.11" jasmine-core "~2.4.0" -jasminewd2@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-0.0.10.tgz#94f48ae2bc946cad643035467b4bb7ea9c1075ef" +jasminewd2@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.0.0.tgz#10aacd2c588c1ceb6a0b849f1a7f3f959f777c91" jodid25519@^1.0.0: version "1.0.2" @@ -3596,11 +3614,7 @@ lower-case@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -lru-cache@2.2.x: +lru-cache@2, lru-cache@2.2.x: version "2.2.4" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" @@ -4553,25 +4567,25 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -protractor@~4.0.14: - version "4.0.14" - resolved "https://registry.yarnpkg.com/protractor/-/protractor-4.0.14.tgz#efc4a877fac3a182a9dded26cd5869f4762fd172" +protractor@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.1.1.tgz#10c4e336571b28875b8acc3ae3e4e1e40ef7e986" dependencies: - "@types/jasmine" "^2.5.36" "@types/node" "^6.0.46" "@types/q" "^0.0.32" - "@types/selenium-webdriver" "2.53.37" - adm-zip "0.4.7" + "@types/selenium-webdriver" "~2.53.39" + blocking-proxy "0.0.5" chalk "^1.1.3" glob "^7.0.3" - jasmine "2.4.1" - jasminewd2 "0.0.10" + jasmine "^2.5.3" + jasminewd2 "^2.0.0" optimist "~0.6.0" q "1.4.1" saucelabs "~1.3.0" - selenium-webdriver "2.53.3" + selenium-webdriver "3.0.1" source-map-support "~0.4.0" - webdriver-manager "^10.3.0" + webdriver-js-extender "^1.0.0" + webdriver-manager "^12.0.1" proxy-addr@~1.1.3: version "1.1.4" @@ -4870,7 +4884,7 @@ request-progress@~2.0.1: dependencies: throttleit "^1.0.0" -request@2, request@^2.72.0, request@^2.78.0, request@^2.79.0, request@~2.79.0: +request@2, request@^2.72.0, request@^2.79.0, request@~2.79.0: version "2.79.0" resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de" dependencies: @@ -4920,7 +4934,7 @@ request@2.78.0: tough-cookie "~2.3.0" tunnel-agent "~0.4.1" -request@^2.81.0: +request@^2.78.0, request@^2.81.0: version "2.81.0" resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" dependencies: @@ -5098,7 +5112,7 @@ sax@0.6.x: version "0.6.1" resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9" -sax@~1.2.1: +sax@>=0.6.0, sax@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" @@ -5112,7 +5126,16 @@ select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" -selenium-webdriver@2.53.3: +selenium-webdriver@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-3.0.1.tgz#a2dea5da4a97f6672e89e7ca7276cefa365147a7" + dependencies: + adm-zip "^0.4.7" + rimraf "^2.5.4" + tmp "0.0.30" + xml2js "^0.4.17" + +selenium-webdriver@^2.53.2: version "2.53.3" resolved "https://registry.yarnpkg.com/selenium-webdriver/-/selenium-webdriver-2.53.3.tgz#d29ff5a957dff1a1b49dc457756e4e4bfbdce085" dependencies: @@ -5666,6 +5689,12 @@ tmp@0.0.24: version "0.0.24" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12" +tmp@0.0.30: + version "0.0.30" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.30.tgz#72419d4a8be7d6ce75148fd8b324e593a711c2ed" + dependencies: + os-tmpdir "~1.0.1" + tmp@0.0.31, tmp@0.0.x, tmp@^0.0.31: version "0.0.31" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" @@ -5997,9 +6026,16 @@ wbuf@^1.1.0, wbuf@^1.4.0: dependencies: minimalistic-assert "^1.0.0" -webdriver-manager@^10.3.0: - version "10.3.0" - resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-10.3.0.tgz#99314588a0b1dbe688c441d74288c6cb1875fa8b" +webdriver-js-extender@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/webdriver-js-extender/-/webdriver-js-extender-1.0.0.tgz#81c533a9e33d5bfb597b4e63e2cdb25b54777515" + dependencies: + "@types/selenium-webdriver" "^2.53.35" + selenium-webdriver "^2.53.2" + +webdriver-manager@^12.0.1: + version "12.0.4" + resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.0.4.tgz#658e431c805bc3a7e6bf74bc819475884e6d4861" dependencies: adm-zip "^0.4.7" chalk "^1.1.1" @@ -6011,6 +6047,7 @@ webdriver-manager@^10.3.0: request "^2.78.0" rimraf "^2.5.2" semver "^5.3.0" + xml2js "^0.4.17" webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.9.0: version "1.10.1" @@ -6193,20 +6230,13 @@ ws@1.1.1: options ">=0.0.5" ultron "1.0.x" -ws@1.1.2: +ws@1.1.2, ws@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.2.tgz#8a244fa052401e08c9886cf44a85189e1fd4067f" dependencies: options ">=0.0.5" ultron "1.0.x" -ws@^1.0.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.4.tgz#57f40d036832e5f5055662a397c4de76ed66bf61" - dependencies: - options ">=0.0.5" - ultron "1.0.x" - wtf-8@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a" @@ -6226,10 +6256,23 @@ xml2js@0.4.4: sax "0.6.x" xmlbuilder ">=1.0.0" +xml2js@^0.4.17: + version "0.4.17" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" + dependencies: + sax ">=0.6.0" + xmlbuilder "^4.1.0" + xmlbuilder@>=1.0.0: version "8.2.2" resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-8.2.2.tgz#69248673410b4ba42e1a6136551d2922335aa773" +xmlbuilder@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-4.2.1.tgz#aa58a3041a066f90eaa16c2f5389ff19f3f461a5" + dependencies: + lodash "^4.0.0" + xmldom@^0.1.19: version "0.1.27" resolved "https://registry.yarnpkg.com/xmldom/-/xmldom-0.1.27.tgz#d501f97b3bdb403af8ef9ecc20573187aadac0e9" diff --git a/aio/yarn.lock b/aio/yarn.lock index 1c50220272..12ab9df634 100644 --- a/aio/yarn.lock +++ b/aio/yarn.lock @@ -1505,6 +1505,14 @@ cross-spawn@^4.0.0: lru-cache "^4.0.1" which "^1.2.9" +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -2684,7 +2692,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^2.0.0, fs-extra@^2.1.1: +fs-extra@^2.0.0, fs-extra@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" dependencies: @@ -6057,6 +6065,16 @@ sha.js@^2.3.6: dependencies: inherits "^2.0.1" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + shelljs@^0.7.0, shelljs@^0.7.5, shelljs@^0.7.7: version "0.7.7" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" @@ -7538,6 +7556,13 @@ yargs-parser@^4.2.0: camelcase "^3.0.0" yargs@3.32.0, yargs@^3.32.0: +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + +yargs@^3.32.0: version "3.32.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" dependencies: @@ -7586,6 +7611,24 @@ yargs@^6.0.0: y18n "^3.2.1" yargs-parser "^4.2.0" +yargs@^7.0.2: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" diff --git a/scripts/ci/install.sh b/scripts/ci/install.sh index a817064ecc..a64d393785 100755 --- a/scripts/ci/install.sh +++ b/scripts/ci/install.sh @@ -41,7 +41,7 @@ travisFoldStart "npm-install" travisFoldEnd "npm-install" -if [[ ${TRAVIS} && (${CI_MODE} == "e2e" || ${CI_MODE} == "e2e_2" || ${CI_MODE} == "aio" || ${CI_MODE} == "docs_test") ]]; then +if [[ ${TRAVIS} && (${CI_MODE} == "e2e" || ${CI_MODE} == "e2e_2" || ${CI_MODE} == "aio" || ${CI_MODE} == "aio_e2e" || ${CI_MODE} == "docs_test") ]]; then # Install version of yarn that we are locked against travisFoldStart "install-yarn" curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version "${YARN_VERSION}" @@ -49,7 +49,7 @@ if [[ ${TRAVIS} && (${CI_MODE} == "e2e" || ${CI_MODE} == "e2e_2" || ${CI_MODE} = fi -if [[ ${TRAVIS} && (${CI_MODE} == "aio" || ${CI_MODE} == "docs_test") ]]; then +if [[ ${TRAVIS} && (${CI_MODE} == "aio" || ${CI_MODE} == "aio_e2e" || ${CI_MODE} == "docs_test") ]]; then # angular.io: Install all yarn dependencies according to angular.io/yarn.lock travisFoldStart "yarn-install.aio" ( @@ -61,7 +61,7 @@ fi # Install Chromium -if [[ ${CI_MODE} == "js" || ${CI_MODE} == "e2e" || ${CI_MODE} == "e2e_2" || ${CI_MODE} == "aio" ]]; then +if [[ ${CI_MODE} == "js" || ${CI_MODE} == "e2e" || ${CI_MODE} == "e2e_2" || ${CI_MODE} == "aio" || ${CI_MODE} == "aio_e2e" ]]; then travisFoldStart "install-chromium" ( ${thisDir}/install-chromium.sh diff --git a/scripts/ci/test-aio-e2e.sh b/scripts/ci/test-aio-e2e.sh new file mode 100755 index 0000000000..1f16f036be --- /dev/null +++ b/scripts/ci/test-aio-e2e.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash + +set -u -e -o pipefail + +# Setup environment +readonly thisDir=$(cd $(dirname $0); pwd) +source ${thisDir}/_travis-fold.sh + + +# run in subshell to avoid polluting cwd +( + cd ${PROJECT_ROOT}/aio + + # Start xvfb for local Chrome used for testing + if [[ ${TRAVIS} ]]; then + travisFoldStart "test.aio.xvfb-start" + sh -e /etc/init.d/xvfb start + travisFoldEnd "test.aio.xvfb-start" + fi + + # Run example e2e tests + travisFoldStart "test.aio.example-e2e" + yarn example-e2e -- --setup + travisFoldEnd "test.aio.example-e2e" +) diff --git a/scripts/ci/test-aio.sh b/scripts/ci/test-aio.sh index cc86badba2..1d840c8de8 100755 --- a/scripts/ci/test-aio.sh +++ b/scripts/ci/test-aio.sh @@ -37,13 +37,11 @@ source ${thisDir}/_travis-fold.sh yarn e2e travisFoldEnd "test.aio.e2e" - # Run PWA-score tests travisFoldStart "test.aio.pwaScore" yarn test-pwa-score-local travisFoldEnd "test.aio.pwaScore" - # Run unit tests for aio/aio-builds-setup travisFoldStart "test.aio.aio-builds-setup" ./aio-builds-setup/scripts/test.sh diff --git a/scripts/ci/test.sh b/scripts/ci/test.sh index 20aee520d4..8b5cffe5c9 100755 --- a/scripts/ci/test.sh +++ b/scripts/ci/test.sh @@ -43,4 +43,7 @@ case ${CI_MODE} in aio) ${thisDir}/test-aio.sh ;; + aio_e2e) + ${thisDir}/test-aio-e2e.sh + ;; esac