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
This commit is contained in:
parent
c5e178997c
commit
2b6b9c95f9
|
@ -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', () => {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
{
|
||||
"tests": [
|
||||
{
|
||||
"cmd": "yarn",
|
||||
"args": [
|
||||
"e2e",
|
||||
"--protractor-config=e2e/protractor-puppeteer.conf.js",
|
||||
"--no-webdriver-update",
|
||||
"--port={PORT}"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -30,22 +30,21 @@
|
|||
<app-vote-taker></app-vote-taker>
|
||||
</div>
|
||||
<a href="#top" class="to-top">Back to Top</a>
|
||||
<hr>
|
||||
|
||||
<hr>
|
||||
<div id="parent-to-child-local-var">
|
||||
<app-countdown-parent-lv></app-countdown-parent-lv>
|
||||
</div>
|
||||
<a href="#top" class="to-top">Back to Top</a>
|
||||
<hr>
|
||||
|
||||
<hr>
|
||||
<div id="parent-to-view-child">
|
||||
<app-countdown-parent-vc></app-countdown-parent-vc>
|
||||
</div>
|
||||
<a href="#top" class="to-top">Back to Top</a>
|
||||
<hr>
|
||||
|
||||
<hr>
|
||||
<div id="bidirectional-service">
|
||||
<app-mission-control></app-mission-control>
|
||||
</div>
|
||||
<a href="#top" class="to-top">Back to Top</a>
|
||||
<hr>
|
||||
|
|
|
@ -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 { }
|
||||
|
|
|
@ -1,19 +1,16 @@
|
|||
// #docregion
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-countdown-timer',
|
||||
template: '<p>{{message}}</p>'
|
||||
})
|
||||
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(() => {
|
||||
|
|
Loading…
Reference in New Issue