Skip to content

Commit 7303332

Browse files
author
Glynn Bird
committed
added test coverage output and ensure 100% test coverage of lib/nano.js
1 parent 470ae5e commit 7303332

File tree

4 files changed

+102
-6
lines changed

4 files changed

+102
-6
lines changed

lib/nano.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,18 @@ export default function Nano(cfg) {
100100
}
101101

102102
function scrubRequest(req, cloned) {
103-
// scrub credentials
104-
req.url = scrubURL(req.url)
103+
// scrub
104+
if (req.url) {
105+
req.url = scrubURL(req.url)
106+
}
105107
if (req.headers.cookie) {
106-
req.headers.cookie = 'XXXXXXX'
108+
req.headers.cookie = SCRUBBED_STR
107109
}
108110
if (req.headers.Authorization) {
109-
req.headers.Authorization = 'XXXXXXX'
111+
req.headers.Authorization = SCRUBBED_STR
112+
}
113+
if (req.headers['set-cookie']) {
114+
req.headers['set-cookie'] = SCRUBBED_STR
110115
}
111116
}
112117

@@ -195,7 +200,9 @@ export default function Nano(cfg) {
195200
}
196201

197202
// either return the output
198-
log({ err: null, body: output, headers: response.headers })
203+
const loggedObj = { err: null, body: output, headers: Object.fromEntries(response.headers) }
204+
scrubRequest(loggedObj)
205+
log(loggedObj)
199206
if (response.ok) return output
200207

201208
// or throw an Error

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
"typescript": "^5.9.2"
2626
},
2727
"scripts": {
28-
"test": "tsc lib/nano.d.ts && node --test ./test/*.test.js"
28+
"test": "tsc lib/nano.d.ts && node --experimental-test-coverage --test ./test/*.test.js"
2929
},
3030
"main": "./lib/nano.js",
3131
"types": "./lib/nano.d.ts",

test/nano.basic.test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed under the Apache License, Version 2.0 (the 'License'); you may not
2+
// use this file except in compliance with the License. You may obtain a copy of
3+
// the License at
4+
//
5+
// http://www.apache.org/licenses/LICENSE-2.0
6+
//
7+
// Unless required by applicable law or agreed to in writing, software
8+
// distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
9+
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
// License for the specific language governing permissions and limitations under
11+
// the License.
12+
13+
import test from 'node:test'
14+
import assert from 'node:assert/strict'
15+
import { COUCH_URL, mockAgent, mockPool, JSON_HEADERS } from './mock.js'
16+
import Nano from '../lib/nano.js'
17+
const username = 'username'
18+
const password = 'password'
19+
const nano = Nano(`http://${username}:${password}@127.0.0.1:5984`)
20+
21+
test('should be able to authenticate with basic auth', async () => {
22+
// mocks
23+
const response = ['replicator']
24+
25+
mockPool
26+
.intercept({
27+
path: '/_all_dbs',
28+
headers: {
29+
Authorization: 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='
30+
}
31+
})
32+
.reply(200, response, JSON_HEADERS)
33+
34+
// test POST /_session
35+
const p = await nano.db.list()
36+
assert.deepEqual(p, response)
37+
mockAgent.assertNoPendingInterceptors()
38+
})

test/nano.logger.test.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,54 @@ test('should be able to log output with user-defined function', async () => {
3838
assert.equal(logs.length, 2)
3939
mockAgent.assertNoPendingInterceptors()
4040
})
41+
42+
test('should be able to log output with cookie auth', async () => {
43+
// setup Nano with custom logger
44+
const logs = []
45+
const nano = Nano({
46+
url: COUCH_URL,
47+
log: (data) => {
48+
logs.push(data)
49+
}
50+
})
51+
52+
// mocks
53+
// mocks
54+
const username = 'u'
55+
const password = 'p'
56+
const response = { ok: true, name: 'admin', roles: ['_admin', 'admin'] }
57+
const c = 'AuthSession=YWRtaW46NUU0MTFBMDE6stHsxYnlDy4mYxwZEcnXHn4fm5w'
58+
const cookie = `${c}; Version=1; Expires=Mon, 10-Feb-2050 09:03:21 GMT; Max-Age=600; Path=/; HttpOnly`
59+
60+
mockPool
61+
.intercept({
62+
method: 'post',
63+
path: '/_session',
64+
body: JSON.stringify({ name: username, password })
65+
})
66+
.reply(200, response, {
67+
headers: {
68+
'content-type': 'application/json',
69+
'Set-Cookie': cookie
70+
}
71+
})
72+
mockPool
73+
.intercept({
74+
path: '/_all_dbs',
75+
headers: {
76+
cookie: c
77+
}
78+
})
79+
.reply(200, ['a'], JSON_HEADERS)
80+
81+
// test POST /_session
82+
const p = await nano.auth(username, password)
83+
assert.deepEqual(p, response)
84+
const q = await nano.db.list()
85+
assert.deepEqual(q, ['a'])
86+
assert.equal(logs.length, 4)
87+
// check set-cookie and cookie are scrubbed
88+
assert.equal(logs[1].headers['set-cookie'], 'XXXXXX')
89+
assert.equal(logs[2].headers['cookie'], 'XXXXXX')
90+
mockAgent.assertNoPendingInterceptors()
91+
})

0 commit comments

Comments
 (0)