Skip to content

Commit

Permalink
Refactor addon config generation to Project.prototype.config.
Browse files Browse the repository at this point in the history
  • Loading branch information
rwjblue committed Sep 12, 2014
1 parent 60c0b4e commit b0c240a
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 47 deletions.
20 changes: 7 additions & 13 deletions lib/broccoli/broccoli-config-loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

var fs = require('fs');
var path = require('path');
var merge = require('lodash-node/modern/objects/merge');
var Writer = require('broccoli-caching-writer');

function ConfigLoader (inputTree, options) {
Expand All @@ -17,20 +16,17 @@ function ConfigLoader (inputTree, options) {
ConfigLoader.prototype = Object.create(Writer.prototype);
ConfigLoader.prototype.constructor = ConfigLoader;

ConfigLoader.prototype.getAddonsConfig = function(env, appConfig) {
var addons = this.options.project.addons;
return addons.reduce(function(config, addon) {
return addon.config ? merge(config, addon.config(env, config)) : config;
}, appConfig);
ConfigLoader.prototype.clearConfigGeneratorCache = function() {
var configPath = this.options.project.configPath();

// clear the previously cached version of this module
delete require.cache[configPath];
};

ConfigLoader.prototype.updateCache = function(srcDir, destDir) {
var self = this;
var configPath = path.join(this.options.project.root, srcDir, 'environment.js');

// clear the previously cached version of this module
delete require.cache[configPath];
var configGenerator = require(configPath);
this.clearConfigGeneratorCache();

var outputDir = path.join(destDir, 'environments');
fs.mkdirSync(outputDir);
Expand All @@ -47,9 +43,7 @@ ConfigLoader.prototype.updateCache = function(srcDir, destDir) {
}

environments.forEach(function(env) {
var appConfig = configGenerator(env);
var addonsConfig = this.getAddonsConfig(env, appConfig);
var config = merge(appConfig, addonsConfig);
var config = self.options.project.config(env);
var jsonString = JSON.stringify(config);
var moduleString = 'export default ' + jsonString + ';';
var outputPath = path.join(outputDir, env);
Expand Down
8 changes: 2 additions & 6 deletions lib/broccoli/ember-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,18 +175,13 @@ function EmberApp(options) {

EmberApp.prototype._notifyAddonIncluded = function() {
this.initializeAddons();
this.configureAddons();
this.project.addons.forEach(function(addon) {
if (addon.included) {
addon.included(this);
}
}, this);
};

EmberApp.prototype.configureAddons = function() {
// do something that will make addon `config` hook to fire
};

EmberApp.prototype.initializeAddons = function() {
this.project.initializeAddons();
};
Expand Down Expand Up @@ -424,7 +419,8 @@ EmberApp.prototype._configTree = function() {
var configTree = configLoader(path.dirname(configPath), {
env: this.env,
tests: this.tests,
project: this.project
project: this.project,
configPath: configPath
});

this._cachedConfigTree = pickFiles(configTree, {
Expand Down
37 changes: 33 additions & 4 deletions lib/models/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var assign = require('lodash-node/modern/objects/assign');
var DAG = require('../utilities/DAG');
var Command = require('../models/command');
var Addon = require('../models/addon');
var merge = require('lodash-node/modern/objects/merge');

var emberCLIVersion = require('../utilities/ember-cli-version');

Expand Down Expand Up @@ -48,19 +49,41 @@ Project.prototype.isEmberCLIAddon = function() {
return this.pkg.keywords && this.pkg.keywords.indexOf('ember-addon') > -1;
};

Project.prototype.config = function(env) {
Project.prototype.configPath = function() {
var configPath = 'config';

if (this.pkg['ember-addon'] && this.pkg['ember-addon']['configPath']) {
configPath = this.pkg['ember-addon']['configPath'];
}
if (fs.existsSync(path.join(this.root, configPath, 'environment.js'))) {
return this.require('./' + path.join(configPath, 'environment'))(env);

return path.join(configPath, 'environment');
};

Project.prototype.config = function(env) {
var configPath = this.configPath();

if (fs.existsSync(path.join(this.root, configPath + '.js'))) {
var appConfig = this.require('./' + configPath)(env);
var addonsConfig = this.getAddonsConfig(env, appConfig);

return merge(addonsConfig, appConfig);
} else {
return { };
return this.getAddonsConfig(env, {});
}
};

Project.prototype.getAddonsConfig = function(env, appConfig) {
this.initializeAddons();

return this.addons.reduce(function(config, addon) {
if (addon.config) {
merge(config, addon.config(env, config));
}

return config;
}, appConfig);
};

Project.prototype.has = function(file) {
return fs.existsSync(path.join(this.root, file)) || fs.existsSync(path.join(this.root, file + '.js'));
};
Expand Down Expand Up @@ -134,6 +157,10 @@ Project.prototype.addIfAddon = function(addonPath) {
};

Project.prototype.initializeAddons = function() {
if (this._addonsInitialized) {
return;
}

var project = this;
var graph = new DAG();
var addon, emberAddonConfig;
Expand All @@ -154,6 +181,8 @@ Project.prototype.initializeAddons = function() {

project.addons.push(new AddonConstructor(project));
});

this._addonsInitialized = true;
};

Project.prototype.addonCommands = function() {
Expand Down
72 changes: 72 additions & 0 deletions tests/unit/broccoli/config-loader-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
'use strict';

var fs = require('fs');
var path = require('path');
var ConfigLoader = require('../../../lib/broccoli/broccoli-config-loader');
var assert = require('assert');
var root = process.cwd();
var tmp = require('tmp-sync');
var tmproot = path.join(root, 'tmp');
var rimraf = require('rimraf');

describe('broccoli/broccoli-config-loader', function() {
var configLoader, tmpDestDir, tmpSrcDir, project, options;

beforeEach(function() {
tmpDestDir = tmp.in(tmproot);
tmpSrcDir = tmp.in(tmproot);

project = {
root: tmpSrcDir,
addons: [],
configPath: function() {
return 'config/environment';
},

config: function(env) {
return {
env: env,
foo: 'bar',
baz: 'qux'
};
}
};

options = {
env: 'development',
tests: true,
project: project
};

configLoader = new ConfigLoader('.', options);
});

afterEach(function() {
rimraf.sync(tmpDestDir);
});

describe('updateCache', function() {
it('writes the current environments file', function() {
configLoader.updateCache(tmpSrcDir, tmpDestDir);

assert(fs.existsSync(path.join(tmpDestDir, 'environment.js')));
assert(fs.existsSync(path.join(tmpDestDir, 'environments', 'development.js')));
assert(fs.existsSync(path.join(tmpDestDir, 'environments', 'development.json')));

assert(fs.existsSync(path.join(tmpDestDir, 'environments', 'test.js')));
assert(fs.existsSync(path.join(tmpDestDir, 'environments', 'test.json')));
});

it('does not generate test environment files if testing is disabled', function() {
options.tests = false;
configLoader.updateCache(tmpSrcDir, tmpDestDir);

assert(fs.existsSync(path.join(tmpDestDir, 'environment.js')));
assert(fs.existsSync(path.join(tmpDestDir, 'environments', 'development.js')));
assert(fs.existsSync(path.join(tmpDestDir, 'environments', 'development.json')));

assert(!fs.existsSync(path.join(tmpDestDir, 'environments', 'test.js')));
assert(!fs.existsSync(path.join(tmpDestDir, 'environments', 'test.json')));
});
});
});
98 changes: 74 additions & 24 deletions tests/unit/models/project-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ var emberCLIVersion = require('../../../lib/utilities/ember-cli-version');
describe('models/project.js', function() {
var project, projectPath;

describe('Project.prototype.config default', function() {
describe('Project.prototype.config', function() {
var called = false;
projectPath = process.cwd() + '/tmp/test-app';

before(function() {
beforeEach(function() {
projectPath = process.cwd() + '/tmp/test-app';
called = false;
tmp.setup(projectPath);

touch(projectPath + '/config/environment.js', {
Expand All @@ -39,39 +40,88 @@ describe('models/project.js', function() {
project.config('development');
assert.equal(called, true);
});
});

describe('Project.prototype.config custom config path from addon', function() {
var called = false;
projectPath = process.cwd() + '/tmp/test-app';

before(function() {
tmp.setup(projectPath);

touch(projectPath + '/tests/dummy/config/environment.js', {
baseURL: '/foo/bar'
});

project = new Project(projectPath, { });
it('configPath() returns tests/dummy/config/environment', function() {
project.pkg = {
'ember-addon': {
'configPath': 'tests/dummy/config'
}
};
project.require = function() {
called = true;
return function() {};

assert.equal(project.configPath(), 'tests/dummy/config/environment');
});

it('calls getAddonsConfig', function() {
var addonConfigCalled = false;

project.getAddonsConfig = function() {
addonConfigCalled = true;

return {};
};

project.config('development');
assert.equal(addonConfigCalled, true);
});

it('returns getAddonsConfig result when configPath is not present', function() {
var expected = {
foo: 'bar'
};
tmp.setup(projectPath); // ensure no config/environment.js is present
project.getAddonsConfig = function() {
return expected;
};

after(function() {
tmp.teardown(projectPath);
var actual = project.config('development');
assert.deepEqual(actual, expected);
});

it('config() finds and requires tests/dummy/config/environment', function() {
project.config('development');
assert.equal(called, true);
describe('merges getAddonsConfig result with app config', function() {
var projectConfig, addonsConfig;

beforeEach(function() {
addonsConfig = { addon: { derp: 'herp' } };
projectConfig = { foo: 'bar', baz: 'qux' };

project.getAddonsConfig = function() {
return addonsConfig;
};

project.require = function() {
return function() {
return projectConfig;
};
};
});

it('merges getAddonsConfig result with app config', function() {
var expected = {
foo: 'bar',
baz: 'qux',
addon: {
derp: 'herp'
}
};

var actual = project.config('development');
assert.deepEqual(actual, expected);
});

it('getAddonsConfig does NOT override project config', function() {
var expected = {
foo: 'bar',
baz: 'qux',
addon: {
derp: 'herp'
}
};

addonsConfig.foo = 'NO!!!!!!';

var actual = project.config('development');
assert.deepEqual(actual, expected);
});
});
});

Expand Down

0 comments on commit b0c240a

Please sign in to comment.