diff --git a/.circleci/config.yml b/.circleci/config.yml index 0dbb726..289faf7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -17,8 +17,6 @@ commands: - run: name: Test command: npm test - - coverage - - save-npm-cache save-npm-cache: steps: - save_cache: diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..9cf9495 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/lib/nconf/provider.js b/lib/nconf/provider.js index 48bdb99..027cc1a 100644 --- a/lib/nconf/provider.js +++ b/lib/nconf/provider.js @@ -229,7 +229,7 @@ Provider.prototype.get = function (key, callback) { // the entire set of stores, but up until there is a defined value. // var current = 0, - names = Object.keys(this.stores), + names = Object.keys(this.stores).filter(x => x !== 'mock'), self = this, response, mergeObjs = []; @@ -437,7 +437,7 @@ Provider.prototype.load = function (callback) { function loadStoreSync(store) { if (!store.loadSync) { - throw new Error('nconf store ' + store.type + ' has no loadSync() method'); + throw new Error('nconf store "' + store.type + '" has no loadSync() method'); } return store.loadSync(); @@ -597,7 +597,7 @@ Provider.prototype._execute = function (action, syncLength /* [arguments] */) { self = this, response, mergeObjs = [], - keys = Object.keys(this.stores); + keys = Object.keys(this.stores).filter(x => x !== 'mock'); function runAction (name, next) { diff --git a/package.json b/package.json index 012b942..92148d4 100644 --- a/package.json +++ b/package.json @@ -23,17 +23,11 @@ "ini": "^1.3.0" }, "devDependencies": { - "coveralls": "^3.0.2", - "eslint": "^6.0.0", - "istanbul": "^0.4.1", - "jest": "^24.0.0", - "nconf-yaml": "^1.0.2" + "eltro": "^1.0.2" }, - "main": "./lib/nconf", + "main": "./lib/nconf.mjs", "scripts": { - "test": "jest --verbose", - "cover": "jest --coverage", - "coveralls": "cat coverage/lcov.info | coveralls", + "test": "eltro test/**/*.test.mjs -r dot", "lint": "eslint ." }, "files": [ diff --git a/test/helpers.js b/test/helpers.js deleted file mode 100644 index fa35e6c..0000000 --- a/test/helpers.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * helpers.js: Test helpers for nconf. - * - * (C) 2011, Charlie Robbins and the Contributors. - * - */ - -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; - - 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 done => { - var env = null; - - 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', data => { - expect(data.toString()).toEqual('foobar'); - done(); - }); - } -} - -// copy a file -exports.cp = function (from, to, callback) { - fs.readFile(from, function (err, data) { - if (err) return callback(err); - fs.writeFile(to, data, callback); - }); -}; - -exports.fixture = function (file) { - return path.join(__dirname, 'fixtures', file); -}; diff --git a/test/helpers.mjs b/test/helpers.mjs new file mode 100644 index 0000000..7c8d124 --- /dev/null +++ b/test/helpers.mjs @@ -0,0 +1,64 @@ +import { assert } from 'eltro' + +import fs from 'fs' +import path from 'path' +import { exec as ex } from 'child_process' +import { fileURLToPath } from 'url' +import nconf from '../lib/nconf.js' + + +let __dirname = path.dirname(fileURLToPath(import.meta.url)) + +export function assertMerged(err, merged) { + merged = merged instanceof nconf.Provider + ? merged.store.store + : merged; + + assert.strictEqual(err, null) + assert.strictEqual(typeof(merged), 'object') + assert.ok(merged.apples) + assert.ok(merged.bananas) + assert.strictEqual(typeof(merged.candy), 'object') + assert.ok(merged.candy.something1) + assert.ok(merged.candy.something2) + assert.ok(merged.candy.something3) + assert.ok(merged.candy.something4) + assert.ok(merged.dates) + assert.ok(merged.elderberries) +}; + +// copy a file +export function cp(from, to) { + return new Promise(function(res, rej) { + fs.readFile(from, function (err, data) { + if (err) return rej(err); + fs.writeFile(to, data, function(err, data) { + if (err) return rej(err) + res(data) + }); + }); + }) +}; + +export function exec(script, prefix = 'node') { + let command = `${prefix} ${script}` + return new Promise(function(res, rej) { + ex(command, + function (err, stdout, stderr) { + if (err) { + err.stdout = stdout + err.stderr = stderr + return rej(err) + } + res({ + stdout, + stderr, + }) + } + ) + }) +} + +export function fixture(file) { + return path.resolve(path.join(__dirname, 'fixtures', file)); +}; diff --git a/test/hierarchy.test.js b/test/hierarchy.test.js deleted file mode 100644 index aa54390..0000000 --- a/test/hierarchy.test.js +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 .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(); - }); - }) -}) diff --git a/test/hierarchy.test.mjs b/test/hierarchy.test.mjs new file mode 100644 index 0000000..b74d1e9 --- /dev/null +++ b/test/hierarchy.test.mjs @@ -0,0 +1,46 @@ +import { Eltro as t, assert} from 'eltro' +import * as helpers from './helpers.mjs' +import nconf from '../lib/nconf.js' + +var globalConfig = helpers.fixture('hierarchy/global.json'); +var userConfig = helpers.fixture('hierarchy/user.json'); + +t.describe('nconf/hierarchy, When using nconf', function() { + t.test("configured with two file stores, should have the appropriate keys present", function() { + nconf.add('user', {type: 'file', file: userConfig}); + nconf.add('global', {type: 'file', file: globalConfig}); + nconf.load(); + + assert.strictEqual(nconf.get('title'), 'My specific title'); + assert.strictEqual(nconf.get('color'), 'green'); + assert.strictEqual(nconf.get('movie'), 'Kill Bill'); + }); + + t.test("configured with two file stores using `file` should have the appropriate keys present", function() { + nconf.file('user', userConfig); + nconf.file('global', globalConfig); + nconf.load(); + + assert.strictEqual(nconf.get('title'), 'My specific title'); + assert.strictEqual(nconf.get('color'), 'green'); + assert.strictEqual(nconf.get('movie'), 'Kill Bill'); + }); + + t.test("configured with .file(), .defaults() should deep merge objects should merge nested objects ", async function() { + var script = helpers.fixture('scripts/nconf-hierarchical-defaults-merge.js'); + let res = await helpers.exec(script) + + assert.deepEqual(JSON.parse(res.stdout), { + candy: { + something: 'much better something for you', + something1: true, + something2: true, + something18: 'completely unique', + something5: { + first: 1, + second: 99 + } + } + }); + }) +}) diff --git a/test/mocks/mock-store.js b/test/mocks/mock-store.js index 4a6c1f3..6daac8d 100644 --- a/test/mocks/mock-store.js +++ b/test/mocks/mock-store.js @@ -1,10 +1,3 @@ -/* - * mock-store.js: Mock store for ensuring certain operations are actually called. - * - * (C) 2011, Charlie Robbins and the Contributors. - * - */ - var util = require('util'), events = require('events'), nconf = require('../../lib/nconf'); @@ -35,4 +28,8 @@ Mock.prototype.save = function (value, callback) { self.emit('save'); callback(); }, 1000); -}; \ No newline at end of file +}; + +Mock.prototype.loadSync = function() { + return {} +} diff --git a/test/nconf.test.js b/test/nconf.test.js deleted file mode 100644 index 377560f..0000000 --- a/test/nconf.test.js +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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(); - }); - }) - }) - }) -}) diff --git a/test/nconf.test.mjs b/test/nconf.test.mjs new file mode 100644 index 0000000..073686b --- /dev/null +++ b/test/nconf.test.mjs @@ -0,0 +1,111 @@ +import fs from 'fs' +import path from 'path' +import { Eltro as t, assert} from 'eltro' +import nconf from '../lib/nconf.js' +import * as helpers from './helpers.mjs' + +t.describe('nconf, When using the nconf', function() { + t.test("should have the correct methods set", function() { + assert.strictEqual(typeof(nconf.key), 'function') + assert.strictEqual(typeof(nconf.path), 'function') + assert.strictEqual(typeof(nconf.use), 'function') + assert.strictEqual(typeof(nconf.any), 'function') + assert.strictEqual(typeof(nconf.get), 'function') + assert.strictEqual(typeof(nconf.set), 'function') + assert.strictEqual(typeof(nconf.clear), 'function') + assert.strictEqual(typeof(nconf.load), 'function') + assert.strictEqual(typeof(nconf.save), 'function') + assert.strictEqual(typeof(nconf.reset), 'function') + assert.strictEqual(typeof(nconf.required), 'function') + }) + + t.test("the use() method should instaniate the correct store", function() { + nconf.use('memory') + nconf.load() + assert.ok(nconf.stores['memory'] instanceof nconf.Memory) + }) + + t.test("nconf should have the correct version set", function () { + let pckg = JSON.parse(fs.readFileSync(helpers.fixture('../../package.json'))) + assert.ok(pckg.version) + assert.strictEqual(nconf.version, pckg.version) + }) + + t.describe("the required() method", function() { + t.test("should throw error with missing keys", function() { + nconf.set('foo:bar:bazz', 'buzz') + assert.throws(function() { + nconf.required(['missing', 'foo:bar:bazz']) + }) + }) + t.test("should return the provider if all required keys exist", function() { + var Provider = nconf.Provider + nconf.set('foo:bar:bazz', 'buzz') + assert.ok(nconf.required(['foo:bar:bazz']) instanceof Provider) + }) + }) + t.describe("with the memory store", function() { + t.describe("the set() method", function() { + t.test("should respond with true", function() { + assert.ok(nconf.set('foo:bar:bazz', 'buzz')) + }) + t.test("should respond allow access to the root and complain about non-objects", function() { + assert.notOk(nconf.set(null, null)) + assert.notOk(nconf.set(null, undefined)) + assert.notOk(nconf.set(null)) + assert.notOk(nconf.set(null, '')) + assert.notOk(nconf.set(null, 1)) + var original = nconf.get() + assert.ok(nconf.set(null, nconf.get())) + assert.notStrictEqual(nconf.get(), original) + assert.deepEqual(nconf.get(), original) + }) + }) + t.describe("the get() method", function() { + t.test("should respond with the correct value without a callback", function() { + assert.strictEqual(nconf.get('foo:bar:bazz'), 'buzz') + }) + t.test("should not step inside strings without a callback", function() { + assert.strictEqual(nconf.get('foo:bar:bazz:0'), undefined) + }) + t.test("should respond with the correct value with a callback", function (done) { + nconf.get('foo:bar:bazz', (err, value) => { + try { + assert.strictEqual(value, 'buzz') + done() + } catch (leErr) { + done(leErr) + } + }) + }) + t.test("should respond allow access to the root", function() { + assert.ok(nconf.get(null)) + assert.ok(nconf.get(undefined)) + assert.ok(nconf.get()) + }) + }) + t.describe("the clear() method", function() { + t.test("should respond with the true", function() { + assert.strictEqual(nconf.get('foo:bar:bazz'), 'buzz') + assert.ok(nconf.clear('foo:bar:bazz')) + assert.ok(typeof(nconf.get('foo:bar:bazz')) === 'undefined') + }) + }) + t.describe("the load() method", function() { + t.test("should respond with the merged store without a callback", function() { + assert.deepEqual(nconf.load(), {"foo": {"bar": {}}}) + }) + t.test("should respond with the merged store", function (done) { + nconf.load((err, store) => { + try { + assert.strictEqual(err, null) + assert.deepEqual(store, {"foo": {"bar": {}}}) + done() + } catch (leErr) { + done(leErr) + } + }) + }) + }) + }) +}) diff --git a/test/provider-save.test.js b/test/provider-save.test.js deleted file mode 100644 index c2a8775..0000000 --- a/test/provider-save.test.js +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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(); - }); - }) - }) -}); \ No newline at end of file diff --git a/test/provider-save.test.mjs b/test/provider-save.test.mjs new file mode 100644 index 0000000..c79b878 --- /dev/null +++ b/test/provider-save.test.mjs @@ -0,0 +1,26 @@ +import { Eltro as t, assert} from 'eltro' +import nconf from '../lib/nconf.js' +import './mocks/mock-store.js' + +t.describe('nconf/provider/save', () => { + t.describe("When using nconf an instance of 'nconf.Provider' with a Mock store", () => { + var nconfMock = nconf.use('mock'); + + t.test("the save() method should actually save before responding", function(done) { + var mock = nconf.stores.mock; + + mock.on('save', function () { + nconfMock.saved = true; + }); + + nconf.save(() => { + try { + assert.strictEqual(nconfMock.saved, true) + done(); + } catch (err) { + done(err) + } + }); + }) + }) +}); \ No newline at end of file diff --git a/test/provider.test.js b/test/provider.test.js deleted file mode 100644 index 618fa78..0000000 --- a/test/provider.test.js +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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 '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("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(); - }); - }); - }) - }) - }) -}); diff --git a/test/provider.test.mjs b/test/provider.test.mjs new file mode 100644 index 0000000..df60ea4 --- /dev/null +++ b/test/provider.test.mjs @@ -0,0 +1,223 @@ +import fs from 'fs' +import path from 'path' +import { spawn } from 'child_process' +import { Eltro as t, assert} from 'eltro' +import * as helpers from './helpers.mjs' +import nconf from '../lib/nconf.js' + +var files = [ + helpers.fixture('merge/file1.json'), + helpers.fixture('merge/file2.json'), +]; +var override = JSON.parse(fs.readFileSync(files[0]), 'utf8'); + +function assertSystemConf(options) { + return new Promise(function(res, rej) { + var env = null; + + 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', data => { + res(data.toString()) + }); + }) +} + +t.describe('nconf/provider When using nconf', function() { + t.describe("an instance of 'nconf.Provider'", function() { + t.test("calling the use() method with the same store type and different options" + + " should use a new instance of the store type", function() { + var provider = new nconf.Provider().use('file', {file: files[0]}); + var old = provider.stores['file']; + + assert.strictEqual(provider.stores.file.file, files[0]); + provider.use('file', {file: files[1]}); + + assert.notStrictEqual(old, provider.stores.file); + assert.strictEqual(provider.stores.file.file, files[1]); + }) + }); + + t.test("respond with correct arg when 'env' is true", async function() { + let result = await assertSystemConf({ + script: helpers.fixture('scripts/provider-env.js'), + env: {SOMETHING: 'foobar'} + }) + + assert.strictEqual(result.toString(), 'foobar') + }); + + t.test("respond with correct arg when 'env' is true and 'parseValues' option is true", 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]; + }); + + assert.strictEqual(provider.get('SOMETHING'), 'foobar'); + assert.strictEqual(provider.get('SOMEBOOL'), true); + assert.notStrictEqual(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'); + }); + + t.describe("an instance of 'nconf.Provider'", function() { + t.describe("the merge() method", function() { + t.test("should have the result merged in", function() { + var provider = new nconf.Provider().use('file', {file: files[1]}); + provider.load(); + provider.merge(override); + helpers.assertMerged(null, provider.stores.file.store); + assert.strictEqual(provider.stores.file.store.candy.something, 'file1'); + }); + + t.test("should merge Objects over null", function() { + var provider = new nconf.Provider().use('file', {file: files[1]}); + provider.load(); + provider.merge(override); + assert.strictEqual(provider.stores.file.store.unicorn.exists, true); + }); + + }) + t.describe("the load() method", function() { + t.test("should respect the hierarchy when sources are passed in", function() { + 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); + assert.strictEqual(merged.candy.something, 'file1'); + }) + t.test("should respect the hierarchy when multiple stores are used", function() { + 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); + assert.strictEqual(merged.foo.bar, 'baz'); + assert.strictEqual(merged.candy.something, 'file1'); + }) + }) + }) + t.describe("the .file() method", function() { + t.test("should use the correct File store with a single filepath", function() { + var provider = new nconf.Provider(); + provider.file(helpers.fixture('store.json')); + assert.strictEqual(typeof(provider.stores.file), 'object'); + }); + t.test("should use the correct File store with a name and a filepath", function() { + var provider = new nconf.Provider(); + provider.file('custom', helpers.fixture('store.json')); + assert.strictEqual(typeof(provider.stores.custom), 'object'); + }); + t.test("should use the correct File store with a single object", function() { + var provider = new nconf.Provider(); + provider.file({ + dir: helpers.fixture(''), + file: 'store.json', + search: true + }); + + assert.strictEqual(typeof(provider.stores.file), 'object'); + assert.strictEqual(provider.stores.file.file, helpers.fixture('store.json')); + }); + t.test("should use the correct File store with a name and an object", function() { + var provider = new nconf.Provider(); + provider.file('custom', { + dir: helpers.fixture(''), + file: 'store.json', + search: true + }); + + assert.strictEqual(typeof(provider.stores.custom), 'object'); + assert.strictEqual(provider.stores.custom.file, helpers.fixture('store.json')); + }) + t.describe("the any() method", function() { + var provider = new nconf.Provider({ + type: 'literal', + store: { + key: "getThisValue" + } + }) + t.describe("without a callback", function() { + t.test("should respond with the correct value given an array of keys with one matching", function() { + assert.strictEqual(provider.any(["notthis", "orthis", "key"]), 'getThisValue'); + }) + t.test("should respond with null given an array of keys with no match", function() { + assert.strictEqual(provider.any(["notthis", "orthis"]), null); + }); + t.test("should respond with the correct value given a variable argument list of keys with one matching", function() { + assert.strictEqual(provider.any("notthis", "orthis", "key"), 'getThisValue'); + }); + t.test("should respond with null given no arguments", function() { + assert.strictEqual(provider.any(), null); + }); + }) + t.describe("with a callback", function() { + t.test("should respond with the correct value given an array of keys with one matching", function(done) { + provider.any(["notthis", "orthis", "key"], (err, value) => { + assert.strictEqual(value, 'getThisValue'); + done(); + }); + }); + t.test("should respond with an undefined value given an array of keys with no match", function(done) { + provider.any(["notthis", "orthis"], (err, value) => { + assert.strictEqual(value, undefined) + done(); + }); + }); + t.test("should respond with the correct value given a variable argument list of keys with one matching", function(done) { + provider.any("notthis", "orthis", "key", (err, value) => { + assert.strictEqual(value, 'getThisValue'); + done(); + }); + }); + + t.test("should respond with an undefined value given no keys", function(done) { + provider.any((err, value) => { + assert.strictEqual(value, undefined) + done(); + }); + }); + }) + }) + }) +});