bricks-cli
Version:
Command line tool for developing ambitious ember.js apps
320 lines (263 loc) • 11.2 kB
JavaScript
;
var Blueprint = require('../../../lib/models/blueprint');
var MockProject = require('../../helpers/mock-project');
var MockUI = require('../../helpers/mock-ui');
var assert = require('assert');
var glob = require('glob');
var path = require('path');
var walkSync = require('walk-sync');
var rimraf = require('rimraf');
var root = process.cwd();
var tmp = require('tmp-sync');
var tmproot = path.join(root, 'tmp');
var defaultBlueprints = path.resolve(__dirname, '..', '..', '..', 'blueprints');
var fixtureBlueprints = path.resolve(__dirname, '..', '..', 'fixtures', 'blueprints');
var basicBlueprint = path.join(fixtureBlueprints, 'basic');
var basicNewBlueprint = path.join(fixtureBlueprints, 'basic_2');
var defaultIgnoredFiles = Blueprint.ignoredFiles;
var basicBlueprintFiles = [
'.ember-cli',
'.gitignore',
'foo.txt',
'test.txt'
];
assert.match = function(actual, matcher) {
assert(matcher.test(actual), 'expected: ' +
actual +
' to match ' +
matcher);
};
describe('Blueprint', function() {
beforeEach(function() {
Blueprint.ignoredFiles = defaultIgnoredFiles;
});
describe('.lookup', function() {
it('uses an explicit path if one is given', function() {
var expectedClass = require(basicBlueprint);
var blueprint = Blueprint.lookup(basicBlueprint);
assert.equal(blueprint.name, 'basic');
assert.equal(blueprint.path, basicBlueprint);
assert(blueprint instanceof expectedClass);
});
it('finds blueprints within given lookup paths', function() {
var expectedClass = require(basicBlueprint);
var blueprint = Blueprint.lookup('basic', {
paths: [fixtureBlueprints]
});
assert.equal(blueprint.name, 'basic');
assert.equal(blueprint.path, basicBlueprint);
assert(blueprint instanceof expectedClass);
});
it('finds blueprints in the ember-cli package', function() {
var expectedPath = path.resolve(defaultBlueprints, 'app');
var expectedClass = require('../../../blueprints/app');
var blueprint = Blueprint.lookup('app');
assert.equal(blueprint.name, 'app');
assert.equal(blueprint.path, expectedPath);
assert(blueprint instanceof expectedClass);
});
it('can instantiate a blueprint that exports an object instead of a constructor', function() {
var blueprint = Blueprint.lookup('exporting-object', {
paths: [fixtureBlueprints]
});
assert.equal(blueprint.woot, 'someValueHere');
assert(blueprint instanceof Blueprint);
});
it('throws an error if no blueprint is found', function() {
assert.throws(function() {
Blueprint.lookup('foo');
}, 'Unknown blueprint: foo');
});
});
describe('.list', function() {
it('returns a list of blueprints grouped by lookup path', function() {
var expectedDefaults = glob.sync(path.join(defaultBlueprints, '*'));
expectedDefaults = expectedDefaults.map(function(blueprint) {
return path.basename(blueprint);
});
var expectedFixtures = glob.sync(path.join(fixtureBlueprints, '*'));
expectedFixtures = expectedFixtures.map(function(blueprint) {
return path.basename(blueprint);
});
assert.deepEqual(Blueprint.list({ paths: [fixtureBlueprints] }), [{
source: 'fixtures',
blueprints: expectedFixtures
}, {
source: 'bricks-cli',
blueprints: expectedDefaults
}]);
});
});
it('exists', function() {
var blueprint = new Blueprint(basicBlueprint);
assert(blueprint);
});
it('derives name from path', function() {
var blueprint = new Blueprint(basicBlueprint);
assert.equal(blueprint.name, 'basic');
});
describe('basic blueprint installation', function() {
var blueprint;
var ui;
var project;
var options;
var tmpdir;
beforeEach(function() {
tmpdir = tmp.in(tmproot);
blueprint = new Blueprint(basicBlueprint);
ui = new MockUI();
project = new MockProject();
options = {
ui: ui,
project: project,
target: tmpdir
};
});
afterEach(function() {
rimraf.sync(tmproot);
});
it('installs basic files', function() {
assert(blueprint);
return blueprint.install(options)
.then(function() {
var actualFiles = walkSync(tmpdir).sort();
var output = ui.output.trim().split('\n');
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /create.* .ember-cli/);
assert.match(output.shift(), /create.* .gitignore/);
assert.match(output.shift(), /create.* foo.txt/);
assert.match(output.shift(), /create.* test.txt/);
assert.equal(output.length, 0);
assert.deepEqual(actualFiles, basicBlueprintFiles);
});
});
it('re-installing identical files', function() {
return blueprint.install(options)
.then(function() {
var output = ui.output.trim().split('\n');
ui.output = '';
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /create.* \.ember-cli/);
assert.match(output.shift(), /create.* \.gitignore/);
assert.match(output.shift(), /create.* foo.txt/);
assert.match(output.shift(), /create.* test.txt/);
assert.equal(output.length, 0);
return blueprint.install(options);
})
.then(function() {
var actualFiles = walkSync(tmpdir).sort();
var output = ui.output.trim().split('\n');
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /identical.* \.ember-cli/);
assert.match(output.shift(), /identical.* \.gitignore/);
assert.match(output.shift(), /identical.* foo.txt/);
assert.match(output.shift(), /identical.* test.txt/);
assert.equal(output.length, 0);
assert.deepEqual(actualFiles, basicBlueprintFiles);
});
});
it('re-installing conflicting files', function() {
return blueprint.install(options)
.then(function() {
var output = ui.output.trim().split('\n');
ui.output = '';
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /create.* \.ember-cli/);
assert.match(output.shift(), /create.* \.gitignore/);
assert.match(output.shift(), /create.* foo.txt/);
assert.match(output.shift(), /create.* test.txt/);
assert.equal(output.length, 0);
var blueprintNew = new Blueprint(basicNewBlueprint);
setTimeout(function(){
ui.inputStream.write('n\n');
}, 25);
setTimeout(function(){
ui.inputStream.write('y\n');
}, 50);
return blueprintNew.install(options);
})
.then(function() {
var actualFiles = walkSync(tmpdir).sort();
var output = ui.output.trim().split('\n');
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /Overwrite.*foo.*\?/); // Prompt
assert.match(output.shift(), /Overwrite.*foo.*No, skip/);
assert.match(output.shift(), /Overwrite.*test.*\?/); // Prompt
assert.match(output.shift(), /Overwrite.*test.*Yes, overwrite/);
assert.match(output.shift(), /identical.* \.ember-cli/);
assert.match(output.shift(), /identical.* \.gitignore/);
assert.match(output.shift(), /skip.* foo.txt/);
assert.match(output.shift(), /overwrite.* test.txt/);
assert.equal(output.length, 0);
assert.deepEqual(actualFiles, basicBlueprintFiles);
});
});
describe('called on an existing project', function() {
beforeEach(function() {
Blueprint.ignoredUpdateFiles.push('foo.txt');
});
it('ignores files in ignoredUpdateFiles', function() {
return blueprint.install(options)
.then(function() {
var output = ui.output.trim().split('\n');
ui.output = '';
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /create.* \.ember-cli/);
assert.match(output.shift(), /create.* \.gitignore/);
assert.match(output.shift(), /create.* foo.txt/);
assert.match(output.shift(), /create.* test.txt/);
assert.equal(output.length, 0);
var blueprintNew = new Blueprint(basicNewBlueprint);
setTimeout(function(){
ui.inputStream.write('n\n');
}, 25);
setTimeout(function(){
ui.inputStream.write('n\n');
}, 50);
options.project.isEmberCLIProject = function() { return true; };
return blueprintNew.install(options);
})
.then(function() {
var actualFiles = walkSync(tmpdir).sort();
var output = ui.output.trim().split('\n');
assert.match(output.shift(), /^installing/);
assert.match(output.shift(), /Overwrite.*test.*\?/); // Prompt
assert.match(output.shift(), /Overwrite.*test.*No, skip/);
assert.match(output.shift(), /identical.* \.ember-cli/);
assert.match(output.shift(), /identical.* \.gitignore/);
assert.match(output.shift(), /skip.* test.txt/);
assert.equal(output.length, 0);
assert.deepEqual(actualFiles, basicBlueprintFiles);
});
});
});
it('throws error when there is a trailing forward slash in entityName', function(){
options.entity = { name: 'foo/' };
assert.throws(function(){
blueprint.install(options);
}, /You specified "foo\/", but you can't use a trailing slash as an entity name with generators. Please re-run the command with "foo"./);
options.entity = { name: 'foo\\' };
assert.throws(function(){
blueprint.install(options);
}, /You specified "foo\\", but you can't use a trailing slash as an entity name with generators. Please re-run the command with "foo"./);
options.entity = { name: 'foo' };
assert.doesNotThrow(function(){
blueprint.install(options);
});
});
it('calls normalizeEntityName hook during install', function(done){
blueprint.normalizeEntityName = function(){ done(); };
options.entity = { name: 'foo' };
blueprint.install(options);
});
it('normalizeEntityName hook can modify the entity name', function(){
blueprint.normalizeEntityName = function(){ return 'foo'; };
options.entity = { name: 'bar' };
return blueprint.install(options)
.then(function() {
var actualFiles = walkSync(tmpdir).sort();
assert.deepEqual(actualFiles, basicBlueprintFiles);
});
});
});
});