7

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!

kazinov
  • 701
  • 1
  • 6
  • 11

2 Answers2

4

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

kazinov
  • 701
  • 1
  • 6
  • 11
2

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:

martin
  • 93,354
  • 25
  • 191
  • 226
  • Well, if you want to use marble tests you'll have to at least pass the `scheduler` to `delay`. Otherwise it's not able to work with time and marble tests are based proper on timing. – martin May 18 '18 at 15:00
  • 1
    Thank you for the detailed answer, @martin. In your answer you assumes that I can edit my original observable. But I'm trying to test some observable from the real code of my application. ` class SomeService { observable$ = of(a, b).concat(of(c, d).delay(20)); } ` I know that this observable suppose to produce the following stream: '(ab)-(cd)'. And I want to test it using marbles. My problem is that using the marble syntax i can't do it because of sync groupings syntax. In Rxjs 6 too. For my project I migrated to rx-sanbox where sync grouping works correct and it solved my problem – kazinov May 18 '18 at 15:02