UNPKG

suspenders-js

Version:

Asynchronous programming library utilizing coroutines, functional reactive programming and structured concurrency.

232 lines (184 loc) 5.23 kB
import { flowOf } from "./Flow"; import { Scope } from "./Scope"; import { awaitCancelation, wait } from "./Util"; describe(`Scope tests`, () => { it(`sibling coroutine is canceled when scope is canceled`, (done) => { const scope = new Scope(); scope.launch(function* () { try { yield wait(5); } finally { done(); } }); scope.launch(function* () { throw new Error(); }); }); it(`coroutine is canceled when scope is canceled`, (done) => { const scope = new Scope(); scope.launch(function* () { try { yield awaitCancelation(); } finally { done(); } }); scope.cancel(); }); it(`canceling a coroutine doesn't cancel it's scope`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); const cancelFunction = scope.launch(function* () { yield awaitCancelation(); }); cancelFunction(); scope.launch(function* () { done(); }); }); it(`throwing in non-canceling scope doesn't cancel it`, (done) => { const scope = new Scope({ isCancelable: false, errorCallback: (error) => { done(error); }}); scope.launch(function* () { throw new Error(); }); if (!scope.isActive()) { done(`scope is no longer active after throw`); } scope.launch(function*() { done(); }); }); it(`calling coroutine asynchronously`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); scope.launch(function* () { const asyncValue = this.callAsync(function* () { return 1; }); const value = yield* this.suspend(asyncValue); if (value === 1) { done(); } else { done(`unexpected result`); } }); }); it(`calling coroutine asynchronously in finally block`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); const cancel = scope.launch(function* () { try { yield awaitCancelation(); } finally { const asyncValue = this.callAsync(function* () { return 1; }); const value = yield* this.suspend(asyncValue); if (value === 1) { done(); } else { done(`unexpected result`); } } }); cancel(); }); it(`calling coroutine asynchronously in finally block on canceled scope`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); scope.launch(function* () { try { yield awaitCancelation(); } finally { const asyncValue = this.callAsync(function* () { return 1; }); const value = yield* this.suspend(asyncValue); if (value === 1) { done(); } else { done(`unexpected result`); } } }); scope.cancel(); }); it(`calling another coroutine`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); scope.launch(function* () { const value = yield* this.call(function* () { return 1; }); if (value === 1) { done(); } else { done(`unexpected result`); } }); }); it(`calling another coroutine in finally block`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); const cancel = scope.launch(function* () { try { yield awaitCancelation(); } finally { yield wait(1); const value = yield* this.call(function* () { yield wait(1); return 1; }); if (value === 1) { done(); } else { done(`unexpected result`); } } }); cancel(); }); it(`calling another coroutine in finally block on canceled scope`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); scope.launch(function* () { try { yield awaitCancelation(); } finally { yield wait(1); const value = yield* this.call(function* () { yield wait(1); return 1; }); if (value === 1) { done(); } else { done(`unexpected result`); } } }); scope.cancel(); }); it(`completed coroutines are not longer referenced by scope`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); scope.launch(function* () { yield wait(1); }); setTimeout(() => { if (scope._cancelCallbacks.size === 0) { done(); } else { done(`scope still has reference to coroutine`); } }, 5); }); it(`completed flows are not longer referenced by scope`, (done) => { const scope = new Scope({ errorCallback: (error) => { done(error); }}); flowOf<number>((observer) => function*() { observer.emit(1); observer.emit(2); observer.emit(3); }).launchIn(scope); setTimeout(() => { if (scope._cancelCallbacks.size === 0) { done(); } else { done(`scope still has reference to coroutine`); } }, 5); }); });