Migrating test to jest (#292)

* set up jest dependencies

* add parser option to eslint to support es6

* migrate first test to jest

* migrate the argv test to shpec

* convert the env and literal store tests

* convert the file-store tests

* convert the memory-store tests

* convert the hierarchy tests

* convert the provider-save test

* convert the complete test

* convert the provider test

* convert the conf test

* tweak a test that was no longer working (context changed)

* replace in place the helpers file

* remove vows dependency

* update the test invocation to rely on jest

* update the argv test to be able to use the jest --verbose option

* Some tweaks to the test to have them working

* Update node version tested (+10 +12 -9)

* Replace const by var until we drop 0.10/0.12/4 node

* Replace let by var until we drop 0.10/0.12/4 node
master
Adrien Becchis 2019-04-30 04:26:02 +02:00 committed by Matt Hamann
parent 17376d4d17
commit b8686aeff0
28 changed files with 4466 additions and 1927 deletions

View File

@ -2,6 +2,9 @@
"env": {
"node": true
},
"parserOptions": {
"ecmaVersion": 6
},
"rules": {
"no-unused-vars": "error"
}

View File

@ -6,7 +6,8 @@ node_js:
- "4"
- "6"
- "8"
- "9"
- "10"
- "12"
script:
- npm test
@ -19,7 +20,6 @@ matrix:
allow_failures:
- node_js: "0.10"
- node_js: "0.12"
- node_js: "9"
notifications:
email:

View File

@ -27,6 +27,7 @@ var Argv = exports.Argv = function (options, usage) {
if(typeof options.readOnly === 'boolean') {
this.readOnly = options.readOnly;
delete options.readOnly;
// FIXME; should not mutate options!!!!
} else {
this.readOnly = true;
}

3413
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,7 @@
],
"dependencies": {
"ini": "^1.3.0",
"jest": "^21.2.1",
"secure-keys": "^1.0.0",
"yargs": "^10.0.3"
},
@ -28,13 +29,12 @@
"coveralls": "^3.0.2",
"eslint": "^5.5.0",
"istanbul": "^0.4.1",
"nconf-yaml": "^1.0.2",
"vows": "^0.8.2"
"nconf-yaml": "^1.0.2"
},
"main": "./lib/nconf",
"scripts": {
"test": "vows test/*-test.js test/**/*-test.js --spec",
"cover": "istanbul cover vows -- test/*-test.js test/**/*-test.js --spec",
"test": "jest --verbose",
"cover": "jest --coverage",
"coveralls": "cat coverage/lcov.info | coveralls",
"lint": "eslint ."
},

View File

@ -1,31 +0,0 @@
/*
* common.js: Tests for common utility function in nconf.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
helpers = require('./helpers'),
nconf = require('../lib/nconf');
var mergeDir = path.join(__dirname, 'fixtures', 'merge'),
files = fs.readdirSync(mergeDir).map(function (f) { return path.join(mergeDir, f) });
vows.describe('nconf/common').addBatch({
"Using nconf.common module": {
"the loadFiles() method": {
topic: function () {
nconf.loadFiles(files, this.callback);
},
"should merge the files correctly": helpers.assertMerged
},
"the loadFilesSync() method": {
"should merge the files correctly": function () {
helpers.assertMerged(null, nconf.loadFilesSync(files));
}
}
}
}).export(module);

28
test/common.test.js Normal file
View File

@ -0,0 +1,28 @@
/*
* common.js: Tests for common utility function in nconf.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs');
var path = require('path');
var helpers = require('./helpers');
var nconf = require('../lib/nconf');
var mergeDir = path.join(__dirname, 'fixtures', 'merge');
var files = fs.readdirSync(mergeDir).map(function (f) { return path.join(mergeDir, f) });
describe('nconf/common', () => {
describe('Using nconf.common module', () => {
it('the loadFiles() method should merge the files correctly', done => {
nconf.loadFiles(files, (err, res) => {
helpers.assertMerged(err, res);
done();
});
});
it("the loadFilesSync() method should merge the files correctly", () => {
helpers.assertMerged(null, nconf.loadFilesSync(files));
});
});
});

View File

@ -1,357 +0,0 @@
/*
* complete-test.js: Complete test for multiple stores.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs'),
vows = require('vows'),
assert = require('assert'),
nconf = require('../lib/nconf'),
data = require('./fixtures/data').data,
helpers = require('./helpers');
var completeTest = helpers.fixture('complete-test.json'),
complete = helpers.fixture('complete.json');
// prime the process.env
process.env['NCONF_foo'] = 'bar';
process.env.FOO = 'bar';
process.env.BAR = 'zalgo';
process.env.NODE_ENV = 'debug';
process.env.FOOBAR = 'should not load';
process.env.TES = 'TING';
process.env.json_array = JSON.stringify(['foo', 'bar', 'baz']);
process.env.json_obj = JSON.stringify({foo: 'bar', baz: 'foo'});
process.env.NESTED__VALUE = 'nested';
process.env.NESTED___VALUE_EXTRA_LODASH = '_nested_';
vows.describe('nconf/multiple-stores').addBatch({
"When using the nconf with multiple providers": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env({
// separator: '__',
match: /^NCONF_/,
whitelist: ['NODE_ENV', 'FOO', 'BAR', 'TES']
});
nconf.file({ file: completeTest });
nconf.use('argv', { type: 'literal', store: data });
that.callback();
});
},
"should have the correct `stores`": function () {
assert.isObject(nconf.stores.env);
assert.isObject(nconf.stores.argv);
assert.isObject(nconf.stores.file);
},
"env vars": {
"are present": function () {
['NODE_ENV', 'FOO', 'BAR', 'NCONF_foo'].forEach(function (key) {
assert.equal(nconf.get(key), process.env[key]);
});
},
"are readOnly": function () {
nconf.set('tes', 'broken');
assert(nconf.get('tes'), 'TING');
}
},
"json vars": {
topic: function () {
fs.readFile(complete, 'utf8', this.callback);
},
"are present": function (err, data) {
assert.isNull(err);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
assert.deepEqual(nconf.get(key), data[key]);
});
}
},
"literal vars": {
"are present": function () {
Object.keys(data).forEach(function (key) {
assert.deepEqual(nconf.get(key), data[key]);
});
}
},
"and saving *synchronously*": {
topic: function () {
nconf.set('weebls', 'stuff');
return nconf.save();
},
"correct return value": function (topic) {
Object.keys(topic).forEach(function (key) {
assert.deepEqual(topic[key], nconf.get(key));
});
},
"the file": {
topic: function () {
fs.readFile(completeTest, 'utf8', this.callback);
},
"saved correctly": function (err, data) {
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
assert.deepEqual(data[key], nconf.get(key));
});
assert.equal(nconf.get('weebls'), 'stuff');
}
}
},
teardown: function () {
// remove the file so that we can test saving it async
fs.unlinkSync(completeTest);
}
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using the nconf with multiple providers": {
"and saving *asynchronously*": {
topic: function () {
nconf.set('weebls', 'crap');
nconf.save(this.callback);
},
"correct return value": function (err, data) {
assert.isNull(err);
Object.keys(data).forEach(function (key) {
assert.deepEqual(data[key], nconf.get(key));
});
},
"the file": {
topic: function () {
fs.readFile(completeTest, 'utf8', this.callback);
},
"saved correctly": function (err, data) {
assert.isNull(err);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
assert.deepEqual(nconf.get(key), data[key]);
});
assert.equal(nconf.get('weebls'), 'crap');
}
}
},
teardown: function () {
fs.unlinkSync(completeTest);
nconf.remove('file');
nconf.remove('memory');
nconf.remove('argv');
nconf.remove('env');
}
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with lowerCase:true": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env({ lowerCase: true });
that.callback();
});
},
"env vars": {
"keys also available as lower case": function () {
Object.keys(process.env).forEach(function (key) {
assert.equal(nconf.get(key.toLowerCase()), process.env[key]);
});
}
},
teardown: function () {
nconf.remove('env');
}
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with parseValues:true": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env({ parseValues: true });
that.callback();
});
},
"env vars": {
"JSON keys properly parsed": function () {
Object.keys(process.env).forEach(function (key) {
var val = process.env[key];
try {
val = JSON.parse(val);
} catch (err) {}
assert.deepEqual(nconf.get(key), val);
});
}
},
teardown: function () {
nconf.remove('env');
}
},
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with transform:fn": {
topic: function () {
function testTransform(obj) {
if (obj.key === 'FOO') {
obj.key = 'FOOD';
obj.value = 'BARFOO';
}
return obj;
}
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env({ transform: testTransform })
that.callback();
});
}, "env vars": {
"port key/value properly transformed": function() {
assert.equal(nconf.get('FOOD'), 'BARFOO');
}
}
},
teardown: function () {
nconf.remove('env');
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with a transform:fn that drops an entry": {
topic: function () {
function testTransform(obj) {
if (obj.key === 'FOO') {
return false;
}
return obj;
}
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env({ transform: testTransform });
that.callback();
});
}, "env vars": {
"port key/value properly transformed": function() {
assert.equal(typeof nconf.get('FOO'), 'undefined');
}
}
},
teardown: function () {
nconf.remove('env');
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with a transform:fn that return an undefined value": {
topic: function () {
function testTransform(obj) {
if (obj.key === 'FOO') {
return {key: 'FOO', value: undefined};
}
return obj;
}
var that = this;
helpers.cp(complete, completeTest, function () {
nconf.env({ transform: testTransform });
that.callback();
});
}, "env vars": {
"port key/value properly transformed": function() {
assert.equal(typeof nconf.get('FOO'), 'undefined');
}
}
},
teardown: function () {
nconf.remove('env');
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with a bad transform:fn": {
topic: function () {
function testTransform() {
return {foo: 'bar'};
}
var that = this;
helpers.cp(complete, completeTest, function () {
try {
nconf.env({ transform: testTransform });
that.callback();
} catch (err) {
that.callback(null, err);
}
});
}, "env vars": {
"port key/value throws transformation error": function(err) {
assert.equal(err.name, 'RuntimeError');
}
}
},
teardown: function () {
nconf.remove('env');
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with a bad transform:fn": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
try {
nconf.env({ separator: /__+/ });
that.callback();
} catch (err) {
that.callback(null, err);
}
});
}, "env vars": {
"can access to nested values": function(/*err*/) {
assert.deepEqual(nconf.get('NESTED'), {VALUE:'nested', VALUE_EXTRA_LODASH: '_nested_'});
}
}
},
teardown: function () {
nconf.remove('env');
}
}).addBatch({
// Threw this in it's own batch to make sure it's run separately from the
// sync check
"When using env with a readOnly:false": {
topic: function () {
var that = this;
helpers.cp(complete, completeTest, function () {
try {
nconf.env({ readOnly: false });
that.callback();
} catch (err) {
that.callback(null, err);
}
});
}, "env vars": {
"can be changed when readOnly is false": function() {
assert.equal(nconf.get('TES'), 'TING');
nconf.set('TES', 'changed');
assert.equal(nconf.get('TES'), 'changed');
}
}
},
teardown: function () {
nconf.remove('env');
}
}).export(module);

