I've read the documentation for testing two-way binding in Angular2. All examples are simple, too simple, actually.
It seems like they only test the out-binding...
I'll post some code to illustrate:
import { Component, Input } from "@angular/core";
import { ComponentFixture, async, TestBed, tick, fakeAsync } from
"@angular/core/testing";
import { FormsModule } from "@angular/forms";
import { By } from "@angular/platform-browser";
@Component({
selector: 'test',
template: `
<input type="text" [(ngModel)]="myValue" />
<div>{{ myValue }}</div>
`
})
class TestComponent {
@Input() myValue: string
}
describe('Example', () => {
let component: TestComponent
let fixture: ComponentFixture<TestComponent>
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [TestComponent],
providers: [],
imports: [FormsModule]
})
.compileComponents()
}))
beforeEach(() => {
fixture = TestBed.createComponent(TestComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
it('should test two-way binding by setting the component member',
fakeAsync(() => {
const testValue = 'Component member test'
component.myValue = testValue // Should be the correct way to
test ngModel
tick();
fixture.detectChanges();
// Assertion error: Expected '' to equal 'Component member test'
// Why wasn't the value set in the textbox?
expect(fixture.debugElement.query(By.css('input'))
.nativeElement.value).toEqual(testValue)
//Yeah, the bananas are working. We have out-binding
expect(fixture.debugElement
.query(By.css('div'))
.nativeElement
.textContent
).toEqual(testValue);
}))
it('should test two-way binding by setting value directly on the native
element. But that just tests the out-binding', fakeAsync(() => {
const testValue = 'NativeElement test'
let element =
fixture.debugElement.query(By.css('input')).nativeElement;
element.value = testValue // this tests only the out-binding
element.dispatchEvent(new Event('input'));
tick();
fixture.detectChanges();
//of course this is Ok, we just set it directly
expect(fixture.debugElement.query(By.css('input'))
.nativeElement.value).toEqual(testValue)
//Yeah, the bananas are working. We have out-binding
expect(fixture.debugElement
.query(By.css('div'))
.nativeElement
.textContent
).toEqual(testValue);
}))
})
So is there a way actually test the component by setting myValue? I think that I am missing something...
Try swapping two lines:
tick();
fixture.detectChanges();
so it should be
fixture.detectChanges();
tick();
It means firstly you need to set value and then wait while angular is updating control value because it will happen inside Promise.then
you have to add name attribute in your html input tag
<input type="text" [(ngModel)]="myValue" name="myValue"/>