From e21dfc65d295f27af1492dab642e73ff2612868b Mon Sep 17 00:00:00 2001 From: OJ Kwon Date: Fri, 6 Nov 2020 10:12:25 -0800 Subject: [PATCH] docs(readme): update documentation --- README.md | 31 +++++++++++++++++++++++++++++++ src/index.ts | 15 +++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 109c171..1927668 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,13 @@ it('testcase', () => { ```typescript rxSandbox.create(autoFlush?: boolean, frameTimeFactor?: number, maxFrameValue?: number): RxSandboxInstance + +rxSandbox.create({ + autoFlush?: boolean, + frameTimeFactor?: number, + maxFrameValue?: boolean, + flushWithAsyncTick?: boolean, +}): RxSandboxInstance | RxAsyncSandboxInstance ``` `frameTimeFactor` allows to override default frame passage `1` to given value. @@ -232,9 +239,33 @@ expect(messages).to.deep.equal(expected); //subsequent attempt will throw expect(() => getMessages(e1.mapTo('y'))).to.throw(); +``` + +### Scheduling flush into native async tick (Experimental) +If you create sandbox instance with `flushWithAsyncTick` option, sandbox will return instance of `RxAsyncSandboxInstance` which all of flush interfaces need to be asynchronously awaited: + +``` +interface RxAsyncSandboxInstance { + ..., + advanceTo(toFrame: number) => Promise; + flush: () => Promise; + getMessages: (observable: Observable, unsubscriptionMarbles?: string | null) => Promise; +} ``` +It is not uncommon practices chaining native async function or promise inside of observables, especially for inner observables. Let's say if there's a redux-observable epic like below + +``` +const epic = (actionObservable) => actionObservable.ofType(...).pipe((mergeMap) => { + return new Promise.resolve(...); +}) +``` + +Testing this epic via rxSandbox won't work. Once sandbox flush all internal actions synchronously, promises are still scheduled into next tick so there's no inner observable subscription value collected by flush. `RxAsyncSandboxInstance` in opposite no longer flush actions synchronously but schedule each individual action into promise tick to try to collect values from async functions. + +**NOTE: this is beta feature and likely have some issues. Also Until stablized internal implementation can change without semver breaking.** + #### Custom frame time factor Each timeframe `-` is predefined to `1`, can be overridden. diff --git a/src/index.ts b/src/index.ts index 7e32a7d..b761726 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,13 +17,24 @@ export { type marbleAssertion = typeof marbleAssert; /** - * Creates new instance of test scheduler for testing observables. + * Creates a new instance of test scheduler for testing observables. * - * @param {SandboxOptions} [options] customizable options to create test scheduler. * @return {RxSandboxInstance} instance of test scheduler interfaces. */ function create(autoFlush?: boolean, frameTimeFactor?: number, maxFrameValue?: number): RxSandboxInstance; +/** + * Creates a new instance of test scheduler flushes action with native async tick for testing observables. + * + * NOTE: this is beta feature and likely have some issues. Also Until stablized internal implementation can change without sember breaking. + * @param {AsyncFlushSandboxOption} [options] customizable options to create test scheduler + */ function create(options: AsyncFlushSandboxOption): RxAsyncSandboxInstance; +/** + * Creates a new instance of test scheduler for testing observables. + * + * @param {SandboxOptions} [options] customizable options to create test scheduler. + * @return {RxSandboxInstance} instance of test scheduler interfaces. + */ function create(options?: Partial): RxSandboxInstance; function create(...args: Array): any { const { autoFlush, frameTimeFactor, maxFrameValue, flushWithAsyncTick } = interopOptionsFromArgument(args);