From 2b6b9c95f9a67a5f830fd0430e63eec5aaa24ba1 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Fri, 25 Sep 2020 16:31:31 +0300 Subject: [PATCH] fix(docs-infra): fix the `component-interaction` example e2e tests to run in prod mode (#39001) Previously, the `component-interaction` docs example was configured to run e2e tests on CI in development mode (in contrast to the default for all docs examples, which is to run e2e tests in production mode). This was necessary due to the following reasons: - One of the components, `CountdownTimerComponent`, which is used by `CountdownLocalVarParentComponent` and `CountdownViewChildParentComponent`, was triggering a periodic asynchronous task (via `setInterval()`), which prevented the app from stabilizing and caused tests to fail. - In order to prevent this from happening, the example's `AppModule` had special provisioning to not include the problematic components in its declarations when testing. - Since this had to be determined dynamically at runtime (via inspecting the URL query params), the `AppModule`'s config could not be statically evaluated in AOT compilation. This commit fixes the example to make it compatible with AOT compilation and removes the custom test command from its `example-config.json` (allowing it to be run with the default e2e test command, i.e. in production mode). PR Close #39001 --- .../e2e/src/app.e2e-spec.ts | 20 +++++------ .../component-interaction/example-config.json | 13 -------- .../src/app/app.component.html | 7 ++-- .../src/app/app.module.ts | 33 ++++++------------- .../src/app/countdown-timer.component.ts | 9 +++-- 5 files changed, 27 insertions(+), 55 deletions(-) diff --git a/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts b/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts index 903691f898..692d67c27c 100644 --- a/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/component-interaction/e2e/src/app.e2e-spec.ts @@ -2,11 +2,7 @@ import { browser, element, by } from 'protractor'; describe('Component Communication Cookbook Tests', () => { - // Note: '?e2e' which app can read to know it is running in protractor - // e.g. `if (!/e2e/.test(location.search)) { ...` - beforeAll(() => { - browser.get('?e2e'); - }); + beforeAll(() => browser.get(browser.baseUrl)); describe('Parent-to-child communication', () => { // #docregion parent-to-child @@ -156,11 +152,11 @@ describe('Component Communication Cookbook Tests', () => { // Can't run timer tests in protractor because // interaction w/ zones causes all tests to freeze & timeout. xdescribe('Parent calls child via local var', () => { - countDownTimerTests('countdown-parent-lv'); + countDownTimerTests('app-countdown-parent-lv'); }); xdescribe('Parent calls ViewChild', () => { - countDownTimerTests('countdown-parent-vc'); + countDownTimerTests('app-countdown-parent-vc'); }); function countDownTimerTests(parentTag: string) { @@ -168,10 +164,14 @@ describe('Component Communication Cookbook Tests', () => { // ... it('timer and parent seconds should match', () => { const parent = element(by.tagName(parentTag)); + const startButton = parent.element(by.tagName('button')).get(0); const message = parent.element(by.tagName('app-countdown-timer')).getText(); - browser.sleep(10); // give `seconds` a chance to catchup with `message` - const seconds = parent.element(by.className('seconds')).getText(); - expect(message).toContain(seconds); + + startButton.click().then(() => { + browser.sleep(10); // give `seconds` a chance to catchup with `message` + const seconds = parent.element(by.className('seconds')).getText(); + expect(message).toContain(seconds); + }); }); it('should stop the countdown', () => { diff --git a/aio/content/examples/component-interaction/example-config.json b/aio/content/examples/component-interaction/example-config.json index 05e262817d..e69de29bb2 100644 --- a/aio/content/examples/component-interaction/example-config.json +++ b/aio/content/examples/component-interaction/example-config.json @@ -1,13 +0,0 @@ -{ - "tests": [ - { - "cmd": "yarn", - "args": [ - "e2e", - "--protractor-config=e2e/protractor-puppeteer.conf.js", - "--no-webdriver-update", - "--port={PORT}" - ] - } - ] -} diff --git a/aio/content/examples/component-interaction/src/app/app.component.html b/aio/content/examples/component-interaction/src/app/app.component.html index 907e0181fa..88d05abdb1 100644 --- a/aio/content/examples/component-interaction/src/app/app.component.html +++ b/aio/content/examples/component-interaction/src/app/app.component.html @@ -30,22 +30,21 @@ Back to Top -
+
Back to Top -
+
Back to Top -
+
Back to Top -
diff --git a/aio/content/examples/component-interaction/src/app/app.module.ts b/aio/content/examples/component-interaction/src/app/app.module.ts index d1b4570665..caecee59e5 100644 --- a/aio/content/examples/component-interaction/src/app/app.module.ts +++ b/aio/content/examples/component-interaction/src/app/app.module.ts @@ -1,4 +1,4 @@ -import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; @@ -15,10 +15,17 @@ import { VersionParentComponent } from './version-parent.component'; import { VoterComponent } from './voter.component'; import { VoteTakerComponent } from './votetaker.component'; -const directives: any[] = [ + +@NgModule({ + imports: [ + BrowserModule, + ], + declarations: [ AppComponent, AstronautComponent, + CountdownLocalVarParentComponent, CountdownTimerComponent, + CountdownViewChildParentComponent, HeroChildComponent, HeroParentComponent, MissionControlComponent, @@ -27,28 +34,8 @@ const directives: any[] = [ VersionChildComponent, VersionParentComponent, VoterComponent, - VoteTakerComponent - ]; - -const schemas: any[] = []; - -// Include Countdown examples -// unless in e2e tests which they break. -if (!/e2e/.test(location.search)) { - console.log('adding countdown timer examples'); - directives.push(CountdownLocalVarParentComponent); - directives.push(CountdownViewChildParentComponent); -} else { - // In e2e test use CUSTOM_ELEMENTS_SCHEMA to suppress unknown element errors - schemas.push(CUSTOM_ELEMENTS_SCHEMA); -} - -@NgModule({ - imports: [ - BrowserModule + VoteTakerComponent, ], - declarations: directives, bootstrap: [ AppComponent ], - schemas }) export class AppModule { } diff --git a/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts b/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts index dcc88334d0..cba4de07ac 100644 --- a/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts +++ b/aio/content/examples/component-interaction/src/app/countdown-timer.component.ts @@ -1,19 +1,16 @@ // #docregion -import { Component, OnDestroy, OnInit } from '@angular/core'; +import { Component, OnDestroy } from '@angular/core'; @Component({ selector: 'app-countdown-timer', template: '

{{message}}

' }) -export class CountdownTimerComponent implements OnInit, OnDestroy { +export class CountdownTimerComponent implements OnDestroy { intervalId = 0; message = ''; seconds = 11; - clearTimer() { clearInterval(this.intervalId); } - - ngOnInit() { this.start(); } ngOnDestroy() { this.clearTimer(); } start() { this.countDown(); } @@ -22,6 +19,8 @@ export class CountdownTimerComponent implements OnInit, OnDestroy { this.message = `Holding at T-${this.seconds} seconds`; } + private clearTimer() { clearInterval(this.intervalId); } + private countDown() { this.clearTimer(); this.intervalId = window.setInterval(() => {