diff --git a/lib/nconf/stores/memory.js b/lib/nconf/stores/memory.js index 74b5520..b4cbe9b 100644 --- a/lib/nconf/stores/memory.js +++ b/lib/nconf/stores/memory.js @@ -36,7 +36,7 @@ Memory.prototype.get = function (key) { // while (path.length > 0) { key = path.shift(); - if (!target[key]) { + if (!(target && key in target)) { return; } diff --git a/lib/nconf/stores/redis.js b/lib/nconf/stores/redis.js index b07ddeb..015f458 100644 --- a/lib/nconf/stores/redis.js +++ b/lib/nconf/stores/redis.js @@ -151,7 +151,7 @@ Redis.prototype.set = function (key, value, callback) { var fullKey = nconf.key(self.namespace, key); - if (!Array.isArray(value) && typeof value === 'object') { + if (!Array.isArray(value) && value !== null && typeof value === 'object') { // // If the value is an `Object` (and not an `Array`) then // nest into the value and set the child keys appropriately. diff --git a/test/file-store-test.js b/test/file-store-test.js index 7a020ac..c66301f 100644 --- a/test/file-store-test.js +++ b/test/file-store-test.js @@ -63,11 +63,19 @@ vows.describe('nconf/stores/file').addBatch({ "the set() method": { "should respond with true": function () { assert.isTrue(store.set('foo:bar:bazz', 'buzz')); + assert.isTrue(store.set('falsy:number', 0)); + assert.isTrue(store.set('falsy:string', '')); + assert.isTrue(store.set('falsy:boolean', false)); + assert.isTrue(store.set('falsy:object', null)); } }, "the get() method": { "should respond with the correct value": function () { assert.equal(store.get('foo:bar:bazz'), 'buzz'); + assert.equal(store.get('falsy:number'), 0); + assert.equal(store.get('falsy:string'), ''); + assert.equal(store.get('falsy:boolean'), false); + assert.equal(store.get('falsy:object'), null); } }, "the clear() method": { diff --git a/test/memory-store-test.js b/test/memory-store-test.js index 57c6244..210879a 100644 --- a/test/memory-store-test.js +++ b/test/memory-store-test.js @@ -15,11 +15,29 @@ vows.describe('nconf/stores/memory').addBatch({ "the set() method": { "should respond with true": function (store) { assert.isTrue(store.set('foo:bar:bazz', 'buzz')); + assert.isTrue(store.set('falsy:number', 0)); + assert.isTrue(store.set('falsy:string', '')); + assert.isTrue(store.set('falsy:boolean', false)); + assert.isTrue(store.set('falsy:object', null)); } }, "the get() method": { "should respond with the correct value": function (store) { assert.equal(store.get('foo:bar:bazz'), 'buzz'); + assert.equal(store.get('falsy:number'), 0); + assert.equal(store.get('falsy:string'), ''); + assert.equal(store.get('falsy:boolean'), false); + assert.equal(store.get('falsy:object'), null); + }, + "should not fail when retrieving non-existent keys": function (store) { + assert.doesNotThrow(function() { + assert.equal(store.get('this:key:does:not:exist'), undefined); + }, TypeError); + }, + "should not fail when drilling into non-objects": function (store) { + assert.doesNotThrow(function() { + assert.equal(store.get('falsy:number:uh:oh'), undefined); + }, TypeError); } }, "the clear() method": { diff --git a/test/redis-store-test.js b/test/redis-store-test.js index a7ea55e..2c8cf2b 100644 --- a/test/redis-store-test.js +++ b/test/redis-store-test.js @@ -37,6 +37,14 @@ vows.describe('nconf/stores/redis').addBatch({ "should respond without an error": function (err, ok) { assert.isNull(err); } + }, + "with null": { + topic: function (store) { + store.set('falsy:object', null, this.callback); + }, + "should respond without an error": function(err, ok) { + assert.isNull(err); + } } } } @@ -75,6 +83,14 @@ vows.describe('nconf/stores/redis').addBatch({ "should respond with the correct value": function (err, value) { assert.deepEqual(value, data.obj.auth); } + }, + "with null": { + topic: function(store) { + store.get('falsy:object', this.callback); + }, + "should respond with the correct value": function(err, value) { + assert.equal(value, null); + } } } }