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

@ -410,7 +410,6 @@ jobs:
- *define_env_vars
- *yarn_install
- run: yarn tsc -p packages
- run: yarn tsc -p packages/examples
- run: yarn tsc -p modules
- run: yarn karma start ./karma-js.conf.js --single-run --browsers=ChromeNoSandbox
@ -437,7 +436,6 @@ jobs:
command: ./scripts/saucelabs/start-tunnel.sh
background: true
- run: yarn tsc -p packages
- run: yarn tsc -p packages/examples
- run: yarn tsc -p modules
# Waits for the Saucelabs tunnel to be ready. This ensures that we don't run tests
# too early without Saucelabs not being ready.
@ -465,10 +463,9 @@ jobs:
- run: ./scripts/build-e2e-tests.sh --use-existing-packages-dist
- run:
name: Starting servers for e2e tests
command: yarn gulp serve serve-examples
command: yarn gulp serve
background: true
- run: NODE_PATH=$NODE_PATH:./dist/all yarn protractor ./protractor-e2e.conf.js --bundles=true
- run: NODE_PATH=$NODE_PATH:./dist/all yarn protractor ./protractor-examples-e2e.conf.js --bundles=true
- run: NODE_PATH=$NODE_PATH:./dist/all yarn protractor ./protractor-perf.conf.js --bundles=true --dryrun
legacy-misc-tests:

View File

@ -39,7 +39,6 @@ gulp.task('source-map-test', loadTask('source-map-test'));
gulp.task('tools:build', loadTask('tools-build'));
gulp.task('check-cycle', loadTask('check-cycle'));
gulp.task('serve', loadTask('serve', 'default'));
gulp.task('serve-examples', loadTask('serve', 'examples'));
gulp.task('changelog', loadTask('changelog'));
gulp.task('check-env', () => {/* this is a noop because the env test ran already above */});
gulp.task('cldr:extract', loadTask('cldr', 'extract'));

View File

@ -38,12 +38,14 @@
"@bazel/karma": "~0.22.1",
"@bazel/typescript": "~0.22.1",
"@schematics/angular": "^7.0.4",
"@types/angular": "^1.6.47",
"@types/chokidar": "1.7.3",
"@types/convert-source-map": "^1.5.1",
"@types/diff": "^3.2.2",
"@types/fs-extra": "4.0.2",
"@types/hammerjs": "2.0.35",
"@types/jasmine": "^2.8.8",
"@types/jasminewd2": "^2.0.6",
"@types/mock-fs": "^3.6.30",
"@types/node": "^10.9.4",
"@types/selenium-webdriver": "3.0.7",
@ -98,9 +100,7 @@
"@bazel/bazel": "~0.22.0",
"@bazel/buildifier": "^0.19.2",
"@bazel/ibazel": "~0.9.0",
"@types/angular": "^1.6.47",
"@types/base64-js": "1.2.5",
"@types/jasminewd2": "^2.0.4",
"@types/minimist": "^1.2.0",
"@types/systemjs": "0.19.32",
"browserstacktunnel-wrapper": "2.0.1",

View File

@ -0,0 +1,4 @@
exports_files([
"index.html",
"tsconfig-e2e.json",
])

View File

