Skip to content

Commit

Permalink
[dist api test] Finished integrating features from reconf and updatin…
Browse files Browse the repository at this point in the history
…g associated tests
  • Loading branch information
indexzero committed Aug 23, 2011
1 parent add8922 commit a6533aa
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 28 deletions.
37 changes: 34 additions & 3 deletions lib/nconf/provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
*
*/

var stores = require('./stores');
var optimist = require('optimist'),
stores = require('./stores');

//
// ### function Provider (options)
Expand All @@ -14,7 +15,10 @@ var stores = require('./stores');
// for exposing the pluggable storage features of `nconf`.
//
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);
};

Expand Down Expand Up @@ -50,6 +54,14 @@ Provider.prototype.use = function (type, options) {
// Retrieves the value for the specified key (if any).
//
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);
};

Expand Down Expand Up @@ -154,4 +166,23 @@ Provider.prototype.save = function (value, callback) {
//
Provider.prototype.reset = function (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;
});
44 changes: 31 additions & 13 deletions lib/nconf/stores/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var File = exports.File = function (options) {

this.type = 'file';
this.file = options.file;
this.search = options.search || false;
this.dir = options.dir || process.cwd();
this.format = options.format || {
stringify: function (obj) {
return JSON.stringify(obj, null, 2)
Expand Down Expand Up @@ -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.
// Attempts to find `this.file` by iteratively searching up the
// directory structure
//
File.prototype.resolve = function (base) {
var looking = this.search,
File.prototype.search = function (base) {
var looking = true,
fullpath,
previous,
stats;

base = base || process.cwd();

if (this.file[0] === '/') {
//
// If filename for this instance is a fully qualified path
// (i.e. it starts with a `'/'`) then check if it exists
//
try {
stats = fs.statSync(fs.realpathSync(fullpath));
stats = fs.statSync(fs.realpathSync(this.file));
if (stats.isFile()) {
fullpath = this.file;
looking = false;
Expand Down Expand Up @@ -186,32 +191,45 @@ File.prototype.resolve = function (base) {
}

while (looking) {
//
// Iteratively look up the directory structure from `base`
//
try {
stats = fs.statSync(fs.realpathSync(fullpath = path.join(base, this.file)));
looking = stats.isDirectory();
}
catch (ex) {
var olddir = dir;
dir = path.dirname(dir);

if (olddir === dir) {
previous = base;
base = path.dirname(base);

if (previous === base) {
//
// If we've reached the top of the directory structure then simply use
// the default file path.
//
try {
var stat = fs.statSync(fs.realpathSync(configPath = path.join(process.env.HOME, filename)));
if(stat.isDirectory()) {
configPath = undefined;
stats = fs.statSync(fs.realpathSync(fullpath = path.join(this.dir, this.file)));
if (stats.isDirectory()) {
fullpath = undefined;
}
}
catch (ex) {
//
// Ignore errors
//
configPath = undefined;
}

looking = false;
}
}
}

//
// 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;
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"keywords": ["configuration", "key value store", "plugabble"],
"dependencies": {
"async": "0.1.x",
"optimist": "0.2.x",
"pkginfo": "0.2.x"
},
"devDependencies": {
Expand Down
32 changes: 32 additions & 0 deletions test/file-store-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
11 changes: 11 additions & 0 deletions test/fixtures/scripts/default-override.js
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions test/fixtures/scripts/nconf-override.js
Original file line number Diff line number Diff line change
@@ -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'));
43 changes: 31 additions & 12 deletions test/provider-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,47 @@
*
*/

var fs = require('fs'),
var assert = require('assert'),
fs = require('fs'),
path = require('path'),
spawn = require('child_process').spawn,
vows = require('vows'),
assert = require('assert'),
nconf = require('../lib/nconf')

var first = '/path/to/file1',
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({
"When using an instance of nconf.Provier": {
"calling the use() method with the same store type and different options": {
topic: new nconf.Provider().use('file', { file: first }),
"should use a new instance of the store type": function (provider) {
var old = provider.store;
"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: first }),
"should use a new instance of the store type": function (provider) {
var old = provider.store;

assert.equal(provider.store.file, first);
provider.use('file', { file: second });
assert.equal(provider.store.file, first);
provider.use('file', { file: second });

assert.notStrictEqual(old, provider.store);
assert.equal(provider.store.file, second);
}
assert.notStrictEqual(old, provider.store);
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);

0 comments on commit a6533aa

Please sign in to comment.