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(fixtureponentInstance, 'save');
fixture.detectChanges();
const compiled = fixture.nativeElement;
compiled.querySelector('#title').value = 'testTitle';
compiled.querySelector('#primaryImage').value = 'tabc.png';
compiled.querySelector('button').click();
expect(fixtureponentInstance.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?
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?
Share Improve this question asked Apr 16, 2016 at 23:15 František ŽiačikFrantišek Žiačik 7,6141 gold badge36 silver badges61 bronze badges3 Answers
Reset to default 10To 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. :)
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.
Try to add fixture.detectChanges();
right before click.