From 9a0b8b89a09f35e12b603ca08c3d2f1554e4ed2c Mon Sep 17 00:00:00 2001 From: Matt Ringer Date: Wed, 13 Jun 2018 11:29:49 -0700 Subject: [PATCH 1/6] rebase to master --- src/helper.ts | 36 ++++++++++++++- test/unit/helper_spec.js | 99 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/src/helper.ts b/src/helper.ts index c2a73c9..dd31faa 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -1,4 +1,6 @@ +import { createResolver } from "./resolver"; import * as merge from "deepmerge"; +import { isFunction } from "./util"; // Helper function to combine multiple resolver definition hashes into a single hash for consumption by Apollostack's graphql-server export const combineResolvers = (resolvers = []) => resolvers @@ -26,4 +28,36 @@ export const or = (...conditions) => resolver => (...query) => { }); attempt(0); }); -} \ No newline at end of file +} + +export class Composable { + resolver: any; // stricter types won't pass the compiler because createResolver is unexpected on Funciton. + + /** + * + * @param resolver + * TODO: a Resolver type is probably needed, but outside the scope of this PR because it requires refactoring resolver.ts + */ + constructor(resFn, errFn) { + this.resolver = createResolver(resFn, errFn); + } + + /** + * + * @param resolvers + */ + public compose( resolvers: {} ) { + const composed = {}; + + Object.keys(resolvers).forEach(key => { + const resolver = resolvers[key]; + + composed[key] = (resolver.resolve || resolver.error) + ? this.resolver.createResolver(resolver.resolve, resolver.error) + : this.resolver.createResolver(resolver); + }); + + return composed; + } + +} diff --git a/test/unit/helper_spec.js b/test/unit/helper_spec.js index 394f4f8..72b5ea0 100644 --- a/test/unit/helper_spec.js +++ b/test/unit/helper_spec.js @@ -2,9 +2,10 @@ import { expect } from 'chai'; import { stub } from 'sinon'; import { - combineResolvers, and, or, + combineResolvers, and, or, compose, Composable } from '../../dist/helper'; import { createResolver } from '../../dist/resolver'; +import { resolveAll } from 'jspm-config'; describe('(unit) src/helper.js', () => { describe('combineResolvers', () => { @@ -174,4 +175,100 @@ describe('(unit) src/helper.js', () => { }); }); + + describe('Compose resolvers', () => { + const compositionErr = new Error('composition error'); + const successResolver = createResolver(() => null, () => null); + const failureResolver = createResolver(() => { throw compositionErr; }, () => null); + + it('composed resolvers are chained, and base resolver is called for each', () => { + + const b = { + resolve: () => {}, + error: d => compositionErr + }; + + stub(b, 'resolve', b.resolve); + + const base = new Composable(b.resolve, b.error); + const comp = base.compose({ + r1: () => true, + r2: () => true, + r3: () => true, + }); + + return Promise.all([ + + comp.r1().then(r => { + expect(b.resolve.calledThrice).to.be.true; + expect(r).to.be.true; + }), + + comp.r2().then(r => { + expect(b.resolve.calledThrice).to.be.true; + expect(r).to.be.true; + }), + + comp.r3().then(r => { + expect(r).to.be.true; + expect(b.resolve.calledThrice).to.be.true; + }) + + ]); + }); + + it('when base throws, child is not called ', () => { + + const b = { + resolve: null, + error: d => compositionErr + }; + + const r1 = { + resolve: () => true, + error: () => compositionErr + }; + + stub(b, 'error', b.error); + stub(r1, 'error', r1.error); + + const base = new Composable(b.resolve, b.error); + const comp = base.compose( { r1: r1 } ); + + comp.r1() + .catch( e => { + expect(b.error.calledOnce).to.be.true; + expect(r1.resolve.notCalled).to.be.true; + expect(r1.error.notCalled).to.be.true; + expect(e).to.equal(compositionErr); + }); + }); + + it('when child throws, parent error is called ', () => { + + const b = { + resolve: null, + error: d => null + }; + + const r1 = { + resolve: () => true, + error: () => compositionErr + }; + + stub(b, 'error', b.error); + stub(r1, 'error', r1.error); + + const base = new Composable(b.resolve, b.error); + const comp = base.compose( { r1: r1 } ); + + comp.r1() + .catch( e => { + expect(b.error.calledOnce).to.be.true; + expect(r1.error.calledOnce).to.be.true; + expect(e).to.equal(compositionErr); + }); + }); + + }); }); From d2d097f4739a24332c36d6099025a579d150e4c5 Mon Sep 17 00:00:00 2001 From: Matt Ringer Date: Wed, 13 Jun 2018 11:33:38 -0700 Subject: [PATCH 2/6] rebase --- src/helper.ts | 40 ++++++++++------------ test/unit/helper_spec.js | 73 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 28 deletions(-) diff --git a/src/helper.ts b/src/helper.ts index dd31faa..acddecb 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -30,34 +30,28 @@ export const or = (...conditions) => resolver => (...query) => { }); } -export class Composable { - resolver: any; // stricter types won't pass the compiler because createResolver is unexpected on Funciton. - - /** - * - * @param resolver - * TODO: a Resolver type is probably needed, but outside the scope of this PR because it requires refactoring resolver.ts - */ - constructor(resFn, errFn) { - this.resolver = createResolver(resFn, errFn); - } - - /** - * - * @param resolvers - */ - public compose( resolvers: {} ) { +/** + * Constructs a composable resolver with the same arguments as createResolver. + * The composable resolver provides the compose method which takes an object of named resolver functions. + * @param resFn resolver function + * @param errFn error handler + */ +export const composable = (resFn, errFn) => { + const baseResolver = createResolver(resFn, errFn); + + baseResolver['compose'] = ( resolvers: {} ) => { const composed = {}; - Object.keys(resolvers).forEach(key => { const resolver = resolvers[key]; - - composed[key] = (resolver.resolve || resolver.error) - ? this.resolver.createResolver(resolver.resolve, resolver.error) - : this.resolver.createResolver(resolver); + // composed[key] = baseResolver['createResolver'](resolver); + composed[key] = (resolver.resolve || resolver.error) + // supports syntax: compose( { myResolver: { resolve: resFn, error: errFn } } ) + ? baseResolver['createResolver'](resolver.resolve, resolver.error) + // suports syntax: compose( { myResolver: resolver } ) + : baseResolver['createResolver'](resolver); }); - return composed; } + return baseResolver; } diff --git a/test/unit/helper_spec.js b/test/unit/helper_spec.js index 72b5ea0..ced2e2c 100644 --- a/test/unit/helper_spec.js +++ b/test/unit/helper_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { stub } from 'sinon'; import { - combineResolvers, and, or, compose, Composable + combineResolvers, and, or, compose, composable } from '../../dist/helper'; import { createResolver } from '../../dist/resolver'; import { resolveAll } from 'jspm-config'; @@ -190,7 +190,7 @@ describe('(unit) src/helper.js', () => { stub(b, 'resolve', b.resolve); - const base = new Composable(b.resolve, b.error); + const base = composable(b.resolve, b.error); const comp = base.compose({ r1: () => true, r2: () => true, @@ -232,7 +232,7 @@ describe('(unit) src/helper.js', () => { stub(b, 'error', b.error); stub(r1, 'error', r1.error); - const base = new Composable(b.resolve, b.error); + const base = composable(b.resolve, b.error); const comp = base.compose( { r1: r1 } ); comp.r1() @@ -245,7 +245,6 @@ describe('(unit) src/helper.js', () => { }); it('when child throws, parent error is called ', () => { - const b = { resolve: null, error: d => null @@ -259,7 +258,7 @@ describe('(unit) src/helper.js', () => { stub(b, 'error', b.error); stub(r1, 'error', r1.error); - const base = new Composable(b.resolve, b.error); + const base = composable(b.resolve, b.error); const comp = base.compose( { r1: r1 } ); comp.r1() @@ -270,5 +269,69 @@ describe('(unit) src/helper.js', () => { }); }); + it('composed resolvers with { resolve: resFn, error: resFn } syntax, resolve and bubble errors correctly', () => { + + const b = { + resolve: () => {}, + error: d => compositionErr + }; + + const r1 = { + resolve: () => { throw Error('some other error') }, + error: () => compositionErr }; + + const r2 = { resolve: () => 'r2Result', error: () => compositionErr }; + + stub(b, 'resolve', b.resolve); + stub(r1, 'error', r1.error); + stub(r1, 'resolve', r1.resolve); + stub(r2, 'resolve', r2.resolve); + stub(r2, 'error', r2.error); + + const base = composable(b.resolve, b.error); + const comp = base.compose({ + r1: r1, + r2: r2, + }); + + return Promise.all([ + comp.r1().catch(e => { + expect(e).to.equal(compositionErr); + }), + comp.r2().then(r => { + expect(r).to.equal('r2Result'); + }), + + ]).then(()=> { + expect(r1.resolve.calledOnce).to.be.true; + expect(r1.error.calledOnce).to.be.true; + expect(r2.resolve.calledOnce).to.be.true; + expect(r2.error.notCalled).to.be.true; + }); + }); + + it('composed result has correct structure', () => { + + const b = { + resolve: () => {}, + error: d => compositionErr + }; + + stub(b, 'resolve', b.resolve); + + const base = composable(b.resolve, b.error); + const comp = base.compose({ + r1: { resolve: () => { throw Error('some other error') }, error: () => compositionErr }, + r2: { resolve: () => 'r2Result', error: () => compositionErr }, + r3: {} // should this throw an exception since it is not a resolver or createResolver params? + }); + + console.log(typeof Function); + expect(comp.r1).to.be.a(typeof Function); + expect(comp.r2).to.be.a(typeof Function); + expect(comp.r3).to.be.a(typeof Function); + + }); + }); }); From bc95b73fa14e592fcbbdd9adb077b741b6a3d960 Mon Sep 17 00:00:00 2001 From: Matt Ringer Date: Wed, 13 Jun 2018 11:34:46 -0700 Subject: [PATCH 3/6] rebase --- src/helper.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/helper.ts b/src/helper.ts index acddecb..ecf3ea0 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -33,8 +33,13 @@ export const or = (...conditions) => resolver => (...query) => { /** * Constructs a composable resolver with the same arguments as createResolver. * The composable resolver provides the compose method which takes an object of named resolver functions. - * @param resFn resolver function - * @param errFn error handler + * The resolvers object can contain, constructed resolver functions or { resolve: fn, error: fn } params + * to construct a new resolver. Compose returns an object of resolvers who inherit from the baseResolver + * on which compose was called. + * + * @param resFn: resolver function + * @param errFn: error handler + * @returns resolverFn: { createResolver(resFn, errFn), compose({ resolvers }): { composed resolvers } ...} */ export const composable = (resFn, errFn) => { const baseResolver = createResolver(resFn, errFn); @@ -43,7 +48,6 @@ export const composable = (resFn, errFn) => { const composed = {}; Object.keys(resolvers).forEach(key => { const resolver = resolvers[key]; - // composed[key] = baseResolver['createResolver'](resolver); composed[key] = (resolver.resolve || resolver.error) // supports syntax: compose( { myResolver: { resolve: resFn, error: errFn } } ) ? baseResolver['createResolver'](resolver.resolve, resolver.error) From da50b096715f45c24944e9dc242872812f1ad11f Mon Sep 17 00:00:00 2001 From: Matt Ringer Date: Fri, 18 May 2018 12:20:21 -0700 Subject: [PATCH 4/6] replace babel-preset-es2015 with babel-preset-env for deprecation add babel-plugin-transform-object-rest-spread for spread syntax support add test to cover spreading composed into object. --- .babelrc | 5 +++-- package.json | 3 ++- test/unit/helper_spec.js | 12 +++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.babelrc b/.babelrc index 1b790bf..49ae8b2 100644 --- a/.babelrc +++ b/.babelrc @@ -1,4 +1,5 @@ { - "presets": ["es2015"], - "sourceMaps": true + "presets": ["env"], + "sourceMaps": true, + "plugins": ["transform-object-rest-spread"] } diff --git a/package.json b/package.json index bd8ba92..c39ba82 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "babel-cli": "^6.18.0", "babel-core": "^6.17.0", "babel-eslint": "^7.0.0", - "babel-preset-es2015": "^6.16.0", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-preset-env": "^1.7.0", "babel-register": "^6.18.0", "bluebird": "^3.5.0", "chai": "^3.5.0", diff --git a/test/unit/helper_spec.js b/test/unit/helper_spec.js index ced2e2c..6e043d2 100644 --- a/test/unit/helper_spec.js +++ b/test/unit/helper_spec.js @@ -323,13 +323,15 @@ describe('(unit) src/helper.js', () => { const comp = base.compose({ r1: { resolve: () => { throw Error('some other error') }, error: () => compositionErr }, r2: { resolve: () => 'r2Result', error: () => compositionErr }, - r3: {} // should this throw an exception since it is not a resolver or createResolver params? + r3: {} // should we throw an exception since it is not a resolver or createResolver params? }); - console.log(typeof Function); - expect(comp.r1).to.be.a(typeof Function); - expect(comp.r2).to.be.a(typeof Function); - expect(comp.r3).to.be.a(typeof Function); + const composed = { r0: () => {}, ...comp }; + + expect(composed.r0).to.be.a(typeof Function); + expect(composed.r1).to.be.a(typeof Function); + expect(composed.r2).to.be.a(typeof Function); + expect(composed.r3).to.be.a(typeof Function); }); From 3593237a8ef9dee5295d9bfb52cb9a2bfd030f4b Mon Sep 17 00:00:00 2001 From: Matt Ringer Date: Wed, 13 Jun 2018 12:14:03 -0700 Subject: [PATCH 5/6] interate compose method into createResolver instead of a separate helper --- src/helper.ts | 34 ++++---- src/resolver.ts | 19 +++++ test/unit/helper_spec.js | 161 ------------------------------------- test/unit/resolver_spec.js | 161 +++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 178 deletions(-) diff --git a/src/helper.ts b/src/helper.ts index ecf3ea0..f0b5f62 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -1,4 +1,4 @@ -import { createResolver } from "./resolver"; +import { createResolver, ResultFunction, ErrorFunction, Resolver } from "./resolver"; import * as merge from "deepmerge"; import { isFunction } from "./util"; @@ -41,21 +41,21 @@ export const or = (...conditions) => resolver => (...query) => { * @param errFn: error handler * @returns resolverFn: { createResolver(resFn, errFn), compose({ resolvers }): { composed resolvers } ...} */ -export const composable = (resFn, errFn) => { - const baseResolver = createResolver(resFn, errFn); +// export const composable = (resFn: ResultFunction, errFn: ErrorFunction) => { +// const baseResolver = createResolver(resFn, errFn); - baseResolver['compose'] = ( resolvers: {} ) => { - const composed = {}; - Object.keys(resolvers).forEach(key => { - const resolver = resolvers[key]; - composed[key] = (resolver.resolve || resolver.error) - // supports syntax: compose( { myResolver: { resolve: resFn, error: errFn } } ) - ? baseResolver['createResolver'](resolver.resolve, resolver.error) - // suports syntax: compose( { myResolver: resolver } ) - : baseResolver['createResolver'](resolver); - }); - return composed; - } +// baseResolver['compose'] = ( resolvers: {} ) => { +// const composed = {}; +// Object.keys(resolvers).forEach(key => { +// const _resolver = resolvers[key]; +// composed[key] = (_resolver.resolve || _resolver.error) +// // supports syntax: compose( { myResolver: { resolve: resFn, error: errFn } } ) +// ? baseResolver.createResolver(_resolver.resolve, _resolver.error) +// // supports syntax: compose( { myResolver: resolver } ) +// : baseResolver.createResolver(_resolver); +// }); +// return composed; +// } - return baseResolver; -} +// return baseResolver; +// } diff --git a/src/resolver.ts b/src/resolver.ts index a734582..bf4cd91 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -15,9 +15,14 @@ export interface CreateResolverFunction { (resFn: ResultFunction, errFn?: ErrorFunction): Resolver } +export interface ComposeResolversFunction { + ( resolvers: any ): {} // { [name: string]: Resolver | {} } +} + export interface Resolver { (root, args: {}, context: {}, info: {}): Promise createResolver?: CreateResolverFunction + compose?: ComposeResolversFunction } export const createResolver: CreateResolverFunction = (resFn: ResultFunction, errFn: ErrorFunction) => { @@ -38,6 +43,7 @@ export const createResolver: CreateResolverFunction = (resFn: ResultFuncti }); }); }; + baseResolver.createResolver = (cResFn, cErrFn) => { const Promise = getPromise(); @@ -74,5 +80,18 @@ export const createResolver: CreateResolverFunction = (resFn: ResultFuncti return createResolver(childResFn, childErrFn); } + baseResolver.compose = ( resolvers: {} ) => { + const composed = {}; + Object.keys(resolvers).forEach(key => { + const _resolver = resolvers[key]; + composed[key] = (_resolver.resolve || _resolver.error) + // supports syntax: compose( { myResolver: { resolve: resFn, error: errFn } } ) + ? baseResolver.createResolver(_resolver.resolve, _resolver.error) + // supports syntax: compose( { myResolver: resolver } ) + : baseResolver.createResolver(_resolver); + }); + return composed; + } + return baseResolver; }; diff --git a/test/unit/helper_spec.js b/test/unit/helper_spec.js index 6e043d2..3485375 100644 --- a/test/unit/helper_spec.js +++ b/test/unit/helper_spec.js @@ -175,165 +175,4 @@ describe('(unit) src/helper.js', () => { }); }); - - describe('Compose resolvers', () => { - const compositionErr = new Error('composition error'); - const successResolver = createResolver(() => null, () => null); - const failureResolver = createResolver(() => { throw compositionErr; }, () => null); - - it('composed resolvers are chained, and base resolver is called for each', () => { - - const b = { - resolve: () => {}, - error: d => compositionErr - }; - - stub(b, 'resolve', b.resolve); - - const base = composable(b.resolve, b.error); - const comp = base.compose({ - r1: () => true, - r2: () => true, - r3: () => true, - }); - - return Promise.all([ - - comp.r1().then(r => { - expect(b.resolve.calledThrice).to.be.true; - expect(r).to.be.true; - }), - - comp.r2().then(r => { - expect(b.resolve.calledThrice).to.be.true; - expect(r).to.be.true; - }), - - comp.r3().then(r => { - expect(r).to.be.true; - expect(b.resolve.calledThrice).to.be.true; - }) - - ]); - }); - - it('when base throws, child is not called ', () => { - - const b = { - resolve: null, - error: d => compositionErr - }; - - const r1 = { - resolve: () => true, - error: () => compositionErr - }; - - stub(b, 'error', b.error); - stub(r1, 'error', r1.error); - - const base = composable(b.resolve, b.error); - const comp = base.compose( { r1: r1 } ); - - comp.r1() - .catch( e => { - expect(b.error.calledOnce).to.be.true; - expect(r1.resolve.notCalled).to.be.true; - expect(r1.error.notCalled).to.be.true; - expect(e).to.equal(compositionErr); - }); - }); - - it('when child throws, parent error is called ', () => { - const b = { - resolve: null, - error: d => null - }; - - const r1 = { - resolve: () => true, - error: () => compositionErr - }; - - stub(b, 'error', b.error); - stub(r1, 'error', r1.error); - - const base = composable(b.resolve, b.error); - const comp = base.compose( { r1: r1 } ); - - comp.r1() - .catch( e => { - expect(b.error.calledOnce).to.be.true; - expect(r1.error.calledOnce).to.be.true; - expect(e).to.equal(compositionErr); - }); - }); - - it('composed resolvers with { resolve: resFn, error: resFn } syntax, resolve and bubble errors correctly', () => { - - const b = { - resolve: () => {}, - error: d => compositionErr - }; - - const r1 = { - resolve: () => { throw Error('some other error') }, - error: () => compositionErr }; - - const r2 = { resolve: () => 'r2Result', error: () => compositionErr }; - - stub(b, 'resolve', b.resolve); - stub(r1, 'error', r1.error); - stub(r1, 'resolve', r1.resolve); - stub(r2, 'resolve', r2.resolve); - stub(r2, 'error', r2.error); - - const base = composable(b.resolve, b.error); - const comp = base.compose({ - r1: r1, - r2: r2, - }); - - return Promise.all([ - comp.r1().catch(e => { - expect(e).to.equal(compositionErr); - }), - comp.r2().then(r => { - expect(r).to.equal('r2Result'); - }), - - ]).then(()=> { - expect(r1.resolve.calledOnce).to.be.true; - expect(r1.error.calledOnce).to.be.true; - expect(r2.resolve.calledOnce).to.be.true; - expect(r2.error.notCalled).to.be.true; - }); - }); - - it('composed result has correct structure', () => { - - const b = { - resolve: () => {}, - error: d => compositionErr - }; - - stub(b, 'resolve', b.resolve); - - const base = composable(b.resolve, b.error); - const comp = base.compose({ - r1: { resolve: () => { throw Error('some other error') }, error: () => compositionErr }, - r2: { resolve: () => 'r2Result', error: () => compositionErr }, - r3: {} // should we throw an exception since it is not a resolver or createResolver params? - }); - - const composed = { r0: () => {}, ...comp }; - - expect(composed.r0).to.be.a(typeof Function); - expect(composed.r1).to.be.a(typeof Function); - expect(composed.r2).to.be.a(typeof Function); - expect(composed.r3).to.be.a(typeof Function); - - }); - - }); }); diff --git a/test/unit/resolver_spec.js b/test/unit/resolver_spec.js index d4cdb9a..1846185 100644 --- a/test/unit/resolver_spec.js +++ b/test/unit/resolver_spec.js @@ -197,4 +197,165 @@ describe('(unit) dist/resolver.js', () => { childResolver(null, null, null, { info: 'info' }) }) }) + + describe('Compose resolvers', () => { + const compositionErr = new Error('composition error'); + const successResolver = createResolver(() => null, () => null); + const failureResolver = createResolver(() => { throw compositionErr; }, () => null); + + it('composed resolvers are chained, and base resolver is called for each', () => { + + const b = { + resolve: () => {}, + error: d => compositionErr + }; + + stub(b, 'resolve', b.resolve); + + const base = createResolver(b.resolve, b.error); + const comp = base.compose({ + r1: () => true, + r2: () => true, + r3: () => true, + }); + + return Promise.all([ + + comp.r1().then(r => { + expect(b.resolve.calledThrice).to.be.true; + expect(r).to.be.true; + }), + + comp.r2().then(r => { + expect(b.resolve.calledThrice).to.be.true; + expect(r).to.be.true; + }), + + comp.r3().then(r => { + expect(r).to.be.true; + expect(b.resolve.calledThrice).to.be.true; + }) + + ]); + }); + + it('when base throws, child is not called ', () => { + + const b = { + resolve: null, + error: d => compositionErr + }; + + const r1 = { + resolve: () => true, + error: () => compositionErr + }; + + stub(b, 'error', b.error); + stub(r1, 'error', r1.error); + + const base = createResolver(b.resolve, b.error); + const comp = base.compose( { r1: r1 } ); + + comp.r1() + .catch( e => { + expect(b.error.calledOnce).to.be.true; + expect(r1.resolve.notCalled).to.be.true; + expect(r1.error.notCalled).to.be.true; + expect(e).to.equal(compositionErr); + }); + }); + + it('when child throws, parent error is called ', () => { + const b = { + resolve: null, + error: d => null + }; + + const r1 = { + resolve: () => true, + error: () => compositionErr + }; + + stub(b, 'error', b.error); + stub(r1, 'error', r1.error); + + const base = createResolver(b.resolve, b.error); + const comp = base.compose( { r1: r1 } ); + + comp.r1() + .catch( e => { + expect(b.error.calledOnce).to.be.true; + expect(r1.error.calledOnce).to.be.true; + expect(e).to.equal(compositionErr); + }); + }); + + it('composed resolvers with { resolve: resFn, error: resFn } syntax, resolve and bubble errors correctly', () => { + + const b = { + resolve: () => {}, + error: d => compositionErr + }; + + const r1 = { + resolve: () => { throw Error('some other error') }, + error: () => compositionErr }; + + const r2 = { resolve: () => 'r2Result', error: () => compositionErr }; + + stub(b, 'resolve', b.resolve); + stub(r1, 'error', r1.error); + stub(r1, 'resolve', r1.resolve); + stub(r2, 'resolve', r2.resolve); + stub(r2, 'error', r2.error); + + const base = createResolver(b.resolve, b.error); + const comp = base.compose({ + r1: r1, + r2: r2, + }); + + return Promise.all([ + comp.r1().catch(e => { + expect(e).to.equal(compositionErr); + }), + comp.r2().then(r => { + expect(r).to.equal('r2Result'); + }), + + ]).then(()=> { + expect(r1.resolve.calledOnce).to.be.true; + expect(r1.error.calledOnce).to.be.true; + expect(r2.resolve.calledOnce).to.be.true; + expect(r2.error.notCalled).to.be.true; + }); + }); + + it('composed result has correct structure', () => { + + const b = { + resolve: () => {}, + error: d => compositionErr + }; + + stub(b, 'resolve', b.resolve); + + const base = createResolver(b.resolve, b.error); + const comp = base.compose({ + r1: { resolve: () => { throw Error('some other error') }, error: () => compositionErr }, + r2: { resolve: () => 'r2Result', error: () => compositionErr }, + r3: {} // should we throw an exception since it is not a resolver or createResolver params? + }); + + const composed = { r0: () => {}, ...comp }; + + expect(composed.r0).to.be.a(typeof Function); + expect(composed.r1).to.be.a(typeof Function); + expect(composed.r2).to.be.a(typeof Function); + expect(composed.r3).to.be.a(typeof Function); + + }); + + }); }); From 42083afd5dc6d7f8114677b95c6de8776e5c3708 Mon Sep 17 00:00:00 2001 From: Matt Ringer Date: Wed, 13 Jun 2018 12:21:42 -0700 Subject: [PATCH 6/6] delete commented code --- src/helper.ts | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/helper.ts b/src/helper.ts index f0b5f62..1fb2d34 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -30,32 +30,3 @@ export const or = (...conditions) => resolver => (...query) => { }); } -/** - * Constructs a composable resolver with the same arguments as createResolver. - * The composable resolver provides the compose method which takes an object of named resolver functions. - * The resolvers object can contain, constructed resolver functions or { resolve: fn, error: fn } params - * to construct a new resolver. Compose returns an object of resolvers who inherit from the baseResolver - * on which compose was called. - * - * @param resFn: resolver function - * @param errFn: error handler - * @returns resolverFn: { createResolver(resFn, errFn), compose({ resolvers }): { composed resolvers } ...} - */ -// export const composable = (resFn: ResultFunction, errFn: ErrorFunction) => { -// const baseResolver = createResolver(resFn, errFn); - -// baseResolver['compose'] = ( resolvers: {} ) => { -// const composed = {}; -// Object.keys(resolvers).forEach(key => { -// const _resolver = resolvers[key]; -// composed[key] = (_resolver.resolve || _resolver.error) -// // supports syntax: compose( { myResolver: { resolve: resFn, error: errFn } } ) -// ? baseResolver.createResolver(_resolver.resolve, _resolver.error) -// // supports syntax: compose( { myResolver: resolver } ) -// : baseResolver.createResolver(_resolver); -// }); -// return composed; -// } - -// return baseResolver; -// }