How to test form.valueChanges in Angular?
10,051
You want to test changes on a form without inputs. Maybe try with this :
this.searchForm = this.fb.group({description: ['your_input']});
.
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [...],
providers: [
{ provide: Store, useValue: MOCK_STORE },
],
declarations: [FormComponent],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should dispatch action for valueChanges', () => {
const spy = spyOn(TestBed.get(Store<AppState>), 'dispatch')
component.searchForm.controls['your_input'].setValue('test') // This will trigger change
expect(spy).toHaveBeenCalledTimes(1);
});
![Felix](https://i.stack.imgur.com/2HV6U.png?s=256&g=1)
Author by
Felix
Updated on June 24, 2022Comments
-
Felix about 2 years
How to correctly unit test (Karma, Jasmine), that emmisions of
valueChanges
dispatches aFormUpdated
action?beforeEach(async(() => { TestBed.configureTestingModule({ imports: [...], providers: [ { provide: Store, useValue: MOCK_STORE }, ], declarations: [FormComponent], schemas: [NO_ERRORS_SCHEMA] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(FormComponent); component = fixture.componentInstance; fixture.detectChanges(); });
export class FormComponent implements OnInit { searchForm: FormGroup; constructor(private readonly fb: FormBuilder, private readonly store: Store<AppState>) { } ngOnInit(): void { this.searchForm = this.fb.group({}); this.searchForm.valueChanges.subscribe(value => this.store.dispatch(new FormUpdated(value))); } }
I have tried something like this:
it('should dispatch action for valueChanges', () => { const spy = spyOn(component['store'], 'dispatch'); spyOn(component.searchForm, 'valueChanges').and.returnValue(of({})); expect(spy).toHaveBeenCalledTimes(1); });
But this does not work - the spy has not been called.
[Edit1] - Based on comments and answer:
The problem is with the test asynchronicity. Some part of
ngOnInit
callssetTimeout(() => this.searchForm.get('field').updateValueAndValidity();)
) which causes an emmision tothis.searchForm.valueChanges()
so thethis.store.dispatch
is actually called but after theexpect(spy).toHaveBeenCalledTimes(1)
.I have tried to add
fakeAsync()
,tick()
andflushMicrotasks()
but with same outcome.it('should dispatch action for valueChanges', () => { const spy = spyOn(component['store'], 'dispatch'); spyOn(component.searchForm, 'valueChanges').and.returnValue(of({})); tick(); flushMicrotasks(); expect(spy).toHaveBeenCalledTimes(1); });
-
malvadao over 5 years
component.searchForm.controls['your_input'].setValue('test')
this has successfully triggered the valueChange. Thank you!