Skip to content
This repository was archived by the owner on Nov 9, 2023. It is now read-only.

Commit 6509b94

Browse files
authored
Full test coverage (#52)
* 100% test coverage everywhere * add nyc config, check coverage, use in CI * add next handler test case * add async handle tests * add sinon; use stub
1 parent 2860ab9 commit 6509b94

5 files changed

Lines changed: 240 additions & 4 deletions

File tree

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
at: .
5656
- run:
5757
name: Unit tests
58-
command: yarn test
58+
command: yarn coverage
5959

6060
all-tests-pass:
6161
docker:

nyc.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
branches: 100,
3+
lines: 100,
4+
functions: 100,
5+
statements: 100,
6+
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"lint": "eslint . --ext js,json",
1414
"lint:fix": "eslint . --ext js,json --fix",
1515
"test": "mocha ./test",
16-
"coverage": "nyc yarn test"
16+
"coverage": "nyc --check-coverage yarn test"
1717
},
1818
"dependencies": {
1919
"eth-rpc-errors": "^2.1.1",
@@ -26,7 +26,8 @@
2626
"eslint-plugin-json": "^2.1.0",
2727
"eslint-plugin-mocha": "^6.3.0",
2828
"mocha": "^7.1.1",
29-
"nyc": "^15.0.0"
29+
"nyc": "^15.0.0",
30+
"sinon": "^9.0.2"
3031
},
3132
"repository": {
3233
"type": "git",
Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
'use strict'
33

44
const { strict: assert } = require('assert')
5+
const { stub } = require('sinon')
56
const RpcEngine = require('../src')
67

7-
describe('basic tests', function () {
8+
describe('RpcEngine tests', function () {
89
it('basic middleware test 1', function (done) {
910
const engine = new RpcEngine()
1011

@@ -43,6 +44,21 @@ describe('basic tests', function () {
4344
})
4445
})
4546

47+
it('basic middleware test (async)', async function () {
48+
const engine = new RpcEngine()
49+
50+
engine.push(function (_req, res, _next, end) {
51+
res.result = 42
52+
end()
53+
})
54+
55+
const payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
56+
57+
const res = await engine.handle(payload)
58+
assert.ok(res, 'has res')
59+
assert.equal(res.result, 42, 'has expected result')
60+
})
61+
4662
it('allow null result', function (done) {
4763
const engine = new RpcEngine()
4864

@@ -84,6 +100,28 @@ describe('basic tests', function () {
84100
})
85101
})
86102

103+
it('middleware ending request before all middlewares applied', function (done) {
104+
const engine = new RpcEngine()
105+
106+
engine.push(function (_req, res, _next, end) {
107+
res.result = 42
108+
end()
109+
})
110+
111+
engine.push(function (_req, _res, _next, _end) {
112+
assert.fail('should not have called second middleware')
113+
})
114+
115+
const payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
116+
117+
engine.handle(payload, function (err, res) {
118+
assert.ifError(err, 'did not error')
119+
assert.ok(res, 'has res')
120+
assert.equal(res.result, 42, 'has expected result')
121+
done()
122+
})
123+
})
124+
87125
it('erroring middleware test: end(error)', function (done) {
88126
const engine = new RpcEngine()
89127

@@ -185,6 +223,37 @@ describe('basic tests', function () {
185223
})
186224
})
187225

226+
it('handle batch payloads (async signature)', async function () {
227+
const engine = new RpcEngine()
228+
229+
engine.push(function (req, res, _next, end) {
230+
if (req.id === 4) {
231+
delete res.result
232+
res.error = new Error('foobar')
233+
return end(res.error)
234+
}
235+
res.result = req.id
236+
return end()
237+
})
238+
239+
const payloadA = { id: 1, jsonrpc: '2.0', method: 'hello' }
240+
const payloadB = { id: 2, jsonrpc: '2.0', method: 'hello' }
241+
const payloadC = { id: 3, jsonrpc: '2.0', method: 'hello' }
242+
const payloadD = { id: 4, jsonrpc: '2.0', method: 'hello' }
243+
const payloadE = { id: 5, jsonrpc: '2.0', method: 'hello' }
244+
const payload = [payloadA, payloadB, payloadC, payloadD, payloadE]
245+
246+
const res = await engine.handle(payload)
247+
assert.ok(res, 'has res')
248+
assert.ok(Array.isArray(res), 'res is array')
249+
assert.equal(res[0].result, 1, 'has expected result')
250+
assert.equal(res[1].result, 2, 'has expected result')
251+
assert.equal(res[2].result, 3, 'has expected result')
252+
assert.ok(!res[3].result, 'has no result')
253+
assert.equal(res[3].error.code, -32603, 'has expected error')
254+
assert.equal(res[4].result, 5, 'has expected result')
255+
})
256+
188257
it('basic notifications', function (done) {
189258
const engine = new RpcEngine()
190259

@@ -286,4 +355,72 @@ describe('basic tests', function () {
286355
done()
287356
})
288357
})
358+
359+
it('handles error in next handler', function (done) {
360+
const engine = new RpcEngine()
361+
362+
engine.push(function (_req, _res, next, _end) {
363+
next(function (_cb) {
364+
throw new Error('foo')
365+
})
366+
})
367+
368+
engine.push(function (_req, res, _next, end) {
369+
res.result = 42
370+
end()
371+
})
372+
373+
const payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
374+
375+
engine.handle(payload, (err, _res) => {
376+
assert.ok(err, 'did error')
377+
assert.equal(err.message, 'foo', 'error has expected message')
378+
done()
379+
})
380+
})
381+
382+
it('handles failure to end request', function (done) {
383+
const engine = new RpcEngine()
384+
385+
engine.push(function (_req, res, next, _end) {
386+
res.result = 42
387+
next()
388+
})
389+
390+
const payload = { id: 1, jsonrpc: '2.0', method: 'hello' }
391+
392+
engine.handle(payload, (err, res) => {
393+
assert.ok(err, 'should have errored')
394+
assert.ok(
395+
err.message.startsWith('JsonRpcEngine: Nothing ended request:'),
396+
'should have expected error message',
397+
)
398+
assert.ok(!res.result, 'should not have result')
399+
done()
400+
})
401+
})
402+
403+
it('handles batch request processing error', function (done) {
404+
const engine = new RpcEngine()
405+
stub(engine, '_promiseHandle').throws(new Error('foo'))
406+
407+
engine.handle([{}], (err) => {
408+
assert.ok(err, 'did error')
409+
assert.equal(err.message, 'foo', 'error has expected message')
410+
done()
411+
})
412+
})
413+
414+
it('handles batch request processing error (async)', async function () {
415+
const engine = new RpcEngine()
416+
stub(engine, '_promiseHandle').throws(new Error('foo'))
417+
418+
try {
419+
await engine.handle([{}])
420+
assert.fail('should have errored')
421+
} catch (err) {
422+
assert.ok(err, 'did error')
423+
assert.equal(err.message, 'foo', 'error has expected message')
424+
}
425+
})
289426
})

yarn.lock

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,42 @@
155155
resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-2.1.0.tgz#36b5592ed5e322750b790959517fcb4aaaff9896"
156156
integrity sha512-MjpcXCeMu8hULHxqgrgtvYYsZQHpsOWM4VF4DzKMquXAfaaNgiAvcAT1lKeqYD+RobBf/kqChCu5ASysnmTC1Q==
157157

158+
"@sinonjs/commons@^1", "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.7.2":
159+
version "1.8.1"
160+
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
161+
integrity sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==
162+
dependencies:
163+
type-detect "4.0.8"
164+
165+
"@sinonjs/fake-timers@^6.0.0", "@sinonjs/fake-timers@^6.0.1":
166+
version "6.0.1"
167+
resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40"
168+
integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==
169+
dependencies:
170+
"@sinonjs/commons" "^1.7.0"
171+
172+
"@sinonjs/formatio@^5.0.1":
173+
version "5.0.1"
174+
resolved "https://registry.yarnpkg.com/@sinonjs/formatio/-/formatio-5.0.1.tgz#f13e713cb3313b1ab965901b01b0828ea6b77089"
175+
integrity sha512-KaiQ5pBf1MpS09MuA0kp6KBQt2JUOQycqVG1NZXvzeaXe5LGFqAKueIS0bw4w0P9r7KuBSVdUk5QjXsUdu2CxQ==
176+
dependencies:
177+
"@sinonjs/commons" "^1"
178+
"@sinonjs/samsam" "^5.0.2"
179+
180+
"@sinonjs/samsam@^5.0.2", "@sinonjs/samsam@^5.0.3":
181+
version "5.0.3"
182+
resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-5.0.3.tgz#86f21bdb3d52480faf0892a480c9906aa5a52938"
183+
integrity sha512-QucHkc2uMJ0pFGjJUDP3F9dq5dx8QIaqISl9QgwLOh6P9yv877uONPGXh/OH/0zmM3tW1JjuJltAZV2l7zU+uQ==
184+
dependencies:
185+
"@sinonjs/commons" "^1.6.0"
186+
lodash.get "^4.4.2"
187+
type-detect "^4.0.8"
188+
189+
"@sinonjs/text-encoding@^0.7.1":
190+
version "0.7.1"
191+
resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz#8da5c6530915653f3a1f38fd5f101d8c3f8079c5"
192+
integrity sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==
193+
158194
"@types/color-name@^1.1.1":
159195
version "1.1.1"
160196
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
@@ -514,6 +550,11 @@ diff@3.5.0:
514550
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
515551
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
516552

553+
diff@^4.0.2:
554+
version "4.0.2"
555+
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
556+
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
557+
517558
doctrine@1.5.0:
518559
version "1.5.0"
519560
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
@@ -1206,6 +1247,11 @@ is-windows@^1.0.2:
12061247
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
12071248
integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==
12081249

1250+
isarray@0.0.1:
1251+
version "0.0.1"
1252+
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
1253+
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
1254+
12091255
isarray@^1.0.0:
12101256
version "1.0.0"
12111257
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -1320,6 +1366,11 @@ jsonc-parser@^2.2.1:
13201366
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-2.2.1.tgz#db73cd59d78cce28723199466b2a03d1be1df2bc"
13211367
integrity sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w==
13221368

1369+
just-extend@^4.0.2:
1370+
version "4.1.0"
1371+
resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-4.1.0.tgz#7278a4027d889601640ee0ce0e5a00b992467da4"
1372+
integrity sha512-ApcjaOdVTJ7y4r08xI5wIqpvwS48Q0PBG4DJROcEkH1f8MdAiNFyFxz3xoL0LWAVwjrwPYZdVHHxhRHcx/uGLA==
1373+
13231374
levn@^0.3.0, levn@~0.3.0:
13241375
version "0.3.0"
13251376
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
@@ -1366,6 +1417,11 @@ lodash.flattendeep@^4.4.0:
13661417
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
13671418
integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=
13681419

1420+
lodash.get@^4.4.2:
1421+
version "4.4.2"
1422+
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
1423+
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
1424+
13691425
lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15:
13701426
version "4.17.19"
13711427
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
@@ -1469,6 +1525,17 @@ nice-try@^1.0.4:
14691525
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
14701526
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
14711527

1528+
nise@^4.0.1:
1529+
version "4.0.4"
1530+
resolved "https://registry.yarnpkg.com/nise/-/nise-4.0.4.tgz#d73dea3e5731e6561992b8f570be9e363c4512dd"
1531+
integrity sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==
1532+
dependencies:
1533+
"@sinonjs/commons" "^1.7.0"
1534+
"@sinonjs/fake-timers" "^6.0.0"
1535+
"@sinonjs/text-encoding" "^0.7.1"
1536+
just-extend "^4.0.2"
1537+
path-to-regexp "^1.7.0"
1538+
14721539
node-environment-flags@1.0.6:
14731540
version "1.0.6"
14741541
resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088"
@@ -1725,6 +1792,13 @@ path-parse@^1.0.6:
17251792
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
17261793
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
17271794

1795+
path-to-regexp@^1.7.0:
1796+
version "1.8.0"
1797+
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
1798+
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
1799+
dependencies:
1800+
isarray "0.0.1"
1801+
17281802
path-type@^2.0.0:
17291803
version "2.0.0"
17301804
resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
@@ -1950,6 +2024,19 @@ signal-exit@^3.0.2:
19502024
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
19512025
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
19522026

2027+
sinon@^9.0.2:
2028+
version "9.0.2"
2029+
resolved "https://registry.yarnpkg.com/sinon/-/sinon-9.0.2.tgz#b9017e24633f4b1c98dfb6e784a5f0509f5fd85d"
2030+
integrity sha512-0uF8Q/QHkizNUmbK3LRFqx5cpTttEVXudywY9Uwzy8bTfZUhljZ7ARzSxnRHWYWtVTeh4Cw+tTb3iU21FQVO9A==
2031+
dependencies:
2032+
"@sinonjs/commons" "^1.7.2"
2033+
"@sinonjs/fake-timers" "^6.0.1"
2034+
"@sinonjs/formatio" "^5.0.1"
2035+
"@sinonjs/samsam" "^5.0.3"
2036+
diff "^4.0.2"
2037+
nise "^4.0.1"
2038+
supports-color "^7.1.0"
2039+
19532040
slice-ansi@^2.1.0:
19542041
version "2.1.0"
19552042
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636"
@@ -2193,6 +2280,11 @@ type-check@~0.3.2:
21932280
dependencies:
21942281
prelude-ls "~1.1.2"
21952282

2283+
type-detect@4.0.8, type-detect@^4.0.8:
2284+
version "4.0.8"
2285+
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
2286+
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
2287+
21962288
type-fest@^0.8.0, type-fest@^0.8.1:
21972289
version "0.8.1"
21982290
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"

0 commit comments

Comments
 (0)