@ -7,28 +7,15 @@ behavior) just like an Angular application developer would write.
# Running the examples
```
# # execute the following command only when framework code changes
./build.sh
# Serving individual examples (e.g. common)
yarn bazel run //packages/examples/common:devserver
# run when test change
./packages/examples/build.sh
# start server
$(npm bin)/gulp serve-examples
# "core" examples
yarn bazel run //packages/examples/core:devserver
```
navigate to [http://localhost:8001](http://localhost:8001)
# Running the tests
```
# run only when framework code changes
./build.sh
# run to compile tests and run them
./packages/examples/test.sh
yarn bazel test //packages/examples/...
```
NOTE: sometimes the http server does not exit properly and it retains the `8001` port.
in such a case you can use `lsof -i:8001` to see which process it is and then use `kill`
to remove it. (Or in single command: `lsof -i:8001 -t | xargs kill`)

View File

@ -1,21 +0,0 @@
/**
* @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
*/
(function(global: any) {
writeScriptTag('/vendor/zone.js');
writeScriptTag('/vendor/task-tracking.js');
writeScriptTag('/vendor/system.js');
writeScriptTag('/vendor/Reflect.js');
writeScriptTag('/_common/system-config.js');
if (location.pathname.indexOf('/upgrade/') != -1) {
writeScriptTag('/vendor/angular.js');
}
function writeScriptTag(scriptUrl: string, onload: string = '') {
document.write('<script src="' + scriptUrl + '" onload="' + onload + '"></script>');
}
}(window));

View File

@ -1,26 +0,0 @@
/**
* @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
*/
/* tslint:disable:no-console */
import * as webdriver from 'selenium-webdriver';
declare var browser: any;
declare var expect: any;
// TODO (juliemr): remove this method once this becomes a protractor plugin
export function verifyNoBrowserErrors() {
browser.manage().logs().get('browser').then(function(browserLog: any[]) {
const errors: any[] = [];
browserLog.filter(logEntry => {
const msg = logEntry.message;
console.log('>> ' + msg);
if (logEntry.level.value >= webdriver.logging.Level.INFO.value) {
errors.push(msg);
}
});
expect(errors).toEqual([]);
});
}

View File

@ -1,16 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
<script type="text/javascript" src="bootstrap.js"></script>
<script type="text/javascript">
System.import('main-dynamic').catch(console.error.bind(console));
</script>
</head>
<body>
<example-app>
loading...
</example-app>
</body>
</html>

View File

@ -1,19 +0,0 @@
/**
* @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
*/
/*
DO NOT DELETE THIS FILE
=======================
The purpose of this file is to allow `main-dynamic.ts` to be tsc-compiled
BEFORE it is copied over to each of the associated example directories
within `dist/examples`.
*/
export class AppModule {};

View File

@ -1,36 +0,0 @@
/**
* @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
*/
System.config({
defaultJSExtensions: true,
map: {
'@angular/common': '/vendor/@angular/common/bundles/common.umd.js',
'@angular/compiler': '/vendor/@angular/compiler/bundles/compiler.umd.js',
'@angular/animations': '/vendor/@angular/animations/bundles/animations.umd.js',
'@angular/animations/browser': '/vendor/@angular/animations/bundles/animations-browser.umd.js',
'@angular/platform-browser/animations':
'/vendor/@angular/platform-browser/bundles/platform-browser-animations.umd.js',
'@angular/core': '/vendor/@angular/core/bundles/core.umd.js',
'@angular/forms': '/vendor/@angular/forms/bundles/forms.umd.js',
'@angular/http': '/vendor/@angular/forms/bundles/http.umd.js',
'@angular/platform-browser':
'/vendor/@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic':
'/vendor/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/router': '/vendor/@angular/router/bundles/router.umd.js',
'@angular/upgrade': '/vendor/@angular/upgrade/bundles/upgrade.umd.js',
'@angular/upgrade/static': '/vendor/@angular/upgrade/bundles/upgrade-static.umd.js',
'rxjs': '/vendor/rxjs'
},
packages: {
'rxjs/ajax': {main: 'index.js', defaultExtension: 'js'},
'rxjs/operators': {main: 'index.js', defaultExtension: 'js'},
'rxjs/testing': {main: 'index.js', defaultExtension: 'js'},
'rxjs/websocket': {main: 'index.js', defaultExtension: 'js'},
'rxjs': {main: 'index.js', defaultExtension: 'js'},
},
});

View File

@ -1,44 +0,0 @@
#!/usr/bin/env bash
set -u -e -o pipefail
#
# This script is used to compile and copy the contents for each of
# example directories over to the dist/examples directory so that they
# can be tested with karma and protractor. The `gulp serve-examples` command
# can be used to run each of the examples in isolation via http as well.
#
(
cd `dirname $0`
DIST="../../dist/examples";
rm -rf -- $DIST
$(npm bin)/tsc -p ./tsconfig-build.json --importHelpers false
mkdir $DIST/vendor/
ln -s ../../../dist/packages-dist/ $DIST/vendor/@angular
for FILE in \
../../../node_modules/angular/angular.js \
../../../node_modules/zone.js/dist/zone.js \
../../../node_modules/zone.js/dist/task-tracking.js \
../../../node_modules/systemjs/dist/system.js \
../../../node_modules/reflect-metadata/Reflect.js \
../../../node_modules/rxjs
do
ln -s $FILE $DIST/vendor/`basename $FILE`
done
for MODULE in `find . -name module.ts`; do
FINAL_DIR_PATH=$DIST/`dirname $MODULE`
echo "==== $MODULE"
cp _common/*.html $FINAL_DIR_PATH
cp $DIST/_common/*.js $FINAL_DIR_PATH
cp $DIST/_common/*.js.map $FINAL_DIR_PATH
find `dirname $MODULE` -name \*.css -exec cp {} $FINAL_DIR_PATH \;
done
)

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 = "common_examples",
srcs = glob(
["**/*.ts"],
exclude = ["**/*_spec.ts"],
),
# TODO: FW-1004 Type checking is currently not complete.
type_check = False,
deps = [
"//packages/common",
"//packages/core",
"//packages/platform-browser",
"//packages/platform-browser-dynamic",
"//packages/router",
"@rxjs",
],
)
ts_library(
name = "common_tests_lib",
testonly = True,
srcs = glob(["**/*_spec.ts"]),
tsconfig = "//packages/examples:tsconfig-e2e.json",
deps = [
"//packages/examples/test-utils",
"//packages/private/testing",
"@ngdeps//@types/jasminewd2",
"@ngdeps//protractor",
],
)
ts_devserver(
name = "devserver",
entry_module = "@angular/examples/common/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",
# This is needed because the "ngComponentOutlet" test uses the JIT compiler
# and needs to be able to read metadata at runtime.
"@ngdeps//node_modules/reflect-metadata:Reflect.js",
],
deps = [":common_examples"],
)
protractor_web_test_suite(
name = "protractor_tests",
data = ["//packages/bazel/src/protractor/utils"],
on_prepare = ":start-server.js",
server = ":devserver",
deps = [
":common_tests_lib",
"@ngdeps//protractor",
"@ngdeps//selenium-webdriver",
],
)

View File

@ -8,7 +8,7 @@
import {$, browser, by, element, protractor} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
function waitForElement(selector: string) {
@ -21,10 +21,9 @@ describe('Location', () => {
afterEach(verifyNoBrowserErrors);
it('should verify paths', () => {
browser.get('/common/location/ts/#/bar/baz');
browser.get('/location/#/bar/baz');
waitForElement('hash-location');
expect(element.all(by.css('path-location code')).get(0).getText())
.toEqual('/common/location/ts');
expect(element.all(by.css('path-location code')).get(0).getText()).toEqual('/location');
expect(element.all(by.css('hash-location code')).get(0).getText()).toEqual('/bar/baz');
});
});

View File

@ -17,14 +17,13 @@ import {PathLocationComponent} from './path_location_component';
selector: 'example-app',
template: `<hash-location></hash-location><path-location></path-location>`
})
export class ExampleAppComponent {
export class AppComponent {
}
@NgModule({
declarations: [ExampleAppComponent, PathLocationComponent, HashLocationComponent],
declarations: [AppComponent, PathLocationComponent, HashLocationComponent],
providers: [{provide: APP_BASE_HREF, useValue: '/'}],
imports: [BrowserModule],
bootstrap: [ExampleAppComponent]
})
export class AppModule {
}

View File

@ -5,9 +5,8 @@
* 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 * as mod from './module';
if (mod.AppModule) {
platformBrowserDynamic().bootstrapModule(mod.AppModule);
}
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {TestsAppModuleNgFactory} from './test_module.ngfactory';
platformBrowserDynamic().bootstrapModuleFactory(TestsAppModuleNgFactory);

View File

@ -7,7 +7,8 @@
*/
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;

View File

@ -7,21 +7,22 @@
*/
import {CommonModule} from '@angular/common';
import {Compiler, Component, Injectable, Injector, NgModule, NgModuleFactory} from '@angular/core';
import {COMPILER_OPTIONS, Compiler, CompilerFactory, Component, Injectable, Injector, NgModule, NgModuleFactory} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {JitCompilerFactory} from '@angular/platform-browser-dynamic';
// #docregion SimpleExample
@Component({selector: 'hello-world', template: 'Hello World!'})
class HelloWorld {
export class HelloWorld {
}
@Component({
selector: 'ng-component-outlet-simple-example',
template: `<ng-container *ngComponentOutlet="HelloWorld"></ng-container>`
})
class NgTemplateOutletSimpleExample {
export class NgTemplateOutletSimpleExample {
// This field is necessary to expose HelloWorld to the template.
HelloWorld = HelloWorld;
}
@ -29,7 +30,7 @@ class NgTemplateOutletSimpleExample {
// #docregion CompleteExample
@Injectable()
class Greeter {
export class Greeter {
suffix = '!';
}
@ -37,7 +38,7 @@ class Greeter {
selector: 'complete-component',
template: `Complete: <ng-content></ng-content> <ng-content></ng-content>{{ greeter.suffix }}`
})
class CompleteComponent {
export class CompleteComponent {
constructor(public greeter: Greeter) {}
}
@ -48,7 +49,7 @@ class CompleteComponent {
injector: myInjector;
content: myContent"></ng-container>`
})
class NgTemplateOutletCompleteExample {
export class NgTemplateOutletCompleteExample {
// This field is necessary to expose CompleteComponent to the template.
CompleteComponent = CompleteComponent;
myInjector: Injector;
@ -64,7 +65,7 @@ class NgTemplateOutletCompleteExample {
// #docregion NgModuleFactoryExample
@Component({selector: 'other-module-component', template: `Other Module Component!`})
class OtherModuleComponent {
export class OtherModuleComponent {
}
@Component({
@ -73,7 +74,7 @@ class OtherModuleComponent {
<ng-container *ngComponentOutlet="OtherModuleComponent;
ngModuleFactory: myModule;"></ng-container>`
})
class NgTemplateOutletOtherModuleExample {
export class NgTemplateOutletOtherModuleExample {
// This field is necessary to expose OtherModuleComponent to the template.
OtherModuleComponent = OtherModuleComponent;
myModule: NgModuleFactory<any>;
@ -91,19 +92,7 @@ class NgTemplateOutletOtherModuleExample {
<hr/>
<ng-component-outlet-other-module-example></ng-component-outlet-other-module-example>`
})
class ExampleApp {
}
@NgModule({
imports: [BrowserModule],
declarations: [
ExampleApp, NgTemplateOutletSimpleExample, NgTemplateOutletCompleteExample,
NgTemplateOutletOtherModuleExample, HelloWorld, CompleteComponent
],
entryComponents: [HelloWorld, CompleteComponent],
bootstrap: [ExampleApp]
})
export class AppModule {
export class AppComponent {
}
@NgModule({
@ -113,3 +102,26 @@ export class AppModule {
})
export class OtherModule {
}
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
@NgModule({
imports: [BrowserModule],
declarations: [
AppComponent, NgTemplateOutletSimpleExample, NgTemplateOutletCompleteExample,
NgTemplateOutletOtherModuleExample, HelloWorld, CompleteComponent
],
entryComponents: [HelloWorld, CompleteComponent],
providers: [
// Setup the JIT compiler that is not set up by default because the examples
// are bootstrapped using their NgModule factory. Since this example uses the
// JIT compiler, we manually set it up for this module.
{provide: COMPILER_OPTIONS, useValue: {}, multi: true},
{provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
{provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory]}
]
})
export class AppModule {
}

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;
@ -16,7 +16,7 @@ function waitForElement(selector: string) {
}
describe('ngIf', () => {
const URL = 'common/ngIf/ts/';
const URL = '/ngIf';
afterEach(verifyNoBrowserErrors);
describe('ng-if-simple', () => {

View File

@ -21,7 +21,7 @@ import {Subject} from 'rxjs';
<div *ngIf="show">Text to show</div>
`
})
class NgIfSimple {
export class NgIfSimple {
show: boolean = true;
}
// #enddocregion
@ -37,7 +37,7 @@ class NgIfSimple {
<ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>
`
})
class NgIfElse {
export class NgIfElse {
show: boolean = true;
}
// #enddocregion
@ -56,7 +56,7 @@ class NgIfElse {
<ng-template #elseBlock>Alternate text while primary text is hidden</ng-template>
`
})
class NgIfThenElse implements OnInit {
export class NgIfThenElse implements OnInit {
thenBlock: TemplateRef<any>|null = null;
show: boolean = true;
@ -85,7 +85,7 @@ class NgIfThenElse implements OnInit {
<ng-template #loading let-user>Waiting... (user is {{user|json}})</ng-template>
`
})
class NgIfAs {
export class NgIfAs {
userObservable = new Subject<{first: string, last: string}>();
first = ['John', 'Mike', 'Mary', 'Bob'];
firstIndex = 0;
@ -116,13 +116,12 @@ class NgIfAs {
<hr>
`
})
class ExampleApp {
export class AppComponent {
}
@NgModule({
imports: [BrowserModule],
declarations: [ExampleApp, NgIfSimple, NgIfElse, NgIfThenElse, NgIfAs],
bootstrap: [ExampleApp]
declarations: [AppComponent, NgIfSimple, NgIfElse, NgIfThenElse, NgIfAs],
})
export class AppModule {
}

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;
@ -16,7 +16,7 @@ function waitForElement(selector: string) {
}
describe('ngTemplateOutlet', () => {
const URL = 'common/ngTemplateOutlet/ts/';
const URL = '/ngTemplateOutlet';
afterEach(verifyNoBrowserErrors);
describe('ng-template-outlet-example', () => {

View File

@ -26,7 +26,7 @@ import {BrowserModule} from '@angular/platform-browser';
<ng-template #svk let-person="localSk"><span>Ahoj {{person}}!</span></ng-template>
`
})
class NgTemplateOutletExample {
export class NgTemplateOutletExample {
myContext = {$implicit: 'World', localSk: 'Svet'};
}
// #enddocregion
@ -36,13 +36,12 @@ class NgTemplateOutletExample {
selector: 'example-app',
template: `<ng-template-outlet-example></ng-template-outlet-example>`
})
class ExampleApp {
export class AppComponent {
}
@NgModule({
imports: [BrowserModule],
declarations: [ExampleApp, NgTemplateOutletExample],
bootstrap: [ExampleApp]
declarations: [AppComponent, NgTemplateOutletExample],
})
export class AppModule {
}

View File

@ -58,7 +58,7 @@ export class AsyncObservablePipeComponent {
// protractor will not see us. Also we want to have this outside the docregion so as not to confuse
// the reader.
function setInterval(fn: Function, delay: number) {
const zone = Zone.current;
const zone = (window as any)['Zone'].current;
let rootZone = zone;
while (rootZone.parent) {
rootZone = rootZone.parent;

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;
@ -17,7 +17,7 @@ function waitForElement(selector: string) {
describe('pipe', () => {
afterEach(verifyNoBrowserErrors);
const URL = '/common/pipes/ts/';
const URL = '/pipes';
describe('async', () => {
it('should resolve and display promise', () => {

View File

@ -59,19 +59,19 @@ import {TitleCasePipeComponent} from './titlecase_pipe';
<keyvalue-pipe></keyvalue-pipe>
`
})
export class ExampleAppComponent {
export class AppComponent {
}
@NgModule({
declarations: [
AsyncPromisePipeComponent, AsyncObservablePipeComponent, ExampleAppComponent, JsonPipeComponent,
AsyncPromisePipeComponent, AsyncObservablePipeComponent, AppComponent, JsonPipeComponent,
DatePipeComponent, DeprecatedDatePipeComponent, LowerUpperPipeComponent, TitleCasePipeComponent,
NumberPipeComponent, PercentPipeComponent, DeprecatedPercentPipeComponent,
CurrencyPipeComponent, DeprecatedCurrencyPipeComponent, SlicePipeStringComponent,
SlicePipeListComponent, I18nPluralPipeComponent, I18nSelectPipeComponent, KeyValuePipeComponent
NumberPipeComponent, DeprecatedNumberPipeComponent, PercentPipeComponent,
DeprecatedPercentPipeComponent, CurrencyPipeComponent, DeprecatedCurrencyPipeComponent,
SlicePipeStringComponent, SlicePipeListComponent, I18nPluralPipeComponent,
I18nSelectPipeComponent, KeyValuePipeComponent
],
imports: [BrowserModule],
bootstrap: [ExampleAppComponent]
})
export class AppModule {
}

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,41 @@
/**
* @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 locationExample from './location/ts/module';
import * as ngComponentOutletExample from './ngComponentOutlet/ts/module';
import * as ngIfExample from './ngIf/ts/module';
import * as ngTemplateOutletExample from './ngTemplateOutlet/ts/module';
import * as pipesExample from './pipes/ts/module';
@Component({selector: 'example-app', template: '<router-outlet></router-outlet>'})
export class TestsAppComponent {
}
@NgModule({
imports: [
locationExample.AppModule, ngComponentOutletExample.AppModule, ngIfExample.AppModule,
ngTemplateOutletExample.AppModule, pipesExample.AppModule,
// Router configuration so that the individual e2e tests can load their
// app components.
RouterModule.forRoot([
{path: 'location', component: locationExample.AppComponent},
{path: 'ngComponentOutlet', component: ngComponentOutletExample.AppComponent},
{path: 'ngIf', component: ngIfExample.AppComponent},
{path: 'ngTemplateOutlet', component: ngTemplateOutletExample.AppComponent},
{path: 'pipes', component: pipesExample.AppComponent},
])
],
declarations: [TestsAppComponent],
bootstrap: [TestsAppComponent]
})
export class TestsAppModule {
}

View File

@ -0,0 +1,13 @@
package(default_visibility = ["//visibility:public"])
load("//tools:defaults.bzl", "ng_module")
ng_module(
name = "compiler_examples",
srcs = glob(["**/*.ts"]),
deps = [
"//packages/core",
"//packages/platform-browser",
"//packages/platform-browser-dynamic",
],
)

View File

@ -7,11 +7,13 @@
*/
import {UrlResolver} from '@angular/compiler';
import {NgModule} from '@angular/core';
import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
let MyApp: any;
@Component({selector: 'my-app', template: 'empty'})
class MyApp {
}
// #docregion url_resolver
class MyUrlResolver extends UrlResolver {

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({
@ -64,3 +64,9 @@ export class MyOutputComponent {
onEveryFiveSeconds() { console.log('five seconds'); }
}
// #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

View File

@ -0,0 +1,59 @@
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 = "forms_examples",
srcs = glob(
["**/*.ts"],
exclude = ["**/*_spec.ts"],
),
# TODO: FW-1004 Type checking is currently not complete.
type_check = False,
deps = [
"//packages/core",
"//packages/forms",
"//packages/platform-browser",
"//packages/platform-browser-dynamic",
"//packages/router",
],
)
ts_library(
name = "forms_e2e_tests_lib",
testonly = True,
srcs = glob(["**/e2e_test/*_spec.ts"]),
tsconfig = "//packages/examples:tsconfig-e2e.json",
deps = [
"//packages/examples/test-utils",
"//packages/private/testing",
"@ngdeps//@types/jasminewd2",
"@ngdeps//protractor",
],
)
ts_devserver(
name = "devserver",
entry_module = "@angular/examples/forms/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",
],
deps = [":forms_examples"],
)
protractor_web_test_suite(
name = "protractor_tests",
data = ["//packages/bazel/src/protractor/utils"],
on_prepare = ":start-server.js",
server = ":devserver",
deps = [
":forms_e2e_tests_lib",
"@ngdeps//protractor",
"@ngdeps//selenium-webdriver",
],
)

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,58 @@
/**
* @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 formBuilderExample from './ts/formBuilder/module';
import * as nestedFormArrayExample from './ts/nestedFormArray/module';
import * as nestedFormGroupExample from './ts/nestedFormGroup/module';
import * as ngModelGroupExample from './ts/ngModelGroup/module';
import * as radioButtonsExample from './ts/radioButtons/module';
import * as reactiveRadioButtonsExample from './ts/reactiveRadioButtons/module';
import * as reactiveSelectControlExample from './ts/reactiveSelectControl/module';
import * as selectControlExample from './ts/selectControl/module';
import * as simpleFormExample from './ts/simpleForm/module';
import * as simpleFormControlExample from './ts/simpleFormControl/module';
import * as simpleFormGroupExample from './ts/simpleFormGroup/module';
import * as simpleNgModelExample from './ts/simpleNgModel/module';
@Component({selector: 'example-app', template: '<router-outlet></router-outlet>'})
export class TestsAppComponent {
}
@NgModule({
imports: [
formBuilderExample.AppModule, nestedFormArrayExample.AppModule,
nestedFormGroupExample.AppModule, ngModelGroupExample.AppModule, radioButtonsExample.AppModule,
reactiveRadioButtonsExample.AppModule, reactiveSelectControlExample.AppModule,
selectControlExample.AppModule, simpleFormExample.AppModule, simpleFormControlExample.AppModule,
simpleFormGroupExample.AppModule, simpleNgModelExample.AppModule,
// Router configuration so that the individual e2e tests can load their
// app components.
RouterModule.forRoot([
{path: 'formBuilder', component: formBuilderExample.AppComponent},
{path: 'nestedFormArray', component: nestedFormArrayExample.AppComponent},
{path: 'nestedFormGroup', component: nestedFormGroupExample.AppComponent},
{path: 'ngModelGroup', component: ngModelGroupExample.AppComponent},
{path: 'radioButtons', component: radioButtonsExample.AppComponent},
{path: 'reactiveRadioButtons', component: reactiveRadioButtonsExample.AppComponent},
{path: 'reactiveSelectControl', component: reactiveSelectControlExample.AppComponent},
{path: 'selectControl', component: selectControlExample.AppComponent},
{path: 'simpleForm', component: simpleFormExample.AppComponent},
{path: 'simpleFormControl', component: simpleFormControlExample.AppComponent},
{path: 'simpleFormGroup', component: simpleFormGroupExample.AppComponent},
{path: 'simpleNgModel', component: simpleNgModelExample.AppComponent}
])
],
declarations: [TestsAppComponent],
bootstrap: [TestsAppComponent]
})
export class TestsAppModule {
}

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('formBuilder example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('formBuilder example', () => {
let paragraphs: ElementArrayFinder;
beforeEach(() => {
browser.get('/forms/ts/formBuilder/index.html');
browser.get('/formBuilder');
inputs = element.all(by.css('input'));
paragraphs = element.all(by.css('p'));
});

View File

@ -9,12 +9,14 @@
import {NgModule} from '@angular/core';
import {ReactiveFormsModule} from '@angular/forms';
import {BrowserModule} from '@angular/platform-browser';
import {FormBuilderComp} from './form_builder_example';
import {DisabledFormControlComponent, FormBuilderComp} from './form_builder_example';
@NgModule({
imports: [BrowserModule, ReactiveFormsModule],
declarations: [FormBuilderComp],
declarations: [FormBuilderComp, DisabledFormControlComponent],
bootstrap: [FormBuilderComp]
})
export class AppModule {
}
export {FormBuilderComp as AppComponent};

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('nestedFormArray example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('nestedFormArray example', () => {
let buttons: ElementArrayFinder;
beforeEach(() => {
browser.get('/forms/ts/nestedFormArray/index.html');
browser.get('/nestedFormArray');
inputs = element.all(by.css('input'));
buttons = element.all(by.css('button'));
});

View File

@ -18,3 +18,5 @@ import {NestedFormArray} from './nested_form_array_example';
})
export class AppModule {
}
export {NestedFormArray 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('nestedFormGroup example', () => {
afterEach(verifyNoBrowserErrors);
@ -16,7 +16,7 @@ describe('nestedFormGroup example', () => {
let button: ElementFinder;
beforeEach(() => {
browser.get('/forms/ts/nestedFormGroup/index.html');
browser.get('/nestedFormGroup');
firstInput = element(by.css('[formControlName="first"]'));
lastInput = element(by.css('[formControlName="last"]'));
button = element(by.css('button:not([type="submit"])'));

View File

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

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('ngModelGroup example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('ngModelGroup example', () => {
let buttons: ElementArrayFinder;
beforeEach(() => {
browser.get('/forms/ts/ngModelGroup/index.html');
browser.get('/ngModelGroup');
inputs = element.all(by.css('input'));
buttons = element.all(by.css('button'));
});

View File

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

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('radioButtons example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('radioButtons example', () => {
let paragraphs: ElementArrayFinder;
beforeEach(() => {
browser.get('/forms/ts/radioButtons/index.html');
browser.get('/radioButtons');
inputs = element.all(by.css('input'));
paragraphs = element.all(by.css('p'));
});

View File

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

View File

@ -7,14 +7,14 @@
*/
import {ElementArrayFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('radioButtons example', () => {
afterEach(verifyNoBrowserErrors);
let inputs: ElementArrayFinder;
beforeEach(() => {
browser.get('/forms/ts/reactiveRadioButtons/index.html');
browser.get('/reactiveRadioButtons');
inputs = element.all(by.css('input'));
});

View File

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

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('reactiveSelectControl example', () => {
afterEach(verifyNoBrowserErrors);
@ -16,7 +16,7 @@ describe('reactiveSelectControl example', () => {
let p: ElementFinder;
beforeEach(() => {
browser.get('/forms/ts/reactiveSelectControl/index.html');
browser.get('/reactiveSelectControl');
select = element(by.css('select'));
options = element.all(by.css('option'));
p = element(by.css('p'));

View File

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

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('selectControl example', () => {
afterEach(verifyNoBrowserErrors);
@ -16,7 +16,7 @@ describe('selectControl example', () => {
let p: ElementFinder;
beforeEach(() => {
browser.get('/forms/ts/selectControl/index.html');
browser.get('/selectControl');
select = element(by.css('select'));
options = element.all(by.css('option'));
p = element(by.css('p'));

View File

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

View File

@ -7,7 +7,7 @@
*/
import {ElementArrayFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../test-utils';
describe('simpleForm example', () => {
afterEach(verifyNoBrowserErrors);
@ -15,7 +15,7 @@ describe('simpleForm example', () => {
let paragraphs: ElementArrayFinder;
beforeEach(() => {
browser.get('/forms/ts/simpleForm/index.html');
browser.get('/simpleForm');
inputs = element.all(by.css('input'));
paragraphs = element.all(by.css('p'));
});

View File

@ -18,3 +18,5 @@ import {SimpleFormComp} from './simple_form_example';
})
export class AppModule {
}
export {SimpleFormComp 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('simpleFormControl example', () => {
afterEach(verifyNoBrowserErrors);
@ -18,7 +18,7 @@ describe('simpleFormControl example', () => {
let statusP: ElementFinder;
beforeEach(() => {
browser.get('/forms/ts/simpleFormControl/index.html');
browser.get('/simpleFormControl');
input = element(by.css('input'));
valueP = element(by.css('p:first-of-type'));
statusP = element(by.css('p:last-of-type'));

View File

@ -18,3 +18,5 @@ import {SimpleFormControl} from './simple_form_control_example';
})
export class AppModule {
}
export {SimpleFormControl 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('formControlName example', () => {
afterEach(verifyNoBrowserErrors);
@ -17,7 +17,7 @@ describe('formControlName example', () => {
let lastInput: ElementFinder;
beforeEach(() => {
browser.get('/forms/ts/simpleFormGroup/index.html');
browser.get('/simpleFormGroup');
firstInput = element(by.css('[formControlName="first"]'));
lastInput = element(by.css('[formControlName="last"]'));
});

View File

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

View File

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

View File

@ -0,0 +1 @@
package(default_visibility = ["//visibility:public"])

View File

@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Angular Examples</title>
<base href="/">
<!-- Prevent the browser from requesting any favicon. This could throw off the console
output checks. -->
<link rel="icon" href="data:,">
</head>
<body>
<example-app>Loading...</example-app>
</body>
</html>

View File

@ -0,0 +1,14 @@
package(default_visibility = ["//visibility:public"])
load("//tools:defaults.bzl", "ng_module")
ng_module(
name = "platform_browser_examples",
srcs = glob(["**/*.ts"]),
deps = [
"//packages/compiler",
"//packages/core",
"//packages/platform-browser",
"//packages/platform-browser-dynamic",
],
)

View File

@ -11,7 +11,7 @@ import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@Component({selector: 'my-component'})
@Component({selector: 'my-component', template: 'text'})
class MyAppComponent {
}

View File

@ -0,0 +1,11 @@
package(default_visibility = ["//visibility:public"])
load("//tools:defaults.bzl", "ts_library")
ts_library(
name = "test-utils",
srcs = ["index.ts"],
deps = [
"@ngdeps//@types/selenium-webdriver",
],
)

View File

@ -0,0 +1,43 @@
/**
* @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
*/
/* tslint:disable:no-console */
import {WebDriver, logging} from 'selenium-webdriver';
declare var browser: WebDriver;
declare var expect: any;
// TODO (juliemr): remove this method once this becomes a protractor plugin
export async function verifyNoBrowserErrors() {
const browserLog = await browser.manage().logs().get('browser');
const collectedErrors: any[] = [];
browserLog.forEach(logEntry => {
const msg = logEntry.message;
// Since we currently use the `ts_devserver` from the Bazel TypeScript rules, which does
// fallback to the "index.html" file for HTML5 pushState routing but does always serve the
// expected fallback with a 404 status code, the browser will print a message about the 404,
// while the page loaded properly. Ideally the "ts_devserver" would allow us to opt-in for
// just returning a 200 status code, but the devserver is intended to be kept manually, so
// we manually filter this error before ensuring there are no console errors.
// TODO: This is a current limitation of using the "ts_devserver" with Angular routing.
// Tracked with: TOOL-629
if (msg.includes(
`Failed to load resource: the server responded with a status of 404 (Not Found)`)) {
return;
}
console.log('>> ' + msg, logEntry);
if (logEntry.level.value >= logging.Level.INFO.value) {
collectedErrors.push(msg);
}
});
expect(collectedErrors).toEqual([]);
}

View File

@ -1,17 +0,0 @@
#!/usr/bin/env bash
set -u -e -o pipefail
(
cd `dirname $0`
./build.sh
gulp serve-examples &
trap "kill $!" EXIT
(
cd ../../
NODE_PATH=${NODE_PATH:-}:dist/all
$(npm bin)/protractor protractor-examples-e2e.conf.js --bundles=true
)
)

View File

@ -0,0 +1,13 @@
package(default_visibility = ["//visibility:public"])
load("//tools:defaults.bzl", "ts_library")
ts_library(
name = "testing_examples",
srcs = glob(["**/*.ts"]),
tsconfig = "//packages:tsconfig-test.json",
deps = [
"@ngdeps//@types/jasmine",
"@ngdeps//@types/node",
],
)

View File

@ -1,22 +0,0 @@
{
"extends": "../tsconfig-build.json",
"compilerOptions": {
"module": "commonjs",
"emitDecoratorMetadata": true,
"baseUrl": ".",
"rootDir": ".",
"paths": {
"@angular/*": ["../../dist/packages-dist/*"],
"rxjs/*": ["../../node_modules/rxjs/*"]
},
"outDir": "../../dist/examples",
"types": ["angular"]
},
"include": [
"../../node_modules/@types/jasminewd2/index.d.ts",
"../types.d.ts",
"**/*.ts"
]
}

View File

@ -0,0 +1,6 @@
{
"compilerOptions": {
"lib": ["es2015"],
"types": ["node", "jasminewd2"]
}
}

View File

@ -1,18 +0,0 @@
// WARNING:
// This file is used to build the e2e tests only.
// The rest of the files are included in `/packages/tsconfig.json`.
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": []
},
"include": [
"../../node_modules/@types/jasminewd2/index.d.ts",
"../types.d.ts",
"**/e2e_test/*"
],
"exclude": []
}

View File

@ -0,0 +1,4 @@
exports_files([
"tsconfig-build.json",
"start-server.js",
])

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,14 @@
package(default_visibility = ["//visibility:public"])
load("//packages/examples/upgrade:upgrade_example.bzl", "create_upgrade_example_targets")
create_upgrade_example_targets(
name = "full",
srcs = glob(
["**/*.ts"],
exclude = ["**/*_spec.ts"],
),
assets = ["styles.css"],
e2e_srcs = glob(["e2e_test/*_spec.ts"]),
entry_module = "@angular/examples/upgrade/static/ts/full/module",
)

View File

@ -7,11 +7,11 @@
*/
import {browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
function loadPage() {
browser.rootEl = 'example-app';
browser.get('/upgrade/static/ts/full/');
browser.get('/');
}
describe('upgrade/static (full)', () => {

View File

@ -0,0 +1,13 @@
package(default_visibility = ["//visibility:public"])
load("//packages/examples/upgrade:upgrade_example.bzl", "create_upgrade_example_targets")
create_upgrade_example_targets(
name = "lite-multi-shared",
srcs = glob(
["**/*.ts"],
exclude = ["**/*_spec.ts"],
),
e2e_srcs = glob(["e2e_test/*_spec.ts"]),
entry_module = "@angular/examples/upgrade/static/ts/lite-multi-shared/module",
)

View File

@ -8,7 +8,7 @@
import {browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
describe('upgrade/static (lite with multiple downgraded modules and shared root module)', () => {
@ -16,7 +16,7 @@ describe('upgrade/static (lite with multiple downgraded modules and shared root
const compB = element(by.css('ng2-b'));
const compC = element(by.css('ng2-c'));
beforeEach(() => browser.get('/upgrade/static/ts/lite-multi-shared/'));
beforeEach(() => browser.get('/'));
afterEach(verifyNoBrowserErrors);
it('should share the same injectable instance across downgraded modules A and B', () => {

View File

@ -0,0 +1,13 @@
package(default_visibility = ["//visibility:public"])
load("//packages/examples/upgrade:upgrade_example.bzl", "create_upgrade_example_targets")
create_upgrade_example_targets(
name = "lite-multi",
srcs = glob(
["**/*.ts"],
exclude = ["**/*_spec.ts"],
),
e2e_srcs = glob(["e2e_test/*_spec.ts"]),
entry_module = "@angular/examples/upgrade/static/ts/lite-multi/module",
)

View File

@ -8,14 +8,14 @@
import {browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
describe('upgrade/static (lite with multiple downgraded modules)', () => {
const navButtons = element.all(by.css('nav button'));
const mainContent = element(by.css('main'));
beforeEach(() => browser.get('/upgrade/static/ts/lite-multi/'));
beforeEach(() => browser.get('/'));
afterEach(verifyNoBrowserErrors);
it('should correctly bootstrap multiple downgraded modules', () => {

View File

@ -0,0 +1,14 @@
package(default_visibility = ["//visibility:public"])
load("//packages/examples/upgrade:upgrade_example.bzl", "create_upgrade_example_targets")
create_upgrade_example_targets(
name = "lite",
srcs = glob(
["**/*.ts"],
exclude = ["e2e_test/*"],
),
assets = ["styles.css"],
e2e_srcs = glob(["e2e_test/*.ts"]),
entry_module = "@angular/examples/upgrade/static/ts/lite/module",
)

View File

@ -7,13 +7,13 @@
*/
import {ElementArrayFinder, ElementFinder, browser, by, element} from 'protractor';
import {verifyNoBrowserErrors} from '../../../../../test-utils';
import {verifyNoBrowserErrors} from '../../../../../_common/e2e_util';
import {addCustomMatchers} from './e2e_util';
function loadPage() {
browser.rootEl = 'example-app';
browser.get('/upgrade/static/ts/lite/');
browser.get('/');
}
describe('upgrade/static (lite)', () => {

View File

@ -0,0 +1,6 @@
{
"compilerOptions": {
"lib": ["dom", "es2015"],
"types": ["angular"]
}
}

View File

@ -0,0 +1,66 @@
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")
"""
Macro that can be used to create the Bazel targets for an "upgrade" example. Since the
upgrade examples bootstrap their application manually, and we cannot serve all examples,
we need to define the devserver for each example. This macro reduces code duplication
for defining these targets.
"""
def create_upgrade_example_targets(name, srcs, e2e_srcs, entry_module, assets = []):
ng_module(
name = "%s_sources" % name,
srcs = srcs,
# TODO: FW-1004 Type checking is currently not complete.
type_check = False,
deps = [
"@ngdeps//@types/angular",
"//packages/core",
"//packages/platform-browser",
"//packages/platform-browser-dynamic",
"//packages/upgrade/static",
],
tsconfig = "//packages/examples/upgrade:tsconfig-build.json",
)
ts_library(
name = "%s_e2e_lib" % name,
srcs = e2e_srcs,
testonly = True,
deps = [
"@ngdeps//@types/jasminewd2",
"@ngdeps//protractor",
"//packages/examples/test-utils",
"//packages/private/testing",
],
tsconfig = "//packages/examples:tsconfig-e2e.json",
)
ts_devserver(
name = "devserver",
port = 4200,
entry_module = entry_module,
static_files = [
"@ngdeps//node_modules/zone.js:dist/zone.js",
"@ngdeps//node_modules/angular:angular.js",
"@ngdeps//node_modules/reflect-metadata:Reflect.js",
],
index_html = "//packages/examples:index.html",
scripts = ["@ngdeps//node_modules/tslib:tslib.js"],
deps = [":%s_sources" % name],
data = assets,
)
protractor_web_test_suite(
name = "%s_protractor" % name,
data = ["//packages/bazel/src/protractor/utils"],
on_prepare = "//packages/examples/upgrade:start-server.js",
server = ":devserver",
deps = [
":%s_e2e_lib" % name,
"@ngdeps//protractor",
"@ngdeps//selenium-webdriver",
],
)

View File

@ -33,7 +33,12 @@
"common/locales",
"compiler-cli/integrationtest",
"elements/schematics",
// Do not build the example e2e spec files since those require custom typings and
// aren't required to build all packages.
"examples/**/e2e_test/*",
// Exclude the "main.ts" files for each example group because this file is used by
// Bazel to launch the devserver and uses AOT compilation.
"examples/*/main.ts",
"platform-server/integrationtest",
"router/test/aot_ngsummary_test",
]

View File

@ -1,35 +0,0 @@
/**
* @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
*/
// Make sure that the command line is read as the first thing
// as this could exit node if the help script should be printed.
require('./dist/all/e2e_util/e2e_util').readCommandLine();
require('reflect-metadata');
Error.stackTraceLimit = 9999;
exports.config = {
onPrepare: function() { beforeEach(function() { browser.ignoreSynchronization = false; }); },
allScriptsTimeout: 11000,
specs: ['dist/examples/**/e2e_test/*_spec.js'],
capabilities: {
'browserName': 'chrome',
// Enables concurrent testing. Currently runs four e2e files in parallel.
shardTestFiles: true,
maxInstances: 4,
},
directConnect: true,
baseUrl: 'http://localhost:8001/',
framework: 'jasmine2',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 60000,
print: function(msg) { console.log(msg); },
},
useAllAngular2AppRoots: true
};

Some files were not shown because too many files have changed in this diff Show More