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:

committed by
Jason Aden

parent
66335c36e6
commit
98e5af1480
63
packages/examples/core/BUILD.bazel
Normal file
63
packages/examples/core/BUILD.bazel
Normal 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",
|
||||
],
|
||||
)
|
@ -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);
|
||||
|
@ -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';
|
||||
|
@ -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'));
|
||||
});
|
||||
|
@ -17,3 +17,5 @@ import {ContentChildComp, Pane, Tab} from './content_child_example';
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
||||
export {ContentChildComp as AppComponent};
|
||||
|
@ -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'));
|
||||
|
@ -17,3 +17,5 @@ import {ContentChildrenComp, Pane, Tab} from './content_children_example';
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
||||
export {ContentChildrenComp as AppComponent};
|
||||
|
@ -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'));
|
||||
});
|
||||
|
@ -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};
|
||||
|
@ -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'));
|
||||
});
|
||||
|
@ -18,3 +18,5 @@ import {Pane, ViewChildrenComp} from './view_children_example';
|
||||
})
|
||||
export class AppModule {
|
||||
}
|
||||
|
||||
export {ViewChildrenComp as AppComponent};
|
||||
|
12
packages/examples/core/main.ts
Normal file
12
packages/examples/core/main.ts
Normal 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);
|
17
packages/examples/core/start-server.js
Normal file
17
packages/examples/core/start-server.js
Normal 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;
|
||||
};
|
44
packages/examples/core/test_module.ts
Normal file
44
packages/examples/core/test_module.ts
Normal 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 {
|
||||
}
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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';
|
||||
|
23
packages/examples/core/testing/ts/BUILD.bazel
Normal file
23
packages/examples/core/testing/ts/BUILD.bazel
Normal 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",
|
||||
],
|
||||
)
|
12
packages/examples/core/testing/ts/example_spec.ts
Normal file
12
packages/examples/core/testing/ts/example_spec.ts
Normal 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';
|
@ -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 {
|
||||
}
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user