diff --git a/src/JsonRpc.test.ts b/src/JsonRpc.test.ts index b801ec0..dba29b5 100644 --- a/src/JsonRpc.test.ts +++ b/src/JsonRpc.test.ts @@ -3,76 +3,68 @@ import JsonRpc, {ErrorCodes} from './JsonRpc'; const defer = (ms: number, val?: any) => new Promise(resolve => setTimeout(() => resolve(val), ms)); -it('handles requests', async () => { - const rpc = new JsonRpc({ - methods: { - hello: () => 'goodbye', - }, - }); - - const request = { - id: 123, - jsonrpc: '2.0', - method: 'hello', - }; - - const response = await (rpc as any).handleRequest(request); - expect(response).toEqual({ +describe('handling requests', () => { + let rpc: any; + const buildRequest = (method: string, params?: any[] | object) => ({ jsonrpc: '2.0', id: 123, - result: 'goodbye', + method, + params, }); -}); -it('waits on promise results', async () => { - const rpc = new JsonRpc({ - methods: { - deferred: () => Promise.resolve('deferredResult'), - }, + beforeEach(() => { + rpc = new JsonRpc({ + methods: { + hello: (name: string) => `goodbye ${name}`, + canVote: (voter: {age: number}) => voter.age > 18, + deferred: () => Promise.resolve('deferredResult'), + blowUp: () => { + throw Error('BOOM!'); + }, + }, + }); }); - const request = { - id: 123, - jsonrpc: '2.0', - method: 'deferred', - }; + it('handles array params', async () => { + const request = buildRequest('hello', ['Alice']); + const response = await rpc.handleRequest(request); - const response = await (rpc as any).handleRequest(request); - expect(response.result).toEqual('deferredResult'); -}); + expect(response.jsonrpc).toEqual('2.0'); + expect(response.id).toEqual(request.id); + expect(response.result).toEqual('goodbye Alice'); + }); -it('errors on missing method', async () => { - const rpc = new JsonRpc(); + it('handles object params', async () => { + const request = buildRequest('canVote', {age: 22}); + const response = await rpc.handleRequest(request); - const request = { - id: 123, - jsonrpc: '2.0', - method: 'missing', - }; + expect(response.jsonrpc).toEqual('2.0'); + expect(response.id).toEqual(request.id); + expect(response.result).toEqual(true); + }); - const response = await (rpc as any).handleRequest(request); - expect(response.id).toEqual(123); - expect(response.error.code).toEqual(ErrorCodes.MethodNotFound); -}); + it('waits on promise results', async () => { + const request = buildRequest('deferred'); + const response = await rpc.handleRequest(request); -it('errors on throwing method', async () => { - const rpc = new JsonRpc({ - methods: { - blowUp: () => { - throw Error('BOOM!'); - }, - }, + expect(response.result).toEqual('deferredResult'); }); - const request = { - id: 123, - jsonrpc: '2.0', - method: 'blowUp', - }; + it('errors on missing method', async () => { + const request = buildRequest('missing'); + const response = await rpc.handleRequest(request); - const response = await (rpc as any).handleRequest(request); - expect(response.id).toEqual(123); - expect(response.error.code).toEqual(ErrorCodes.InternalError); + expect(response.id).toEqual(request.id); + expect(response.error.code).toEqual(ErrorCodes.MethodNotFound); + }); + + it('errors on throwing method', async () => { + const request = buildRequest('blowUp'); + const response = await rpc.handleRequest(request); + + expect(response.id).toEqual(request.id); + expect(response.error.code).toEqual(ErrorCodes.InternalError); + }); }); describe('mounted', () => { diff --git a/src/JsonRpc.ts b/src/JsonRpc.ts index 8b45024..e4c80a6 100644 --- a/src/JsonRpc.ts +++ b/src/JsonRpc.ts @@ -59,6 +59,9 @@ const buildErrorResponse = (id: number) => (error: { }, }); +const ensureArray = (source: any) => + Array.isArray(source) ? source : [source]; + class JsonRpc { private methods: Methods; private destination: JsonRpcDestination; @@ -91,12 +94,21 @@ class JsonRpc { return promise; } + mount(source: EventTarget) { + this.source = source; + source.addEventListener('message', this.handleMessage); + } + + unmount() { + this.source.removeEventListener('message', this.handleMessage); + } + private handleRequest(request: JsonRpcRequest): Promise { return Promise.resolve() .then(() => { const method = this.methods[request.method]; return method - ? method.apply(null, request.params) + ? method.apply(null, ensureArray(request.params)) : Promise.reject({ code: ErrorCodes.MethodNotFound, message: 'Method not found', @@ -132,15 +144,6 @@ class JsonRpc { this.handleResponse(e.data); } }; - - mount(source: EventTarget) { - this.source = source; - source.addEventListener('message', this.handleMessage); - } - - unmount() { - this.source.removeEventListener('message', this.handleMessage); - } } export default JsonRpc;