ReactiveX / ReactiveX/rxjs

Would you be interested in async/await TestScheduler that works with promises?

Open
#5,028 4 comments 12 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
31.7k
Forks
3k
PR merge metrics
No merged PRs in 30d

Description

Feature Request

My goal is to simplify testing of promises passed into operators, e.g. switchMap. This is slightly simpler than #701 as for now promises can just resolve on the same frame, same as of(x). However I believe my solution can be extended to support full #701 in the future.

Note: I already have a solution -- but I would like to confirm that you would be interested in it before I spend more time polishing.

Is your feature request related to a problem? Please describe.
I would like to use async/await in my Redux epics, but my team will only consider it if marble tests work.

Somewhat artificial test example (real cases are a bit more complicated):

it('mergeMap + promise', (() => {
  testScheduler.run(({ cold, expectObservable }) => {
      const observable = cold('(ab|)').pipe(mergeMap(x => {
        switch (x) {
          case 'a': return of('a');
          case 'b': return Promise.resolve('b');
        }
      }));
      expectObservable(observable).toBe('(ab|)');
  });
}));

Describe the solution you'd like
My current solution looks like this:

it('mergeMap + promise', (async () => {
  await testScheduler.runAsync(({ cold, expectObservable }) => {
      const observable = cold('(ab|)').pipe(mergeMap(x => {
        switch (x) {
          case 'a': return of('a');
          case 'b': return Promise.resolve('b');
        }
      }));
      expectObservable(observable).toBe('(ab|)');
  });
}));

This is very similar to the current model, but async.
This allows it to flush all promises between actions.

The test above passes on my (ugly/incomplete) prototype which you can see here: https://gist.github.com/ashmind/0cdf41c25a9e50c37a634d9a7bd0ab6b.

What I would like to understand is:

  1. Would you be interested in accepting that as a PR (obviously after some serious code cleanup), or should I release it as a separate library?
  2. If you are open to accepting it, should it be in TestScheduler or a separate class? What API design would you prefer? The only technical constraint for it is to return a promise (which test needs to await), other than that any design is fine.

Describe alternatives you've considered
Alternative: Use observables for individual values in Redux epics (instead of async/await, e.g. for web requests). However given web requests return a single value I find this unnatural and a missed learning opportunity for any new developers in our codebase.

Additional context

It would be really great if someone could help with test cases -- I am only really using/learning rxjs for a week, so I am guaranteed to be missing things.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue centers on TestScheduler, its current run API, and the proposed runAsync entry point; begin by reading the existing scheduler behavior and the linked prototype. Done means an agreed API and test cases demonstrate promise-based operators such as mergeMap under async/await.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.