Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Jasmine How to test a function of a component

How do I mock the click event of a function in Angular 2? For my Home Component I have:

Home Component

import { Component } from '@angular/core';
import { Router } from '@angular/router';

@Component({
  moduleId: module.id,
  templateUrl: 'home.component.html',
  styleUrls: ['home.component.css'],
  selector: 'home',
})
export class HomeComponent {

    constructor(private router: Router) {

    }

    redirectToUpload() {
        this.router.navigate(['/upload']);
    }
    redirectToAbout() {
        this.router.navigate(['/about']);
    }

}

Home Component spec

import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { HomeComponent } from './home.component';
import { DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { Router } from '@angular/router';
import { HomeModule } from './home.module';
import { RouterLinkStubDirective, RouterOutletStubComponent } from '../../../test/router-stubs';
import { RouterModule } from '@angular/router';


export function main() {

    let de: DebugElement;
    let comp: HomeComponent;
    let fixture: ComponentFixture<HomeComponent>;
    let mockRouter:any;
    class MockRouter {
        //noinspection TypeScriptUnresolvedFunction
        navigate = jasmine.createSpy('navigate');
    }



    describe('Home component', () => {

        // preparing module for testing
        beforeEach(async(() => {
            mockRouter = new MockRouter();
            TestBed.configureTestingModule({
                imports: [HomeModule],

            }).overrideModule(HomeModule, {
                remove: {
                    imports: [ RouterModule ],

                },
                add: {
                    declarations: [ RouterLinkStubDirective, RouterOutletStubComponent ],
                    providers: [ { provide: Router, useValue: mockRouter }],
                }
            }).compileComponents().then(() => {

                fixture = TestBed.createComponent(HomeComponent);
                comp = fixture.componentInstance;


            });
        }));
            tests();
        });

        function tests() {


            beforeEach(() => {
                // trigger initial data binding
                fixture.detectChanges();



                de = fixture.debugElement.query(By.css('h1'));

            });

            it('can instantiate Home', () => {
                expect(comp).not.toBeNull();
            });


            it('should have expected <h1> text', () => {
                fixture.detectChanges();
                const h1 = de.nativeElement;
                expect(h1.innerText).toMatch("Home");
            });          


        }

}

I want to test redirectToUpload() and redirectToAbout(). How would I mock the click and ensure that the redirect is for the specified link?

like image 320
Bhetzie Avatar asked Dec 01 '16 16:12

Bhetzie


People also ask

How can we get an instance of the component to be tested?

You should configure a testing module before each test, using the TestBed . Here you can declare you component to test, and any providers it needs. Then you create the component using the TestBed also.


2 Answers

First, I recommend you writing your test in Typescript, it keeps cohesion between your components and your tests.

Here are the basic steps in your spec file:

Get the element (I recommend using an Id tag if possible)

const element = fixture.debugElement.query(By.css("#your-element"));

Trigger the event. NOTE: there must be a (click) event on the element

element.triggerEventHandler("click", null);

Then detect the changes from the event

fixture.detectChanges();

In your HTML template, you would need to have click events pointed at the functions you wish to test (click)="redirectToUpload()"

like image 141
ed-tester Avatar answered Oct 12 '22 14:10

ed-tester


You need to get the button then click it

de.nativeElement.querySelector('.theButtonClass').click();

Then check that the stub's navigate method is called with the correct argument

expect(mockRouter.navigate).toHaveBeenCalledWith(['/about']);

You may or may not need to use async. If it doesn't work, you might need to use async and wait for the asynchronous click event to stabilize

import { async } from '@angular/core/async';

it('..', async(() => {
  ...click();
  fixture.whenStable().then(() => {
    expect(mockRouter.navigate).toHaveBeenCalledWith(['/about']);
  })
})
like image 38
Paul Samsotha Avatar answered Oct 12 '22 13:10

Paul Samsotha