/jest-marbles

Helpers library for marbles testing with Jest

Primary LanguageTypeScriptMIT LicenseMIT

jest-marbles

npm version Build Status Packagist Conventional Commits Greenkeeper badge

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.

Features

  • Multiple bundle formats: UMD, ES5 + ES2015 for module shaking, FESM
  • Typescript
  • Marblized error messages

Prerequisites

Usage

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();

Examples

toBeObservable

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-----|"

toBeMarble

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);
    });

toHaveSubscriptions

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:
  ["-^------------!", "----^---!", "--------^------------!"]

toHaveNoSubscriptions

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:
  ["----^------------!"]