I am trying to test the two way data binding of ngModel with the following code, but when I am running my test I always get: Expected '' to be '[email protected]', 'searchQuery property changes after text input'. Maybe it has something to do with the searchField.dispatchEvent part, but so far I couldn't figure out why the test is not changing the textContent of my displayField. The project was built with angular-cli": "1.0.0-beta.15. I tried to follow this guide but so far had no luck. Would be nice if you could help me make my test pass. I am not sure if I have to use fixture.whenStable() - as I've seen it used in the answer to another question - but I don't think that typing text into an input field is an asynchronous activity - I also implemented the sendInput() method mentioned in this question, but so far without any success.
This is my component:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-search',
templateUrl: './search.component.html',
styleUrls: ['./search.component.css']
})
export class SearchComponent implements OnInit {
searchQuery: string;
active: boolean = false;
onSubmit(): void {
this.active = true;
}
}
This is my component template:
<input id="name" [(ngModel)]="searchQuery" placeholder="customer">
<h2><span>{{searchQuery}}</span></h2>
And here are is my spec:
/* tslint:disable:no-unused-variable */
import {TestBed, async, ComponentFixture, tick} from '@angular/core/testing';
import { SearchComponent } from './search.component';
import {CommonModule} from "@angular/common";
import {FormsModule} from "@angular/forms";
import {By} from "@angular/platform-browser";
describe('Component: SearchComponent', () => {
let component: SearchComponent;
let fixture: ComponentFixture<SearchComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [SearchComponent],
imports: [
CommonModule,
FormsModule
]
});
fixture = TestBed.createComponent(SearchComponent);
component = fixture.componentInstance;
});
it('should bind the search input to the searchQuery variable', () => {
const searchInputText: string = '[email protected]';
const searchField: HTMLInputElement = fixture.debugElement.query(By.css('input')).nativeElement;
const displayField: HTMLElement = fixture.debugElement.query(By.css('span')).nativeElement;
searchField.value = searchInputText;
searchField.dispatchEvent(new Event('input'));
fixture.detectChanges();
expect(displayField.textContent).toBe(searchInputText, 'searchQuery property changes after text input');
});
});
Update: I changed my test to the following, which made it pass - as long as the input field is not inside a form tag:
/* tslint:disable:no-unused-variable */
import {TestBed, async, ComponentFixture, tick} from '@angular/core/testing';
import { SearchComponent } from './search.component';
import {CommonModule} from "@angular/common";
import {FormsModule} from "@angular/forms";
import {By} from "@angular/platform-browser";
describe('Component: SearchComponent', () => {
let component: SearchComponent;
let fixture: ComponentFixture<SearchComponent>;
function sendInput(text: string, inputElement: HTMLInputElement) {
inputElement.value = text;
inputElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
return fixture.whenStable();
}
beforeEach(done => {
declarations: [SearchComponent],
imports: [
CommonModule,
FormsModule
]
});
TestBed.compileComponents().then(() => {
fixture = TestBed.createComponent(SearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
done();
})
});
it('should bind the search input to the searchQuery variable', done => {
const searchInputText: string = '[email protected]';
const searchField: HTMLInputElement = fixture.debugElement.query(By.css('#name')).nativeElement;
sendInput(searchInputText, searchField).then(() => {
expect(component.searchQuery).toBe(searchInputText);
done();
});
});
});
Here is the updated template:
<form>
<input id="name" [(ngModel)]="searchQuery" placeholder="customer" name="name" #name="ngModel">
</form>
<h2><span>{{searchQuery}}</span></h2>
The test result I get is: Expected undefined to be '[email protected]'.
TestBed.compileComponents().then(...)to make sure the component is correctly initialised. You may also need more waiting (resolving a.whenStable) for the component to have updated correctly. See e.g. github.com/textbook/known-for-web/blob/master/src/app/actor/…<input class="form-control" id="customerSearch" [(ngModel)]="searchQuery" name="customerSearch">