简体   繁体   中英

Angular2 testing form: submit method not called

Having this component

import {Component} from 'angular2/core';
import { FORM_DIRECTIVES } from 'angular2/common';

@Component({
    selector: 'something',
    templateUrl: 'something.html',
    providers: [],
    directives: [FORM_DIRECTIVES],
    pipes: []
})
export class Something {

    constructor() { }

    save(data) {
        alert(data);
    }
}

with this template (something.html)

<form #myForm="ngForm" (ngSubmit)="save(myForm.value)">
    <label for="title">Title</label>
    <input id="title" type="text" ngControl="title" />

    <label for="primaryImage">Primary Image</label>
    <input id="primaryImage" type="text" ngControl="primaryImage" />

    <button type="submit">Save</button>
</form>

and this test

it('should call save method after clicking a Save button', injectAsync([TestComponentBuilder], (tcb: TestComponentBuilder) => {
    return tcb.createAsync(Something).then((fixture) => {
        spyOn(fixture.componentInstance, 'save');
        fixture.detectChanges();
        const compiled = fixture.nativeElement;
        compiled.querySelector('#title').value = 'testTitle';
        compiled.querySelector('#primaryImage').value = 'tabc.png';                   
        compiled.querySelector('button').click();
        expect(fixture.componentInstance.save).toHaveBeenCalledWith({
            title: 'testTitle',
            primaryImage: 'abc.png'
        });
    });
}));

The test fails, the save method hasn't been called on the spy. However, when I manually try it in browser, if works, alert is shown. The test fails too when instead of button.click I do form.submit.

When I use (click)="save(myForm.value)" on the button instead of ngSubmit on the form, test still fails, but the reason is different. Save method on the spy has been called in this case, but the data passed to it is {} .

Can anyone tell me what am I missing here?

Just in case it can help someone:

I have been able to trigger the submit event in the form using the By selector and triggerHandle

let form = fixture.debugElement.query(By.css('form'));
form.triggerEventHandler('submit', null);
fixture.detectChanges();
// your component function should have been called

If you try to trigger the click in the button the event it doesn't seem to trigger the ngSubmit. And if you try to do .submit on the form it will not be captured by angular and will refresh the page.

To add to Juanmi's answer for the test to be fully complete, the event have to be triggered by clicking on the button, because for example, if the button is moved out of the tag, the application would fail, but the test would still pass.

I have managed to go around the problem above, by calling the 'click()' method of the native element (not the debug element). See the code below. Note that in my code below, i'm using the ReactiveForms syntax, but it shouldn't make a difference for the test.

<form [formGroup]="sampleForm" (submit)="submit($event)">
    <input id="sampleBtn" type="submit" class="btn-default btn btn-primary" value="Click Me">
</form>

And in my spec.ts file

spyOn(fixture.componentInstance, 'submit');
let loginBtn: DebugElement = fixture.debugElement.query(By.css('#sampleBtn'));
loginBtn.nativeElement.click();
fixture.detectChanges();
expect(fixture.componentInstance.submit).toHaveBeenCalled();

This click() on the button would, in turn, trigger the (submit) handler function. Hope this helps. :)

Try to add fixture.detectChanges(); right before click.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM