Marble Diagrams, a way to test and deeply understand RxJS code: Part 1 — syntax


Testing code is part and parcel of a software developer’s job. However, depending on your company, you may be in lack of time for writing tests, therefore it’s crucial to define which parts of an application requires testing the most. The Angular application I’ve been working on recently makes use of ngrx libraries to mange the state. Being in short of time devoted to testing, I’ve decided to cover both ngrx selector’s project functions and ngrx effects with unit tests. A great tool for testing ngrx effects, which obviously contain a good deal of RxJS code, is jasmine-marbles package.


Introduction

Before you test ngrx effects with the aid of jasmine-marbles you need to get familiar with the syntax and go through some benchmark examples.

In short, the package allows to define a source stream which will be an input into a considered/currently tested RxJS operator/function and compare a resulting observable to an expected stream.

Besides, the tool helps to deeply understand inner workings of RxJS components. For example, when you first succeed in using the switchMap operator, you may be so overjoyed that you don’t even care why the catchError operator should be applied to the inner observable instead of the outer one, like the guy in the video below:

With jasmine-marbles you can easily figure out how the resulting observable will look like by trying to pass a given test spec. It’s a great way to understand flattening operators or functions used to combine streams of data.


Syntax

The package ships with two utility functions, namely cold and hot, allowing to define cold and hot observables, respectively.

Let’s dive into syntax:

  • - indicates 10 frames of time (10 miliseconds),
  • | indicates a complete notification,
  • # indicates an error notification,
  • ^ indicates a point of subscription to a hot observable,
  • ( ) are used to group multiple values emitted at the same frame (more on that later),
  • any other character indicates a next notification.

You define both source and expected streams with the aid of the above-mentioned syntax and provided it (a string representing an observable) as the first argument to the hot or cold functions.

The functions accept 1–3 parameters with the second being a map of characters representing next notifications and the third one being an error notification value.

Last but not least, the package provides the toBeObservable matcher enabling comparison of a source stream to an expected one.


Basic examples

Let’s start with basic RxJS operators to get familiar with the jasmine-marbles syntax.

map operator

Let’s investigate the above example:

  • inputStream can be read as follows: wait for 10ms and emit 5,
  • expectedStream can be read as follows: wait for 10ms and emit 10,
  • outputStream is the result of applying the map operator, with the provided project function (doubling value), to the inputStream,
  • finally the outputStream is compared to the expectedStream.

reduce operator

The above example can be read as follows:

  • inputStream: wait for 10ms; emit 3 values in a sequence (it takes 30ms); then complete,
  • expectedStream: wait for 40ms (since the resulting stream with applied reduce operator will emit a value when the source observable completes and the source one needs 40ms to complete); emit both next and complete notifications at the same frame (the source stream completes at 40 frame which is a signal for the resulting observable to emit a value, however the output stream has to emit a complete notification as well, since its source observable has already completed),
  • outputStream is the result of applying the reduce operator with the provided accumulator function (adding up values) to the inputStream,
  • finally the outputStream is compared to the expectedStream.

Conclusions

In the article I presented the basics of testing RxJS code with the aid of jasmine-marbles package. I believe it’s the most convenient way of testing reactive code.

In the next articles of the series I’m going to focus on testing flattening operators, functions used to combine streams, custom operators doing awesome stuff :) and finally ngrx effects.

If you like the article, found out something new or simply enjoyed reading it, please give me a clap. Stay tunned!

JavaScript everyday

Improve your JavaScript skills everyday!

Wojciech Trawiński

Written by

Doing awesome things using JavaScript

JavaScript everyday

Improve your JavaScript skills everyday!

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade