Skip to content
This repository was archived by the owner on May 14, 2024. It is now read-only.

Commit 0ccbec6

Browse files
authored
Merge pull request #569 from ldapjs/client-options-tweaks
Clean up options checking and add some tests
2 parents eb4f665 + 5a31aba commit 0ccbec6

File tree

2 files changed

+70
-24
lines changed

2 files changed

+70
-24
lines changed

lib/client/index.js

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
1-
// Copyright 2012 Mark Cavage, Inc. All rights reserved.
1+
'use strict'
22

33
const logger = require('../logger')
44
const Client = require('./client')
55

6-
/// --- Functions
7-
8-
function xor () {
9-
var b = false
10-
for (var i = 0; i < arguments.length; i++) {
11-
if (arguments[i] && !b) {
12-
b = true
13-
} else if (arguments[i] && b) {
14-
return false
15-
}
16-
}
17-
return b
18-
}
19-
20-
/// --- Exports
21-
226
module.exports = {
237
Client: Client,
248
createClient: function createClient (options) {
25-
if (typeof (options) !== 'object') { throw new TypeError('options (object) required') }
26-
if (options.url && typeof (options.url) !== 'string') { throw new TypeError('options.url (string) required') }
27-
if (options.socketPath && typeof (options.socketPath) !== 'string') { throw new TypeError('options.socketPath must be a string') }
28-
if (!xor(options.url, options.socketPath)) { throw new TypeError('options.url ^ options.socketPath (String) required') }
29-
if (!options.log) { options.log = logger }
30-
if (!options.log.child) { options.log.child = function () { return options.log } }
31-
if (typeof (options.log) !== 'object') { throw new TypeError('options.log must be an object') }
9+
if (isObject(options) === false) throw TypeError('options (object) required')
10+
if (options.url && typeof options.url !== 'string') throw TypeError('options.url (string) required')
11+
if (options.socketPath && typeof options.socketPath !== 'string') throw TypeError('options.socketPath must be a string')
12+
if ((options.url && options.socketPath) || !(options.url || options.socketPath)) throw TypeError('options.url ^ options.socketPath (String) required')
13+
if (!options.log) options.log = logger
14+
if (isObject(options.log) !== true) throw TypeError('options.log must be an object')
15+
if (!options.log.child) options.log.child = function () { return options.log }
3216

3317
return new Client(options)
3418
}
3519
}
20+
21+
function isObject (input) {
22+
return Object.prototype.toString.apply(input) === '[object Object]'
23+
}

test/client.test.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,64 @@ tap.afterEach((done, t) => {
331331
})
332332
})
333333

334+
tap.test('createClient', t => {
335+
t.test('requires an options object', async t => {
336+
const match = /options.+required/
337+
t.throws(() => ldap.createClient(), match)
338+
t.throws(() => ldap.createClient([]), match)
339+
t.throws(() => ldap.createClient(''), match)
340+
t.throws(() => ldap.createClient(42), match)
341+
})
342+
343+
t.test('url must be a string', async t => {
344+
const match = /options\.url \(string\) required/
345+
t.throws(() => ldap.createClient({ url: {} }), match)
346+
t.throws(() => ldap.createClient({ url: [] }), match)
347+
t.throws(() => ldap.createClient({ url: 42 }), match)
348+
})
349+
350+
t.test('socketPath must be a string', async t => {
351+
const match = /options\.socketPath must be a string/
352+
t.throws(() => ldap.createClient({ socketPath: {} }), match)
353+
t.throws(() => ldap.createClient({ socketPath: [] }), match)
354+
t.throws(() => ldap.createClient({ socketPath: 42 }), match)
355+
})
356+
357+
t.test('cannot supply both url and socketPath', async t => {
358+
t.throws(
359+
() => ldap.createClient({ url: 'foo', socketPath: 'bar' }),
360+
/options\.url \^ options\.socketPath \(String\) required/
361+
)
362+
})
363+
364+
t.test('must supply at least url or socketPath', async t => {
365+
t.throws(
366+
() => ldap.createClient({}),
367+
/options\.url \^ options\.socketPath \(String\) required/
368+
)
369+
})
370+
371+
// TODO: this test is really flaky. It would be better if we could validate
372+
// the options _withouth_ having to connect to a server.
373+
// t.test('attaches a child function to logger', async t => {
374+
// /* eslint-disable-next-line */
375+
// let client
376+
// const logger = Object.create(require('abstract-logging'))
377+
// const socketPath = getSock()
378+
// const server = ldap.createServer()
379+
// server.listen(socketPath, () => {})
380+
// t.tearDown(() => {
381+
// client.unbind(() => server.close())
382+
// })
383+
384+
// client = ldap.createClient({ socketPath, log: logger })
385+
// t.ok(logger.child)
386+
// t.true(typeof client.log.child === 'function')
387+
// })
388+
389+
t.end()
390+
})
391+
334392
tap.test('simple bind failure', function (t) {
335393
t.context.client.bind(BIND_DN, uuid(), function (err, res) {
336394
t.ok(err)

0 commit comments

Comments
 (0)