[dist api test] Finished integrating features from reconf and updating associated tests
This commit is contained in:
parent
add8922c04
commit
a6533aa7bf
7 changed files with 151 additions and 27 deletions
|
@ -5,7 +5,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var stores = require('./stores');
|
var optimist = require('optimist'),
|
||||||
|
stores = require('./stores');
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function Provider (options)
|
// ### function Provider (options)
|
||||||
|
@ -14,7 +15,10 @@ var stores = require('./stores');
|
||||||
// for exposing the pluggable storage features of `nconf`.
|
// for exposing the pluggable storage features of `nconf`.
|
||||||
//
|
//
|
||||||
var Provider = exports.Provider = function (options) {
|
var Provider = exports.Provider = function (options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
this.overrides = options.overrides || null
|
||||||
|
this.useArgv = options.useArgv || false;
|
||||||
|
|
||||||
this.store = stores.create(options.type || 'memory', options);
|
this.store = stores.create(options.type || 'memory', options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -50,6 +54,14 @@ Provider.prototype.use = function (type, options) {
|
||||||
// Retrieves the value for the specified key (if any).
|
// Retrieves the value for the specified key (if any).
|
||||||
//
|
//
|
||||||
Provider.prototype.get = function (key, callback) {
|
Provider.prototype.get = function (key, callback) {
|
||||||
|
if (this.overrides && Object.prototype.hasOwnProperty.call(this.overrides, key)) {
|
||||||
|
if (callback) {
|
||||||
|
callback(null, this.overrides[key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.overrides[key];
|
||||||
|
}
|
||||||
|
|
||||||
return this.store.get(key, callback);
|
return this.store.get(key, callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,4 +166,23 @@ Provider.prototype.save = function (value, callback) {
|
||||||
//
|
//
|
||||||
Provider.prototype.reset = function (callback) {
|
Provider.prototype.reset = function (callback) {
|
||||||
return this.store.reset(callback);
|
return this.store.reset(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### getter @useArgv {boolean}
|
||||||
|
// Gets a property indicating if we should wrap calls to `.get`
|
||||||
|
// by checking `optimist.argv`.
|
||||||
|
//
|
||||||
|
Provider.prototype.__defineGetter__('useArgv', function () {
|
||||||
|
return this._useArgv;
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// ### setter @useArgv {boolean}
|
||||||
|
// Sets a property indicating if we should wrap calls to `.get`
|
||||||
|
// by checking `optimist.argv`.
|
||||||
|
//
|
||||||
|
Provider.prototype.__defineSetter__('useArgv', function (val) {
|
||||||
|
this._useArgv = val || false;
|
||||||
|
this.overrides = this.overrides || optimist.argv;
|
||||||
|
});
|
|
@ -25,7 +25,7 @@ var File = exports.File = function (options) {
|
||||||
|
|
||||||
this.type = 'file';
|
this.type = 'file';
|
||||||
this.file = options.file;
|
this.file = options.file;
|
||||||
this.search = options.search || false;
|
this.dir = options.dir || process.cwd();
|
||||||
this.format = options.format || {
|
this.format = options.format || {
|
||||||
stringify: function (obj) {
|
stringify: function (obj) {
|
||||||
return JSON.stringify(obj, null, 2)
|
return JSON.stringify(obj, null, 2)
|
||||||
|
@ -144,21 +144,26 @@ File.prototype.loadSync = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// ### function resolve (base)
|
// ### function search (base)
|
||||||
// #### @base {string} Base directory (or file) to begin searching for the target file.
|
// #### @base {string} Base directory (or file) to begin searching for the target file.
|
||||||
|
// Attempts to find `this.file` by iteratively searching up the
|
||||||
|
// directory structure
|
||||||
//
|
//
|
||||||
File.prototype.resolve = function (base) {
|
File.prototype.search = function (base) {
|
||||||
var looking = this.search,
|
var looking = true,
|
||||||
fullpath,
|
fullpath,
|
||||||
|
previous,
|
||||||
stats;
|
stats;
|
||||||
|
|
||||||
|
base = base || process.cwd();
|
||||||
|
|
||||||
if (this.file[0] === '/') {
|
if (this.file[0] === '/') {
|
||||||
//
|
//
|
||||||
// If filename for this instance is a fully qualified path
|
// If filename for this instance is a fully qualified path
|
||||||
// (i.e. it starts with a `'/'`) then check if it exists
|
// (i.e. it starts with a `'/'`) then check if it exists
|
||||||
//
|
//
|
||||||
try {
|
try {
|
||||||
stats = fs.statSync(fs.realpathSync(fullpath));
|
stats = fs.statSync(fs.realpathSync(this.file));
|
||||||
if (stats.isFile()) {
|
if (stats.isFile()) {
|
||||||
fullpath = this.file;
|
fullpath = this.file;
|
||||||
looking = false;
|
looking = false;
|
||||||
|
@ -186,26 +191,32 @@ File.prototype.resolve = function (base) {
|
||||||
}
|
}
|
||||||
|
|
||||||
while (looking) {
|
while (looking) {
|
||||||
|
//
|
||||||
|
// Iteratively look up the directory structure from `base`
|
||||||
|
//
|
||||||
try {
|
try {
|
||||||
stats = fs.statSync(fs.realpathSync(fullpath = path.join(base, this.file)));
|
stats = fs.statSync(fs.realpathSync(fullpath = path.join(base, this.file)));
|
||||||
looking = stats.isDirectory();
|
looking = stats.isDirectory();
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
var olddir = dir;
|
previous = base;
|
||||||
dir = path.dirname(dir);
|
base = path.dirname(base);
|
||||||
|
|
||||||
if (olddir === dir) {
|
if (previous === base) {
|
||||||
|
//
|
||||||
|
// If we've reached the top of the directory structure then simply use
|
||||||
|
// the default file path.
|
||||||
|
//
|
||||||
try {
|
try {
|
||||||
var stat = fs.statSync(fs.realpathSync(configPath = path.join(process.env.HOME, filename)));
|
stats = fs.statSync(fs.realpathSync(fullpath = path.join(this.dir, this.file)));
|
||||||
if(stat.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
configPath = undefined;
|
fullpath = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
//
|
//
|
||||||
// Ignore errors
|
// Ignore errors
|
||||||
//
|
//
|
||||||
configPath = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
looking = false;
|
looking = false;
|
||||||
|
@ -213,5 +224,12 @@ File.prototype.resolve = function (base) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set the file for this instance to the fullpath
|
||||||
|
// that we have found during the search. In the event that
|
||||||
|
// the search was unsuccessful use the original value for `this.file`.
|
||||||
|
//
|
||||||
|
this.file = fullpath || this.file;
|
||||||
|
|
||||||
return fullpath;
|
return fullpath;
|
||||||
};
|
};
|
|
@ -10,6 +10,7 @@
|
||||||
"keywords": ["configuration", "key value store", "plugabble"],
|
"keywords": ["configuration", "key value store", "plugabble"],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "0.1.x",
|
"async": "0.1.x",
|
||||||
|
"optimist": "0.2.x",
|
||||||
"pkginfo": "0.2.x"
|
"pkginfo": "0.2.x"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -101,4 +101,36 @@ vows.describe('nconf/stores/file').addBatch({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}).addBatch({
|
||||||
|
"When using the nconf file store": {
|
||||||
|
"the search() method": {
|
||||||
|
"when the target file exists higher in the directory tree": {
|
||||||
|
topic: function () {
|
||||||
|
var filePath = this.filePath = path.join(process.env.HOME, '.nconf');
|
||||||
|
fs.writeFileSync(filePath, JSON.stringify(data, null, 2));
|
||||||
|
return new (nconf.stores.File)({
|
||||||
|
file: '.nconf'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"should update the file appropriately": function (store) {
|
||||||
|
store.search();
|
||||||
|
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.stores.File)({
|
||||||
|
dir: path.dirname(filePath),
|
||||||
|
file: 'search-store.json'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
"should update the file appropriately": function (store) {
|
||||||
|
store.search();
|
||||||
|
assert.equal(store.file, this.filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}).export(module);
|
}).export(module);
|
11
test/fixtures/scripts/default-override.js
vendored
Normal file
11
test/fixtures/scripts/default-override.js
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/*
|
||||||
|
* nconf-override.js: Test fixture for using optimist defaults with nconf.
|
||||||
|
*
|
||||||
|
* (C) 2011, Charlie Robbins
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var nconf = require('../../../lib/nconf');
|
||||||
|
|
||||||
|
nconf.useArgv = true;
|
||||||
|
process.stdout.write(nconf.get('something'));
|
12
test/fixtures/scripts/nconf-override.js
vendored
Normal file
12
test/fixtures/scripts/nconf-override.js
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* nconf-override.js: Test fixture for using optimist defaults with nconf.
|
||||||
|
*
|
||||||
|
* (C) 2011, Charlie Robbins
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
var nconf = require('../../../lib/nconf');
|
||||||
|
|
||||||
|
var provider = new (nconf.Provider)({ useArgv: true });
|
||||||
|
|
||||||
|
process.stdout.write(provider.get('something'));
|
|
@ -5,28 +5,47 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fs = require('fs'),
|
var assert = require('assert'),
|
||||||
|
fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
|
spawn = require('child_process').spawn,
|
||||||
vows = require('vows'),
|
vows = require('vows'),
|
||||||
assert = require('assert'),
|
|
||||||
nconf = require('../lib/nconf')
|
nconf = require('../lib/nconf')
|
||||||
|
|
||||||
var first = '/path/to/file1',
|
var first = '/path/to/file1',
|
||||||
second = '/path/to/file2';
|
second = '/path/to/file2';
|
||||||
|
|
||||||
|
function assertDefaults (script) {
|
||||||
|
return {
|
||||||
|
topic: function () {
|
||||||
|
spawn('node', [script, '--something', 'foobar'])
|
||||||
|
.stdout.once('data', this.callback.bind(this, null));
|
||||||
|
},
|
||||||
|
"should respond with the value passed into the script": function (_, data) {
|
||||||
|
assert.equal(data.toString(), 'foobar');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vows.describe('nconf/provider').addBatch({
|
vows.describe('nconf/provider').addBatch({
|
||||||
"When using an instance of nconf.Provier": {
|
"When using nconf": {
|
||||||
"calling the use() method with the same store type and different options": {
|
"an instance of 'nconf.Provider'": {
|
||||||
topic: new nconf.Provider().use('file', { file: first }),
|
"calling the use() method with the same store type and different options": {
|
||||||
"should use a new instance of the store type": function (provider) {
|
topic: new nconf.Provider().use('file', { file: first }),
|
||||||
var old = provider.store;
|
"should use a new instance of the store type": function (provider) {
|
||||||
|
var old = provider.store;
|
||||||
|
|
||||||
assert.equal(provider.store.file, first);
|
assert.equal(provider.store.file, first);
|
||||||
provider.use('file', { file: second });
|
provider.use('file', { file: second });
|
||||||
|
|
||||||
assert.notStrictEqual(old, provider.store);
|
assert.notStrictEqual(old, provider.store);
|
||||||
assert.equal(provider.store.file, second);
|
assert.equal(provider.store.file, second);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"when 'useArgv' is true": assertDefaults(path.join(__dirname, 'fixtures', 'scripts', 'nconf-override.js'))
|
||||||
|
},
|
||||||
|
"the default nconf provider": {
|
||||||
|
"when 'useArgv' is true": assertDefaults(path.join(__dirname, 'fixtures', 'scripts', 'default-override.js'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).export(module);
|
}).export(module);
|
Loading…
Reference in a new issue