test(docs-infra): fix unit tests and run them for specific docs examples on CI (#36143)

Previously, only e2e tests were run for docs examples on CI. As a
result, unit tests (which are included in the zipped archives we provide
for users to download and play with the examples locally) were often
outdated and broken.

This commit configures specific docs examples that have meaningful unit
tests to run them on CI (via the `run-example-e2e.js` script). Where
necessary, the unit tests are fixed to ensure they pass and reflect the
changes in the corresponding component/service.
This commit also removes some auto-generated unit tests that are not
meaningful (e.g. make trivial assertions, such that a component instance
is truthy) and are often broken anyway (e.g. because the corresponding
component has been changed in ways that make the tests fail).

PR Close #36143
This commit is contained in:
George Kalpakas
2020-03-23 17:31:55 +02:00
committed by Kara Erickson
parent aece3669e5
commit d707124fd9
76 changed files with 74 additions and 1478 deletions

View File

@ -10,7 +10,7 @@ describe('AboutComponent (highlightDirective)', () => {
// #docregion tests
beforeEach(() => {
fixture = TestBed.configureTestingModule({
declarations: [ AboutComponent, HighlightDirective],
declarations: [ AboutComponent, HighlightDirective ],
schemas: [ NO_ERRORS_SCHEMA ]
})
.createComponent(AboutComponent);

View File

@ -1,16 +1,18 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AboutComponent } from './about/about.component';
export const routes: Routes = [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full'},
{ path: 'about', component: AboutComponent },
{ path: 'heroes', loadChildren: () => import('./hero/hero.module').then(m => m.HeroModule)},
];
@NgModule({
imports: [
RouterModule.forRoot([
{ path: '', redirectTo: 'dashboard', pathMatch: 'full'},
{ path: 'about', component: AboutComponent },
{ path: 'heroes', loadChildren: () => import('./hero/hero.module').then(m => m.HeroModule)}
])
RouterModule.forRoot(routes),
],
exports: [ RouterModule ] // re-export the module declarations
})
export class AppRoutingModule { };
export class AppRoutingModule { }

View File

@ -1,16 +1,13 @@
// For more examples:
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts
import { async, ComponentFixture, fakeAsync, TestBed, tick,
} from '@angular/core/testing';
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { asyncData } from '../testing';
import { RouterTestingModule } from '@angular/router/testing';
import { SpyLocation } from '@angular/common/testing';
// r - for relatively obscure router symbols
import * as r from '@angular/router';
import { Router, RouterLinkWithHref } from '@angular/router';
import { By } from '@angular/platform-browser';
@ -19,6 +16,7 @@ import { Location } from '@angular/common';
import { click } from '../testing';
import { routes } from './app-routing.module';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { AboutComponent } from './about/about.component';
@ -37,7 +35,10 @@ describe('AppComponent & RouterTestingModule', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ AppModule, RouterTestingModule ],
imports: [
AppModule,
RouterTestingModule.withRoutes(routes),
],
providers: [
{ provide: HeroService, useClass: TestHeroService }
]
@ -48,7 +49,7 @@ describe('AppComponent & RouterTestingModule', () => {
it('should navigate to "Dashboard" immediately', fakeAsync(() => {
createComponent();
tick(); // wait for async data to arrive
expect(location.path()).toEqual('/dashboard', 'after initialNavigation()');
expectPathToBe('/dashboard', 'after initialNavigation()');
expectElementOf(DashboardComponent);
}));
@ -96,14 +97,17 @@ xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [ AppModule, RouterTestingModule ]
imports: [
AppModule,
RouterTestingModule.withRoutes(routes),
],
})
.compileComponents();
}));
beforeEach(fakeAsync(() => {
createComponent();
loader = TestBed.inject(NgModuleFactoryLoader);
loader = TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader;
loader.stubbedModules = { expected: HeroModule };
router.resetConfig([{path: 'heroes', loadChildren: 'expected'}]);
}));

View File

@ -44,7 +44,8 @@ import { InMemoryDataService } from './in-memory-data.service';
AboutComponent,
BannerComponent,
TwainComponent,
WelcomeComponent ],
WelcomeComponent,
],
bootstrap: [ AppComponent ]
})
export class AppModule { }

View File

