A set of helper functions and Jest matchers for RxJs marble testing.
This library will help you to test your reactive code in easy and clear way.
- Multiple bundle formats: UMD, ES5 + ES2015 for module shaking, FESM
- Typescript
- Marblized error messages
- Jest
- RxJs
- Familiarity with marbles syntax
For RxJs 5:
npm i jest-marbles@1 -D
For RxJs 6:
npm i jest-marbles@latest -D
In the test file:
import {cold, hot, time} from 'jest-marbles';
Inside the test:
expect(stream).toBeObservable(expected);
expect(stream).toBeMarble(marbleString);
expect(stream).toHaveSubscriptions(marbleString);
expect(stream).toHaveSubscriptions(marbleStringsArray);
expect(stream).toHaveNoSubscriptions();
Verifies that the resulting stream emits certain values at certain time frames
it('Should merge two hot observables and start emitting from the subscription point', () => {
const e1 = hot('----a--^--b-------c--|', {a: 0});
const e2 = hot( '---d-^--e---------f-----|', {a: 0});
const expected = cold('---(be)----c-f-----|', {a: 0});
expect(e1.pipe(merge(e2))).toBeObservable(expected);
});
Sample output when the test fails (if change the expected result to '-d--(be)----c-f-----|'
):
Expected notifications to be:
"-d--(be)----c-f-----|"
But got:
"---(be)----c-f-----|"
Same as toBeObservable
but receives marble string instead
it('Should concatenate two cold observables into single cold observable', () => {
const a = cold('-a-|');
const b = cold('-b-|');
const expected = '-a--b-|';
expect(a.pipe(concat(b))).toBeMarble(expected);
});
Verifies that the observable was subscribed in the provided time frames.
Useful, for example, when you want to verify that particular switchMap
worked as expected:
it('Should figure out single subscription points', () => {
const x = cold( '--a---b---c--|');
const xsubs = '------^-------!';
const y = cold( '---d--e---f---|');
const ysubs = '--------------^-------------!';
const e1 = hot( '------x-------y------|', { x, y });
const expected = cold('--------a---b----d--e---f---|');
expect(e1.pipe(switchAll())).toBeObservable(expected);
expect(x).toHaveSubscriptions(xsubs);
expect(y).toHaveSubscriptions(ysubs);
});
The matcher can also accept multiple subscription marbles:
it('Should figure out multiple subscription points', () => {
const x = cold( '--a---b---c--|');
const y = cold( '----x---x|', {x});
const ySubscription1 = '----^---!';
// '--a---b---c--|'
const ySubscription2 = '--------^------------!';
const expectedY = cold( '------a---a---b---c--|');
const z = cold( '-x|', {x});
// '--a---b---c--|'
const zSubscription = '-^------------!';
const expectedZ = cold( '---a---b---c--|');
expect(y.pipe(switchAll())).toBeObservable(expectedY);
expect(z.pipe(switchAll())).toBeObservable(expectedZ);
expect(x).toHaveSubscriptions([ySubscription1, ySubscription2, zSubscription]);
});
Sample output when the test fails (if change ySubscription1
to '-----------------^---!'
):
Expected observable to have the following subscription points:
["-----------------^---!", "--------^------------!", "-^------------!"]
But got:
["-^------------!", "----^---!", "--------^------------!"]
Verifies that the observable was not subscribed during the test.
Especially useful when you want to verify that certain chain was not called due to an error:
it('Should verify that switchMap was not performed due to an error', () => {
const x = cold('--a---b---c--|');
const y = cold('---#-x--', {x});
const result = y.pipe(switchAll());
expect(result).toBeMarble('---#');
expect(x).toHaveNoSubscriptions();
});
Sample output when the test fails (if remove error and change the expected marble to '------a---b---c--|'
):
Expected observable to have no subscription points
But got:
["----^------------!"]