258
test/complete.test.js Normal file
View File

@ -0,0 +1,258 @@
/*
* complete-test.js: Complete test for multiple stores.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs');
var nconf = require('../lib/nconf');
var data = require('./fixtures/data').data;
var helpers = require('./helpers');
var completeTest = helpers.fixture('complete-test.json');
var complete = helpers.fixture('complete.json');
// prime the process.env
process.env['NCONF_foo'] = 'bar';
process.env.FOO = 'bar';
process.env.BAR = 'zalgo';
process.env.NODE_ENV = 'debug';
process.env.FOOBAR = 'should not load';
process.env.json_array = JSON.stringify(['foo', 'bar', 'baz']);
process.env.json_obj = JSON.stringify({foo: 'bar', baz: 'foo'});
process.env.NESTED__VALUE = 'nested';
process.env.NESTED___VALUE_EXTRA_LODASH = '_nested_';
describe('nconf/multiple-stores', () => {
describe("When using the nconf with multiple providers", () => {
beforeAll(done => {
helpers.cp(complete, completeTest, function () {
nconf.env({
// separator: '__',
match: /^NCONF_/,
whitelist: ['NODE_ENV', 'FOO', 'BAR']
});
nconf.file({file: completeTest});
nconf.use('argv', {type: 'literal', store: data});
done();
});
});
afterAll(() => {
fs.unlinkSync(completeTest);
nconf.remove('file');
nconf.remove('memory');
nconf.remove('argv');
nconf.remove('env');
})
it("should have the correct `stores`", () => {
expect(typeof nconf.stores.env).toBe('object');
expect(typeof nconf.stores.argv).toBe('object');
expect(typeof nconf.stores.file).toBe('object');
});
it("env vars, are present", () => {
['NODE_ENV', 'FOO', 'BAR', 'NCONF_foo'].forEach(function (key) {
expect(nconf.get(key)).toEqual(process.env[key]);
});
});
it("json vars are present", done => {
fs.readFile(complete, 'utf8', (err, data) => {
expect(err).toBe(null);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
expect(nconf.get(key)).toEqual(data[key]);
});
done();
})
});
it("literal vars are present", () => {
Object.keys(data).forEach(function (key) {
expect(nconf.get(key)).toEqual(data[key]);
});
});
describe('saving', () => {
afterEach(() => {
// remove the file so that we can test saving it async
fs.unlinkSync(completeTest);
});
it("and saving *synchronously* correct return value, the file, saved correctly", done => {
nconf.set('weebls', 'stuff');
var topic = nconf.save();
Object.keys(topic).forEach(function (key) {
expect(topic[key]).toEqual(nconf.get(key));
});
fs.readFile(completeTest, 'utf8', function (err, data) {
expect(err).toBe(null);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
expect(data[key]).toEqual(nconf.get(key));
});
expect(nconf.get('weebls')).toEqual('stuff');
done();
});
});
it("and saving *asynchronously* correct return value, the file, saved correctly", done => {
nconf.set('weebls', 'crap');
nconf.save((err, data) => {
Object.keys(data).forEach(function (key) {
expect(data[key]).toEqual(nconf.get(key));
});
fs.readFile(completeTest, 'utf8', function (err, data) {
expect(err).toBe(null);
data = JSON.parse(data);
Object.keys(data).forEach(function (key) {
expect(data[key]).toEqual(nconf.get(key));
});
expect(nconf.get('weebls')).toEqual('crap');
done();
});
});
});
});
});
describe("When using the nconf env with custom options", () => {
describe("When using env with lowerCase:true", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
beforeAll(done => {
helpers.cp(complete, completeTest, () => {
nconf.env({lowerCase: true});
done();
})
})
it("env vars keys also available as lower case", () => {
Object.keys(process.env).forEach(function (key) {
expect(nconf.get(key.toLowerCase())).toEqual(process.env[key]);
});
})
afterAll(() => nconf.remove('env'))
});
describe("When using env with parseValues:true", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
beforeAll(done => {
helpers.cp(complete, completeTest, () => {
nconf.env({parseValues: true});
done();
})
})
it("JSON keys properly parsed", () => {
Object.keys(process.env).forEach(function (key) {
var val = process.env[key];
try {
val = JSON.parse(val);
} catch (err) {
}
expect(nconf.get(key)).toEqual(val);
})
afterAll(() => nconf.remove('env'))
});
});
describe("When using env with transform:fn", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
beforeAll(done => {
function testTransform(obj) {
if (obj.key === 'FOO') {
obj.key = 'FOOD';
obj.value = 'BARFOO';
}
return obj;
}
helpers.cp(complete, completeTest, () => {
nconf.env({transform: testTransform});
done();
})
});
it("env vars port key/value properly transformed", () => {
expect(nconf.get('FOOD')).toEqual('BARFOO');
});
afterAll(() => nconf.remove('env'))
});
describe("When using env with transform:fn that drops an entry", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
beforeAll(done => {
function testTransform(obj) {
if (obj.key === 'FOO') {
return false;
}
return obj;
}
helpers.cp(complete, completeTest, () => {
nconf.env({transform: testTransform});
done();
})
});
it("env vars port key/value properly transformed", () => {
expect(nconf.get('FOO')).toBe(undefined);
});
afterAll(() => nconf.remove('env'))
});
describe("When using env with transform:fn that return an undefined value", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
beforeAll(done => {
function testTransform(obj) {
if (obj.key === 'FOO') {
return {key: 'FOO', value: undefined};
}
return obj;
}
helpers.cp(complete, completeTest, () => {
nconf.env({transform: testTransform});
done();
})
});
it("env vars port key/value properly transformed", () => {
expect(nconf.get('FOO')).toBe(undefined);
});
afterAll(() => nconf.remove('env'))
});
describe("When using env with bad transform:fn", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
it(" port key/value throws transformation error", done => {
function testTransform(obj) {
return {foo: 'bar'};
}
helpers.cp(complete, completeTest, () => {
try {
nconf.env({transform: testTransform});
} catch (err) {
expect(err.name).toEqual('RuntimeError')
done();
}
})
});
afterAll(() => nconf.remove('env'))
});
describe("When using env with a separator", () => {
// Threw this in it's own batch to make sure it's run separately from the sync check
beforeAll(done => {
helpers.cp(complete, completeTest, () => {
nconf.env({separator: /__+/});
done();
})
});
it("can access to nested values", () => {
expect(nconf.get('NESTED')).toEqual({VALUE: 'nested', VALUE_EXTRA_LODASH: '_nested_'});
});
afterAll(() => nconf.remove('env'))
});
});
});

View File

@ -5,52 +5,51 @@
*
*/
var assert = require('assert'),
spawn = require('child_process').spawn,
fs = require('fs'),
path = require('path'),
nconf = require('../lib/nconf');
var spawn = require('child_process').spawn;
var fs = require('fs');
var path = require('path');
var nconf = require('../lib/nconf');
exports.assertMerged = function (err, merged) {
merged = merged instanceof nconf.Provider
? merged.store.store
: merged;
assert.isNull(err);
assert.isObject(merged);
assert.isTrue(merged.apples);
assert.isTrue(merged.bananas);
assert.isObject(merged.candy);
assert.isTrue(merged.candy.something1);
assert.isTrue(merged.candy.something2);
assert.isTrue(merged.candy.something3);
assert.isTrue(merged.candy.something4);
assert.isTrue(merged.dates);
assert.isTrue(merged.elderberries);
expect()
expect(err).toBeNull();
expect(typeof merged).toBe('object');
expect(merged.apples).toBeTruthy();
expect(merged.bananas).toBeTruthy();
expect(typeof merged.candy).toBe('object');
expect(merged.candy.something1).toBeTruthy();
expect(merged.candy.something2).toBeTruthy();
expect(merged.candy.something3).toBeTruthy();
expect(merged.candy.something4).toBeTruthy();
expect(merged.dates).toBeTruthy();
expect(merged.elderberries).toBeTruthy();
};
//FIXME TODO
exports.assertSystemConf = function (options) {
return {
topic: function () {
var env = null;
return done => {
var env = null;
if (options.env) {
env = {}
Object.keys(process.env).forEach(function (key) {
env[key] = process.env[key];
});
if (options.env) {
env = {}
Object.keys(process.env).forEach(function (key) {
env[key] = process.env[key];
});
Object.keys(options.env).forEach(function (key) {
env[key] = options.env[key];
});
}
var child = spawn('node', [options.script].concat(options.argv), { env: env });
child.stdout.once('data', this.callback.bind(this, null));
},
"should respond with the value passed into the script": function (_, data) {
assert.equal(data.toString(), 'foobar');
Object.keys(options.env).forEach(function (key) {
env[key] = options.env[key];
});
}
var child = spawn('node', [options.script].concat(options.argv), {env: env});
child.stdout.once('data', data => {
expect(data.toString()).toEqual('foobar');
done();
});
}
}

View File

@ -1,183 +0,0 @@
/*
* hierarchy-test.js: Basic tests for hierarchical file stores.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var assert = require('assert'),
fs = require('fs'),
path = require('path'),
spawn = require('child_process').spawn,
vows = require('vows'),
nconf = require('../lib/nconf');
var configDir = path.join(__dirname, 'fixtures', 'hierarchy'),
globalConfig = path.join(configDir, 'global.json'),
userConfig = path.join(configDir, 'user.json');
vows.describe('nconf/hierarchy').addBatch({
"When using nconf": {
"configured with two file stores": {
topic: function () {
nconf.add('user', { type: 'file', file: userConfig });
nconf.add('global', { type: 'file', file: globalConfig });
nconf.load();
return nconf;
},
"should have the appropriate keys present": function () {
assert.equal(nconf.get('title'), 'My specific title');
assert.equal(nconf.get('color'), 'green');
assert.equal(nconf.get('movie'), 'Kill Bill');
}
},
"configured with two file stores using `file`": {
topic: function () {
nconf.file('user', userConfig);
nconf.file('global', globalConfig);
nconf.load();
return nconf;
},
"should have the appropriate keys present": function () {
assert.equal(nconf.get('title'), 'My specific title');
assert.equal(nconf.get('color'), 'green');
assert.equal(nconf.get('movie'), 'Kill Bill');
}
},
"configured with .argv(), .env() and .file()": {
topic: function () {
var configFile = path.join(__dirname, 'fixtures', 'load-save.json'),
script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-save.js'),
argv = ['--foo', 'foo', '--bar', 'bar'],
that = this,
data = '',
child;
try { fs.unlinkSync(configFile) }
catch (ex) {
// No-op
}
child = spawn('node', [script].concat(argv));
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function () {
fs.readFile(configFile, 'utf8', that.callback.bind(null, null, data));
});
},
"should not persist information passed in to process.env and process.argv to disk ": function (_, data, _, ondisk){
assert.equal(data, 'foo');
assert.deepEqual(JSON.parse(ondisk), {
database: {
host: '127.0.0.1',
port: 5984
}
});
}
},
"configured with .argv(), .file() and invoked with nested command line options": {
topic: function () {
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-merge.js'),
argv = ['--candy:something', 'foo', '--candy:something5:second', 'bar'],
that = this,
data = '',
child;
child = spawn('node', [script].concat(argv));
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function() {
that.callback(null, data);
});
},
"should merge nested objects ": function (err, data) {
assert.deepEqual(JSON.parse(data), {
apples: true,
candy: {
something: 'foo',
something1: true,
something2: true,
something5: {
first: 1,
second: 'bar'
}
}
});
}
},
"configured with .argv() and separator, .file() and invoked with nested command line options": {
topic: function () {
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-merge-with-separator.js'),
argv = ['--candy--something', 'foo', '--candy--something5--second', 'bar'],
that = this,
data = '',
child;
process.env.candy__bonbon = 'sweet';
child = spawn('node', [script].concat(argv));
delete process.env.candy__bonbon;
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function() {
that.callback(null, data);
});
},
"should merge nested objects ": function (err, data) {
console.log(data)
assert.deepEqual(JSON.parse(data), {
apples: true,
candy: {
bonbon: 'sweet',
something: 'foo',
something1: true,
something2: true,
something5: {
first: 1,
second: 'bar'
}
}
});
}
},
"configured with .file(), .defaults() should deep merge objects": {
topic: function () {
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-defaults-merge.js'),
that = this,
data = '',
child;
child = spawn('node', [script]);
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function() {
that.callback(null, data);
});
},
"should merge nested objects ": function (err, data) {
assert.deepEqual(JSON.parse(data), {
candy: {
something: 'much better something for you',
something1: true,
something2: true,
something18: 'completely unique',
something5: {
first: 1,
second: 99
}
}
});
}
}
}
}).export(module);

159
test/hierarchy.test.js Normal file
View File

@ -0,0 +1,159 @@
/*
* hierarchy-test.js: Basic tests for hierarchical file stores.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var nconf = require('../lib/nconf');
var configDir = path.join(__dirname, 'fixtures', 'hierarchy');
var globalConfig = path.join(configDir, 'global.json');
var userConfig = path.join(configDir, 'user.json');
describe('nconf/hierarchy, When using nconf', () => {
it("configured with two file stores, should have the appropriate keys present", () => {
nconf.add('user', {type: 'file', file: userConfig});
nconf.add('global', {type: 'file', file: globalConfig});
nconf.load();
expect(nconf.get('title')).toEqual('My specific title');
expect(nconf.get('color')).toEqual('green');
expect(nconf.get('movie')).toEqual('Kill Bill');
});
it("configured with two file stores using `file` should have the appropriate keys present", () => {
nconf.file('user', userConfig);
nconf.file('global', globalConfig);
nconf.load();
expect(nconf.get('title')).toEqual('My specific title');
expect(nconf.get('color')).toEqual('green');
expect(nconf.get('movie')).toEqual('Kill Bill');
});
it("configured with .argv(), .env() and .file() should not persist information passed in to process.env and process.argv to disk",
done => {
var configFile = path.join(__dirname, 'fixtures', 'load-save.json');
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-save.js');
var argv = ['--foo', 'foo', '--bar', 'bar'];
var data = '';
try {
fs.unlinkSync(configFile)
}
catch (ex) {
// No-op
}
var child = spawn('node', [script].concat(argv));
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function () {
fs.readFile(configFile, 'utf8', (err, ondisk) => {
expect(data).toEqual('foo');
expect(JSON.parse(ondisk)).toEqual({
database: {
host: '127.0.0.1',
port: 5984
}
});
});
done();
});
});
it("configured with .argv(), .file() and invoked with nested command line options, should merge nested objects",
done => {
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-load-merge.js');
var argv = ['--candy:something', 'foo', '--candy:something5:second', 'bar'];
var data = '';
var child = spawn('node', [script].concat(argv));
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function () {
expect(JSON.parse(data)).toEqual({
apples: true,
candy: {
something: 'foo',
something1: true,
something2: true,
something5: {
first: 1,
second: 'bar'
}
}
});
done();
});
});
it("configured with .argv() and separator, .file() and invoked with nested command line options should merge nested objects", done => {
var script = path.join(__dirname, 'fixtures',
'scripts', 'nconf-hierarchical-load-merge-with-separator.js');
var argv = ['--candy--something', 'foo', '--candy--something5--second', 'bar'];
var data = '';
process.env.candy__bonbon = 'sweet';
var child = spawn('node', [script].concat(argv));
delete process.env.candy__bonbon;
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function () {
console.log(data)
expect(JSON.parse(data)).toEqual({
apples: true,
candy: {
bonbon: 'sweet',
something: 'foo',
something1: true,
something2: true,
something5: {
first: 1,
second: 'bar'
}
}
});
done();
});
});
it("configured with .file(), .defaults() should deep merge objects should merge nested objects ", done => {
var script = path.join(__dirname, 'fixtures', 'scripts', 'nconf-hierarchical-defaults-merge.js');
var data = '';
var child = spawn('node', [script]);
child.stdout.on('data', function (d) {
data += d;
});
child.on('close', function () {
expect(JSON.parse(data)).toEqual({
candy: {
something: 'much better something for you',
something1: true,
something2: true,
something18: 'completely unique',
something5: {
first: 1,
second: 99
}
}
});
done();
});
})
})

View File

@ -1,147 +0,0 @@
/*
* file-store-test.js: Tests for the nconf File store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
assert = require('assert'),
nconf = require('../lib/nconf')
vows.describe('nconf').addBatch({
"When using the nconf": {
"should have the correct methods set": function () {
assert.isFunction(nconf.key);
assert.isFunction(nconf.path);
assert.isFunction(nconf.use);
assert.isFunction(nconf.any);
assert.isFunction(nconf.get);
assert.isFunction(nconf.set);
assert.isFunction(nconf.clear);
assert.isFunction(nconf.load);
assert.isFunction(nconf.save);
assert.isFunction(nconf.reset);
assert.isFunction(nconf.required);
},
"the use() method": {
"should instaniate the correct store": function () {
nconf.use('memory');
nconf.load();
assert.instanceOf(nconf.stores['memory'], nconf.Memory);
}
},
"it should": {
topic: function () {
fs.readFile(path.join(__dirname, '..', 'package.json'), this.callback);
},
"have the correct version set": function (err, data) {
assert.isNull(err);
data = JSON.parse(data.toString());
assert.equal(nconf.version, data.version);
}
},
"the required() method": {
"should throw error with missing keys": function() {
nconf.set('foo:bar:bazz', 'buzz');
assert.throws(nconf.required.bind(nconf, ['missing', 'foo:bar:bazz']), Error);
},
"should return the provider if all required keys exist": function() {
var Provider = nconf.Provider;
nconf.set('foo:bar:bazz', 'buzz');
assert.isTrue(nconf.required(['foo:bar:bazz']) instanceof Provider);
}
}
}
}).addBatch({
"When using the nconf": {
"with the memory store": {
"the set() method": {
"should respond with true": function () {
assert.isTrue(nconf.set('foo:bar:bazz', 'buzz'));
}
},
"the get() method": {
"without a callback": {
"should respond with the correct value": function () {
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
},
"should not step inside strings": function () {
assert.equal(nconf.get('foo:bar:bazz:0'), undefined);
}
},
"with a callback": {
topic: function () {
nconf.get('foo:bar:bazz', this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'buzz');
}
}
}
}
}
}).addBatch({
"When using the nconf": {
"with the memory store": {
"the get() method": {
"should respond allow access to the root": function () {
assert(nconf.get(null));
assert(nconf.get(undefined));
assert(nconf.get());
}
},
"the set() method": {
"should respond allow access to the root and complain about non-objects": function () {
assert(!nconf.set(null, null));
assert(!nconf.set(null, undefined));
assert(!nconf.set(null));
assert(!nconf.set(null, ''));
assert(!nconf.set(null, 1));
var original = nconf.get();
assert(nconf.set(null, nconf.get()));
assert.notEqual(nconf.get(), original);
assert.deepEqual(nconf.get(), original)
}
}
}
}
}).addBatch({
"When using nconf": {
"with the memory store": {
"the clear() method": {
"should respond with the true": function () {
assert.equal(nconf.get('foo:bar:bazz'), 'buzz');
assert.isTrue(nconf.clear('foo:bar:bazz'));
assert.isTrue(typeof nconf.get('foo:bar:bazz') === 'undefined');
}
},
"the load() method": {
"without a callback": {
"should respond with the merged store": function () {
assert.deepEqual(nconf.load(), {
title: 'My specific title',
color: 'green',
movie: 'Kill Bill'
});
}
},
"with a callback": {
topic: function () {
nconf.load(this.callback.bind(null, null));
},
"should respond with the merged store": function (ign, err, store) {
assert.isNull(err);
assert.deepEqual(store, {
title: 'My specific title',
color: 'green',
movie: 'Kill Bill'
});
}
}
}
}
}
}).export(module);

108
test/nconf.test.js Normal file
View File

@ -0,0 +1,108 @@
/*
* file-store-test.js: Tests for the nconf File store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs');
var path = require('path');
var nconf = require('../lib/nconf');
describe('nconf, When using the nconf', () => {
it("should have the correct methods set", () => {
expect(typeof nconf.key).toBe('function');
expect(typeof nconf.path).toBe('function');
expect(typeof nconf.use).toBe('function');
expect(typeof nconf.any).toBe('function');
expect(typeof nconf.get).toBe('function');
expect(typeof nconf.set).toBe('function');
expect(typeof nconf.clear).toBe('function');
expect(typeof nconf.load).toBe('function');
expect(typeof nconf.save).toBe('function');
expect(typeof nconf.reset).toBe('function');
expect(typeof nconf.required).toBe('function');
});
it("the use() method should instaniate the correct store", () => {
nconf.use('memory');
nconf.load();
expect(nconf.stores['memory'] instanceof nconf.Memory).toBe(true);
});
it("nconf should have the correct version set", done => {
fs.readFile(path.join(__dirname, '..', 'package.json'), (err, data) => {
expect(err).toBe(null);
data = JSON.parse(data.toString());
expect(nconf.version).toEqual(data.version);
done();
})
});
describe("the required() method", () => {
it("should throw error with missing keys", () => {
nconf.set('foo:bar:bazz', 'buzz');
expect(nconf.required.bind(nconf, ['missing', 'foo:bar:bazz'])).toThrow(Error);
});
it("should return the provider if all required keys exist", () => {
var Provider = nconf.Provider;
nconf.set('foo:bar:bazz', 'buzz');
expect(nconf.required(['foo:bar:bazz']) instanceof Provider).toBe(true);
});
});
describe("with the memory store", () => {
describe("the set() method", () => {
it("should respond with true", () => {
expect(nconf.set('foo:bar:bazz', 'buzz')).toBeTruthy();
});
it("should respond allow access to the root and complain about non-objects", () => {
expect(nconf.set(null, null)).toBeFalsy();
expect(nconf.set(null, undefined)).toBeFalsy();
expect(nconf.set(null)).toBeFalsy();
expect(nconf.set(null, '')).toBeFalsy();
expect(nconf.set(null, 1)).toBeFalsy();
var original = nconf.get();
expect(nconf.set(null, nconf.get())).toBeTruthy();
expect(nconf.get()).not.toBe(original);
expect(nconf.get()).toEqual(original)
})
});
describe("the get() method", () => {
it("should respond with the correct value without a callback", () => {
expect(nconf.get('foo:bar:bazz')).toEqual('buzz');
})
it("should not step inside strings without a callback", () => {
expect(nconf.get('foo:bar:bazz:0')).toEqual(undefined);
});
it("should respond with the correct value with a callback", done => {
nconf.get('foo:bar:bazz', (err, value) => {
expect(value).toEqual('buzz');
done();
})
})
it("should respond allow access to the root", () => {
expect(nconf.get(null)).toBeTruthy();
expect(nconf.get(undefined)).toBeTruthy();
expect(nconf.get()).toBeTruthy();
})
});
describe("the clear() method", () => {
it("should respond with the true", () => {
expect(nconf.get('foo:bar:bazz')).toEqual('buzz');
expect(nconf.clear('foo:bar:bazz')).toBeTruthy();
expect(typeof nconf.get('foo:bar:bazz') === 'undefined').toBeTruthy();
})
})
describe("the load() method", () => {
it("should respond with the merged store without a callback", () => {
expect(nconf.load()).toEqual({"foo": {"bar": {}}});
});
it("should respond with the merged store", done => {
nconf.load((err, store) => {
expect(err).toBe(null);
expect(store).toEqual({"foo": {"bar": {}}});
done();
});
})
})
})
})

View File

@ -1,39 +0,0 @@
/*
* provider-save-test.js: Ensures consistency for Provider `save` operations.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var assert = require('assert'),
vows = require('vows'),
nconf = require('../lib/nconf');
//
// Expose `nconf.Mock`
//
require('./mocks/mock-store');
vows.describe('nconf/provider/save').addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"with a Mock store": {
topic: function () {
return nconf.use('mock');
},
"the save() method": {
topic: function () {
var mock = nconf.stores.mock,
that = this;
mock.on('save', function () { that.saved = true });
nconf.save(this.callback);
},
"should actually save before responding": function () {
assert.isTrue(this.saved);
}
}
}
}
}
}).export(module);

View File

@ -0,0 +1,31 @@
/*
* provider-save-test.js: Ensures consistency for Provider `save` operations.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var nconf = require('../lib/nconf');
//
// Expose `nconf.Mock`
//
require('./mocks/mock-store');
describe('nconf/provider/save', () => {
describe("When using nconf an instance of 'nconf.Provider' with a Mock store", () => {
var nconfMock = nconf.use('mock');
it("the save() method should actually save before responding", done => {
var mock = nconf.stores.mock;
mock.on('save', function () {
nconfMock.saved = true;
});
nconf.save(() => {
expect(nconfMock.saved).toBeTruthy();
done();
});
})
})
});

View File

@ -1,273 +0,0 @@
/*
* provider-test.js: Tests for the nconf Provider object.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var assert = require('assert'),
fs = require('fs'),
path = require('path'),
vows = require('vows'),
helpers = require('./helpers'),
nconf = require('../lib/nconf');
var fixturesDir = path.join(__dirname, 'fixtures'),
mergeFixtures = path.join(fixturesDir, 'merge'),
files = [path.join(mergeFixtures, 'file1.json'), path.join(mergeFixtures, 'file2.json')],
override = JSON.parse(fs.readFileSync(files[0]), 'utf8');
function assertProvider(test) {
return {
topic: new nconf.Provider(),
"should use the correct File store": test
};
}
vows.describe('nconf/provider').addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"calling the use() method with the same store type and different options": {
topic: new nconf.Provider().use('file', { file: files[0] }),
"should use a new instance of the store type": function (provider) {
var old = provider.stores['file'];
assert.equal(provider.stores.file.file, files[0]);
provider.use('file', { file: files[1] });
assert.notStrictEqual(old, provider.stores.file);
assert.equal(provider.stores.file.file, files[1]);
}
},
"when 'argv' is true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-argv.js'),
argv: ['--something', 'foobar']
}),
"when 'env' is true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-env.js'),
env: { SOMETHING: 'foobar' }
}),
"when 'env' is true and 'parseValues' option is true": {
topic: function() {
var env = {
SOMETHING: 'foobar',
SOMEBOOL: 'true',
SOMENULL: 'null',
SOMEUNDEF: 'undefined',
SOMEINT: '3600',
SOMEFLOAT: '0.5',
SOMEBAD: '5.1a'
};
var oenv = {};
Object.keys(env).forEach(function (key) {
if (process.env[key]) oenv[key] = process.env[key];
process.env[key] = env[key];
});
var provider = new nconf.Provider().use('env', {parseValues: true});
Object.keys(env).forEach(function (key) {
delete process.env[key];
if (oenv[key]) process.env[key] = oenv[key];
});
return provider;
},
"should respond with parsed values": function (provider) {
assert.equal(provider.get('SOMETHING'), 'foobar');
assert.strictEqual(provider.get('SOMEBOOL'), true);
assert.notEqual(provider.get('SOMEBOOL'), 'true');
assert.strictEqual(provider.get('SOMENULL'), null);
assert.strictEqual(provider.get('SOMEUNDEF'), undefined);
assert.strictEqual(provider.get('SOMEINT'), 3600);
assert.strictEqual(provider.get('SOMEFLOAT'), .5);
assert.strictEqual(provider.get('SOMEBAD'), '5.1a');
}
}
},
"the default nconf provider": {
"when 'argv' is set to true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-argv.js'),
argv: ['--something', 'foobar'],
env: { SOMETHING: true }
}),
"when 'env' is set to true": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-env.js'),
env: { SOMETHING: 'foobar' }
}),
"when 'argv' is set to true and process.argv is modified": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-change-argv.js'),
argv: ['--something', 'badValue', 'evenWorse', 'OHNOEZ', 'foobar']
}),
"when hierarchical 'argv' get": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-hierarchical-file-argv.js'),
argv: ['--something', 'foobar'],
env: { SOMETHING: true }
}),
"when 'env' is set to true with a nested separator": helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-nested-env.js'),
env: { SOME_THING: 'foobar' }
})
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the merge() method": {
topic: new nconf.Provider().use('file', { file: files[1] }),
"should have the result merged in": function (provider) {
provider.load();
provider.merge(override);
helpers.assertMerged(null, provider.stores.file.store);
assert.equal(provider.stores.file.store.candy.something, 'file1');
},
"should merge Objects over null": function (provider) {
provider.load();
provider.merge(override);
assert.equal(provider.stores.file.store.unicorn.exists, true);
}
}
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the load() method": {
"when sources are passed in": {
topic: new nconf.Provider({
sources: {
user: {
type: 'file',
file: files[0]
},
global: {
type: 'file',
file: files[1]
}
}
}),
"should respect the hierarchy ": function (provider) {
var merged = provider.load();
helpers.assertMerged(null, merged);
assert.equal(merged.candy.something, 'file1');
}
},
"when multiple stores are used": {
topic: new nconf.Provider().overrides({foo: {bar: 'baz'}})
.add('file1', {type: 'file', file: files[0]})
.add('file2', {type: 'file', file: files[1]}),
"should respect the hierarchy": function(provider) {
var merged = provider.load();
helpers.assertMerged(null, merged);
assert.equal(merged.foo.bar, 'baz');
assert.equal(merged.candy.something, 'file1');
}
}
}
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the .file() method": {
"with a single filepath": assertProvider(function (provider) {
provider.file(helpers.fixture('store.json'));
assert.isObject(provider.stores.file);
}),
"with a name and a filepath": assertProvider(function (provider) {
provider.file('custom', helpers.fixture('store.json'));
assert.isObject(provider.stores.custom);
}),
"with a single object": assertProvider(function (provider) {
provider.file({
dir: helpers.fixture(''),
file: 'store.json',
search: true
});
assert.isObject(provider.stores.file);
assert.equal(provider.stores.file.file, helpers.fixture('store.json'));
}),
"with a name and an object": assertProvider(function (provider) {
provider.file('custom', {
dir: helpers.fixture(''),
file: 'store.json',
search: true
});
assert.isObject(provider.stores.custom);
assert.equal(provider.stores.custom.file, helpers.fixture('store.json'));
})
}
}
}
}).addBatch({
"When using nconf": {
"an instance of 'nconf.Provider'": {
"the any() method": {
topic: new nconf.Provider({
type: 'literal',
store: {
key: "getThisValue"
}
}),
"without a callback": {
"given an array of keys with one matching": {
"should respond with the correct value": function (provider) {
assert.equal(provider.any(["notthis", "orthis", "key"]), 'getThisValue');
}
},
"given an array of keys with no match": {
"should respond with null": function (provider) {
assert.isNull(provider.any(["notthis", "orthis"]));
}
},
"given a variable argument list of keys with one matching": {
"should respond with the correct value": function (provider) {
assert.equal(provider.any("notthis", "orthis", "key"), 'getThisValue');
}
},
"given no arguments": {
"should respond with null": function (provider) {
assert.isNull(provider.any());
}
}
},
"with a callback": {
"given an array of keys with one matching": {
topic: function(provider) {
provider.any(["notthis", "orthis", "key"], this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'getThisValue');
}
},
"given an array of keys with no match": {
topic: function(provider) {
provider.any(["notthis", "orthis"], this.callback);
},
"should respond with an undefined value": function (err, value) {
assert.isUndefined(value);
}
},
"given a variable argument list of keys with one matching": {
topic: function(provider) {
provider.any("notthis", "orthis", "key", this.callback);
},
"should respond with the correct value": function (err, value) {
assert.equal(value, 'getThisValue');
}
},
"given no keys": {
topic: function(provider) {
provider.any(this.callback);
},
"should respond with an undefined value": function (err, value) {
assert.isUndefined(value);
}
}
}
}
}
}
}).export(module);

233
test/provider.test.js Normal file
View File

@ -0,0 +1,233 @@
/*
* provider-test.js: Tests for the nconf Provider object.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs');
var path = require('path');
var helpers = require('./helpers');
var nconf = require('../lib/nconf');
var fixturesDir = path.join(__dirname, 'fixtures');
var mergeFixtures = path.join(fixturesDir, 'merge');
var files = [path.join(mergeFixtures, 'file1.json'), path.join(mergeFixtures, 'file2.json')];
var override = JSON.parse(fs.readFileSync(files[0]), 'utf8');
describe('nconf/provider When using nconf', () => {
describe("an instance of 'nconf.Provider'", () => {
it("calling the use() method with the same store type and different options"
+ " should use a new instance of the store type", () => {
var provider = new nconf.Provider().use('file', {file: files[0]});
var old = provider.stores['file'];
expect(provider.stores.file.file).toEqual(files[0]);
provider.use('file', {file: files[1]});
expect(old).not.toEqual(provider.stores.file);
expect(provider.stores.file.file).toEqual(files[1]);
})
});
it("respond with correct arg when 'argv' is true",
helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-argv.js'),
argv: ['--something', 'foobar']
}));
it("respond with correct arg when 'env' is true", helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'provider-env.js'),
env: {SOMETHING: 'foobar'}
}));
it("respond with correct arg when 'env' is true and 'parseValues' option is true", () => {
var env = {
SOMETHING: 'foobar',
SOMEBOOL: 'true',
SOMENULL: 'null',
SOMEUNDEF: 'undefined',
SOMEINT: '3600',
SOMEFLOAT: '0.5',
SOMEBAD: '5.1a'
};
var oenv = {};
Object.keys(env).forEach(function (key) {
if (process.env[key]) oenv[key] = process.env[key];
process.env[key] = env[key];
});
var provider = new nconf.Provider().use('env', {parseValues: true});
Object.keys(env).forEach(function (key) {
delete process.env[key];
if (oenv[key]) process.env[key] = oenv[key];
});
expect(provider.get('SOMETHING')).toEqual('foobar');
expect(provider.get('SOMEBOOL')).toEqual(true);
expect(provider.get('SOMEBOOL')).not.toEqual('true');
expect(provider.get('SOMENULL')).toEqual(null);
expect(provider.get('SOMEUNDEF')).toEqual(undefined);
expect(provider.get('SOMEINT')).toEqual(3600);
expect(provider.get('SOMEFLOAT')).toEqual(.5);
expect(provider.get('SOMEBAD')).toEqual('5.1a');
});
describe("the default nconf provider", () => {
it("respond with correct arg when 'argv' is set to true", helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-argv.js'),
argv: ['--something', 'foobar'],
env: {SOMETHING: true}
}));
it("respond with correct arg when 'env' is set to true", helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-env.js'),
env: {SOMETHING: 'foobar'}
}));
it("respond with correct arg when 'argv' is set to true and process.argv is modified", helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-change-argv.js'),
argv: ['--something', 'badValue', 'evenWorse', 'OHNOEZ', 'foobar']
}));
it("respond with correct arg when hierarchical 'argv' get", helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-hierarchical-file-argv.js'),
argv: ['--something', 'foobar'],
env: {SOMETHING: true}
}));
it("respond with correct arg when 'env' is set to true with a nested separator", helpers.assertSystemConf({
script: path.join(fixturesDir, 'scripts', 'nconf-nested-env.js'),
env: {SOME_THING: 'foobar'}
}));
});
describe("an instance of 'nconf.Provider'", () => {
describe("the merge() method", () => {
it("should have the result merged in", () => {
var provider = new nconf.Provider().use('file', {file: files[1]});
provider.load();
provider.merge(override);
helpers.assertMerged(null, provider.stores.file.store);
expect(provider.stores.file.store.candy.something).toEqual('file1');
});
it("should merge Objects over null", () => {
var provider = new nconf.Provider().use('file', {file: files[1]});
provider.load();
provider.merge(override);
expect(provider.stores.file.store.unicorn.exists).toEqual(true);
});
})
describe("the load() method", () => {
it("should respect the hierarchy when sources are passed in", () => {
var provider = new nconf.Provider({
sources: {
user: {
type: 'file',
file: files[0]
},
global: {
type: 'file',
file: files[1]
}
}
});
var merged = provider.load();
helpers.assertMerged(null, merged);
expect(merged.candy.something).toEqual('file1');
})
it("should respect the hierarchy when multiple stores are used", () => {
var provider = new nconf.Provider().overrides({foo: {bar: 'baz'}})
.add('file1', {type: 'file', file: files[0]})
.add('file2', {type: 'file', file: files[1]});
var merged = provider.load();
helpers.assertMerged(null, merged);
expect(merged.foo.bar).toEqual('baz');
expect(merged.candy.something).toEqual('file1');
})
})
})
describe("the .file() method", () => {
it("should use the correct File store with a single filepath", () => {
var provider = new nconf.Provider();
provider.file(helpers.fixture('store.json'));
expect(typeof provider.stores.file).toBe('object');
});
it("should use the correct File store with a name and a filepath", () => {
var provider = new nconf.Provider();
provider.file('custom', helpers.fixture('store.json'));
expect(typeof provider.stores.custom).toBe('object');
});
it("should use the correct File store with a single object", () => {
var provider = new nconf.Provider();
provider.file({
dir: helpers.fixture(''),
file: 'store.json',
search: true
});
expect(typeof provider.stores.file).toBe('object');
expect(provider.stores.file.file).toEqual(helpers.fixture('store.json'));
});
it("should use the correct File store with a name and an object", () => {
var provider = new nconf.Provider();
provider.file('custom', {
dir: helpers.fixture(''),
file: 'store.json',
search: true
});
expect(typeof provider.stores.custom).toBe('object');
expect(provider.stores.custom.file).toEqual(helpers.fixture('store.json'));
})
describe("the any() method", () => {
var provider = new nconf.Provider({
type: 'literal',
store: {
key: "getThisValue"
}
})
describe("without a callback", () => {
it("should respond with the correct value given an array of keys with one matching", () => {
expect(provider.any(["notthis", "orthis", "key"])).toEqual('getThisValue');
})
it("should respond with null given an array of keys with no match", () => {
expect(provider.any(["notthis", "orthis"])).toBe(null);
});
it("should respond with the correct value given a variable argument list of keys with one matching", () => {
expect(provider.any("notthis", "orthis", "key")).toEqual('getThisValue');
});
it("should respond with null given no arguments", () => {
expect(provider.any()).toBe(null);
});
})
describe("with a callback", () => {
it("should respond with the correct value given an array of keys with one matching", done => {
provider.any(["notthis", "orthis", "key"], (err, value) => {
expect(value).toEqual('getThisValue');
done();
});
});
it("should respond with an undefined value given an array of keys with no match", done => {
provider.any(["notthis", "orthis"], (err, value) => {
expect(value).toBe(undefined)
done();
});
});
it("should respond with the correct value given a variable argument list of keys with one matching", done => {
provider.any("notthis", "orthis", "key", (err, value) => {
expect(value).toEqual('getThisValue');
done();
});
});
it("should respond with an undefined value given no keys", done => {
provider.any((err, value) => {
expect(value).toBe(undefined)
done();
});
});
})
})
})
});

View File

@ -1,72 +0,0 @@
/*
* argv-test.js: Tests for the nconf argv store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var vows = require('vows'),
assert = require('assert'),
yargs = require('yargs')
nconf = require('../../lib/nconf');
vows.describe('nconf/stores/argv').addBatch({
"An instance of nconf.Argv": {
topic: new nconf.Argv(),
"should have the correct methods defined": function (argv) {
assert.isFunction(argv.loadSync);
assert.isFunction(argv.loadArgv);
assert.deepEqual(argv.options, {});
},
"can be created with a custom yargs":{
topic: function(){
var yargsInstance = yargs.alias('v', 'verbose').default('v', 'false');
return [yargsInstance, new nconf.Argv(yargsInstance)];
},
"and can give access to them": function (argv) {
var yargsInstance = argv[0];
argv = argv[1]
assert.equal(argv.options, yargsInstance)
},
"values are the one from the custom yargv": function (argv) {
argv = argv[1]
argv.loadSync()
assert.equal(argv.get('verbose'), 'false');
assert.equal(argv.get('v'), 'false');
}
},
"can be created with a nconf yargs":{
topic: function(){
var options = {verbose: {alias: 'v', default: 'false'}};
return new nconf.Argv(options);
},
"and can give access to them": function (argv) {
assert.deepEqual(argv.options, {verbose: {alias: 'v', default: 'false'}})
},
"values are the one from the custom yargv": function (argv) {
argv.loadSync()
assert.equal(argv.get('verbose'), 'false');
assert.equal(argv.get('v'), 'false');
},
"values cannot be altered with set when readOnly:true": function (argv) {
argv.set('verbose', 'true');
assert.equal(argv.get('verbose'), 'false');
}
},
"can be created with readOnly set to be false":{
topic: function(){
var options = {verbose: {alias: 'v', default: 'false'}, readOnly: false};
return new nconf.Argv(options);
},
"readOnly is actually false": function (argv) {
assert.equal(argv.readOnly, false);
},
"values can be changed by calling .set": function (argv) {
argv.loadSync()
assert.equal(argv.get('verbose'), 'false');
argv.set('verbose', 'true');
assert.equal(argv.get('verbose'), 'true');
}
}
}
}).export(module);

72
test/stores/argv.test.js Normal file
View File

@ -0,0 +1,72 @@
/*
* argv-test.js: Tests for the nconf argv store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var yargs = require('yargs');
var nconf = require('../../lib/nconf');
describe('nconf/stores/argv, An instance of nconf.Argv', () => {
it("should have the correct methods defined", () => {
var argv = new nconf.Argv();
expect(typeof argv.loadSync).toBe('function');
expect(typeof argv.loadArgv).toBe('function');
expect(argv.options).toEqual({});
});
describe("can be created with a custom yargs", () => {
var yargsInstance = yargs.alias('s', 'somearg').default('s', 'false');
it("and can give access to them", () => {
var argv = new nconf.Argv(yargsInstance);
expect(argv.options).toBe(yargsInstance);
});
it("values are the one from the custom yargv", () => {
var argv = new nconf.Argv(yargsInstance);
argv.loadSync();
expect(argv.get('somearg')).toBe('false');
expect(argv.get('s')).toBe('false');
});
});
describe("can be created with a nconf yargs", () => {
var options = {somearg: {alias: 's', default: 'false'}};
it("and can give access to them", () => {
var argv = new nconf.Argv(options);
expect(argv.options).toEqual({somearg: {alias: 's', default: 'false'}});
});
it("values are the one from the custom yargv", () => {
var argv = new nconf.Argv(options);
argv.loadSync();
expect(argv.get('somearg')).toBe('false');
expect(argv.get('s')).toBe('false');
});
it("values cannot be altered with set when readOnly:true", () => {
var argv = new nconf.Argv(options);
argv.loadSync();
argv.set('somearg', 'true');
expect(argv.get('somearg')).toBe('false');
});
});
describe("can be created with readOnly set to be false", () => {
it("readOnly is actually false", () => {
var argv = new nconf.Argv({readOnly: false});
expect(argv.readOnly).toBe(false);
});
it("values can be changed by calling .set", () => {
var argv = new nconf.Argv({somearg: {alias: 's', default: 'false'}, readOnly: false});
argv.loadSync();
expect(argv.get('somearg')).toBe('false');
argv.set('somearg', 'true');
expect(argv.get('somearg')).toBe('true');
});
});
});

View File

@ -1,35 +0,0 @@
/*
* env-test.js: Tests for the nconf env store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var vows = require('vows'),
assert = require('assert'),
nconf = require('../../lib/nconf');
process.env.TES = 'TING';
vows.describe('nconf/stores/env').addBatch({
"An instance of nconf.Env": {
topic: new nconf.Env(),
"should have the correct methods defined": function (env) {
assert.isFunction(env.loadSync);
assert.isFunction(env.loadEnv);
assert.isArray(env.whitelist);
assert.lengthOf(env.whitelist, 0);
assert.equal(env.separator, '');
}
},
"An instance of nconf.Env with readOnly option set to false": {
topic: new nconf.Env({readOnly: false}),
"should have it's readOnly property set to false": function (env) {
assert.isFunction(env.loadSync);
assert.isFunction(env.loadEnv);
assert.isArray(env.whitelist);
assert.lengthOf(env.whitelist, 0);
assert.ok(!env.readOnly);
}
}
}).export(module);

28
test/stores/env.test.js Normal file
View File

@ -0,0 +1,28 @@
/*
* env-test.js: Tests for the nconf env store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var nconf = require('../../lib/nconf');
describe('nconf/stores/env, An instance of nconf.Env', () => {
it("should have the correct methods defined", () => {
var env = new nconf.Env();
expect(typeof env.loadSync).toBe('function');
expect(typeof env.loadEnv).toBe('function');
expect(env.whitelist instanceof Array).toBeTruthy();
expect(env.whitelist.length).toEqual(0);
expect(env.separator).toEqual('');
});
it("should have the correct methods defined and with readOnly false", () => {
var env = new nconf.Env({readOnly: false});
expect(typeof env.loadSync).toBe('function');
expect(typeof env.loadEnv).toBe('function');
expect(env.whitelist instanceof Array).toBeTruthy();
expect(env.whitelist.length).toEqual(0);
expect(env.separator).toEqual('');
expect(env.readOnly).toBe(false);
});
});

View File

@ -1,310 +0,0 @@
/*
* file-store-test.js: Tests for the nconf File store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs'),
path = require('path'),
vows = require('vows'),
assert = require('assert'),
nconf = require('../../lib/nconf'),
yamlFormat = require('nconf-yaml'),
data = require('../fixtures/data').data,
store;
vows.describe('nconf/stores/file').addBatch({
"When using the nconf file store": {
"with a valid JSON file": {
topic: function () {
var filePath = path.join(__dirname, '..', 'fixtures', 'store.json');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
this.store = store = new nconf.File({ file: filePath });
return null;
},
"the load() method": {
topic: function () {
this.store.load(this.callback);
},
"should load the data correctly": function (err, data) {
assert.isNull(err);
assert.deepEqual(data, this.store.store);
}
}
},
"with a malformed JSON file": {
topic: function () {
var filePath = path.join(__dirname, '..', 'fixtures', 'malformed.json');
this.store = new nconf.File({ file: filePath });
return null;
},
"the load() method with a malformed JSON config file": {
topic: function () {
this.store.load(this.callback.bind(null, null));
},
"should respond with an error and indicate file name": function (_, err) {
assert.isTrue(!!err);
assert.match(err, /malformed\.json/);
}
}
},
"with a valid UTF8 JSON file that contains a BOM": {
topic: function () {
var filePath = path.join(__dirname, '..', 'fixtures', 'bom.json');
this.store = store = new nconf.File({ file: filePath });
return null;
},
"the load() method": {
topic: function () {
this.store.load(this.callback);
},
"should load the data correctly": function (err, data) {
assert.isNull(err);
assert.deepEqual(data, this.store.store);
}
},
"the loadSync() method": {
topic: function () {
var data = this.store.loadSync();
return data;
},
"should load the data correctly": function (result) {
assert.deepEqual(result, this.store.store);
}
}
},
"with a valid UTF8 JSON file that contains no BOM": {
topic: function () {
var filePath = path.join(__dirname, '..', 'fixtures', 'no-bom.json');
this.store = store = new nconf.File({ file: filePath });
return null;
},
"the load() method": {
topic: function () {
this.store.load(this.callback);
},
"should load the data correctly": function (err, data) {
assert.isNull(err);
assert.deepEqual(data, this.store.store);
}
},
"the loadSync() method": {
topic: function () {
var data = this.store.loadSync();
return data;
},
"should load the data correctly": function (result) {
assert.deepEqual(result, this.store.store);
}
}
}
}
}).addBatch({
"When using the nconf file store": {
topic: function () {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json'),
tmpStore = new nconf.File({ file: tmpPath });
return tmpStore;
},
"the save() method": {
topic: function (tmpStore) {
var that = this;
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.save(function () {
fs.readFile(tmpStore.file, function (err, d) {
fs.unlinkSync(tmpStore.file);
return err
? that.callback(err)
: that.callback(err, JSON.parse(d.toString()));
});
});
},
"should save the data correctly": function (err, read) {
assert.isNull(err);
assert.deepEqual(read, data);
}
},
"the saveToFile() method": {
topic: function (tmpStore) {
var that = this,
pathFile = '/tmp/nconf-save-toFile.json';
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.saveToFile(pathFile, function () {
fs.readFile(pathFile, function (err, d) {
fs.unlinkSync(pathFile);
return err
? that.callback(err)
: that.callback(err, JSON.parse(d.toString()));
});
});
},
"should save the data correctly": function (err, read) {
assert.isNull(err);
assert.deepEqual(read, data);
}
},
"the saveToFile() method with custom format": {
topic: function (tmpStore) {
var that = this,
pathFile = '/tmp/nconf-save-toFile.yaml';
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.saveToFile(pathFile, yamlFormat, function () {
fs.readFile(pathFile, function (err, d) {
fs.unlinkSync(pathFile);
return err
? that.callback(err)
: that.callback(err, yamlFormat.parse(d.toString()));
});
});
},
"should save the data correctly": function (err, read) {
assert.isNull(err);
assert.deepEqual(read, data);
}
}
}
}).addBatch({
"When using the nconf file store": {
topic: function () {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json'),
tmpStore = new nconf.File({ file: tmpPath });
return tmpStore;
},
"the saveSync() method": {
topic: function (tmpStore) {
var that = this;
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
var saved = tmpStore.saveSync();
fs.readFile(tmpStore.file, function (err, d) {
fs.unlinkSync(tmpStore.file);
return err
? that.callback(err)
: that.callback(err, JSON.parse(d.toString()), saved);
});
},
"should save the data correctly": function (err, read, saved) {
assert.isNull(err);
assert.deepEqual(read, data);
assert.deepEqual(read, saved);
}
}
}
}).addBatch({
"When using the nconf file store": {
"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": {
"should respond with the true": function () {
assert.equal(store.get('foo:bar:bazz'), 'buzz');
assert.isTrue(store.clear('foo:bar:bazz'));
assert.isTrue(typeof store.get('foo:bar:bazz') === 'undefined');
}
}
}
}).addBatch({
"When using the nconf file store": {
"the search() method": {
"when the target file exists higher in the directory tree": {
topic: function () {
var searchBase = this.searchBase = process.env.HOME;
var filePath = this.filePath = path.join(searchBase, '.nconf');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
return new (nconf.File)({
file: '.nconf'
})
},
"should update the file appropriately": function (store) {
store.search(this.searchBase);
assert.equal(store.file, this.filePath);
fs.unlinkSync(this.filePath);
}
},
"when the target file doesn't exist higher in the directory tree": {
topic: function () {
var filePath = this.filePath = path.join(__dirname, '..', 'fixtures', 'search-store.json');
return new (nconf.File)({
dir: path.dirname(filePath),
file: 'search-store.json'
})
},
"should update the file appropriately": function (store) {
store.search();
assert.equal(store.file, this.filePath);
}
}
}
}
}).addBatch({
"When using the nconf file store": {
topic: function () {
var secureStore = new nconf.File({
file: path.join(__dirname, '..', 'fixtures', 'secure.json'),
secure: 'super-secretzzz'
});
secureStore.store = data;
return secureStore;
},
"the stringify() method should encrypt properly": function (store) {
var contents = JSON.parse(store.stringify());
Object.keys(data).forEach(function (key) {
assert.isObject(contents[key]);
assert.isString(contents[key].value);
assert.equal(contents[key].alg, 'aes-256-ctr');
});
},
"the parse() method should decrypt properly": function (store) {
var contents = store.stringify();
var parsed = store.parse(contents);
assert.deepEqual(parsed, data);
},
"the load() method should decrypt properly": function (store) {
store.load(function (err, loaded) {
assert.isNull(err);
assert.deepEqual(loaded, data);
});
},
"the loadSync() method should decrypt properly": function (store) {
var loaded = store.loadSync()
assert.deepEqual(loaded, data);
}
}
}).export(module);

View File

@ -0,0 +1,239 @@
/*
* file-store-test.js: Tests for the nconf File store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var fs = require('fs');
var path = require('path');
var nconf = require('../../lib/nconf');
var yamlFormat = require('nconf-yaml');
var data = require('../fixtures/data').data;
// FIXME TO RENAME
describe('nconf/stores/file', () => {
describe("When using the nconf file store", () => {
describe("with a valid JSON file", () => {
var filePath = path.join(__dirname, '..', 'fixtures', 'store.json');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
it("the load() method should load the data correctly", done => {
var store = new nconf.File({file: filePath});
store.load((err, data) => {
expect(err).toBe(null);
expect(data).toEqual(store.store);
done();
})
});
});
describe("with a malformed JSON file", () => {
var filePath = path.join(__dirname, '..', 'fixtures', 'malformed.json');
it("the load() method with a malformed JSON config file, should respond with an error and indicate file name",
done => {
var store = new nconf.File({file: filePath});
//FIXME this.store.load(this.callback.bind(null, null));
store.load((err) => {
expect(err).toBeTruthy();
expect(err.message).toMatch(/malformed\.json/);
done();
})
});
});
describe("with a valid UTF8 JSON file that contains a BOM", () => {
var filePath = path.join(__dirname, '..', 'fixtures', 'bom.json');
var store = new nconf.File({file: filePath});
it("the load() method should load the data correctly", done => {
store.load((err, data) => {
expect(err).toBe(null);
expect(data).toEqual(store.store);
done();
});
});
it("the loadSync() method should load the data correctly", () => {
var data = store.loadSync();
expect(data).toEqual(store.store);
});
});
describe("with a valid UTF8 JSON file that contains no BOM", () => {
var filePath = path.join(__dirname, '..', 'fixtures', 'no-bom.json');
var store = new nconf.File({file: filePath});
it("the load() method should load the data correctly", done => {
store.load((err, data) => {
expect(err).toBe(null);
expect(data).toEqual(store.store);
done();
});
});
it("the loadSync() method should load the data correctly", () => {
var data = store.loadSync();
expect(data).toEqual(store.store);
});
})
});
describe("When using the nconf file store", () => {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json');
it("the save() method should save the data correctly", done => {
var tmpStore = new nconf.File({file: tmpPath});
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.save(function () {
fs.readFile(tmpStore.file, function (err, d) {
fs.unlinkSync(tmpStore.file);
expect(err).toBe(null);
expect(JSON.parse(d.toString())).toEqual(data);
done();
});
});
});
it("the saveToFile() method should save the data correctly", done => {
var tmpStore = new nconf.File({file: tmpPath});
var pathFile = '/tmp/nconf-save-toFile.json';
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.saveToFile(pathFile, function () {
fs.readFile(pathFile, function (err, d) {
fs.unlinkSync(pathFile);
expect(err).toBe(null);
expect(JSON.parse(d.toString())).toEqual(data);
done();
});
});
});
it("the saveToFile() method with custom format should save the data correctly", done => {
var tmpStore = new nconf.File({file: tmpPath});
var pathFile = '/tmp/nconf-save-toFile.yaml';
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
tmpStore.saveToFile(pathFile, yamlFormat, function () {
fs.readFile(pathFile, function (err, d) {
fs.unlinkSync(pathFile);
expect(err).toBe(null);
expect(yamlFormat.parse(d.toString())).toEqual(data);
done();
});
});
});
});
describe("When using the nconf file store", () => {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json');
it("the saveSync() method should save the data correctly", done => {
var tmpStore = new nconf.File({file: tmpPath});
Object.keys(data).forEach(function (key) {
tmpStore.set(key, data[key]);
});
var saved = tmpStore.saveSync();
fs.readFile(tmpStore.file, function (err, d) {
fs.unlinkSync(tmpStore.file);
expect(err).toBe(null);
var read = JSON.parse(d.toString());
expect(read).toEqual(data);
expect(read).toEqual(saved);
done();
});
});
});
describe("When using the nconf file store", () => {
var tmpPath = path.join(__dirname, '..', 'fixtures', 'tmp.json');
var store = new nconf.File({file: tmpPath});
it("the set() method should respond with true", () => {
expect(store.set('foo:bar:bazz', 'buzz')).toBeTruthy();
expect(store.set('falsy:number', 0)).toBeTruthy();
expect(store.set('falsy:string', '')).toBeTruthy();
expect(store.set('falsy:boolean', false)).toBeTruthy();
expect(store.set('falsy:object', null)).toBeTruthy();
});
it("the get() method should respond with the correct value", () => {
expect(store.get('foo:bar:bazz')).toEqual('buzz');
expect(store.get('falsy:number')).toEqual(0);
expect(store.get('falsy:string')).toEqual('');
expect(store.get('falsy:boolean')).toEqual(false);
expect(store.get('falsy:object')).toEqual(null);
});
it("the clear() method should respond with the true", () => {
expect(store.get('foo:bar:bazz')).toEqual('buzz');
expect(store.clear('foo:bar:bazz')).toBeTruthy();
expect(typeof store.get('foo:bar:bazz') === 'undefined').toBeTruthy();
});
});
describe("When using the nconf file store", () => {
it("the search() method when the target file exists higher in the directory tree should update the file appropriately", () => {
var searchBase = process.env.HOME;
var filePath = path.join(searchBase, '.nconf');
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
var store = new nconf.File({
file: '.nconf'
});
store.search(store.searchBase);
expect(store.file).toEqual(filePath);
fs.unlinkSync(filePath);
});
it("the search() method when the target file doesn't exist higher in the directory tree should update the file appropriately", () => {
var filePath = path.join(__dirname, '..', 'fixtures', 'search-store.json');
var store = new nconf.File({
dir: path.dirname(filePath),
file: 'search-store.json'
});
store.search();
expect(store.file).toEqual(filePath);
});
})
describe("When using the nconf file store", () => {
var secureStore = new nconf.File({
file: path.join(__dirname, '..', 'fixtures', 'secure.json'),
secure: 'super-secretzzz'
});
secureStore.store = data;
it("the stringify() method should encrypt properly", () => {
var contents = JSON.parse(secureStore.stringify());
Object.keys(data).forEach(key => {
expect(typeof contents[key]).toBe('object');
expect(typeof contents[key].value).toBe('string');
expect(contents[key].alg).toEqual('aes-256-ctr');
});
});
it("the parse() method should decrypt properly", () => {
var contents = secureStore.stringify();
var parsed = secureStore.parse(contents);
expect(parsed).toEqual(data);
});
it("the load() method should decrypt properly", () => {
secureStore.load(function (err, loaded) {
expect(err).toBe(null);
expect(loaded).toEqual(data);
});
});
it("the loadSync() method should decrypt properly", () => {
var loaded = secureStore.loadSync()
expect(loaded).toEqual(data);
});
})
});

View File

@ -1,30 +0,0 @@
/*
* literal-test.js: Tests for the nconf literal store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var vows = require('vows'),
assert = require('assert'),
nconf = require('../../lib/nconf');
vows.describe('nconf/stores/literal').addBatch({
"An instance of nconf.Literal": {
topic: new nconf.Literal({
foo: 'bar',
one: 2
}),
"should have the correct methods defined": function (literal) {
assert.equal(literal.type, 'literal');
assert.isFunction(literal.get);
assert.isFunction(literal.set);
assert.isFunction(literal.merge);
assert.isFunction(literal.loadSync);
},
"should have the correct values in the store": function (literal) {
assert.equal(literal.store.foo, 'bar');
assert.equal(literal.store.one, 2);
}
}
}).export(module);

View File

@ -0,0 +1,25 @@
/*
* literal-test.js: Tests for the nconf literal store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var nconf = require('../../lib/nconf');
describe('nconf/stores/literal, An instance of nconf.Literal', () => {
var envOptions = {foo: 'bar', one: 2};
it("should have the correct methods defined", () => {
var literal = new nconf.Literal(envOptions);
expect(literal.type).toEqual('literal');
expect(typeof literal.get).toBe('function');
expect(typeof literal.set).toBe('function');
expect(typeof literal.merge).toBe('function');
expect(typeof literal.loadSync).toBe('function');
});
it("should have the correct values in the store", () => {
var literal = new nconf.Literal(envOptions);
expect(literal.store.foo).toEqual('bar');
expect(literal.store.one).toEqual(2);
});
});

View File

@ -1,125 +0,0 @@
/*
* memory-store-test.js: Tests for the nconf Memory store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var vows = require('vows'),
assert = require('assert'),
nconf = require('../../lib/nconf'),
merge = require('../fixtures/data').merge;
vows.describe('nconf/stores/memory').addBatch({
"When using the nconf memory store": {
topic: new nconf.Memory(),
"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:empty', ''));
assert.isTrue(store.set('falsy:string:value', 'value'));
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:empty'), '');
assert.equal(store.get('falsy:string:value'), 'value');
assert.equal(store.get('falsy:boolean'), false);
assert.equal(store.get('falsy:object'), null);
},
"should not fail when retrieving non-existent keys": {
"at the root level": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('this:key:does:not:exist'), undefined);
}, TypeError);
},
"within numbers": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('falsy:number:not:exist'), undefined);
}, TypeError);
},
"within booleans": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('falsy:boolean:not:exist'), undefined);
}, TypeError);
},
"within objects": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('falsy:object:not:exist'), undefined);
}, TypeError);
},
"within empty strings": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('falsy:string:empty:not:exist'), undefined);
}, TypeError);
},
"within non-empty strings": function (store) {
assert.doesNotThrow(function() {
assert.equal(store.get('falsy:string:value:not:exist'), undefined);
}, TypeError);
}
}
},
"the clear() method": {
"should respond with the true": function (store) {
assert.equal(store.get('foo:bar:bazz'), 'buzz');
assert.isTrue(store.clear('foo:bar:bazz'));
assert.isTrue(typeof store.get('foo:bar:bazz') === 'undefined');
}
},
"the merge() method": {
"when overriding an existing literal value": function (store) {
store.set('merge:literal', 'string-value');
store.merge('merge:literal', merge);
assert.deepEqual(store.get('merge:literal'), merge);
},
"when overriding an existing Array value": function (store) {
store.set('merge:array', [1,2,3,4]);
store.merge('merge:array', merge);
assert.deepEqual(store.get('merge:literal'), merge);
},
"when merging into an existing Object value": function (store) {
store.set('merge:object', {
prop1: 2,
prop2: 'prop2',
prop3: {
bazz: 'bazz'
},
prop4: ['foo', 'bar']
});
store.merge('merge:object', merge);
assert.equal(store.get('merge:object:prop1'), 1);
assert.equal(store.get('merge:object:prop2').length, 3);
assert.deepEqual(store.get('merge:object:prop3'), {
foo: 'bar',
bar: 'foo',
bazz: 'bazz'
});
assert.equal(store.get('merge:object:prop4').length, 2);
}
}
},
"When using the nconf memory store with different logical separator": {
topic: new nconf.Memory({logicalSeparator: '||' }),
"when storing with : (colon)": {
"should store the config atomicly": function (store) {
store.set('foo:bar:bazz', 'buzz');
assert.isTrue(typeof store.get('foo:bar') === 'undefined');
assert.equal(store.get('foo:bar:bazz'), 'buzz');
}
},
"when storing with separator": {
"should be able to read the object": function (store) {
store.set('foo||bar||bazz', 'buzz');
assert.equal(store.get('foo||bar').bazz, 'buzz');
assert.equal(store.get('foo').bar.bazz, 'buzz');
}
}
}
}).export(module);

View File

@ -0,0 +1,114 @@
/*
* memory-store-test.js: Tests for the nconf Memory store.
*
* (C) 2011, Charlie Robbins and the Contributors.
*
*/
var nconf = require('../../lib/nconf');
var merge = require('../fixtures/data').merge;
describe('nconf/stores/memory', () => {
describe("When using the nconf memory store", () => {
var store = new nconf.Memory();
it("the set() method should respond with true", () => {
expect(store.set('foo:bar:bazz', 'buzz')).toBeTruthy();
expect(store.set('falsy:number', 0)).toBeTruthy();
expect(store.set('falsy:string:empty', '')).toBeTruthy();
expect(store.set('falsy:string:value', 'value')).toBeTruthy();
expect(store.set('falsy:boolean', false)).toBeTruthy();
expect(store.set('falsy:object', null)).toBeTruthy();
});
it("the get() method should respond with the correct value", () => {
expect(store.get('foo:bar:bazz')).toEqual('buzz');
expect(store.get('falsy:number')).toEqual(0);
expect(store.get('falsy:string:empty')).toEqual('');
expect(store.get('falsy:string:value')).toEqual('value');
expect(store.get('falsy:boolean')).toEqual(false);
expect(store.get('falsy:object')).toEqual(null);
});
describe("the get() method should not fail when retrieving non-existent keys", () => {
it("at the root level", () => {
expect(store.get('this:key:does:not:exist')).toEqual(undefined);
});
it("within numbers", () => {
expect(store.get('falsy:number:not:exist')).toEqual(undefined);
});
it("within booleans", () => {
expect(store.get('falsy:boolean:not:exist')).toEqual(undefined);
});
it("within objects", () => {
expect(store.get('falsy:object:not:exist')).toEqual(undefined);
});
it("within empty strings", () => {
expect(store.get('falsy:string:empty:not:exist')).toEqual(undefined);
});
it("within non-empty strings", () => {
expect(store.get('falsy:string:value:not:exist')).toEqual(undefined);
});
});
it("the clear() method, should respond with the true", () => {
expect(store.get('foo:bar:bazz')).toEqual('buzz');
expect(store.clear('foo:bar:bazz')).toBeTruthy();
expect(typeof store.get('foo:bar:bazz') === 'undefined').toBeTruthy();
});
describe("the merge() method", () => {
it("when overriding an existing literal value", () => {
store.set('merge:literal', 'string-value');
store.merge('merge:literal', merge);
expect(store.get('merge:literal')).toEqual(merge);
});
it("when overriding an existing Array value", () => {
store.set('merge:array', [1, 2, 3, 4]);
store.merge('merge:array', merge);
expect(store.get('merge:literal')).toEqual(merge);
});
it("when merging into an existing Object value", () => {
store.set('merge:object', {
prop1: 2,
prop2: 'prop2',
prop3: {
bazz: 'bazz'
},
prop4: ['foo', 'bar']
});
store.merge('merge:object', merge);
expect(store.get('merge:object:prop1')).toEqual(1);
expect(store.get('merge:object:prop2').length).toEqual(3);
expect(store.get('merge:object:prop3')).toEqual({
foo: 'bar',
bar: 'foo',
bazz: 'bazz'
});
expect(store.get('merge:object:prop4').length).toEqual(2);
});
});
});
describe("When using the nconf memory store with different logical separator", () => {
var store = new nconf.Memory({logicalSeparator: '||'});
it("when storing with : (colon), should store the config atomicly", () => {
store.set('foo:bar:bazz', 'buzz');
expect(typeof store.get('foo:bar') === 'undefined').toBeTruthy();
expect(store.get('foo:bar:bazz')).toEqual('buzz');
});
it("when storing with separator, should be able to read the object", () => {
store.set('foo||bar||bazz', 'buzz');
expect(store.get('foo||bar').bazz).toEqual('buzz');
expect(store.get('foo').bar.bazz).toEqual('buzz');
})
});
});