Skip to content

Commit

Permalink
Merge pull request ember-cli#6698 from Turbo87/bower-maybe
Browse files Browse the repository at this point in the history
Remove "bower.json" and only create if necessary
  • Loading branch information
Turbo87 authored Jan 26, 2017
2 parents b90f860 + 624c51d commit be142aa
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 66 deletions.
9 changes: 0 additions & 9 deletions blueprints/addon/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,6 @@ module.exports = {
this._writeContentsToFile(sortPackageJson(contents), 'package.json');
},

generateBowerJson() {
let contents = this._readContentsFromFile('bower.json');

contents.name = '<%= addonName %>';

this._writeContentsToFile(contents, 'bower.json');
},

afterInstall() {
let packagePath = path.join(this.path, 'files', 'package.json');
let bowerPath = path.join(this.path, 'files', 'bower.json');
Expand Down Expand Up @@ -101,7 +93,6 @@ module.exports = {
let appFiles = this._appBlueprint.files();

this.generatePackageJson();
this.generateBowerJson();

let addonFiles = walkSync(path.join(this.path, 'files'));

Expand Down
5 changes: 0 additions & 5 deletions blueprints/app/files/bower.json

This file was deleted.

2 changes: 1 addition & 1 deletion lib/models/blueprint.js
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ let Blueprint = CoreObject.extend({
return task.run({
verbose: true,
packages: packageNamesAndVersions,
installOptions,
installOptions: installOptions || { save: true },
});
},

Expand Down
74 changes: 62 additions & 12 deletions lib/tasks/bower-install.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
'use strict';

// Runs `bower install` in cwd
const fs = require('fs-extra');
const path = require('path');
const existsSync = require('exists-sync');
const execa = require('execa');
const RSVP = require('rsvp');
const Task = require('../models/task');
const formatPackageList = require('../utilities/format-package-list');

const logger = require('heimdalljs-logger')('ember-cli:tasks:bower-install');

const Promise = RSVP.Promise;
const resolve = RSVP.denodeify(require('resolve'));
const writeJson = RSVP.denodeify(fs.writeJson);

const cliPath = path.resolve(`${__dirname}/../..`);

class BowerInstallTask extends Task {

resolveBower() {
logger.info('Resolving "bower" from %s ...', cliPath);
return resolve('bower', { basedir: cliPath });
}

importBower(path) {
logger.info('Importing "bower" from: %s', path);
this.bower = require(path);
}

ensureBower() {
if (this.bower) {
return Promise.resolve(this.bower);
return Promise.resolve();
}

return resolve('bower', { basedir: cliPath })
.catch(() => this.installBower()
.then(() => resolve('bower', { basedir: cliPath })))
.then(bowerPath => require(bowerPath));
return this.resolveBower()
.catch(error => {
if (error.message.indexOf('Cannot find module \'bower\'') === -1) {
throw error;
}

return this.installBower().then(() => this.resolveBower());
})
.then(bowerPath => this.importBower(bowerPath));
}

installBower() {
logger.info('Installing "bower" via NPM into: %s', cliPath);

let ui = this.ui;
const chalk = require('chalk');

Expand All @@ -37,32 +58,61 @@ class BowerInstallTask extends Task {
.then(() => ui.writeLine(chalk.green('NPM: Installed bower')));
}

get bowerJsonPath() {
return path.join(this.project.root, 'bower.json');
}

hasBowerJson() {
return existsSync(this.bowerJsonPath);
}

ensureBowerJson() {
if (this.hasBowerJson()) {
return Promise.resolve();
}

let projectName = this.project.name();
let bowerJsonPath = this.bowerJsonPath;

logger.info('Creating "bower.json" for: %s at: %s', projectName, bowerJsonPath);

return writeJson(bowerJsonPath, { name: projectName });
}

// Options: Boolean verbose
run(options) {
let bowerJson = path.join(this.project.root, '/bower.json');
let ui = this.ui;

if (!existsSync(bowerJson)) {
ui.writeWarnLine('Skipping bower install: bower.json not found');
let packages = options.packages || [];
let installOptions = options.installOptions || {};
let savePackages = installOptions.save || installOptions.saveDev;

// if we are running "bower install" from "ember init" and there is
// no "bower.json" we return early
if (!this.hasBowerJson() && !savePackages) {
logger.info('Skipping "bower install" since "bower.json" does not exist');
return Promise.resolve();
}

return this.ensureBower().then(bower => {
// resolve "bower" and install via NPM if necessary
// -> then check if a "bower.json" file exists and create if necessary
// -> then run the actual "bower install"
return this.ensureBower().then(() => this.ensureBowerJson()).then(() => {
const chalk = require('chalk');
let bowerConfig = this.bowerConfig || require('bower-config');
let packages = options.packages || [];
let installOptions = options.installOptions || { save: true };

let startMessage = this.formatStartMessage(packages);
let completeMessage = this.formatCompleteMessage(packages);

logger.info('Installing %j via Bower with options: %j', packages, installOptions);

ui.startProgress(chalk.green(startMessage));

let config = bowerConfig.read();
config.interactive = true;

return new Promise((resolve, reject) => {
bower.commands.install(packages, installOptions, config) // Packages, options, config
this.bower.commands.install(packages, installOptions, config) // Packages, options, config
.on('log', logBowerMessage)
.on('prompt', ui.prompt.bind(ui))
.on('error', reject)
Expand Down
6 changes: 1 addition & 5 deletions tests/acceptance/addon-smoke-test-slow.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,13 @@ describe('Acceptance: addon-smoke-test', function() {
expect(dir(addonRoot)).to.not.exist;
});

it('generates package.json and bower.json with proper metadata', function() {
it('generates package.json with proper metadata', function() {
let packageContents = fs.readJsonSync('package.json');

expect(packageContents.name).to.equal(addonName);
expect(packageContents.private).to.be.an('undefined');
expect(packageContents.keywords).to.deep.equal(['ember-addon']);
expect(packageContents['ember-addon']).to.deep.equal({ 'configPath': 'tests/dummy/config' });

let bowerContents = fs.readJsonSync('bower.json');

expect(bowerContents.name).to.equal(addonName);
});

it('ember addon foo, clean from scratch', function() {
Expand Down
17 changes: 0 additions & 17 deletions tests/unit/blueprints/addon-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,22 +270,5 @@ describe('blueprint - addon', function() {
expect(json.devDependencies).to.deep.equal({ a: "1", b: "1" });
});
});

describe('generateBowerJson', function() {
it('works', function() {
blueprint.generateBowerJson();

let captor = td.matchers.captor();

td.verify(readJsonSync(path.normalize('test-app-blueprint-path/files/bower.json')));
td.verify(writeFileSync(path.normalize('test-blueprint-path/files/bower.json'), captor.capture()));

// string to test ordering
expect(captor.value).to.equal('\
{\n\
"name": "<%= addonName %>"\n\
}\n');
});
});
});
});
75 changes: 58 additions & 17 deletions tests/unit/tasks/bower-install-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,72 @@

const BowerInstallTask = require('../../../lib/tasks/bower-install');
const MockUI = require('console-ui/mock');
const MockProject = require('../../helpers/mock-project');
const expect = require('chai').expect;
const Promise = require('rsvp').Promise;
const expect = require('../../chai').expect;
const td = require('testdouble');

describe('bower install task', function() {
let bowerInstallTask;
let ui;
describe('BowerInstallTask', function() {
let task, ui;

beforeEach(function() {
let project = new MockProject();
ui = new MockUI();
task = new BowerInstallTask({ ui });
});

bowerInstallTask = new BowerInstallTask({
ui,
project,
describe('ensureBower()', function() {
beforeEach(function() {
task.resolveBower = td.function();
task.importBower = td.function();
task.installBower = td.function();
});
});

afterEach(function() {
ui = undefined;
bowerInstallTask = undefined;
});
it('resolves if "bower" property is set', function() {
let mockValue = 'foobar';
task.bower = mockValue;

td.when(task.resolveBower()).thenReject(new Error());

return task.ensureBower().then(() => {
expect(task.bower).to.equal(mockValue);
});
});

it('imports "bower" if it can be resolved', function() {
td.when(task.resolveBower()).thenResolve('path/to/bower');
td.when(task.importBower('path/to/bower')).thenReturn('ok');

return task.ensureBower().then(ok => {
expect(ok).to.equal('ok');
});
});

it('install "bower" if it can not be resolved', function() {
let error = new Error('Cannot find module \'bower\'');

td.when(task.resolveBower()).thenReturn(Promise.reject(error), Promise.resolve('path/to/bower'));
td.when(task.installBower()).thenResolve();
td.when(task.importBower('path/to/bower')).thenReturn('ok');

return task.ensureBower().then(ok => {
expect(ok).to.equal('ok');
});
});

it('pass other resolve errors on', function() {
let error = new Error('foobar');

td.when(task.resolveBower()).thenReturn(Promise.reject(error));

return expect(task.ensureBower()).to.be.rejectedWith('foobar');
});

it('pass install errors on', function() {
let error = new Error('Cannot find module \'bower\'');

td.when(task.resolveBower()).thenReturn(Promise.reject(error));
td.when(task.installBower()).thenReject(new Error('foobar'));

it('skips bower installs if there is no bower.json', function() {
return bowerInstallTask.run({}).then(() => {
expect(ui.output).to.include('Skipping bower install: bower.json not found');
return expect(task.ensureBower()).to.be.rejectedWith('foobar');
});
});
});

0 comments on commit be142aa

Please sign in to comment.