From 32ab8bbd3daaa708f7b03400d470bb7d8d7e25f3 Mon Sep 17 00:00:00 2001 From: chuan6 Date: Sat, 11 Aug 2018 21:54:07 +0800 Subject: [PATCH 1/3] feat(interceptor): wrap() - empty condition --- package.json | 2 +- src/utils/interceptor.ts | 10 ++++++++++ test/app.ts | 1 + test/utils/index.ts | 1 + test/utils/interceptor.spec.ts | 23 +++++++++++++++++++++++ yarn.lock | 6 +++++- 6 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 src/utils/interceptor.ts create mode 100644 test/utils/index.ts create mode 100644 test/utils/interceptor.spec.ts diff --git a/package.json b/package.json index 123667669..a48056def 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,7 @@ "tslib": "^1.9.0", "tslint": "^5.10.0", "tslint-eslint-rules": "^5.2.0", - "typescript": "^2.8.3", + "typescript": "^3.0.1", "uuid": "^3.3.2" } } diff --git a/src/utils/interceptor.ts b/src/utils/interceptor.ts new file mode 100644 index 000000000..d90ec393b --- /dev/null +++ b/src/utils/interceptor.ts @@ -0,0 +1,10 @@ +import { Observable } from 'rxjs/Observable' + +type Gate = (...args: U) => Observable + +export function wrap( + gate: Gate, + _interceptor?: any +): (options?: {}) => (...args: U) => Observable { + return () => gate +} diff --git a/test/app.ts b/test/app.ts index 0cf16af35..6fe98e8ee 100644 --- a/test/app.ts +++ b/test/app.ts @@ -13,3 +13,4 @@ import './mock' import './apis' import './sockets' import './net' +import './utils/index' diff --git a/test/utils/index.ts b/test/utils/index.ts new file mode 100644 index 000000000..21c0c3204 --- /dev/null +++ b/test/utils/index.ts @@ -0,0 +1 @@ +import './interceptor.spec' diff --git a/test/utils/interceptor.spec.ts b/test/utils/interceptor.spec.ts new file mode 100644 index 000000000..ee7d815ff --- /dev/null +++ b/test/utils/interceptor.spec.ts @@ -0,0 +1,23 @@ +import { expect } from 'chai' +import { it, describe } from 'tman' +import { Observable } from 'rxjs' +import * as ix from '../../src/utils/interceptor' + +describe.only('interceptor spec', () => { + it('wrap: empty condition for no-param gate function', function* () { + const result = 1 + const gate = () => Observable.of(result) + const emptyIntercepted = ix.wrap(gate) + yield emptyIntercepted()().do((x) => { + expect(x).to.equal(result) + }) + }) + + it('wrap: empty condition for has-param gate function', function* () { + const gate = (x: number, y: number) => Observable.of(x + y) + const emptyIntercepted = ix.wrap(gate) + yield emptyIntercepted()(1, 2).do((x) => { + expect(x).to.equal(3) + }) + }) +}) diff --git a/yarn.lock b/yarn.lock index 33f46693e..4de6b1ffa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2692,10 +2692,14 @@ typescript@^2.4.2: version "2.6.2" resolved "https://registry.npmjs.org/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" -typescript@^2.6.1, typescript@^2.8.3: +typescript@^2.6.1: version "2.8.3" resolved "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" +typescript@^3.0.1: + version "3.0.1" + resolved "https://registry.npmjs.org/typescript/-/typescript-3.0.1.tgz#43738f29585d3a87575520a4b93ab6026ef11fdb" + uglify-js@^2.6: version "2.8.29" resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" From 9ffa25374e7501ed2d3cf4cc076b00786224b15f Mon Sep 17 00:00:00 2001 From: chuan6 Date: Sat, 11 Aug 2018 22:44:14 +0800 Subject: [PATCH 2/3] feat(interceptor): wrap() - single interceptor --- src/utils/interceptor.ts | 4 +-- test/utils/interceptor.spec.ts | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/utils/interceptor.ts b/src/utils/interceptor.ts index d90ec393b..df5d7288a 100644 --- a/src/utils/interceptor.ts +++ b/src/utils/interceptor.ts @@ -4,7 +4,7 @@ type Gate = (...args: U) => Observable export function wrap( gate: Gate, - _interceptor?: any + interceptor: any = (_0: any, g: Gate, args: U) => g(...args) ): (options?: {}) => (...args: U) => Observable { - return () => gate + return (options: {} = {}) => (...args: U) => interceptor(options, gate, args) } diff --git a/test/utils/interceptor.spec.ts b/test/utils/interceptor.spec.ts index ee7d815ff..f2074ec36 100644 --- a/test/utils/interceptor.spec.ts +++ b/test/utils/interceptor.spec.ts @@ -20,4 +20,66 @@ describe.only('interceptor spec', () => { expect(x).to.equal(3) }) }) + + it('wrap: single interceptor for request', function* () { + const interceptor = (options: { checkDividedByZero: boolean }, gateFn: any, gateArgs: any[]) => { + if (options.checkDividedByZero) { + const divisor = gateArgs[1] + if (divisor === 0) { + return Observable.of(0) + } + } + return gateFn(...gateArgs) + } + const gate = (x: number, y: number) => Observable.of(x / y) + const wrapped = ix.wrap(gate, interceptor) + const intercepted = wrapped({ checkDividedByZero: true }) + yield intercepted(1, 0) + .do((x) => { + expect(x).to.equal(0) + }) + }) + + it('wrap: single interceptor for response', function* () { + const interceptor = (options: { catchError: boolean }, gateFn: any, gateArgs: any[]) => { + if (options.catchError) { + return gateFn(...gateArgs).catch((err: any) => Observable.of(err.message)) + } + return gateFn(...gateArgs) + } + const gate = () => Observable.throw(new Error('hello')) + const wrapped = ix.wrap(gate, interceptor) + const intercepted = wrapped({ catchError: true }) + yield intercepted() + .do((x) => { + expect(x).to.equal('hello') + }) + }) + + it('wrap: single interceptor for both request and response', function* () { + const interceptor = (options: { checkDividedByZero: boolean, catchError: boolean }, gateFn: any, gateArgs: any[]) => { + let result: Observable + if (options.checkDividedByZero) { + const divisor = gateArgs[1] + if (divisor === 0) { + result = Observable.throw(new Error('divided-by-zero')) + } else { + result = gateFn(...gateArgs) + } + } else { + result = gateFn(...gateArgs) + } + if (options.catchError) { + result = result.catch((err: any) => Observable.of(err.message)) + } + return result + } + const gate = (x: number, y: number) => Observable.of(x / y) + const wrapped = ix.wrap(gate, interceptor) + const intercepted = wrapped({ checkDividedByZero: true, catchError: true }) + yield intercepted(1, 0) + .do((x) => { + expect(x).to.equal('divided-by-zero') + }) + }) }) From a814b7d6a8402a9b96b45c9d86806c7de94246ed Mon Sep 17 00:00:00 2001 From: chuan6 Date: Mon, 13 Aug 2018 23:27:52 +0800 Subject: [PATCH 3/3] ...add test case: 1-to-multi-value Observable conversion --- test/utils/interceptor.spec.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/utils/interceptor.spec.ts b/test/utils/interceptor.spec.ts index f2074ec36..970a225d2 100644 --- a/test/utils/interceptor.spec.ts +++ b/test/utils/interceptor.spec.ts @@ -82,4 +82,30 @@ describe.only('interceptor spec', () => { expect(x).to.equal('divided-by-zero') }) }) + + it('wrap: one-value Observable to multi-value Observable conversion', function* () { + const cache = new Map([['leo', '你好,里奥']]) + const interceptor = (options: { cacheThenRefresh: boolean }, gateFn: any, gateArgs: any[]) => { + const request$ = gateFn(...gateArgs) + if (options.cacheThenRefresh) { + const userName = gateArgs[0] + const requestAndCache = request$.do((hello: string) => cache.set(userName, hello)) + return cache.has(userName) + ? requestAndCache.startWith(cache.get(userName)) + : requestAndCache + } else { + return request$ + } + } + const gate = (userName: string) => { + return Observable.of(`hello ${userName}`) + } + const wrapped = ix.wrap(gate, interceptor) + const intercepted = wrapped({ cacheThenRefresh: true }) + yield intercepted('leo').take(2).toArray() + .do((xs) => { + expect(xs).to.deep.equal(['你好,里奥', 'hello leo']) + expect(cache.get('leo')).to.equal('hello leo') + }) + }) })