Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test observables which emit grouped events with rxjs marbles?

According to rxjs marbles documentation the current behaviour for the sync groupings is the following:

'(ab)-(cd)': on frame 0, emits a and b then on frame 50, emits c and d

From the docs:

While it can be unintuitive at first, after all the values have synchronously emitted time will progress a number of frames equal to the number of ASCII characters in the group, including the parentheses

Ok, but how do I test an observable like this (using marbles or any other technique):

const observable$ = of(1, 2).concat(of(3, 4).delay(20));

Are there any workarounds?

There is a similar question on Stack Overflow but there is no answer on 'How to actually work around it and test this kind of observable'.

Thanks!

like image 804
kazinov Avatar asked May 18 '18 08:05

kazinov


2 Answers

For my project I migrated to rx-sanbox where sync grouping works correct and it solved my problem.

So, in rx-sandbox this is correct: '(ab)-(cd)': on frame 0, emits a and b then on frame 20, emits c and d

like image 99
kazinov Avatar answered Nov 03 '22 18:11

kazinov


I don't know what version of RxJS you're using because you're mixing prototypical and pipable operators but it looks like RxJS 5.5.

In RxJS 5.X it's a bit clumsy. You could rewrite your test like this:

import { of } from 'rxjs/observable/of';
import { TestScheduler } from 'rxjs/testing/TestScheduler';
import { assert } from 'chai';
import 'rxjs/add/operator/concat';
import 'rxjs/add/operator/delay';

const scheduler = new TestScheduler((actual, expected) => {
  console.log(actual, expected);
  return assert.deepEqual(actual, expected);
});

const observable$ = of('a', 'b').concat(of('c', 'd').delay(50, scheduler));

scheduler
  .expectObservable(observable$)
  .toBe('(ab)-(cd|)');

scheduler.flush();

See live demo (open console): https://stackblitz.com/edit/rxjs5-marble-test?file=index.ts

You know this test passes because it doesn't throw any error. Try changing any of the delays or values of next emissions and it'll throw an error.

Also have a look at this answer: How do I test a function that returns an observable using timed intervals in rxjs 5?

However, I'd strongly recommend upgrading to RxJS 6 because it makes everything much easier with cold and hot "creation" functions where you could just use const observable$ = cold('(ab)-(cd|)') to create the same sequence as you're doing with of(...).concat(...).

Testing in RxJS 6:

  • https://github.com/ReactiveX/rxjs/blob/master/doc/marble-testing.md

  • https://github.com/ReactiveX/rxjs/blob/master/doc/internal-marble-tests.md

like image 24
martin Avatar answered Nov 03 '22 18:11

martin