From ac6b2b4dc39668cc9760d0df8768889bdcf2e0f9 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Fri, 15 Feb 2019 00:25:00 +0100 Subject: [PATCH] build: convert examples package to bazel (#28733) * build: switch example e2e tests to bazel * 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. * test: disable failing ivy example e2e tests *Note for patch branch:* We had to disable more examples in Ivy because the patch branch does not contain all Ivy/ngtsc fixes. --- .bazelrc | 2 +- .circleci/config.yml | 2 - gulpfile.js | 1 - packages/examples/BUILD.bazel | 4 ++ packages/examples/README.md | 25 ++----- packages/examples/_common/bootstrap.ts | 21 ------ packages/examples/_common/e2e_util.ts | 26 ------- packages/examples/_common/index.html | 16 ----- packages/examples/_common/module.d.ts | 19 ------ packages/examples/_common/system-config.ts | 36 ---------- packages/examples/build.sh | 44 ------------ packages/examples/common/BUILD.bazel | 68 +++++++++++++++++++ .../ts/e2e_test/location_component_spec.ts | 7 +- .../examples/common/location/ts/module.ts | 5 +- .../main-dynamic.ts => common/main.ts} | 9 ++- .../ts/e2e_test/ngComponentOutlet_spec.ts | 53 ++++++++------- .../common/ngComponentOutlet/ts/module.ts | 54 +++++++++------ .../common/ngIf/ts/e2e_test/ngIf_spec.ts | 32 +++++---- packages/examples/common/ngIf/ts/module.ts | 13 ++-- .../ts/e2e_test/ngTemplateOutlet_spec.ts | 4 +- .../common/ngTemplateOutlet/ts/module.ts | 7 +- .../examples/common/pipes/ts/async_pipe.ts | 2 +- .../common/pipes/ts/e2e_test/pipe_spec.ts | 4 +- packages/examples/common/pipes/ts/module.ts | 12 ++-- packages/examples/common/start-server.js | 17 +++++ packages/examples/common/test_module.ts | 41 +++++++++++ packages/examples/compiler/BUILD.bazel | 13 ++++ .../compiler/ts/url_resolver/url_resolver.ts | 6 +- packages/examples/core/BUILD.bazel | 68 +++++++++++++++++++ .../ts/dsl/e2e_test/animation_example_spec.ts | 4 +- .../examples/core/animation/ts/dsl/module.ts | 3 +- .../e2e_test/content_child_spec.ts | 4 +- .../core/di/ts/contentChild/module.ts | 2 + .../e2e_test/content_children_spec.ts | 4 +- .../core/di/ts/contentChildren/module.ts | 2 + .../ts/viewChild/e2e_test/view_child_spec.ts | 4 +- .../examples/core/di/ts/viewChild/module.ts | 2 + .../e2e_test/view_children_spec.ts | 4 +- .../core/di/ts/viewChildren/module.ts | 2 + packages/examples/core/main.ts | 12 ++++ packages/examples/core/start-server.js | 17 +++++ packages/examples/core/test_module.ts | 44 ++++++++++++ .../e2e_test/testability_example_spec.ts | 12 +++- .../core/testability/ts/whenStable/module.ts | 2 +- packages/examples/core/testing/ts/BUILD.bazel | 23 +++++++ .../examples/core/testing/ts/example_spec.ts | 12 ++++ .../examples/core/ts/metadata/directives.ts | 10 ++- .../core/ts/prod_mode/prod_mode_example.ts | 6 +- packages/examples/forms/BUILD.bazel | 64 +++++++++++++++++ packages/examples/forms/main.ts | 12 ++++ packages/examples/forms/start-server.js | 17 +++++ packages/examples/forms/test_module.ts | 58 ++++++++++++++++ .../formBuilder/e2e_test/form_builder_spec.ts | 4 +- .../examples/forms/ts/formBuilder/module.ts | 6 +- .../e2e_test/nested_form_array_spec.ts | 4 +- .../forms/ts/nestedFormArray/module.ts | 2 + .../e2e_test/nested_form_group_spec.ts | 4 +- .../forms/ts/nestedFormGroup/module.ts | 2 + .../e2e_test/ng_model_group_spec.ts | 4 +- .../examples/forms/ts/ngModelGroup/module.ts | 2 + .../e2e_test/radio_button_spec.ts | 4 +- .../examples/forms/ts/radioButtons/module.ts | 2 + .../e2e_test/reactive_radio_button_spec.ts | 4 +- .../forms/ts/reactiveRadioButtons/module.ts | 2 + .../e2e_test/reactive_select_control_spec.ts | 4 +- .../forms/ts/reactiveSelectControl/module.ts | 2 + .../e2e_test/select_control_spec.ts | 4 +- .../examples/forms/ts/selectControl/module.ts | 2 + .../simpleForm/e2e_test/simple_form_spec.ts | 4 +- .../examples/forms/ts/simpleForm/module.ts | 2 + .../e2e_test/simple_form_control_spec.ts | 4 +- .../forms/ts/simpleFormControl/module.ts | 2 + .../e2e_test/simple_form_group_spec.ts | 4 +- .../forms/ts/simpleFormGroup/module.ts | 2 + .../e2e_test/simple_ng_model_spec.ts | 61 +++++++++-------- .../examples/forms/ts/simpleNgModel/module.ts | 2 + packages/examples/http/BUILD.bazel | 1 + packages/examples/index.html | 15 ++++ .../examples/platform-browser/BUILD.bazel | 17 +++++ .../debug_element_view_listener/providers.ts | 2 +- packages/examples/test-utils/BUILD.bazel | 11 +++ packages/examples/test-utils/index.ts | 43 ++++++++++++ packages/examples/test.sh | 17 ----- packages/examples/testing/BUILD.bazel | 13 ++++ packages/examples/tsconfig-build.json | 22 ------ packages/examples/tsconfig-e2e.json | 6 ++ packages/examples/tsconfig.json | 18 ----- packages/examples/upgrade/BUILD.bazel | 4 ++ packages/examples/upgrade/start-server.js | 17 +++++ .../upgrade/static/ts/full/BUILD.bazel | 14 ++++ .../ts/full/e2e_test/static_full_spec.ts | 68 ++++++++++--------- .../static/ts/lite-multi-shared/BUILD.bazel | 13 ++++ .../e2e_test/static_lite_multi_shared_spec.ts | 4 +- .../upgrade/static/ts/lite-multi/BUILD.bazel | 13 ++++ .../e2e_test/static_lite_multi_spec.ts | 4 +- .../upgrade/static/ts/lite/BUILD.bazel | 14 ++++ .../ts/lite/e2e_test/static_lite_spec.ts | 50 +++++++------- packages/examples/upgrade/tsconfig-build.json | 6 ++ packages/examples/upgrade/upgrade_example.bzl | 66 ++++++++++++++++++ packages/tsconfig.json | 5 ++ protractor-examples-e2e.conf.js | 35 ---------- tools/gulp-tasks/serve.js | 15 ---- yarn.lock | 13 ++-- 103 files changed, 1049 insertions(+), 521 deletions(-) create mode 100644 packages/examples/BUILD.bazel delete mode 100644 packages/examples/_common/bootstrap.ts delete mode 100644 packages/examples/_common/e2e_util.ts delete mode 100644 packages/examples/_common/index.html delete mode 100644 packages/examples/_common/module.d.ts delete mode 100644 packages/examples/_common/system-config.ts delete mode 100755 packages/examples/build.sh create mode 100644 packages/examples/common/BUILD.bazel rename packages/examples/{_common/main-dynamic.ts => common/main.ts} (66%) create mode 100644 packages/examples/common/start-server.js create mode 100644 packages/examples/common/test_module.ts create mode 100644 packages/examples/compiler/BUILD.bazel create mode 100644 packages/examples/core/BUILD.bazel create mode 100644 packages/examples/core/main.ts create mode 100644 packages/examples/core/start-server.js create mode 100644 packages/examples/core/test_module.ts create mode 100644 packages/examples/core/testing/ts/BUILD.bazel create mode 100644 packages/examples/core/testing/ts/example_spec.ts create mode 100644 packages/examples/forms/BUILD.bazel create mode 100644 packages/examples/forms/main.ts create mode 100644 packages/examples/forms/start-server.js create mode 100644 packages/examples/forms/test_module.ts create mode 100644 packages/examples/http/BUILD.bazel create mode 100644 packages/examples/index.html create mode 100644 packages/examples/platform-browser/BUILD.bazel create mode 100644 packages/examples/test-utils/BUILD.bazel create mode 100644 packages/examples/test-utils/index.ts delete mode 100755 packages/examples/test.sh create mode 100644 packages/examples/testing/BUILD.bazel delete mode 100644 packages/examples/tsconfig-build.json create mode 100644 packages/examples/tsconfig-e2e.json delete mode 100644 packages/examples/tsconfig.json create mode 100644 packages/examples/upgrade/BUILD.bazel create mode 100644 packages/examples/upgrade/start-server.js create mode 100644 packages/examples/upgrade/static/ts/full/BUILD.bazel create mode 100644 packages/examples/upgrade/static/ts/lite-multi-shared/BUILD.bazel create mode 100644 packages/examples/upgrade/static/ts/lite-multi/BUILD.bazel create mode 100644 packages/examples/upgrade/static/ts/lite/BUILD.bazel create mode 100644 packages/examples/upgrade/tsconfig-build.json create mode 100644 packages/examples/upgrade/upgrade_example.bzl delete mode 100644 protractor-examples-e2e.conf.js diff --git a/.bazelrc b/.bazelrc index 2d1b8ae5e6..2a21f32349 100644 --- a/.bazelrc +++ b/.bazelrc @@ -33,7 +33,7 @@ test:debug --test_arg=--node_options=--inspect-brk --test_output=streamed --test # eventually a surprising failure with auto-discovery of the C++ toolchain in # MacOS High Sierra. # See https://github.com/bazelbuild/bazel/issues/4603 -build --symlink_prefix=dist/ +build --symlink_prefix=/ # Performance: avoid stat'ing input files build --watchfs diff --git a/.circleci/config.yml b/.circleci/config.yml index 1699c88d9d..c999e0fb94 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -491,7 +491,6 @@ jobs: - *download_yarn - *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 @@ -518,7 +517,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. diff --git a/gulpfile.js b/gulpfile.js index a64eb17ed4..e77ab05b4f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -53,7 +53,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')); diff --git a/packages/examples/BUILD.bazel b/packages/examples/BUILD.bazel new file mode 100644 index 0000000000..70b5855669 --- /dev/null +++ b/packages/examples/BUILD.bazel @@ -0,0 +1,4 @@ +exports_files([ + "index.html", + "tsconfig-e2e.json", +]) diff --git a/packages/examples/README.md b/packages/examples/README.md index 2e3269f41f..c472095b25 100644 --- a/packages/examples/README.md +++ b/packages/examples/README.md @@ -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 -``` - -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`) \ No newline at end of file +yarn bazel test //packages/examples/... +``` \ No newline at end of file diff --git a/packages/examples/_common/bootstrap.ts b/packages/examples/_common/bootstrap.ts deleted file mode 100644 index 24bad23979..0000000000 --- a/packages/examples/_common/bootstrap.ts +++ /dev/null @@ -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(''); - } -}(window)); diff --git a/packages/examples/_common/e2e_util.ts b/packages/examples/_common/e2e_util.ts deleted file mode 100644 index 4ca6732c1e..0000000000 --- a/packages/examples/_common/e2e_util.ts +++ /dev/null @@ -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([]); - }); -} diff --git a/packages/examples/_common/index.html b/packages/examples/_common/index.html deleted file mode 100644 index 645ad3416f..0000000000 --- a/packages/examples/_common/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - loading... - - - diff --git a/packages/examples/_common/module.d.ts b/packages/examples/_common/module.d.ts deleted file mode 100644 index 9038a8f4ac..0000000000 --- a/packages/examples/_common/module.d.ts +++ /dev/null @@ -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 {}; diff --git a/packages/examples/_common/system-config.ts b/packages/examples/_common/system-config.ts deleted file mode 100644 index 2ad12456a6..0000000000 --- a/packages/examples/_common/system-config.ts +++ /dev/null @@ -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'}, - }, -}); diff --git a/packages/examples/build.sh b/packages/examples/build.sh deleted file mode 100755 index ce521af07a..0000000000 --- a/packages/examples/build.sh +++ /dev/null @@ -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 -) diff --git a/packages/examples/common/BUILD.bazel b/packages/examples/common/BUILD.bazel new file mode 100644 index 0000000000..52cfd4d2f3 --- /dev/null +++ b/packages/examples/common/BUILD.bazel @@ -0,0 +1,68 @@ +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: This does not compile with Ivy because the patch branch does not contain + # all ngtsc fixes. + tags = ["fixme-ivy-aot"], + # 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", + ], + tags = ["fixme-ivy-aot"], + deps = [":common_examples"], +) + +protractor_web_test_suite( + name = "protractor_tests", + data = ["//packages/bazel/src/protractor/utils"], + on_prepare = ":start-server.js", + server = ":devserver", + tags = ["fixme-ivy-aot"], + deps = [ + ":common_tests_lib", + "@ngdeps//protractor", + "@ngdeps//selenium-webdriver", + ], +) diff --git a/packages/examples/common/location/ts/e2e_test/location_component_spec.ts b/packages/examples/common/location/ts/e2e_test/location_component_spec.ts index 20e790a3c1..917b3f43c1 100644 --- a/packages/examples/common/location/ts/e2e_test/location_component_spec.ts +++ b/packages/examples/common/location/ts/e2e_test/location_component_spec.ts @@ -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'); }); }); diff --git a/packages/examples/common/location/ts/module.ts b/packages/examples/common/location/ts/module.ts index 10b064e54d..76a902de2a 100644 --- a/packages/examples/common/location/ts/module.ts +++ b/packages/examples/common/location/ts/module.ts @@ -17,14 +17,13 @@ import {PathLocationComponent} from './path_location_component'; selector: 'example-app', template: `` }) -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 { } diff --git a/packages/examples/_common/main-dynamic.ts b/packages/examples/common/main.ts similarity index 66% rename from packages/examples/_common/main-dynamic.ts rename to packages/examples/common/main.ts index e30f1c076b..b5ec0fb33e 100644 --- a/packages/examples/_common/main-dynamic.ts +++ b/packages/examples/common/main.ts @@ -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); diff --git a/packages/examples/common/ngComponentOutlet/ts/e2e_test/ngComponentOutlet_spec.ts b/packages/examples/common/ngComponentOutlet/ts/e2e_test/ngComponentOutlet_spec.ts index fd6110a4b5..2c31d31d40 100644 --- a/packages/examples/common/ngComponentOutlet/ts/e2e_test/ngComponentOutlet_spec.ts +++ b/packages/examples/common/ngComponentOutlet/ts/e2e_test/ngComponentOutlet_spec.ts @@ -6,8 +6,10 @@ * found in the LICENSE file at https://angular.io/license */ +import {fixmeIvy} from '@angular/private/testing'; 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; @@ -15,29 +17,34 @@ function waitForElement(selector: string) { browser.wait(EC.presenceOf($(selector)), 20000); } -describe('ngComponentOutlet', () => { - const URL = 'common/ngComponentOutlet/ts/'; - afterEach(verifyNoBrowserErrors); +fixmeIvy( + 'unknown. Run "yarn bazel run packages/examples/common:devserver --define=compile=aot" ' + + 'to debug') + .describe('ngComponentOutlet', () => { + const URL = '/ngComponentOutlet'; + afterEach(verifyNoBrowserErrors); - describe('ng-component-outlet-example', () => { - it('should render simple', () => { - browser.get(URL); - waitForElement('ng-component-outlet-simple-example'); - expect(element.all(by.css('hello-world')).getText()).toEqual(['Hello World!']); - }); + describe('ng-component-outlet-example', () => { + it('should render simple', () => { + browser.get(URL); + waitForElement('ng-component-outlet-simple-example'); + expect(element.all(by.css('hello-world')).getText()).toEqual(['Hello World!']); + }); - it('should render complete', () => { - browser.get(URL); - waitForElement('ng-component-outlet-complete-example'); - expect(element.all(by.css('complete-component')).getText()).toEqual(['Complete: AhojSvet!']); - }); + it('should render complete', () => { + browser.get(URL); + waitForElement('ng-component-outlet-complete-example'); + expect(element.all(by.css('complete-component')).getText()).toEqual([ + 'Complete: AhojSvet!' + ]); + }); - it('should render other module', () => { - browser.get(URL); - waitForElement('ng-component-outlet-other-module-example'); - expect(element.all(by.css('other-module-component')).getText()).toEqual([ - 'Other Module Component!' - ]); + it('should render other module', () => { + browser.get(URL); + waitForElement('ng-component-outlet-other-module-example'); + expect(element.all(by.css('other-module-component')).getText()).toEqual([ + 'Other Module Component!' + ]); + }); + }); }); - }); -}); diff --git a/packages/examples/common/ngComponentOutlet/ts/module.ts b/packages/examples/common/ngComponentOutlet/ts/module.ts index 1bb2f2442a..a351268186 100644 --- a/packages/examples/common/ngComponentOutlet/ts/module.ts +++ b/packages/examples/common/ngComponentOutlet/ts/module.ts @@ -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: `` }) -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: {{ greeter.suffix }}` }) -class CompleteComponent { +export class CompleteComponent { constructor(public greeter: Greeter) {} } @@ -48,7 +49,7 @@ class CompleteComponent { injector: myInjector; content: myContent">` }) -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 { ` }) -class NgTemplateOutletOtherModuleExample { +export class NgTemplateOutletOtherModuleExample { // This field is necessary to expose OtherModuleComponent to the template. OtherModuleComponent = OtherModuleComponent; myModule: NgModuleFactory; @@ -91,19 +92,7 @@ class NgTemplateOutletOtherModuleExample {
` }) -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 { +} diff --git a/packages/examples/common/ngIf/ts/e2e_test/ngIf_spec.ts b/packages/examples/common/ngIf/ts/e2e_test/ngIf_spec.ts index b0ba5c41c6..69aa158111 100644 --- a/packages/examples/common/ngIf/ts/e2e_test/ngIf_spec.ts +++ b/packages/examples/common/ngIf/ts/e2e_test/ngIf_spec.ts @@ -6,8 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ +import {fixmeIvy} from '@angular/private/testing'; 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 +17,7 @@ function waitForElement(selector: string) { } describe('ngIf', () => { - const URL = 'common/ngIf/ts/'; + const URL = '/ngIf'; afterEach(verifyNoBrowserErrors); describe('ng-if-simple', () => { @@ -44,18 +45,21 @@ describe('ngIf', () => { describe('ng-if-then-else', () => { let comp = 'ng-if-then-else'; - it('should hide/show content', () => { - browser.get(URL); - waitForElement(comp); - expect(element.all(by.css(comp)).get(0).getText()) - .toEqual('hideSwitch Primary show = true\nPrimary text to show'); - element.all(by.css(comp + ' button')).get(1).click(); - expect(element.all(by.css(comp)).get(0).getText()) - .toEqual('hideSwitch Primary show = true\nSecondary text to show'); - element.all(by.css(comp + ' button')).get(0).click(); - expect(element.all(by.css(comp)).get(0).getText()) - .toEqual('showSwitch Primary show = false\nAlternate text while primary text is hidden'); - }); + + fixmeIvy('unknown. Run "yarn bazel run packages/examples/common:devserver" to debug') + .it('should hide/show content', () => { + browser.get(URL); + waitForElement(comp); + expect(element.all(by.css(comp)).get(0).getText()) + .toEqual('hideSwitch Primary show = true\nPrimary text to show'); + element.all(by.css(comp + ' button')).get(1).click(); + expect(element.all(by.css(comp)).get(0).getText()) + .toEqual('hideSwitch Primary show = true\nSecondary text to show'); + element.all(by.css(comp + ' button')).get(0).click(); + expect(element.all(by.css(comp)).get(0).getText()) + .toEqual( + 'showSwitch Primary show = false\nAlternate text while primary text is hidden'); + }); }); describe('ng-if-let', () => { diff --git a/packages/examples/common/ngIf/ts/module.ts b/packages/examples/common/ngIf/ts/module.ts index 902ea6e528..51df5ed019 100644 --- a/packages/examples/common/ngIf/ts/module.ts +++ b/packages/examples/common/ngIf/ts/module.ts @@ -21,7 +21,7 @@ import {Subject} from 'rxjs';
Text to show
` }) -class NgIfSimple { +export class NgIfSimple { show: boolean = true; } // #enddocregion @@ -37,7 +37,7 @@ class NgIfSimple { Alternate text while primary text is hidden ` }) -class NgIfElse { +export class NgIfElse { show: boolean = true; } // #enddocregion @@ -56,7 +56,7 @@ class NgIfElse { Alternate text while primary text is hidden ` }) -class NgIfThenElse implements OnInit { +export class NgIfThenElse implements OnInit { thenBlock: TemplateRef|null = null; show: boolean = true; @@ -85,7 +85,7 @@ class NgIfThenElse implements OnInit { Waiting... (user is {{user|json}}) ` }) -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 {
` }) -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 { } diff --git a/packages/examples/common/ngTemplateOutlet/ts/e2e_test/ngTemplateOutlet_spec.ts b/packages/examples/common/ngTemplateOutlet/ts/e2e_test/ngTemplateOutlet_spec.ts index a57ea4fc9f..508a68b01e 100644 --- a/packages/examples/common/ngTemplateOutlet/ts/e2e_test/ngTemplateOutlet_spec.ts +++ b/packages/examples/common/ngTemplateOutlet/ts/e2e_test/ngTemplateOutlet_spec.ts @@ -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', () => { diff --git a/packages/examples/common/ngTemplateOutlet/ts/module.ts b/packages/examples/common/ngTemplateOutlet/ts/module.ts index dc14eb17be..22e371a38b 100644 --- a/packages/examples/common/ngTemplateOutlet/ts/module.ts +++ b/packages/examples/common/ngTemplateOutlet/ts/module.ts @@ -26,7 +26,7 @@ import {BrowserModule} from '@angular/platform-browser'; Ahoj {{person}}! ` }) -class NgTemplateOutletExample { +export class NgTemplateOutletExample { myContext = {$implicit: 'World', localSk: 'Svet'}; } // #enddocregion @@ -36,13 +36,12 @@ class NgTemplateOutletExample { selector: 'example-app', template: `` }) -class ExampleApp { +export class AppComponent { } @NgModule({ imports: [BrowserModule], - declarations: [ExampleApp, NgTemplateOutletExample], - bootstrap: [ExampleApp] + declarations: [AppComponent, NgTemplateOutletExample], }) export class AppModule { } diff --git a/packages/examples/common/pipes/ts/async_pipe.ts b/packages/examples/common/pipes/ts/async_pipe.ts index 31fa366d10..50eb38ae01 100644 --- a/packages/examples/common/pipes/ts/async_pipe.ts +++ b/packages/examples/common/pipes/ts/async_pipe.ts @@ -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; diff --git a/packages/examples/common/pipes/ts/e2e_test/pipe_spec.ts b/packages/examples/common/pipes/ts/e2e_test/pipe_spec.ts index 10551fcfb1..def858d4a6 100644 --- a/packages/examples/common/pipes/ts/e2e_test/pipe_spec.ts +++ b/packages/examples/common/pipes/ts/e2e_test/pipe_spec.ts @@ -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', () => { diff --git a/packages/examples/common/pipes/ts/module.ts b/packages/examples/common/pipes/ts/module.ts index f21d3af8b1..5600dda996 100644 --- a/packages/examples/common/pipes/ts/module.ts +++ b/packages/examples/common/pipes/ts/module.ts @@ -59,19 +59,19 @@ import {TitleCasePipeComponent} from './titlecase_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 { } diff --git a/packages/examples/common/start-server.js b/packages/examples/common/start-server.js new file mode 100644 index 0000000000..e7d432281a --- /dev/null +++ b/packages/examples/common/start-server.js @@ -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; +}; diff --git a/packages/examples/common/test_module.ts b/packages/examples/common/test_module.ts new file mode 100644 index 0000000000..03e78df027 --- /dev/null +++ b/packages/examples/common/test_module.ts @@ -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: ''}) +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 { +} diff --git a/packages/examples/compiler/BUILD.bazel b/packages/examples/compiler/BUILD.bazel new file mode 100644 index 0000000000..0ca85ef155 --- /dev/null +++ b/packages/examples/compiler/BUILD.bazel @@ -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", + ], +) diff --git a/packages/examples/compiler/ts/url_resolver/url_resolver.ts b/packages/examples/compiler/ts/url_resolver/url_resolver.ts index aac9552714..4519132045 100644 --- a/packages/examples/compiler/ts/url_resolver/url_resolver.ts +++ b/packages/examples/compiler/ts/url_resolver/url_resolver.ts @@ -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 { diff --git a/packages/examples/core/BUILD.bazel b/packages/examples/core/BUILD.bazel new file mode 100644 index 0000000000..fe74e66dbf --- /dev/null +++ b/packages/examples/core/BUILD.bazel @@ -0,0 +1,68 @@ +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: This does not compile with Ivy because the patch branch does not contain + # all ngtsc fixes. + tags = ["fixme-ivy-aot"], + # 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", + ], + tags = ["fixme-ivy-aot"], + deps = [":core_examples"], +) + +protractor_web_test_suite( + name = "protractor_tests", + data = ["//packages/bazel/src/protractor/utils"], + on_prepare = ":start-server.js", + server = ":devserver", + tags = ["fixme-ivy-aot"], + deps = [ + ":core_e2e_tests_lib", + "@ngdeps//protractor", + "@ngdeps//selenium-webdriver", + ], +) diff --git a/packages/examples/core/animation/ts/dsl/e2e_test/animation_example_spec.ts b/packages/examples/core/animation/ts/dsl/e2e_test/animation_example_spec.ts index 11ff8acfb5..550af8d2a5 100644 --- a/packages/examples/core/animation/ts/dsl/e2e_test/animation_example_spec.ts +++ b/packages/examples/core/animation/ts/dsl/e2e_test/animation_example_spec.ts @@ -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); diff --git a/packages/examples/core/animation/ts/dsl/module.ts b/packages/examples/core/animation/ts/dsl/module.ts index 6420007c73..b98014f470 100644 --- a/packages/examples/core/animation/ts/dsl/module.ts +++ b/packages/examples/core/animation/ts/dsl/module.ts @@ -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'; diff --git a/packages/examples/core/di/ts/contentChild/e2e_test/content_child_spec.ts b/packages/examples/core/di/ts/contentChild/e2e_test/content_child_spec.ts index 3d18b2e6c4..8c88393838 100644 --- a/packages/examples/core/di/ts/contentChild/e2e_test/content_child_spec.ts +++ b/packages/examples/core/di/ts/contentChild/e2e_test/content_child_spec.ts @@ -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')); }); diff --git a/packages/examples/core/di/ts/contentChild/module.ts b/packages/examples/core/di/ts/contentChild/module.ts index d64982d351..57a4d9378c 100644 --- a/packages/examples/core/di/ts/contentChild/module.ts +++ b/packages/examples/core/di/ts/contentChild/module.ts @@ -17,3 +17,5 @@ import {ContentChildComp, Pane, Tab} from './content_child_example'; }) export class AppModule { } + +export {ContentChildComp as AppComponent}; diff --git a/packages/examples/core/di/ts/contentChildren/e2e_test/content_children_spec.ts b/packages/examples/core/di/ts/contentChildren/e2e_test/content_children_spec.ts index 1f061af5fe..068e457704 100644 --- a/packages/examples/core/di/ts/contentChildren/e2e_test/content_children_spec.ts +++ b/packages/examples/core/di/ts/contentChildren/e2e_test/content_children_spec.ts @@ -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')); diff --git a/packages/examples/core/di/ts/contentChildren/module.ts b/packages/examples/core/di/ts/contentChildren/module.ts index 18e50ea60c..1182507812 100644 --- a/packages/examples/core/di/ts/contentChildren/module.ts +++ b/packages/examples/core/di/ts/contentChildren/module.ts @@ -17,3 +17,5 @@ import {ContentChildrenComp, Pane, Tab} from './content_children_example'; }) export class AppModule { } + +export {ContentChildrenComp as AppComponent}; diff --git a/packages/examples/core/di/ts/viewChild/e2e_test/view_child_spec.ts b/packages/examples/core/di/ts/viewChild/e2e_test/view_child_spec.ts index 5d58b46a5b..295cd1dbf1 100644 --- a/packages/examples/core/di/ts/viewChild/e2e_test/view_child_spec.ts +++ b/packages/examples/core/di/ts/viewChild/e2e_test/view_child_spec.ts @@ -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')); }); diff --git a/packages/examples/core/di/ts/viewChild/module.ts b/packages/examples/core/di/ts/viewChild/module.ts index 0ea1c25ec6..de45d067f3 100644 --- a/packages/examples/core/di/ts/viewChild/module.ts +++ b/packages/examples/core/di/ts/viewChild/module.ts @@ -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}; diff --git a/packages/examples/core/di/ts/viewChildren/e2e_test/view_children_spec.ts b/packages/examples/core/di/ts/viewChildren/e2e_test/view_children_spec.ts index a61d8e1ed3..701e8cc389 100644 --- a/packages/examples/core/di/ts/viewChildren/e2e_test/view_children_spec.ts +++ b/packages/examples/core/di/ts/viewChildren/e2e_test/view_children_spec.ts @@ -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')); }); diff --git a/packages/examples/core/di/ts/viewChildren/module.ts b/packages/examples/core/di/ts/viewChildren/module.ts index 1783203c2b..59c07ea88d 100644 --- a/packages/examples/core/di/ts/viewChildren/module.ts +++ b/packages/examples/core/di/ts/viewChildren/module.ts @@ -18,3 +18,5 @@ import {Pane, ViewChildrenComp} from './view_children_example'; }) export class AppModule { } + +export {ViewChildrenComp as AppComponent}; diff --git a/packages/examples/core/main.ts b/packages/examples/core/main.ts new file mode 100644 index 0000000000..b5ec0fb33e --- /dev/null +++ b/packages/examples/core/main.ts @@ -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); diff --git a/packages/examples/core/start-server.js b/packages/examples/core/start-server.js new file mode 100644 index 0000000000..e7d432281a --- /dev/null +++ b/packages/examples/core/start-server.js @@ -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; +}; diff --git a/packages/examples/core/test_module.ts b/packages/examples/core/test_module.ts new file mode 100644 index 0000000000..933ed95b81 --- /dev/null +++ b/packages/examples/core/test_module.ts @@ -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: ''}) +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 { +} diff --git a/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts b/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts index 544914552b..9ffc27a774 100644 --- a/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts +++ b/packages/examples/core/testability/ts/whenStable/e2e_test/testability_example_spec.ts @@ -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); }; diff --git a/packages/examples/core/testability/ts/whenStable/module.ts b/packages/examples/core/testability/ts/whenStable/module.ts index a8f49caec7..51fe049302 100644 --- a/packages/examples/core/testability/ts/whenStable/module.ts +++ b/packages/examples/core/testability/ts/whenStable/module.ts @@ -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'; diff --git a/packages/examples/core/testing/ts/BUILD.bazel b/packages/examples/core/testing/ts/BUILD.bazel new file mode 100644 index 0000000000..2fe7a63b68 --- /dev/null +++ b/packages/examples/core/testing/ts/BUILD.bazel @@ -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", + ], +) diff --git a/packages/examples/core/testing/ts/example_spec.ts b/packages/examples/core/testing/ts/example_spec.ts new file mode 100644 index 0000000000..880c5f975a --- /dev/null +++ b/packages/examples/core/testing/ts/example_spec.ts @@ -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'; diff --git a/packages/examples/core/ts/metadata/directives.ts b/packages/examples/core/ts/metadata/directives.ts index d1fa0b28aa..49aa0ea6b1 100644 --- a/packages/examples/core/ts/metadata/directives.ts +++ b/packages/examples/core/ts/metadata/directives.ts @@ -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 \ No newline at end of file +// #enddocregion component-output-interval + +@NgModule({ + declarations: [BankAccountComponent, MyInputComponent, IntervalDirComponent, MyOutputComponent] +}) +export class AppModule { +} diff --git a/packages/examples/core/ts/prod_mode/prod_mode_example.ts b/packages/examples/core/ts/prod_mode/prod_mode_example.ts index 4dcb7a55e2..34cc039b4e 100644 --- a/packages/examples/core/ts/prod_mode/prod_mode_example.ts +++ b/packages/examples/core/ts/prod_mode/prod_mode_example.ts @@ -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 diff --git a/packages/examples/forms/BUILD.bazel b/packages/examples/forms/BUILD.bazel new file mode 100644 index 0000000000..b0d085811b --- /dev/null +++ b/packages/examples/forms/BUILD.bazel @@ -0,0 +1,64 @@ +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: This does not compile with Ivy because the patch branch does not contain + # all ngtsc fixes. + tags = ["fixme-ivy-aot"], + # 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", + ], + tags = ["fixme-ivy-aot"], + deps = [":forms_examples"], +) + +protractor_web_test_suite( + name = "protractor_tests", + data = ["//packages/bazel/src/protractor/utils"], + on_prepare = ":start-server.js", + server = ":devserver", + tags = ["fixme-ivy-aot"], + deps = [ + ":forms_e2e_tests_lib", + "@ngdeps//protractor", + "@ngdeps//selenium-webdriver", + ], +) diff --git a/packages/examples/forms/main.ts b/packages/examples/forms/main.ts new file mode 100644 index 0000000000..b5ec0fb33e --- /dev/null +++ b/packages/examples/forms/main.ts @@ -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); diff --git a/packages/examples/forms/start-server.js b/packages/examples/forms/start-server.js new file mode 100644 index 0000000000..e7d432281a --- /dev/null +++ b/packages/examples/forms/start-server.js @@ -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; +}; diff --git a/packages/examples/forms/test_module.ts b/packages/examples/forms/test_module.ts new file mode 100644 index 0000000000..95d02990f2 --- /dev/null +++ b/packages/examples/forms/test_module.ts @@ -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: ''}) +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 { +} diff --git a/packages/examples/forms/ts/formBuilder/e2e_test/form_builder_spec.ts b/packages/examples/forms/ts/formBuilder/e2e_test/form_builder_spec.ts index 55d4a43a55..03c964d0c6 100644 --- a/packages/examples/forms/ts/formBuilder/e2e_test/form_builder_spec.ts +++ b/packages/examples/forms/ts/formBuilder/e2e_test/form_builder_spec.ts @@ -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')); }); diff --git a/packages/examples/forms/ts/formBuilder/module.ts b/packages/examples/forms/ts/formBuilder/module.ts index d34292d1d3..7e94ea650a 100644 --- a/packages/examples/forms/ts/formBuilder/module.ts +++ b/packages/examples/forms/ts/formBuilder/module.ts @@ -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}; diff --git a/packages/examples/forms/ts/nestedFormArray/e2e_test/nested_form_array_spec.ts b/packages/examples/forms/ts/nestedFormArray/e2e_test/nested_form_array_spec.ts index e594b27290..9baaac992c 100644 --- a/packages/examples/forms/ts/nestedFormArray/e2e_test/nested_form_array_spec.ts +++ b/packages/examples/forms/ts/nestedFormArray/e2e_test/nested_form_array_spec.ts @@ -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')); }); diff --git a/packages/examples/forms/ts/nestedFormArray/module.ts b/packages/examples/forms/ts/nestedFormArray/module.ts index eb2478a6e4..0d1d9b2f61 100644 --- a/packages/examples/forms/ts/nestedFormArray/module.ts +++ b/packages/examples/forms/ts/nestedFormArray/module.ts @@ -18,3 +18,5 @@ import {NestedFormArray} from './nested_form_array_example'; }) export class AppModule { } + +export {NestedFormArray as AppComponent}; diff --git a/packages/examples/forms/ts/nestedFormGroup/e2e_test/nested_form_group_spec.ts b/packages/examples/forms/ts/nestedFormGroup/e2e_test/nested_form_group_spec.ts index 6de78dfe09..a3fb76047c 100644 --- a/packages/examples/forms/ts/nestedFormGroup/e2e_test/nested_form_group_spec.ts +++ b/packages/examples/forms/ts/nestedFormGroup/e2e_test/nested_form_group_spec.ts @@ -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"])')); diff --git a/packages/examples/forms/ts/nestedFormGroup/module.ts b/packages/examples/forms/ts/nestedFormGroup/module.ts index 5773d5281f..0d5503f1ae 100644 --- a/packages/examples/forms/ts/nestedFormGroup/module.ts +++ b/packages/examples/forms/ts/nestedFormGroup/module.ts @@ -18,3 +18,5 @@ import {NestedFormGroupComp} from './nested_form_group_example'; }) export class AppModule { } + +export {NestedFormGroupComp as AppComponent}; diff --git a/packages/examples/forms/ts/ngModelGroup/e2e_test/ng_model_group_spec.ts b/packages/examples/forms/ts/ngModelGroup/e2e_test/ng_model_group_spec.ts index 176a4eb8ae..6d700e69ee 100644 --- a/packages/examples/forms/ts/ngModelGroup/e2e_test/ng_model_group_spec.ts +++ b/packages/examples/forms/ts/ngModelGroup/e2e_test/ng_model_group_spec.ts @@ -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')); }); diff --git a/packages/examples/forms/ts/ngModelGroup/module.ts b/packages/examples/forms/ts/ngModelGroup/module.ts index ce06883c67..692f6edb46 100644 --- a/packages/examples/forms/ts/ngModelGroup/module.ts +++ b/packages/examples/forms/ts/ngModelGroup/module.ts @@ -18,3 +18,5 @@ import {NgModelGroupComp} from './ng_model_group_example'; }) export class AppModule { } + +export {NgModelGroupComp as AppComponent}; diff --git a/packages/examples/forms/ts/radioButtons/e2e_test/radio_button_spec.ts b/packages/examples/forms/ts/radioButtons/e2e_test/radio_button_spec.ts index 04b0ddd715..56f668ec14 100644 --- a/packages/examples/forms/ts/radioButtons/e2e_test/radio_button_spec.ts +++ b/packages/examples/forms/ts/radioButtons/e2e_test/radio_button_spec.ts @@ -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')); }); diff --git a/packages/examples/forms/ts/radioButtons/module.ts b/packages/examples/forms/ts/radioButtons/module.ts index 6a8151e88e..4a146db88f 100644 --- a/packages/examples/forms/ts/radioButtons/module.ts +++ b/packages/examples/forms/ts/radioButtons/module.ts @@ -18,3 +18,5 @@ import {RadioButtonComp} from './radio_button_example'; }) export class AppModule { } + +export {RadioButtonComp as AppComponent}; diff --git a/packages/examples/forms/ts/reactiveRadioButtons/e2e_test/reactive_radio_button_spec.ts b/packages/examples/forms/ts/reactiveRadioButtons/e2e_test/reactive_radio_button_spec.ts index d4286d5199..4b23a8ffd5 100644 --- a/packages/examples/forms/ts/reactiveRadioButtons/e2e_test/reactive_radio_button_spec.ts +++ b/packages/examples/forms/ts/reactiveRadioButtons/e2e_test/reactive_radio_button_spec.ts @@ -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')); }); diff --git a/packages/examples/forms/ts/reactiveRadioButtons/module.ts b/packages/examples/forms/ts/reactiveRadioButtons/module.ts index 17f67b430b..acf2040f9e 100644 --- a/packages/examples/forms/ts/reactiveRadioButtons/module.ts +++ b/packages/examples/forms/ts/reactiveRadioButtons/module.ts @@ -18,3 +18,5 @@ import {ReactiveRadioButtonComp} from './reactive_radio_button_example'; }) export class AppModule { } + +export {ReactiveRadioButtonComp as AppComponent}; diff --git a/packages/examples/forms/ts/reactiveSelectControl/e2e_test/reactive_select_control_spec.ts b/packages/examples/forms/ts/reactiveSelectControl/e2e_test/reactive_select_control_spec.ts index 5d2b338804..1da4d5eff0 100644 --- a/packages/examples/forms/ts/reactiveSelectControl/e2e_test/reactive_select_control_spec.ts +++ b/packages/examples/forms/ts/reactiveSelectControl/e2e_test/reactive_select_control_spec.ts @@ -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')); diff --git a/packages/examples/forms/ts/reactiveSelectControl/module.ts b/packages/examples/forms/ts/reactiveSelectControl/module.ts index 47c53b3fe7..eace263e9b 100644 --- a/packages/examples/forms/ts/reactiveSelectControl/module.ts +++ b/packages/examples/forms/ts/reactiveSelectControl/module.ts @@ -18,3 +18,5 @@ import {ReactiveSelectComp} from './reactive_select_control_example'; }) export class AppModule { } + +export {ReactiveSelectComp as AppComponent}; diff --git a/packages/examples/forms/ts/selectControl/e2e_test/select_control_spec.ts b/packages/examples/forms/ts/selectControl/e2e_test/select_control_spec.ts index f79efa27bb..2fbbc22fd3 100644 --- a/packages/examples/forms/ts/selectControl/e2e_test/select_control_spec.ts +++ b/packages/examples/forms/ts/selectControl/e2e_test/select_control_spec.ts @@ -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')); diff --git a/packages/examples/forms/ts/selectControl/module.ts b/packages/examples/forms/ts/selectControl/module.ts index f2adc86335..722f3baf43 100644 --- a/packages/examples/forms/ts/selectControl/module.ts +++ b/packages/examples/forms/ts/selectControl/module.ts @@ -18,3 +18,5 @@ import {SelectControlComp} from './select_control_example'; }) export class AppModule { } + +export {SelectControlComp as AppComponent}; diff --git a/packages/examples/forms/ts/simpleForm/e2e_test/simple_form_spec.ts b/packages/examples/forms/ts/simpleForm/e2e_test/simple_form_spec.ts index 6f176ca56a..0588a5882d 100644 --- a/packages/examples/forms/ts/simpleForm/e2e_test/simple_form_spec.ts +++ b/packages/examples/forms/ts/simpleForm/e2e_test/simple_form_spec.ts @@ -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')); }); diff --git a/packages/examples/forms/ts/simpleForm/module.ts b/packages/examples/forms/ts/simpleForm/module.ts index 12037114e4..5b004e6ffe 100644 --- a/packages/examples/forms/ts/simpleForm/module.ts +++ b/packages/examples/forms/ts/simpleForm/module.ts @@ -18,3 +18,5 @@ import {SimpleFormComp} from './simple_form_example'; }) export class AppModule { } + +export {SimpleFormComp as AppComponent}; diff --git a/packages/examples/forms/ts/simpleFormControl/e2e_test/simple_form_control_spec.ts b/packages/examples/forms/ts/simpleFormControl/e2e_test/simple_form_control_spec.ts index 5436952a63..810064705c 100644 --- a/packages/examples/forms/ts/simpleFormControl/e2e_test/simple_form_control_spec.ts +++ b/packages/examples/forms/ts/simpleFormControl/e2e_test/simple_form_control_spec.ts @@ -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')); diff --git a/packages/examples/forms/ts/simpleFormControl/module.ts b/packages/examples/forms/ts/simpleFormControl/module.ts index a16a1f4369..860756856e 100644 --- a/packages/examples/forms/ts/simpleFormControl/module.ts +++ b/packages/examples/forms/ts/simpleFormControl/module.ts @@ -18,3 +18,5 @@ import {SimpleFormControl} from './simple_form_control_example'; }) export class AppModule { } + +export {SimpleFormControl as AppComponent}; diff --git a/packages/examples/forms/ts/simpleFormGroup/e2e_test/simple_form_group_spec.ts b/packages/examples/forms/ts/simpleFormGroup/e2e_test/simple_form_group_spec.ts index 5e2b3c8fdf..76fdf8e7c6 100644 --- a/packages/examples/forms/ts/simpleFormGroup/e2e_test/simple_form_group_spec.ts +++ b/packages/examples/forms/ts/simpleFormGroup/e2e_test/simple_form_group_spec.ts @@ -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"]')); }); diff --git a/packages/examples/forms/ts/simpleFormGroup/module.ts b/packages/examples/forms/ts/simpleFormGroup/module.ts index cbafcdd503..e5749d0d56 100644 --- a/packages/examples/forms/ts/simpleFormGroup/module.ts +++ b/packages/examples/forms/ts/simpleFormGroup/module.ts @@ -18,3 +18,5 @@ import {SimpleFormGroup} from './simple_form_group_example'; }) export class AppModule { } + +export {SimpleFormGroup as AppComponent}; diff --git a/packages/examples/forms/ts/simpleNgModel/e2e_test/simple_ng_model_spec.ts b/packages/examples/forms/ts/simpleNgModel/e2e_test/simple_ng_model_spec.ts index a54faabaa2..e6c8a8ce05 100644 --- a/packages/examples/forms/ts/simpleNgModel/e2e_test/simple_ng_model_spec.ts +++ b/packages/examples/forms/ts/simpleNgModel/e2e_test/simple_ng_model_spec.ts @@ -6,40 +6,45 @@ * found in the LICENSE file at https://angular.io/license */ +import {fixmeIvy} from '@angular/private/testing'; import {ElementArrayFinder, ElementFinder, browser, by, element} from 'protractor'; -import {verifyNoBrowserErrors} from '../../../../_common/e2e_util'; -describe('simpleNgModel example', () => { - afterEach(verifyNoBrowserErrors); - let input: ElementFinder; - let paragraphs: ElementArrayFinder; - let button: ElementFinder; +import {verifyNoBrowserErrors} from '../../../../test-utils'; - beforeEach(() => { - browser.get('/forms/ts/simpleNgModel/index.html'); - input = element(by.css('input')); - paragraphs = element.all(by.css('p')); - button = element(by.css('button')); - }); +fixmeIvy( + 'unkown; verifyNoBrowserErrors fails due to "ExpressionChangedAfterItHasBeenCheckedError"' + + 'Debug by running "yarn bazel run //packages/examples/forms:devserver --define=compile=aot') + .describe('simpleNgModel example', () => { + afterEach(verifyNoBrowserErrors); + let input: ElementFinder; + let paragraphs: ElementArrayFinder; + let button: ElementFinder; - it('should update the domain model as you type', () => { - input.click(); - input.sendKeys('Carson'); + beforeEach(() => { + browser.get('/simpleNgModel'); + input = element(by.css('input')); + paragraphs = element.all(by.css('p')); + button = element(by.css('button')); + }); - expect(paragraphs.get(0).getText()).toEqual('Value: Carson'); - }); + it('should update the domain model as you type', () => { + input.click(); + input.sendKeys('Carson'); - it('should report the validity correctly', () => { - expect(paragraphs.get(1).getText()).toEqual('Valid: false'); - input.click(); - input.sendKeys('a'); + expect(paragraphs.get(0).getText()).toEqual('Value: Carson'); + }); - expect(paragraphs.get(1).getText()).toEqual('Valid: true'); - }); + it('should report the validity correctly', () => { + expect(paragraphs.get(1).getText()).toEqual('Valid: false'); + input.click(); + input.sendKeys('a'); - it('should set the value by changing the domain model', () => { - button.click(); - expect(input.getAttribute('value')).toEqual('Nancy'); - }); + expect(paragraphs.get(1).getText()).toEqual('Valid: true'); + }); -}); + it('should set the value by changing the domain model', () => { + button.click(); + expect(input.getAttribute('value')).toEqual('Nancy'); + }); + + }); diff --git a/packages/examples/forms/ts/simpleNgModel/module.ts b/packages/examples/forms/ts/simpleNgModel/module.ts index 9f0872c544..86e1e7d726 100644 --- a/packages/examples/forms/ts/simpleNgModel/module.ts +++ b/packages/examples/forms/ts/simpleNgModel/module.ts @@ -18,3 +18,5 @@ import {SimpleNgModelComp} from './simple_ng_model_example'; }) export class AppModule { } + +export {SimpleNgModelComp as AppComponent}; diff --git a/packages/examples/http/BUILD.bazel b/packages/examples/http/BUILD.bazel new file mode 100644 index 0000000000..ffd0fb0cdc --- /dev/null +++ b/packages/examples/http/BUILD.bazel @@ -0,0 +1 @@ +package(default_visibility = ["//visibility:public"]) diff --git a/packages/examples/index.html b/packages/examples/index.html new file mode 100644 index 0000000000..7f405e44b9 --- /dev/null +++ b/packages/examples/index.html @@ -0,0 +1,15 @@ + + + + + Angular Examples + + + + + + + Loading... + + diff --git a/packages/examples/platform-browser/BUILD.bazel b/packages/examples/platform-browser/BUILD.bazel new file mode 100644 index 0000000000..5655dc870b --- /dev/null +++ b/packages/examples/platform-browser/BUILD.bazel @@ -0,0 +1,17 @@ +package(default_visibility = ["//visibility:public"]) + +load("//tools:defaults.bzl", "ng_module") + +ng_module( + name = "platform_browser_examples", + srcs = glob(["**/*.ts"]), + # TODO: This does not compile with Ivy because the patch branch does not contain + # all ngtsc fixes. + tags = ["fixme-ivy-aot"], + deps = [ + "//packages/compiler", + "//packages/core", + "//packages/platform-browser", + "//packages/platform-browser-dynamic", + ], +) diff --git a/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts b/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts index 0e47ad0b6f..1e4c53dea6 100644 --- a/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts +++ b/packages/examples/platform-browser/dom/debug/ts/debug_element_view_listener/providers.ts @@ -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 { } diff --git a/packages/examples/test-utils/BUILD.bazel b/packages/examples/test-utils/BUILD.bazel new file mode 100644 index 0000000000..be2496ecae --- /dev/null +++ b/packages/examples/test-utils/BUILD.bazel @@ -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", + ], +) diff --git a/packages/examples/test-utils/index.ts b/packages/examples/test-utils/index.ts new file mode 100644 index 0000000000..4bf0dd2b5d --- /dev/null +++ b/packages/examples/test-utils/index.ts @@ -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([]); +} diff --git a/packages/examples/test.sh b/packages/examples/test.sh deleted file mode 100755 index c8827305a8..0000000000 --- a/packages/examples/test.sh +++ /dev/null @@ -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 - ) -) diff --git a/packages/examples/testing/BUILD.bazel b/packages/examples/testing/BUILD.bazel new file mode 100644 index 0000000000..c8c586c77d --- /dev/null +++ b/packages/examples/testing/BUILD.bazel @@ -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", + ], +) diff --git a/packages/examples/tsconfig-build.json b/packages/examples/tsconfig-build.json deleted file mode 100644 index b2ca2c29c3..0000000000 --- a/packages/examples/tsconfig-build.json +++ /dev/null @@ -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" - ] -} diff --git a/packages/examples/tsconfig-e2e.json b/packages/examples/tsconfig-e2e.json new file mode 100644 index 0000000000..ed38112bb4 --- /dev/null +++ b/packages/examples/tsconfig-e2e.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "lib": ["es2015"], + "types": ["node", "jasminewd2"] + } +} diff --git a/packages/examples/tsconfig.json b/packages/examples/tsconfig.json deleted file mode 100644 index c13db98f55..0000000000 --- a/packages/examples/tsconfig.json +++ /dev/null @@ -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": [] -} diff --git a/packages/examples/upgrade/BUILD.bazel b/packages/examples/upgrade/BUILD.bazel new file mode 100644 index 0000000000..ae7cd15682 --- /dev/null +++ b/packages/examples/upgrade/BUILD.bazel @@ -0,0 +1,4 @@ +exports_files([ + "tsconfig-build.json", + "start-server.js", +]) diff --git a/packages/examples/upgrade/start-server.js b/packages/examples/upgrade/start-server.js new file mode 100644 index 0000000000..e7d432281a --- /dev/null +++ b/packages/examples/upgrade/start-server.js @@ -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; +}; diff --git a/packages/examples/upgrade/static/ts/full/BUILD.bazel b/packages/examples/upgrade/static/ts/full/BUILD.bazel new file mode 100644 index 0000000000..0e1d6defb8 --- /dev/null +++ b/packages/examples/upgrade/static/ts/full/BUILD.bazel @@ -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", +) diff --git a/packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts b/packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts index d941609740..3e295290e1 100644 --- a/packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts +++ b/packages/examples/upgrade/static/ts/full/e2e_test/static_full_spec.ts @@ -6,48 +6,52 @@ * found in the LICENSE file at https://angular.io/license */ +import {fixmeIvy} from '@angular/private/testing'; 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)', () => { - beforeEach(loadPage); - afterEach(verifyNoBrowserErrors); +fixmeIvy('Disabled because the patch branch does not contain all Ivy fixes.') + .describe('upgrade/static (full)', () => { + beforeEach(loadPage); + afterEach(verifyNoBrowserErrors); - it('should render the `ng2-heroes` component', () => { - expect(element(by.css('h1')).getText()).toEqual('Heroes'); - expect(element.all(by.css('p')).get(0).getText()).toEqual('There are 3 heroes.'); - }); + it('should render the `ng2-heroes` component', () => { + expect(element(by.css('h1')).getText()).toEqual('Heroes'); + expect(element.all(by.css('p')).get(0).getText()).toEqual('There are 3 heroes.'); + }); - it('should render 3 ng1-hero components', () => { - const heroComponents = element.all(by.css('ng1-hero')); - expect(heroComponents.count()).toEqual(3); - }); + it('should render 3 ng1-hero components', () => { + const heroComponents = element.all(by.css('ng1-hero')); + expect(heroComponents.count()).toEqual(3); + }); - it('should add a new hero when the "Add Hero" button is pressed', () => { - const addHeroButton = element.all(by.css('button')).last(); - expect(addHeroButton.getText()).toEqual('Add Hero'); - addHeroButton.click(); - const heroComponents = element.all(by.css('ng1-hero')); - expect(heroComponents.last().element(by.css('h2')).getText()).toEqual('Kamala Khan'); - }); + fixmeIvy('unknown; component does not seem to render name & description') + .it('should add a new hero when the "Add Hero" button is pressed', () => { + const addHeroButton = element.all(by.css('button')).last(); + expect(addHeroButton.getText()).toEqual('Add Hero'); + addHeroButton.click(); + const heroComponents = element.all(by.css('ng1-hero')); + expect(heroComponents.last().element(by.css('h2')).getText()).toEqual('Kamala Khan'); + }); - it('should remove a hero when the "Remove" button is pressed', () => { - let firstHero = element.all(by.css('ng1-hero')).get(0); - expect(firstHero.element(by.css('h2')).getText()).toEqual('Superman'); + fixmeIvy('unknown; component does not seem to render name & description') + .it('should remove a hero when the "Remove" button is pressed', () => { + let firstHero = element.all(by.css('ng1-hero')).get(0); + expect(firstHero.element(by.css('h2')).getText()).toEqual('Superman'); - const removeHeroButton = firstHero.element(by.css('button')); - expect(removeHeroButton.getText()).toEqual('Remove'); - removeHeroButton.click(); + const removeHeroButton = firstHero.element(by.css('button')); + expect(removeHeroButton.getText()).toEqual('Remove'); + removeHeroButton.click(); - const heroComponents = element.all(by.css('ng1-hero')); - expect(heroComponents.count()).toEqual(2); + const heroComponents = element.all(by.css('ng1-hero')); + expect(heroComponents.count()).toEqual(2); - firstHero = element.all(by.css('ng1-hero')).get(0); - expect(firstHero.element(by.css('h2')).getText()).toEqual('Wonder Woman'); - }); -}); + firstHero = element.all(by.css('ng1-hero')).get(0); + expect(firstHero.element(by.css('h2')).getText()).toEqual('Wonder Woman'); + }); + }); diff --git a/packages/examples/upgrade/static/ts/lite-multi-shared/BUILD.bazel b/packages/examples/upgrade/static/ts/lite-multi-shared/BUILD.bazel new file mode 100644 index 0000000000..63f5064b7c --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite-multi-shared/BUILD.bazel @@ -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", +) diff --git a/packages/examples/upgrade/static/ts/lite-multi-shared/e2e_test/static_lite_multi_shared_spec.ts b/packages/examples/upgrade/static/ts/lite-multi-shared/e2e_test/static_lite_multi_shared_spec.ts index 8ddefcfae6..9a7c6e45d2 100644 --- a/packages/examples/upgrade/static/ts/lite-multi-shared/e2e_test/static_lite_multi_shared_spec.ts +++ b/packages/examples/upgrade/static/ts/lite-multi-shared/e2e_test/static_lite_multi_shared_spec.ts @@ -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', () => { diff --git a/packages/examples/upgrade/static/ts/lite-multi/BUILD.bazel b/packages/examples/upgrade/static/ts/lite-multi/BUILD.bazel new file mode 100644 index 0000000000..b1e71833a5 --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite-multi/BUILD.bazel @@ -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", +) diff --git a/packages/examples/upgrade/static/ts/lite-multi/e2e_test/static_lite_multi_spec.ts b/packages/examples/upgrade/static/ts/lite-multi/e2e_test/static_lite_multi_spec.ts index 3a4d571243..2b9c846b74 100644 --- a/packages/examples/upgrade/static/ts/lite-multi/e2e_test/static_lite_multi_spec.ts +++ b/packages/examples/upgrade/static/ts/lite-multi/e2e_test/static_lite_multi_spec.ts @@ -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', () => { diff --git a/packages/examples/upgrade/static/ts/lite/BUILD.bazel b/packages/examples/upgrade/static/ts/lite/BUILD.bazel new file mode 100644 index 0000000000..910574f326 --- /dev/null +++ b/packages/examples/upgrade/static/ts/lite/BUILD.bazel @@ -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", +) diff --git a/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts b/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts index 5e7b6395ef..42bc5cc332 100644 --- a/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts +++ b/packages/examples/upgrade/static/ts/lite/e2e_test/static_lite_spec.ts @@ -6,14 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ +import {fixmeIvy} from '@angular/private/testing'; 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)', () => { @@ -58,32 +59,35 @@ describe('upgrade/static (lite)', () => { it('should initially not render the heroes', () => expectHeroes(false)); - it('should toggle the heroes when clicking the "show/hide" button', () => { - showHideBtn.click(); - expectHeroes(true); + fixmeIvy('unknown; component does not seem to render name & description') + .it('should toggle the heroes when clicking the "show/hide" button', () => { + showHideBtn.click(); + expectHeroes(true); - showHideBtn.click(); - expectHeroes(false); - }); + showHideBtn.click(); + expectHeroes(false); + }); - it('should add a new hero when clicking the "add" button', () => { - showHideBtn.click(); - ng2HeroesAddBtn.click(); + fixmeIvy('unknown; component does not seem to render name & description') + .it('should add a new hero when clicking the "add" button', () => { + showHideBtn.click(); + ng2HeroesAddBtn.click(); - expectHeroes(true, 4, 'Added hero Kamala Khan'); - expect(ng1Heroes.last()).toHaveName('Kamala Khan'); - }); + expectHeroes(true, 4, 'Added hero Kamala Khan'); + expect(ng1Heroes.last()).toHaveName('Kamala Khan'); + }); - it('should remove a hero when clicking its "remove" button', () => { - showHideBtn.click(); + fixmeIvy('unknown; component does not seem to render name & description') + .it('should remove a hero when clicking its "remove" button', () => { + showHideBtn.click(); - const firstHero = ng1Heroes.first(); - expect(firstHero).toHaveName('Superman'); + const firstHero = ng1Heroes.first(); + expect(firstHero).toHaveName('Superman'); - const removeBtn = firstHero.element(by.buttonText('Remove')); - removeBtn.click(); + const removeBtn = firstHero.element(by.buttonText('Remove')); + removeBtn.click(); - expectHeroes(true, 2, 'Removed hero Superman'); - expect(ng1Heroes.first()).not.toHaveName('Superman'); - }); + expectHeroes(true, 2, 'Removed hero Superman'); + expect(ng1Heroes.first()).not.toHaveName('Superman'); + }); }); diff --git a/packages/examples/upgrade/tsconfig-build.json b/packages/examples/upgrade/tsconfig-build.json new file mode 100644 index 0000000000..70ccf09202 --- /dev/null +++ b/packages/examples/upgrade/tsconfig-build.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "lib": ["dom", "es2015"], + "types": ["angular"] + } +} diff --git a/packages/examples/upgrade/upgrade_example.bzl b/packages/examples/upgrade/upgrade_example.bzl new file mode 100644 index 0000000000..3934e0cad8 --- /dev/null +++ b/packages/examples/upgrade/upgrade_example.bzl @@ -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", + ], + ) diff --git a/packages/tsconfig.json b/packages/tsconfig.json index 9b8d04667c..720c55d6c9 100644 --- a/packages/tsconfig.json +++ b/packages/tsconfig.json @@ -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", ] diff --git a/protractor-examples-e2e.conf.js b/protractor-examples-e2e.conf.js deleted file mode 100644 index ba143bb6a9..0000000000 --- a/protractor-examples-e2e.conf.js +++ /dev/null @@ -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 -}; diff --git a/tools/gulp-tasks/serve.js b/tools/gulp-tasks/serve.js index 0c0dda239a..d3f476cbd2 100644 --- a/tools/gulp-tasks/serve.js +++ b/tools/gulp-tasks/serve.js @@ -23,19 +23,4 @@ module.exports = { }); }, - // Serve the examples - examples: (gulp) => () => { - const connect = require('gulp-connect'); - const cors = require('cors'); - const path = require('path'); - - connect.server({ - root: path.resolve(__dirname, '../../dist/examples'), - port: 8001, - livereload: false, - open: false, - middleware: (connect, opt) => [cors()], - }); - } - }; diff --git a/yarn.lock b/yarn.lock index 0d177c7347..e296619b6c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -343,15 +343,20 @@ resolved "https://registry.yarnpkg.com/@types/hammerjs/-/hammerjs-2.0.35.tgz#7b7c950c7d54593e23bffc8d2b4feba9866a7277" integrity sha512-4mUIMSZ2U4UOWq1b+iV7XUTE4w+Kr3x+Zb/Qz5ROO6BTZLw2c8/ftjq0aRgluguLs4KRuBnrOy/s389HVn1/zA== -"@types/jasmine@*", "@types/jasmine@^2.8.8": +"@types/jasmine@*": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-3.3.5.tgz#3738ffbf34dffae9ecaac4503d7d969744f0e1d7" + integrity sha512-LJtc52O1PNUffMvH6Q3fS0BOhQWYlkh3SVu/Jc4GoPgJkUytk5Y6YPbw+6lZK2mWWvG62BtVyOFw0ih7r8STsw== + +"@types/jasmine@^2.8.8": version "2.8.8" resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.8.8.tgz#bf53a7d193ea8b03867a38bfdb4fbb0e0bf066c9" integrity sha512-OJSUxLaxXsjjhob2DBzqzgrkLmukM3+JMpRp0r0E4HTdT1nwDCWhaswjYxazPij6uOdzHCJfNbDjmQ1/rnNbCg== "@types/jasminewd2@^2.0.4": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.4.tgz#12422ee719f372d30c3cc7d99cc72dadba6ace01" - integrity sha512-G83fHoholqR7pmsY7ojHJqMAl4zD6ylKNaKCx7zH+GisCBQpnI5a7aUTFWVzv2wppIuWd+mJxyRqTASPfqcQ2w== + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/jasminewd2/-/jasminewd2-2.0.6.tgz#2f57a8d9875a6c9ef328a14bd070ba14a055ac39" + integrity sha512-2ZOKrxb8bKRmP/po5ObYnRDgFE4i+lQiEB27bAMmtMWLgJSqlIDqlLx6S0IRorpOmOPRQ6O80NujTmQAtBkeNw== dependencies: "@types/jasmine" "*"