build: switch example e2e tests to bazel (#28402)

* No longer builds the example e2e tests using "tsc". The examples are now built with Bazel and can therefore be built with Ivy by using the `--define=compile=aot` switch.
* No longer runs the example e2e tests using the protractor CLI. example e2e tests are executed with the Bazel protractor rule and can therefore run incrementally.

NOTE: Unit tests found within the examples are still running within the legacy jobs.

PR Close #28402
This commit is contained in:
Paul Gschwendtner
2019-01-28 21:59:25 +01:00
committed by Jason Aden
parent 66335c36e6
commit 98e5af1480
103 changed files with 898 additions and 416 deletions

View File

@ -0,0 +1,63 @@
package(default_visibility = ["//visibility:public"])
load("//packages/bazel:index.bzl", "protractor_web_test_suite")
load("//tools:defaults.bzl", "ng_module", "ts_library")
load("@build_bazel_rules_typescript//:defs.bzl", "ts_devserver")
ng_module(
name = "core_examples",
srcs = glob(
["**/*.ts"],
exclude = [
"**/*_spec.ts",
"**/*_howto.ts",
],
),
# TODO: FW-1004 Type checking is currently not complete.
type_check = False,
deps = [
"//packages/animations",
"//packages/core",
"//packages/platform-browser",
"//packages/platform-browser-dynamic",
"//packages/platform-browser/animations",
"//packages/router",
],
)
ts_library(
name = "core_e2e_tests_lib",
testonly = True,
srcs = glob(["**/e2e_test/*_spec.ts"]),
tsconfig = "//packages/examples:tsconfig-e2e.json",
deps = [
"//packages/examples/test-utils",
"@ngdeps//@types/jasminewd2",
"@ngdeps//protractor",
],
)
ts_devserver(
name = "devserver",
entry_module = "@angular/examples/core/main",
index_html = "//packages/examples:index.html",
port = 4200,
scripts = ["@ngdeps//node_modules/tslib:tslib.js"],
static_files = [
"@ngdeps//node_modules/zone.js:dist/zone.js",
"@ngdeps//node_modules/zone.js:dist/task-tracking.js",
],
deps = [":core_examples"],
)
protractor_web_test_suite(
name = "protractor_tests",
data = ["//packages/bazel/src/protractor/utils"],
on_prepare = ":start-server.js",
server = ":devserver",
deps = [
":core_e2e_tests_lib",
"@ngdeps//protractor",
"@ngdeps//selenium-webdriver",
],
)

View File

@ -7,7 +7,7 @@
*/
import {$, ExpectedConditions, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
function waitForElement(selector: string) {
const EC = ExpectedConditions;
@ -19,7 +19,7 @@ describe('animation example', () => {
afterEach(verifyNoBrowserErrors);
describe('index view', () => {
const URL = '/core/animation/ts/dsl/';
const URL = '/animation/dsl/';
it('should list out the current collection of items', () => {
browser.get(URL);

View File

@ -5,4 +5,5 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export {AppModule} from './animation_example';
export {AppModule, MyExpandoCmp as AppComponent} from './animation_example';

View File

@ -7,7 +7,7 @@
*/
import {ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
describe('contentChild example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('contentChild example', () => {
let result: ElementFinder;
beforeEach(() => {
browser.get('/core/di/ts/contentChild/index.html');
browser.get('/di/contentChild');
button = element(by.css('button'));
result = element(by.css('div'));
});

View File

@ -17,3 +17,5 @@ import {ContentChildComp, Pane, Tab} from './content_child_example';
})
export class AppModule {
}
export {ContentChildComp as AppComponent};

View File

@ -7,7 +7,7 @@
*/
import {ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
describe('contentChildren example', () => {
afterEach(verifyNoBrowserErrors);
@ -16,7 +16,7 @@ describe('contentChildren example', () => {
let resultNested: ElementFinder;
beforeEach(() => {
browser.get('/core/di/ts/contentChildren/index.html');
browser.get('/di/contentChildren');
button = element(by.css('button'));
resultTopLevel = element(by.css('.top-level'));
resultNested = element(by.css('.nested'));

View File

@ -17,3 +17,5 @@ import {ContentChildrenComp, Pane, Tab} from './content_children_example';
})
export class AppModule {
}
export {ContentChildrenComp as AppComponent};

View File

@ -7,7 +7,7 @@
*/
import {ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
describe('viewChild example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('viewChild example', () => {
let result: ElementFinder;
beforeEach(() => {
browser.get('/core/di/ts/viewChild/index.html');
browser.get('/di/viewChild');
button = element(by.css('button'));
result = element(by.css('div'));
});

View File

@ -15,3 +15,5 @@ import {Pane, ViewChildComp} from './view_child_example';
{imports: [BrowserModule], declarations: [ViewChildComp, Pane], bootstrap: [ViewChildComp]})
export class AppModule {
}
export {ViewChildComp as AppComponent};

View File

@ -8,7 +8,7 @@
import {ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
describe('viewChildren example', () => {
afterEach(verifyNoBrowserErrors);
@ -16,7 +16,7 @@ describe('viewChildren example', () => {
let result: ElementFinder;
beforeEach(() => {
browser.get('/core/di/ts/viewChildren/index.html');
browser.get('/di/viewChildren');
button = element(by.css('button'));
result = element(by.css('div'));
});

View File

@ -18,3 +18,5 @@ import {Pane, ViewChildrenComp} from './view_children_example';
})
export class AppModule {
}
export {ViewChildrenComp as AppComponent};

View File

@ -0,0 +1,12 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {TestsAppModuleNgFactory} from './test_module.ngfactory';
platformBrowserDynamic().bootstrapModuleFactory(TestsAppModuleNgFactory);

View File

@ -0,0 +1,17 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const protractorUtils = require('@angular/bazel/protractor-utils');
const protractor = require('protractor');
module.exports = async function(config) {
const {port} = await protractorUtils.runServer(config.workspace, config.server, '-port', []);
const serverUrl = `http://localhost:${port}`;
protractor.browser.baseUrl = serverUrl;
};

View File

@ -0,0 +1,44 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Component, NgModule} from '@angular/core';
import {RouterModule} from '@angular/router';
import * as animationDslExample from './animation/ts/dsl/module';
import * as diContentChildExample from './di/ts/contentChild/module';
import * as diContentChildrenExample from './di/ts/contentChildren/module';
import * as diViewChildExample from './di/ts/viewChild/module';
import * as diViewChildrenExample from './di/ts/viewChildren/module';
import * as testabilityWhenStableExample from './testability/ts/whenStable/module';
@Component({selector: 'example-app', template: '<router-outlet></router-outlet>'})
export class TestsAppComponent {
}
@NgModule({
imports: [
animationDslExample.AppModule, diContentChildExample.AppModule,
diContentChildrenExample.AppModule, diViewChildExample.AppModule,
diViewChildrenExample.AppModule, testabilityWhenStableExample.AppModule,
// Router configuration so that the individual e2e tests can load their
// app components.
RouterModule.forRoot([
{path: 'animation/dsl', component: animationDslExample.AppComponent},
{path: 'di/contentChild', component: diContentChildExample.AppComponent},
{path: 'di/contentChildren', component: diContentChildrenExample.AppComponent},
{path: 'di/viewChild', component: diViewChildExample.AppComponent},
{path: 'di/viewChildren', component: diViewChildrenExample.AppComponent},
{path: 'testability/whenStable', component: testabilityWhenStableExample.AppComponent},
])
],
declarations: [TestsAppComponent],
bootstrap: [TestsAppComponent]
})
export class TestsAppModule {
}

View File

@ -7,13 +7,19 @@
*/
import {browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
// Declare the global "window" and "document" constant since we don't want to add the "dom"
// TypeScript lib for the e2e specs that execute code in the browser and reference such
// global constants.
declare const window: any;
declare const document: any;
describe('testability example', () => {
afterEach(verifyNoBrowserErrors);
describe('using task tracking', () => {
const URL = '/core/testability/ts/whenStable/';
const URL = '/testability/whenStable/';
it('times out with a list of tasks', done => {
browser.get(URL);
@ -22,7 +28,7 @@ describe('testability example', () => {
// Script that runs in the browser and calls whenStable with a timeout.
let waitWithResultScript = function(done: any) {
let rootEl = document.querySelector('example-app');
let testability = (window as any).getAngularTestability(rootEl);
let testability = window.getAngularTestability(rootEl);
testability.whenStable((didWork: boolean, tasks: any) => { done(tasks); }, 1000);
};

View File

@ -5,4 +5,4 @@
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
export {AppModule} from './testability_example';
export {AppModule, StableTestCmp as AppComponent} from './testability_example';

View File

@ -0,0 +1,23 @@
load("//tools:defaults.bzl", "jasmine_node_test", "ts_library")
ts_library(
name = "fake_async_lib",
srcs = [
"example_spec.ts",
"fake_async.ts",
],
deps = [
"//packages/core/testing",
"@ngdeps//@types/jasmine",
"@ngdeps//@types/node",
],
)
jasmine_node_test(
name = "test",
bootstrap = ["angular/tools/testing/init_node_spec.js"],
deps = [
":fake_async_lib",
"//tools/testing:node",
],
)

View File

@ -0,0 +1,12 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
// Import the "fake_async" example that registers tests which are shown as examples. These need
// to be valid tests, so we run them here. Note that we need to add this layer of abstraction here
// because the "jasmine_node_test" rule only picks up test files with the "_spec.ts" file suffix.
import './fake_async';

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
import {Component, Directive, EventEmitter} from '@angular/core';
import {Component, Directive, EventEmitter, NgModule} from '@angular/core';
// #docregion component-input
@Component({
@ -63,4 +63,10 @@ export class MyOutputComponent {
onEverySecond() { console.log('second'); }
onEveryFiveSeconds() { console.log('five seconds'); }
}
// #enddocregion component-output-interval
// #enddocregion component-output-interval
@NgModule({
declarations: [BankAccountComponent, MyInputComponent, IntervalDirComponent, MyOutputComponent]
})
export class AppModule {
}

View File

@ -13,8 +13,10 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {MyComponent} from './my_component';
enableProdMode();
@NgModule({imports: [BrowserModule], bootstrap: [MyComponent]})
class AppModule {
@NgModule({imports: [BrowserModule], declarations: [MyComponent], bootstrap: [MyComponent]})
export class AppModule {
}
platformBrowserDynamic().bootstrapModule(AppModule);
// #enddocregion