Angular Testing: FormControl valueChanges Observable
At first glance I think you missed the fact that your FormControl is not connected to input because you're using FormControlName
directive that takes control name as @Input
.
If you want to test FormControl then you can consider FormControlDirective
that takes FormControl
as @Input
:
<input name="name" [formControl]="name">
^^^^^
`name` is FormControl instance here not string
Now we can be sure that whenever we change text in input your FormControl
will fire changes. But as soon as you write such template angular will ask you for ReactiveFormsModule
dependency in your test:
import { ReactiveFormsModule } from '@angular/forms';
....
TestBed.configureTestingModule({
imports: [
ReactiveFormsModule <=== add this
],
declarations: [TestComponent],
});
Now regarding your test.
1) You must tell the TestBed
to perform data binding by calling fixture.detectChanges()
:
const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); <== add this
2) You should fire change on input correctly:
el.dispatchEvent(new Event('input'));
Here's the whole code:
it('should display original title', () => {
const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges();
const app = fixture.debugElement.componentInstance;
const el = fixture.nativeElement.querySelector('input');
el.value = 'something';
el.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(app.data).toBe('newvalue');
});
});
Vikas
pro·gram·mer (n) An organism capable of converting caffeine into code. Frameworks and languages that I have worked: For the Web (current projects) Angular (currently V9 ) Vue.js React.js Typescript Javascript spring Boot Go Ruby Social Network:Facebook Email: [email protected] On Medium How to keep an Observable alive after Error in Angular? Favorite answers of mine: Why AOT Compiler requires public properties, while JIT compiler allows private properties. what, why and when to use services?
Updated on July 09, 2022Comments
-
Vikas almost 2 years
I have a text input and I'm listening for the changes.
component
name = new FormControl('',Validators.required); ngOnInit() { this.data = 'oldvalue'; this.checkName(); } checkName() { this.name.valueChanges.subscribe(val=>{ console.log(val); this.data= "newvalue"; // updating Value }); }
HTML
<input name="name" formControlName="name">
My Attempt so far:
component.spec.ts
it('should test data field ', () => { const fixture = TestBed.createComponent(UserComponent); const app=fixture.debugElement.componentInstance; const el = fixture.nativeElement.querySelector('input'); el.value ='something'; dispatchEvent(new Event(el)); fixture.detectChanges(); fixture.whenStable().then(()=>{expect(app.data).toBe('newvalue'); });
Problem: Even though input field is populated the code inside subscribe callback is never executed.
It always shows:
Expected 'oldvalue' to be 'newvalue'.
I tried
setValue()
method too but it did not work. it never goes inside subscribe callbackapp.name.setValue('vikas'); fixture.detectChanges(); fixture.whenStable().then(()=>{expect(app.data).toBe('newvalue');
I referred Updating input html field from within an Angular 2 test and Angular2 Component: Testing form input value change but no luck :(
What am I missing?