Skip to content

Commit

Permalink
Test for heroesComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
dev4ndy committed Sep 20, 2018
1 parent 174f0a0 commit 9066a09
Show file tree
Hide file tree
Showing 12 changed files with 211 additions and 66 deletions.
4 changes: 3 additions & 1 deletion src/app/dashboard.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Hero } from './hero';
import { HeroService } from './hero.service';
import { Route, Router } from '@angular/router';


@Component({
Expand All @@ -12,7 +13,8 @@ export class DashboardComponent implements OnInit {
heroes: Hero[];

constructor(
private heroService: HeroService) {
private heroService: HeroService,
private router: Router) {
}

ngOnInit(): void {
Expand Down
2 changes: 1 addition & 1 deletion src/app/hero-detail.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ <h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
<input [(ngModel)]="hero.name" placeholder="name" type="text"/>
</label>
</div>
<button class="test-button-go-back" (click)="goBack()">go back</button>
Expand Down
26 changes: 17 additions & 9 deletions src/app/hero-detail.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';
import { defaultHeroes, MockHeroService } from './test-mock.help';
import { defaultHeroes, MockHeroService, responseHeroes } from './test-mock.help';
import { DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';

Expand All @@ -19,6 +19,9 @@ describe('Test for HeroDetailComponet', () => {
let param = { id: 1 };
let debugElement: DebugElement;
let upperCase = new UpperCasePipe();
let element;
let input: DebugElement;


//Arrange
beforeEach(async(() => {
Expand All @@ -45,10 +48,15 @@ describe('Test for HeroDetailComponet', () => {
location = TestBed.get(Location);
fixture = TestBed.createComponent(HeroDetailComponent);
debugElement = fixture.debugElement;
element = debugElement.nativeElement;
heroDetailComponent = fixture.componentInstance;
//fixture.detectChanges();// Comments, so that it does run the of method ngOnInit();
});

afterEach(() => {
TestBed.resetTestingModule();
});

it('should create', () => {
expect(heroDetailComponent).toBeTruthy();
});
Expand Down Expand Up @@ -107,7 +115,7 @@ describe('Test for HeroDetailComponet', () => {
button.triggerEventHandler('click', null);
expect(heroDetailComponent.goBack).toHaveBeenCalled();
expect(heroDetailComponent.goBack).toHaveBeenCalledTimes(1);
});
});

it('should call function back of Location', () => {
spyOn(location, 'back');
Expand All @@ -127,20 +135,20 @@ describe('Test for HeroDetailComponet', () => {
expect(heroDetailComponent.save).toHaveBeenCalledTimes(1);
});

it('should update name of the hero', () => {
spyOn(heroService, 'updateHero').and.callThrough();
it('should update name of the hero', fakeAsync(() => {
fixture.detectChanges();
tick();
/**
* First we change the name at input
*/
let input = debugElement.query(By.css('input'));
input = debugElement.query(By.css('input'));
input.nativeElement.value = 'Andres 2';
input.nativeElement.dispatchEvent(new Event('input')); //emmit event from input for detect changes in ngmodel
input.nativeElement.dispatchEvent(new Event('input'));//emmit event from input for detect changes in ngmodel
heroDetailComponent.save();
expect(heroDetailComponent.hero).toEqual(defaultHeroes[0]);
});
expect(heroDetailComponent.hero).toEqual(responseHeroes[0]);
}));

it('should call function goBack()', () =>{
it('should call function goBack()', () => {
spyOn(heroDetailComponent, 'goBack');
fixture.detectChanges();
heroDetailComponent.save();
Expand Down
7 changes: 3 additions & 4 deletions src/app/hero-detail.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, OnDestroy } from '@angular/core';
import { ActivatedRoute, Params } from '@angular/router';
import { Hero } from './hero';
import { HeroService } from './hero.service';
Expand All @@ -10,7 +10,7 @@ import { Location } from '@angular/common';
styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
@Input() hero: Hero;
hero: Hero;

constructor(
private route: ActivatedRoute,
Expand Down Expand Up @@ -42,7 +42,6 @@ export class HeroDetailComponent implements OnInit {
this.heroService.updateHero(this.hero)
.subscribe(() => {
this.goBack()
}
);
});
}
}
5 changes: 2 additions & 3 deletions src/app/hero-search.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
<h4>Hero Search</h4>
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
<div>
<div *ngFor="let hero of heroes | async"
(click)="gotoDetail(hero)" class="search-result" >
<div *ngFor="let hero of heroes | async" [routerLink]="['/detail', hero.id]" class="search-result">
{{hero.name}}
</div>
</div>
</div>
</div>
30 changes: 23 additions & 7 deletions src/app/hero-search.component.spec.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { TestBed, async, ComponentFixture } from "@angular/core/testing";
import { TestBed, async, ComponentFixture, fakeAsync, tick, discardPeriodicTasks } from "@angular/core/testing";
import { CommonModule, UpperCasePipe } from "@angular/common";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { RouterTestingModule, SpyNgModuleFactoryLoader } from "@angular/router/testing";
import { FormsModule } from "@angular/forms";
import { HeroSearchComponent } from "./hero-search.component";
import { HeroSearchService } from "./hero-search.service";
import { DebugElement } from "@angular/core";
import { MockHeroSearchService } from "./mocks/mock-hero-search.service";
import { MockHeroSearchService, defaultHeroes } from "./mocks/mock-hero-search.service";
import { By } from "@angular/platform-browser";
import { of } from "rxjs";

describe('Test for HeroDetailComponet', () => {
describe('Test for HeroSearchComponent', () => {
let heroSearchComponent: HeroSearchComponent;
let fixture: ComponentFixture<HeroSearchComponent>;
let location: Location;
let heroSearchService: HeroSearchService;
let param = { id: 1 };
let debugElement: DebugElement;

//Arrange
Expand Down Expand Up @@ -47,7 +47,7 @@ describe('Test for HeroDetailComponet', () => {
it('should the heros variable be undefined', () => {
expect(heroSearchComponent.heroes).toBeUndefined();
});
it('should the searchTerms variable be defined', ()=>{
it('should the searchTerms variable be defined', () => {
expect(heroSearchComponent['searchTerms']).toBeDefined();
});
});
Expand All @@ -59,7 +59,7 @@ describe('Test for HeroDetailComponet', () => {
});
});

describe('When user witres at search input text', ()=>{
describe('When user witres at search input text', () => {
it('should call function search with search term', () => {
spyOn(heroSearchComponent, 'search')
let term = 'And';
Expand All @@ -75,12 +75,28 @@ describe('Test for HeroDetailComponet', () => {
it('should call function next of the searchTerms with search term', () => {
let term = 'And';
spyOn(heroSearchComponent['searchTerms'], 'next');
fixture.detectChanges();
fixture.detectChanges();
heroSearchComponent.search(term);
expect(heroSearchComponent['searchTerms'].next).toHaveBeenCalled();
expect(heroSearchComponent['searchTerms'].next).toHaveBeenCalledTimes(1);
expect(heroSearchComponent['searchTerms'].next).toHaveBeenCalledWith(term);
});

xit('should with the correct search term, the variable heros have at least a hero', fakeAsync(() => {
spyOn(heroSearchService, 'search').and.callThrough();
fixture.detectChanges();

const input = fixture.debugElement.query(By.css('#search-box'));
input.nativeElement.value = 'And';
input.triggerEventHandler('keyup', null);

tick(600);
fixture.detectChanges();

expect(heroSearchService.search).toHaveBeenCalled();
}));
});



});
30 changes: 6 additions & 24 deletions src/app/hero-search.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, Subject, of } from 'rxjs';
import {
catchError,
debounceTime,
distinctUntilChanged,
switchMap
} from 'rxjs/operators';
import { Observable, of, Subject } from 'rxjs';
import { catchError, debounceTime, distinctUntilChanged, switchMap } from 'rxjs/operators';
import { Hero } from './hero';
import { HeroSearchService } from './hero-search.service';

Expand All @@ -29,28 +23,16 @@ export class HeroSearchComponent implements OnInit {
this.searchTerms.next(term);
}

ngOnInit(): void {
ngOnInit(): void {
this.heroes = this.searchTerms.pipe(
debounceTime(300), // wait for 300ms pause in events
distinctUntilChanged(), // ignore if next search term is same as previous
switchMap(
term =>
term // switch to new observable each time
? // return the http search observable
this.heroSearchService.search(term)
: // or the observable of empty heroes if no search term
of<Hero[]>([])
),
switchMap(term => term ? this.heroSearchService.search(term) : of<Hero[]>([])),
catchError(error => {
// TODO: real error handling
console.log(`Error in component ... ${error}`);
return of<Hero[]>([]);
})
);
);
}

// gotoDetail(hero: Hero): void {
// const link = ['/detail', hero.id];
// this.router.navigate(link);
// }
}
}
2 changes: 1 addition & 1 deletion src/app/hero.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,4 @@ export class HeroService {
private log(message: string) {
this.messageService.add(`HeroService: ${message}`);
}
}
}
2 changes: 1 addition & 1 deletion src/app/heroes.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ <h2>My Heroes</h2>
<button class="delete" title="delete hero"
(click)="delete(hero)">x</button>
</li>
</ul>
</ul>
125 changes: 125 additions & 0 deletions src/app/heroes.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { DebugElement } from "@angular/core";
import { HeroesComponent } from "./heroes.component";
import { ComponentFixture, async, TestBed, tick, fakeAsync } from "@angular/core/testing";
import { HeroService } from "./hero.service";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { RouterTestingModule } from "@angular/router/testing";
import { MockHeroService, defaultHeroes } from "./test-mock.help";
import { FormsModule } from "@angular/forms";
import { By } from "@angular/platform-browser";
import { throwError } from "rxjs";

fdescribe('HeroesComponent', ()=>{
let heroesComponent: HeroesComponent;
let debugElement: DebugElement;
let fixture: ComponentFixture<HeroesComponent>;
let heroeService: HeroService;

//Arrange
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [FormsModule, HttpClientTestingModule, RouterTestingModule],
declarations: [HeroesComponent],
providers: [
{provide: HeroService, useValue: MockHeroService}
]
}).compileComponents()
}));

beforeEach(() => {
MockHeroService.setHeroes(defaultHeroes);
heroeService = TestBed.get(HeroService);
fixture = TestBed.createComponent(HeroesComponent);
debugElement = fixture.debugElement;
heroesComponent = fixture.componentInstance;
});

afterEach(() => {
MockHeroService.setHeroes(defaultHeroes);
});

it('should created', ()=>{
expect(heroesComponent).toBeTruthy();
});

describe('When the component starts', () => {
it('should the heroes variable be undefined', () =>{
expect(heroesComponent.heroes).toBeUndefined();
});
it('should the selectedHero variable be undefined', () => {
expect(heroesComponent.selectedHero).toBeUndefined();
});
it('should the addingHero variable be defined and equal to false', ()=>{
expect(heroesComponent.addingHero).toBeDefined();
expect(heroesComponent.addingHero).toBeFalsy();
});
it('should the error variable be undefined', () => {
expect(heroesComponent.error).toBeUndefined();
});
it('should the showNgFor variable be defined and equal to false', () =>{
expect(heroesComponent.showNgFor).toBeDefined();
expect(heroesComponent.showNgFor).toBeFalsy();
});
});

describe('When the ngOnInit methods starts', ()=>{
it('should call at function getHeroes()', () => {
spyOn(heroesComponent, 'getHeroes');
fixture.detectChanges();
expect(heroesComponent.getHeroes).toHaveBeenCalled();
});
});

describe('When the getHeroes function is run without errors', () =>{

it('should call at function getHeroes of the service', () => {
spyOn(heroeService, 'getHeroes').and.callThrough();
heroesComponent.getHeroes();
expect(heroeService.getHeroes).toHaveBeenCalled();
expect(heroeService.getHeroes).toHaveBeenCalledTimes(1);
});

it('should the heroes variable be defined', () => {
heroesComponent.getHeroes();
expect(heroesComponent.heroes).toBeDefined();
});

it('should render all heroes in the page', () => {
MockHeroService.setHeroes(defaultHeroes);
spyOn(heroeService, 'getHeroes').and.callThrough();
heroesComponent.getHeroes();
let lsLi = debugElement.queryAll(By.css('li'));
expect(lsLi.length).toEqual(defaultHeroes.length);
});
});

describe('When the getHeroes function is run with error in service', () => {

it('should call at function getHeroes of the service', () => {
spyOn(heroeService, 'getHeroes').and.returnValue(throwError('Error'));
heroesComponent.getHeroes();
expect(heroeService.getHeroes).toHaveBeenCalled();
expect(heroeService.getHeroes).toHaveBeenCalledTimes(1);
});

it('should the heroes variable be undefined', () => {
spyOn(heroeService, 'getHeroes').and.returnValue(throwError('Error'));
heroesComponent.getHeroes();
expect(heroesComponent.heroes).toBeUndefined();
});

it('should the error variable to be defined', () => {
spyOn(heroeService, 'getHeroes').and.returnValue(throwError('Error'));
heroesComponent.getHeroes();
expect(heroesComponent.error).toBeDefined();
});

it('should render nothing heroes in the page', ()=>{
spyOn(heroeService, 'getHeroes').and.returnValue(throwError('Error'));
heroesComponent.getHeroes();
fixture.detectChanges();
let ul = debugElement.query(By.css('ul'));
expect(ul.children.length).toBe(0);
});
});
});
Loading

0 comments on commit 9066a09

Please sign in to comment.