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.
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 next
emissions within the same frame you can wrap expected emissions with parenthesis ()
.
For example, '(fttff)'
means all emissions happened at frame 0
. Or '(ft)(tff)'
means ft
were emitted at frame 0
and then tff
at frame 4
.
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 (
.