Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Hero detail: Shallow routed component test suite.
<div *ngIf="hero">
<h2>
{{hero.name | uppercase}} Details
</h2>
<div>
<span>id:</span>
{{hero.id}}
</div>
<div>
<label>
name:
<input [(ngModel)]="hero.name" placeholder="name">
</label>
</div>
<button (click)="goBack()">go back</button>
<button (click)="save()">save</button>
</div>
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import {
ActivatedRoute,
ActivatedRouteSnapshot,
convertToParamMap,
ParamMap,
Params,
} from '@angular/router';
import { of, ReplaySubject } from 'rxjs';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
import { HEROES } from '../mock-heroes';
import { HeroDetailComponent } from './hero-detail.component';
class ActivatedRouteStub implements Partial<ActivatedRoute> {
private _paramMap: ParamMap;
private subject = new ReplaySubject<ParamMap>();
paramMap = this.subject.asObservable();
get snapshot(): ActivatedRouteSnapshot {
const snapshot: Partial<ActivatedRouteSnapshot> = {
paramMap: this._paramMap,
};
return snapshot as ActivatedRouteSnapshot;
}
constructor(initialParams?: Params) {
this.setParamMap(initialParams);
}
setParamMap(params?: Params) {
const paramMap = convertToParamMap(params);
this._paramMap = paramMap;
this.subject.next(paramMap);
}
}
describe('HeroDetailComponent (shallow)', () => {
function getTitle() {
const element = fixture.debugElement.query(By.css('h2'))
.nativeElement as HTMLElement;
return element.textContent.trim();
}
function navigateByHeroId(id: number) {
routeStub.setParamMap({ id });
}
beforeEach(async () => {
const fakeService = {
getHero(id: number) {
const hero = [...fakeHeroes].find(h => h.id === id);
return of(hero);
},
} as Partial<HeroService>;
routeStub = new ActivatedRouteStub();
TestBed.configureTestingModule({
declarations: [HeroDetailComponent],
imports: [FormsModule],
providers: [
{ provide: ActivatedRoute, useValue: routeStub },
{ provide: HeroService, useValue: fakeService },
],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
});
await TestBed.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
});
let component: HeroDetailComponent;
const fakeHeroes: ReadonlyArray<Hero> = [...HEROES];
let fixture: ComponentFixture<HeroDetailComponent>;
let routeStub: ActivatedRouteStub;
it("displays the hero's name in upper-case letters", () => {
const [expectedHero] = fakeHeroes;
navigateByHeroId(expectedHero.id);
fixture.detectChanges();
expect(getTitle()).toContain(expectedHero.name.toUpperCase());
});
});
import { Location } from '@angular/common';
import { Component, Input, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
@Component({
selector: 'app-hero-detail',
styleUrls: ['./hero-detail.component.css'],
templateUrl: './hero-detail.component.html',
})
export class HeroDetailComponent implements OnInit {
@Input() hero: Hero;
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location,
) {}
ngOnInit(): void {
this.getHero();
}
getHero(): void {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
goBack(): void {
this.location.back();
}
save(): void {
this.heroService.updateHero(this.hero)
.subscribe(() => this.goBack());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.