Skip to content

Instantly share code, notes, and snippets.

@LayZeeDK
Created June 1, 2020 22:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LayZeeDK/3e80b507b31089da1bc9b5db07c1519f to your computer and use it in GitHub Desktop.
Save LayZeeDK/3e80b507b31089da1bc9b5db07c1519f to your computer and use it in GitHub Desktop.
Hero detail: Integrated 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 { Component } from '@angular/core';
import {
ComponentFixture,
fakeAsync,
TestBed,
tick,
} from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
import { HEROES } from '../mock-heroes';
import { HeroDetailComponent } from './hero-detail.component';
@Component({
template: '<router-outlet></router-outlet>',
})
class TestRootComponent {}
describe('HeroDetailComponent (integrated)', () => {
function advance() {
tick();
rootFixture.detectChanges();
}
function getTitle() {
const element = rootFixture.debugElement.query(By.css('h2'))
.nativeElement as HTMLElement;
return element.textContent.trim();
}
function navigateByHeroId(id: number) {
rootFixture.ngZone.run(() => router.navigate(['detail', id]));
}
beforeEach(async () => {
const fakeService = {
getHero(id: number) {
const hero = [...fakeHeroes].find(h => h.id === id);
return of(hero);
},
} as Partial<HeroService>;
TestBed.configureTestingModule({
declarations: [
TestRootComponent,
HeroDetailComponent,
],
imports: [
RouterTestingModule.withRoutes([
{ path: 'detail/:id', component: HeroDetailComponent },
]),
FormsModule,
],
providers: [
{ provide: HeroService, useValue: fakeService },
],
});
await TestBed.compileComponents();
rootFixture = TestBed.createComponent(TestRootComponent);
router = TestBed.inject(Router);
});
const fakeHeroes: ReadonlyArray<Hero> = [...HEROES];
let router: Router;
let rootFixture: ComponentFixture<TestRootComponent>;
it("displays the hero's name in upper-case letters", fakeAsync(() => {
const [expectedHero] = fakeHeroes;
navigateByHeroId(expectedHero.id);
advance();
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());
}
}
@LayZeeDK
Copy link
Author

@meirka
I identified a few issues and suggested some stylistic changes to your repo: meirka/angular-unit-test-navigation#1

@meirka
Copy link

meirka commented Jan 23, 2022

@LayZeeDK
Thank you, I'll go over your changes.

I'm attempting to do kinda full integration test: navigation, fill forms, backend calls (mocked by testingController) and all of it from Jasmine tests. I don't want to do e2e (for multiple reasons - long story).

@LayZeeDK
Copy link
Author

@meirka
That's exactly why I built Spectacular, in particular its Feature testing API, preferably used with Angular Testing Library and/or Angular CDK Component Harnesses as described in the docs. Slide deck from NG Poland 2021 coming soon at https://speakerdeck.com/layzee

@meirka
Copy link

meirka commented Jan 25, 2022

@LayZeeDK
Thank you, I'll check it out!
I guess I'm not only one who doesn't want to waste time on e2e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment