Skip to content
This repository has been archived by the owner on Dec 12, 2018. It is now read-only.

Commit

Permalink
Merge pull request #228 from stormpath/feature-config-load-files-befo…
Browse files Browse the repository at this point in the history
…re-env

Feature: Load config env after config files.
  • Loading branch information
robertjd committed Oct 14, 2015
2 parents 5d1f04a + 0206cc9 commit a9c7c22
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 31 deletions.
6 changes: 3 additions & 3 deletions lib/configLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ module.exports = function (extendWithConfig) {
// Load default configuration.
new strategy.LoadFileConfigStrategy(path.join(__dirname, '/config.yml'), true),

// Load configuration from our environment.
new strategy.LoadEnvConfigStrategy('STORMPATH'),

// Load API keys and configuration from home (.stormpath) folder
new strategy.LoadAPIKeyConfigStrategy(stormpathPath + '/apiKey.properties'),
new strategy.LoadFileConfigStrategy(stormpathPath + '/stormpath.json'),
Expand All @@ -37,6 +34,9 @@ module.exports = function (extendWithConfig) {
new strategy.LoadFileConfigStrategy(currentPath + '/stormpath.json'),
new strategy.LoadFileConfigStrategy(currentPath + '/stormpath.yml'),

// Load configuration from our environment.
new strategy.LoadEnvConfigStrategy('STORMPATH'),

// Extend our configuration with the configuration we passed into the client.
// Also, try and load our API key if it was specified in our config.
new strategy.ExtendConfigStrategy(extendWithConfig),
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@
"mocha": "~2.3.3",
"mocha-sinon": "~1.1.0",
"nock": "~0.27.2",
"nodeenv": "^0.2.1",
"sinon": "~1.7.3",
"sinon-chai": "~2.4.0",
"time-grunt": "~0.2.0",
Expand Down
20 changes: 20 additions & 0 deletions test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,25 @@ function random(){
return '' + Math.random()*Date.now();
}

function clone(value) {
return JSON.parse(JSON.stringify(value));
}

function snapshotEnv() {
var originalEnv = clone(process.env);
return function restore() {
var key;
for (key in process.env) {
if (!(key in originalEnv)) {
delete process.env[key];
}
}
for (key in originalEnv) {
process.env[key] = originalEnv[key];
}
};
}

function assertAccessTokenResponse(response){
assert.isDefined(response.accessTokenResponse);
assert.isDefined(response.accessTokenResponse.access_token);
Expand Down Expand Up @@ -56,6 +75,7 @@ module.exports = {
Stormpath: Stormpath,
random: random,
uuid: uuid,
snapshotEnv: snapshotEnv,
assertPasswordGrantResponse: assertPasswordGrantResponse,
assertAccessTokenResponse: assertAccessTokenResponse
};
134 changes: 107 additions & 27 deletions test/sp.config.configLoader_test.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
var fs = require('fs');
var uuid = require('uuid');
var yaml = require('js-yaml');
var nodeenv = require('nodeenv');
var expandHomeDir = require('expand-home-dir');

var FakeFS = require('fake-fs');

var common = require('./common');
var assert = common.assert;

var stormpathConfig = require('stormpath-config');
var configLoader = require('../lib/configLoader');

describe('Configuration loader', function () {
var loader, fakeFs;
var loader, fakeFs, afterIt;

// Sets up our fake file system with mock files.
function setupFakeFs(files) {
Expand Down Expand Up @@ -41,6 +39,7 @@ describe('Configuration loader', function () {
}

before(function () {
afterIt = [];
loader = configLoader({
skipRemoteConfig: true
});
Expand All @@ -52,16 +51,34 @@ describe('Configuration loader', function () {
}
});

it('should load without configuration', function(done) {
// Cleanup functions that should run directly after all "it" tests.
// This is because mocha does not offer this functionality at the moment.
// I.e. mocha's after() is queued and executed after all tests have run.
afterEach(function () {
while (afterIt.length) {
afterIt.shift()();
}
});

it('should error when not providing api key', function (done) {
setupFakeFs();

loader.load(function (err, config) {
if (err) {
throw err;
var restoreEnv = common.snapshotEnv();

// Remove any STORMPATH environment keys.
for (var key in process.env) {
if (key.indexOf('STORMPATH_') === 0) {
delete process.env[key];
}
}

afterIt.push(restoreEnv);

loader.load(function (err, config) {
assert.isUndefined(config);

assert(!!config);
assert(config instanceof stormpathConfig.Config);
assert.isNotNull(err);
assert.equal(err.message, 'API key ID and secret is required.');

done();
});
Expand All @@ -71,7 +88,9 @@ describe('Configuration loader', function () {
setupFakeFs();

loader.load(function (err, config) {
assert.isFalse(!!err);
if (err) {
throw err;
}

assert.isTrue(!!config);

Expand Down Expand Up @@ -106,21 +125,14 @@ describe('Configuration loader', function () {
it('should load configuration from the environment', function (done) {
setupFakeFs();

var env = {
STORMPATH_CLIENT_APIKEY_ID: uuid(),
STORMPATH_CLIENT_APIKEY_SECRET: uuid(),
STORMPATH_APPLICATION_HREF: 'http://api.stormpath.com/v1/applications/' + uuid(),
STORMPATH_APPLICATION_NAME: uuid()
};
var restoreEnv = common.snapshotEnv();

var restoreEnv;
nodeenv(env, function (restore) {
restoreEnv = restore;
});
process.env.STORMPATH_CLIENT_APIKEY_ID = uuid();
process.env.STORMPATH_CLIENT_APIKEY_SECRET = uuid();
process.env.STORMPATH_APPLICATION_HREF = 'http://api.stormpath.com/v1/applications/' + uuid();
process.env.STORMPATH_APPLICATION_NAME = uuid();

after(function () {
restoreEnv();
});
afterIt.push(restoreEnv);

loader.load(function (err, config) {
assert.isFalse(!!err);
Expand All @@ -130,18 +142,31 @@ describe('Configuration loader', function () {
assert.isTrue(!!config.client.apiKey);
assert.isTrue(!!config.application);

assert.equal(config.client.apiKey.id, env.STORMPATH_CLIENT_APIKEY_ID);
assert.equal(config.client.apiKey.secret, env.STORMPATH_CLIENT_APIKEY_SECRET);
assert.equal(config.application.href, env.STORMPATH_APPLICATION_HREF);
assert.equal(config.application.name, env.STORMPATH_APPLICATION_NAME);
assert.equal(config.client.apiKey.id, process.env.STORMPATH_CLIENT_APIKEY_ID);
assert.equal(config.client.apiKey.secret, process.env.STORMPATH_CLIENT_APIKEY_SECRET);
assert.equal(config.application.href, process.env.STORMPATH_APPLICATION_HREF);
assert.equal(config.application.name, process.env.STORMPATH_APPLICATION_NAME);

done();
});
});

function testLoadStormpathConfig(ext, serializeFn) {
function removeStormpathEnv() {
var restore = common.snapshotEnv();

delete process.env['STORMPATH_CLIENT_APIKEY_ID'];
delete process.env['STORMPATH_CLIENT_APIKEY_SECRET'];
delete process.env['STORMPATH_APPLICATION_HREF'];
delete process.env['STORMPATH_APPLICATION_NAME'];

return restore;
}

describe('should load stormpath.' + ext + ' config', function () {
it('from stormpath home folder', function (done) {
afterIt.push(removeStormpathEnv());

var homeConfig = {
client: {
apiKey: {
Expand Down Expand Up @@ -171,6 +196,8 @@ describe('Configuration loader', function () {
});

it('from application directory while overriding home folder', function (done) {
afterIt.push(removeStormpathEnv());

var homeConfig = {
client: {
apiKey: {
Expand Down Expand Up @@ -220,6 +247,59 @@ describe('Configuration loader', function () {
testLoadStormpathConfig('yml', yaml.dump);
testLoadStormpathConfig('json', JSON.stringify);

it('should load config from file before environment', function (done) {
var restoreEnv = common.snapshotEnv();

process.env.STORMPATH_CLIENT_APIKEY_ID = uuid();
process.env.STORMPATH_CLIENT_APIKEY_SECRET = uuid();
process.env.STORMPATH_APPLICATION_HREF = 'http://api.stormpath.com/v1/applications/' + uuid();

afterIt.push(restoreEnv);

var homeConfig = {
client: {
apiKey: {
id: uuid(),
secret: uuid()
}
}
};

var appConfig = {
client: {
apiKey: {
secret: uuid()
}
},
application: {
href: 'http://api.stormpath.com/v1/applications/' + uuid()
}
};

setupFakeFs([{
path: expandHomeDir('~/.stormpath/stormpath.json'),
content: JSON.stringify(homeConfig)
}, {
path: process.cwd() + '/stormpath.json',
content: JSON.stringify(appConfig)
}]);

loader.load(function (err, config) {
assert.isNull(err);

assert.isTrue(!!config);
assert.isTrue(!!config.client);
assert.isTrue(!!config.application);
assert.isTrue(!!config.client.apiKey);

assert.equal(config.client.apiKey.id, process.env.STORMPATH_CLIENT_APIKEY_ID);
assert.equal(config.client.apiKey.secret, process.env.STORMPATH_CLIENT_APIKEY_SECRET);
assert.equal(config.application.href, process.env.STORMPATH_APPLICATION_HREF);

done();
});
});

it('should extend config with custom config object', function (done) {
setupFakeFs();

Expand Down

0 comments on commit a9c7c22

Please sign in to comment.