Given the following code:
import {merge, Observable} from "rxjs";
export function springLatch(handle$: Observable<boolean>, closedByDefault: boolean): Observable<boolean> {
const latch$ = new Observable<boolean>((subscriber) => {
if (closedByDefault) {
subscriber.next(false);
} else {
subscriber.next(true);
}
handle$.subscribe({
next(value: boolean) {
if (closedByDefault && value) {
subscriber.next(value);
} else {
subscriber.next(value);
}
}
})
});
return merge(handle$, latch$);
}
Tested by this unit-test:
describe('SpringLatchTest', () => {
let testScheduler: TestScheduler;
beforeEach(() => {
testScheduler = new TestScheduler((actual, expected) => {
expect(actual).toBe(expected);
});
});
it('should do something', () => {
testScheduler.run(({cold, expectObservable}) => {
// Assemble
const handle$ = cold('-t-f', {t: true, f: false});
// Act
const actual: Observable<boolean> = springLatch(handle$, true);
// Assert
expectObservable(actual).toBe('fttff', {t: true, f: false});
});
});
});
Based on the above I have several questions related to value emissions and frames.
- How do I prevent the unit-test from failing due to mismatching frames between the actual observable and the expected observable based on the marble diagram?
- Do values emissions have a a 1-to-1 relationship with frames?
Versioning
"jest": "^29.5.0",
"rxjs": "^7.8.0"
RxJS has a very good documentation regarding RxJS marble testing. If you need to test that there were multiple
nextemissions within the same frame you can wrap expected emissions with parenthesis().For example,
'(fttff)'means all emissions happened at frame0. Or'(ft)(tff)'meansftwere emitted at frame0and thentffat frame4.There's a known limitation with marble tests. You can't expect groups of emissions that would overlap because each group start at char index of its
(.