feat(aio): add e2e (#15976)

PR Close #15976
This commit is contained in:
Filipe Silva 2017-04-13 22:35:13 +01:00 committed by Miško Hevery
parent 9f66c9c1d1
commit bfd5f27525
40 changed files with 500 additions and 138 deletions

View File

@ -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

1
aio/.gitignore vendored
View File

@ -38,6 +38,7 @@ yarn-error.log
# e2e
/e2e/*.js
/e2e/*.map
protractor-results*.txt
# System Files
.DS_Store

View File

@ -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

View File

@ -8,7 +8,10 @@
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"./node_modules/@types/"
]
},
"files": [

View File

@ -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('');

View File

@ -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});';
}

View File

@ -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('');

View File

@ -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() {

View File

@ -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);
}
}

View File

@ -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));
});

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"node_modules/@types/"
"./node_modules/@types/"
]
},

View File

@ -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() {

View File

@ -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() {

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},
"compileOnSave": true,

View File

@ -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

View File

@ -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() {

View File

@ -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'

View File

@ -11,7 +11,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},
"compileOnSave": true,

View File

@ -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;

View File

@ -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[];

View File

@ -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() {

View File

@ -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'

View File

@ -11,7 +11,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},
"compileOnSave": true,

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../node_modules/@types/"
"./node_modules/@types/"
]
},
"compileOnSave": true,

View File

@ -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"
}
}

View File

@ -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();

View File

@ -10,7 +10,7 @@
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": [
"../../../node_modules/@types/"
"../node_modules/@types/"
]
},
"compileOnSave": true,

View File

@ -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",

View File

@ -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;
}

View File

@ -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: [] };

View File

@ -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"
]
}

View File

@ -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"

View File

@ -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"

View File

@ -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

25
scripts/ci/test-aio-e2e.sh Executable file
View File

@ -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"
)

View File

@ -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

View File

@ -43,4 +43,7 @@ case ${CI_MODE} in
aio)
${thisDir}/test-aio.sh
;;
aio_e2e)
${thisDir}/test-aio-e2e.sh
;;
esac