@ -110,7 +110,7 @@ describe('demo (with TestBed):', () => {
});
// Inject both the service-to-test and its (spy) dependency
masterService = TestBed.inject(MasterService);
valueServiceSpy = TestBed.inject(ValueService);
valueServiceSpy = TestBed.inject(ValueService) as jasmine.SpyObj<ValueService>;
});
// #enddocregion master-service-before-each
@ -373,14 +373,14 @@ describe('demo (with TestBed):', () => {
expect(el.context).toBe(childComp, 'context is the child component');
expect(el.attributes['account']).toBe(childComp.id, 'account attribute');
expect(el.attributes['bank']).toBe(childComp.bank, 'bank attribute');
expect(el.attributes.account).toBe(childComp.id, 'account attribute');
expect(el.attributes.bank).toBe(childComp.bank, 'bank attribute');
expect(el.classes['closed']).toBe(true, 'closed class');
expect(el.classes['open']).toBe(false, 'open class');
expect(el.classes.closed).toBe(true, 'closed class');
expect(el.classes.open).toBeFalsy('open class');
expect(el.styles['color']).toBe(comp.color, 'color style');
expect(el.styles['width']).toBe(comp.width + 'px', 'width style');
expect(el.styles.color).toBe(comp.color, 'color style');
expect(el.styles.width).toBe(comp.width + 'px', 'width style');
// #enddocregion dom-attributes
// Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future?

View File

@ -58,7 +58,7 @@ describe('WelcomeComponent', () => {
let el: HTMLElement; // the DOM element with the welcome message
// #docregion setup, user-service-stub
let userServiceStub: Partial<UserService>;
let userServiceStub: Partial<UserService>;
// #enddocregion user-service-stub
beforeEach(() => {
@ -66,7 +66,7 @@ describe('WelcomeComponent', () => {
// #docregion user-service-stub
userServiceStub = {
isLoggedIn: true,
user: { name: 'Test User'}
user: { name: 'Test User' },
};
// #enddocregion user-service-stub
@ -74,10 +74,10 @@ describe('WelcomeComponent', () => {
TestBed.configureTestingModule({
declarations: [ WelcomeComponent ],
// #enddocregion setup
// providers: [ UserService ] // NO! Don't provide the real service!
// Provide a test-double instead
// providers: [ UserService ], // NO! Don't provide the real service!
// Provide a test-double instead
// #docregion setup
providers: [ {provide: UserService, useValue: userServiceStub } ]
providers: [ { provide: UserService, useValue: userServiceStub } ],
});
// #enddocregion config-test-module
@ -85,7 +85,7 @@ describe('WelcomeComponent', () => {
comp = fixture.componentInstance;
// #enddocregion setup
// #docregion injected-service
// #docregion injected-service
// UserService actually injected into the component
userService = fixture.debugElement.injector.get(UserService);
// #enddocregion injected-service
@ -132,14 +132,4 @@ describe('WelcomeComponent', () => {
it('TestBed and Component UserService should be the same', () => {
expect(userService === componentUserService).toBe(true);
});
// #docregion stub-not-injected
it('stub object and injected UserService should not be the same', () => {
expect(userServiceStub === userService).toBe(false);
// Changing the stub object has no effect on the injected service
userServiceStub.isLoggedIn = false;
expect(userService.isLoggedIn).toBe(true);
});
// #enddocregion stub-not-injected
});

View File

@ -1,6 +1,6 @@
// #docregion
import { Component, OnInit } from '@angular/core';
import { UserService } from '../model/user.service';
import { UserService } from '../model/user.service';
// #docregion component
@Component({
@ -8,7 +8,7 @@ import { UserService } from '../model/user.service';
template: '<h3 class="welcome"><i>{{welcome}}</i></h3>'
})
// #docregion class
export class WelcomeComponent implements OnInit {
export class WelcomeComponent implements OnInit {
welcome: string;
constructor(private userService: UserService) { }

View File

@ -18,6 +18,7 @@ import './app/hero/hero-detail.component.spec.ts';
import './app/hero/hero-list.component.spec.ts';
import './app/model/hero.service.spec.ts';
import './app/model/testing/http-client.spec.ts';
import './app/shared/canvas.component.spec.ts';
import './app/shared/highlight.directive.spec.ts';
import './app/shared/title-case.pipe.spec.ts';
import './app/twain/twain.component.spec.ts';