Angular Component
public setupObservables() {
this.formFieldChanged$ = this.formField
.valueChanges
.pipe(
debounceTime(100),
distinctUntilChanged((a, b) => a === b),
)
}
Jasmine Test
import { of } from 'rxjs';
import { marbles } from 'rxjs-marbles/jasmine';
...
it('should update value on debounced formField change', marbles(m => {
const values = { a: "1", b: "2", c: "3" };
const fakeInputs = m.cold('a 200ms b 50ms c', values);
const expected = m.cold('100ms a 250ms c', values);
// works on stackblitz but otherwise gives TS2540 compiler error
// cannot assign to a read-only property
component.formField.valueChanges = fakeInputs;
component.setupObservables();
m.expect(component.formFieldChanged$).toBeObservable(expected);
}));
The intent is to use marble tests to test Observable
code in context with Angular reactive forms.
- Does this approach make sense?
- How to best mock the
valueChanges
of aFormField
object? - Is there a better way to structure these kind of tests?
valueChanges
is a Subject that emits values. By comparing it tofakeInputs
you're not comparing individual emissions. What you need instead isexpectObservable
github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/… – Disgracecomponent.formField.valueChanges = fakeInputs
instead of the spyOn works. – Limconst expected = '100ms a 500ms c';
and then passvalues
totoBeObservable
. – DisgracevalueChanges
being a read-only property. – Lim(component.formField as any).valueChanges = fakeInputs
. – Disgrace