├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── gulpfile.js ├── index.js ├── package.json └── tests ├── fileSystemUtils.js ├── fixtures ├── bowerConflict.json ├── bowerValid.json ├── bowerrcEmpty.json └── bowerrcValid.json └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | bower_components/ 2 | bower.json 3 | coverage/ 4 | /node_modules 5 | /*.log 6 | .idea/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | install: npm install 2 | script: npm test 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Alexander Zonov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gulp-bower 2 | > Deprecated. Please use [Browserify](https://www.npmjs.com/package/browserify), [Rollup](https://www.npmjs.com/package/rollup) or [Webpack](https://www.npmjs.com/package/webpack) 3 | 4 | [![Build Status](https://travis-ci.org/zont/gulp-bower.svg?branch=master)](https://travis-ci.org/zont/gulp-bower) [![codecov.io](https://codecov.io/github/zont/gulp-bower/coverage.svg?branch=master)](https://codecov.io/github/zont/gulp-bower?branch=master) 5 | 6 | This task is designed for gulp 3+. 7 | 8 | ## Install 9 | 10 | ```sh 11 | $ npm install --save-dev gulp-bower 12 | ``` 13 | 14 | ## Usage 15 | 16 | Install packages into the `bower_components` directory from `bower.json` dependencies: 17 | 18 | ```javascript 19 | var gulp = require('gulp'); 20 | var bower = require('gulp-bower'); 21 | 22 | gulp.task('bower', function() { 23 | return bower(); 24 | }); 25 | ``` 26 | 27 | ### Examples 28 | 29 | * To install packages into a custom directory, pass the `directory` option: 30 | 31 | ```javascript 32 | var gulp = require('gulp'); 33 | var bower = require('gulp-bower'); 34 | 35 | gulp.task('bower', function() { 36 | return bower({ directory: './vendor' }) 37 | }); 38 | ``` 39 | 40 | * To set the current working directory, pass the `cwd` option: 41 | 42 | ```javascript 43 | var gulp = require('gulp'); 44 | var bower = require('gulp-bower'); 45 | 46 | gulp.task('bower', function() { 47 | return bower({ directory: './vendor', cwd: './client' }) 48 | }); 49 | ``` 50 | 51 | * By default gulp-bower runs 'install' command for Bower. Using cmd property, you can specify the custom command (e.g. update): 52 | 53 | ```javascript 54 | var gulp = require('gulp'); 55 | var bower = require('gulp-bower'); 56 | 57 | gulp.task('bower', function() { 58 | return bower({ cmd: 'update' }); 59 | }); 60 | ``` 61 | 62 | ## API 63 | 64 | ### `bower(opts)` 65 | * **opts.directory** - `string` Install directory. Default: taken from `.bowerrc` config or `bower_components` 66 | * **opts.cwd** - `string` Current working directory. Default: `process.cwd()` 67 | * **opts.cmd** - `string` bower command. Default: `install` 68 | * **opts.interactive** - `boolean` Enable prompting on version conflicts. Default: `false` 69 | * **opts.verbosity** - `number` Set verbosity level. Default: `2` 70 | * **0** - No output 71 | * **1** - Error output 72 | * **2** - Info 73 | 74 | ## Changelog 75 | 76 | #####0.0.14 77 | - Drop dependency on deprecated `gulp-util`. (by TheDancingCode) 78 | 79 | #####0.0.13 80 | - Added verbosity options, prompting, .bowerrc handling, tests and CI. (by Crevil) 81 | 82 | #####0.0.12 83 | - Fixed command passing to also handle nested commands (by mechanoid) 84 | 85 | #####0.0.11 86 | - Fixed dependencies (by serbrech) 87 | 88 | #####0.0.10 89 | - Fixed #28 90 | 91 | #####0.0.9 92 | - Fixed #19 93 | - Fixed undefined cwd bug 94 | 95 | #####0.0.8 96 | - Fixed dependencies versions (by Karl-Gustav) 97 | - Fixed cwd bug (by mlegenhausen) 98 | 99 | #####0.0.7 100 | - Added commands support (by Keksinautin) 101 | 102 | #####0.0.6 103 | - Added ability to pass in an initialization object that allows a cwd to be specified (by cb1kenobi) 104 | 105 | #####0.0.5 106 | - Emits "end", so the consumer knows when bower is done installing (by agzam) 107 | 108 | #####0.0.4 109 | - fixed custom bower directory bug 110 | 111 | #####0.0.3 112 | - add logging (by squarejaw) 113 | 114 | #####0.0.2 115 | - parse .bowerrc for the bower install directory or allow the user to specify the directory (by eboskma) 116 | 117 | #####0.0.1 118 | - initial release 119 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /* jshint node:true */ 2 | 'use strict'; 3 | 4 | var gulp = require('gulp'); 5 | var jshint = require('gulp-jshint'); 6 | var mocha = require('gulp-mocha'); 7 | var istanbul = require('gulp-istanbul'); 8 | var codecov = require('gulp-codecov.io'); 9 | 10 | gulp.task('lint', function () { 11 | return gulp.src(['index.js', 'tests/test.js']) 12 | .pipe(jshint()) 13 | .pipe(jshint.reporter('default')) 14 | }); 15 | 16 | gulp.task('coverage-setup', function () { 17 | return gulp.src('index.js') 18 | .pipe(istanbul()) 19 | .pipe(istanbul.hookRequire()); 20 | }); 21 | 22 | gulp.task('test', ['coverage-setup'], function () { 23 | return gulp.src('tests/test.js', { read: false }) 24 | .pipe(mocha({ reporter: 'spec', timeout: 15000 })) 25 | .pipe(istanbul.writeReports()); 26 | }); 27 | 28 | gulp.task('post-coverage', ['test'], function () { 29 | return gulp.src('./coverage/lcov.info') 30 | .pipe(codecov()); 31 | }); 32 | 33 | gulp.task('watch-test', function () { 34 | gulp.watch(['index.js', 'tests/test.js'], ['test']); 35 | }); 36 | 37 | gulp.task('default', ['lint']); 38 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* global process */ 2 | var bower = require('bower'); 3 | var fs = require('fs'); 4 | var Vinyl = require('vinyl'); 5 | var PluginError = require('plugin-error'); 6 | var colors = require('ansi-colors'); 7 | var fancyLog = require('fancy-log'); 8 | var path = require('path'); 9 | var through = require('through2'); 10 | var walk = require('walk'); 11 | var inquirer = require('inquirer'); 12 | 13 | var toString = {}.toString, 14 | enablePrompt, 15 | cmd; 16 | 17 | var PLUGIN_NAME = 'gulp-bower', 18 | DEFAULT_VERBOSITY = 2, 19 | DEFAULT_CMD = 'install', 20 | DEFAULT_DIRECTORY = './bower_components', 21 | DEFAULT_INTERACTIVE = false; 22 | 23 | /* 24 | * Verbosity levels: 25 | * 0: No output 26 | * 1: Error output 27 | * 2: All output 28 | */ 29 | var log = { 30 | verbosity: DEFAULT_VERBOSITY, 31 | info: function (s) { 32 | if (this.verbosity > 1) { 33 | log.output(s); 34 | } 35 | }, 36 | error: function (s) { 37 | if (this.verbosity > 0) { 38 | log.output(colors.red(s)); 39 | } 40 | }, 41 | output: function (s) { 42 | fancyLog.info(s); 43 | } 44 | }; 45 | 46 | /** 47 | * Gulp bower plugin 48 | * 49 | * @param {(object | string)} opts options object or directory string, see opts.directory 50 | * @param {string} opts.cmd bower command (default: install) 51 | * @param {string} opts.cwd current working directory (default: process.cwd()) 52 | * @param {string} opts.directory bower components directory (default: .bowerrc config or 'bower_components') 53 | * @param {boolean} opts.interactive enable prompting from bower (default: false) 54 | * @param {number} opts.verbosity set logging level from 0 (no output) to 2 for info (default: 2) 55 | */ 56 | function gulpBower(opts, cmdArguments) { 57 | opts = parseOptions(opts); 58 | 59 | log.info('Using cwd: ' + opts.cwd); 60 | log.info('Using bower dir: ' + opts.directory); 61 | 62 | cmdArguments = createCmdArguments(cmdArguments, opts); 63 | var bowerCommand = getBowerCommand(cmd); 64 | 65 | var stream = through.obj(function (file, enc, callback) { 66 | this.push(file); 67 | callback(); 68 | }); 69 | 70 | bowerCommand.apply(bower.commands, cmdArguments) 71 | .on('log', function (result) { 72 | log.info(['bower', colors.cyan(result.id), result.message].join(' ')); 73 | }) 74 | .on('prompt', function (prompts, callback) { 75 | if (enablePrompt === true) { 76 | inquirer.prompt(prompts, callback); 77 | } else { 78 | var error = 'Can\'t resolve suitable dependency version.'; 79 | log.error(error); 80 | log.error('Set option { interactive: true } to select.'); 81 | throw new PluginError(PLUGIN_NAME, error); 82 | } 83 | }) 84 | .on('error', function (error) { 85 | stream.emit('error', new PluginError(PLUGIN_NAME, error)); 86 | stream.emit('end'); 87 | }) 88 | .on('end', function () { 89 | writeStreamToFs(opts, stream); 90 | }); 91 | 92 | return stream; 93 | } 94 | 95 | /** 96 | * Parse plugin options 97 | * 98 | * @param {object | string} opts options object or directory string 99 | */ 100 | function parseOptions(opts) { 101 | opts = opts || {}; 102 | if (toString.call(opts) === '[object String]') { 103 | opts = { 104 | directory: opts 105 | }; 106 | } 107 | 108 | opts.cwd = opts.cwd || process.cwd(); 109 | 110 | log.verbosity = toString.call(opts.verbosity) === '[object Number]' ? opts.verbosity : DEFAULT_VERBOSITY; 111 | delete (opts.verbosity); 112 | 113 | cmd = opts.cmd || DEFAULT_CMD; 114 | delete (opts.cmd); 115 | 116 | // enable bower prompting but ignore the actual prompt if interactive == false 117 | enablePrompt = opts.interactive || DEFAULT_INTERACTIVE; 118 | opts.interactive = true; 119 | 120 | if (!opts.directory) { 121 | opts.directory = getDirectoryFromBowerRc(opts.cwd) || DEFAULT_DIRECTORY; 122 | } 123 | 124 | return opts; 125 | } 126 | 127 | /** 128 | * Detect .bowerrc file and read directory from file 129 | * 130 | * @param {string} cwd current working directory 131 | * @returns {string} found directory or empty string 132 | */ 133 | function getDirectoryFromBowerRc(cwd) { 134 | var bowerrc = path.join(cwd, '.bowerrc'); 135 | 136 | if (!fs.existsSync(bowerrc)) { 137 | return ''; 138 | } 139 | 140 | var bower_config = {}; 141 | try { 142 | bower_config = JSON.parse(fs.readFileSync(bowerrc)); 143 | } catch (err) { 144 | return ''; 145 | } 146 | 147 | return bower_config.directory; 148 | } 149 | 150 | /** 151 | * Create command arguments 152 | * 153 | * @param {any} cmdArguments 154 | * @param {object} opts options object 155 | */ 156 | function createCmdArguments(cmdArguments, opts) { 157 | if (toString.call(cmdArguments) !== '[object Array]') { 158 | cmdArguments = []; 159 | } 160 | if (toString.call(cmdArguments[0]) !== '[object Array]') { 161 | cmdArguments[0] = []; 162 | } 163 | cmdArguments[1] = cmdArguments[1] || {}; 164 | cmdArguments[2] = opts; 165 | 166 | return cmdArguments; 167 | } 168 | 169 | /** 170 | * Get bower command instance 171 | * 172 | * @param {string} cmd bower commands, e.g. 'install' | 'update' | 'cache clean' etc. 173 | * @returns {object} bower instance initialised with commands 174 | */ 175 | function getBowerCommand(cmd) { 176 | // bower has some commands that are provided in a nested object structure, e.g. `bower cache clean`. 177 | var bowerCommand; 178 | 179 | // clean up the command given, to avoid unnecessary errors 180 | cmd = cmd.trim(); 181 | 182 | var nestedCommand = cmd.split(' '); 183 | 184 | if (nestedCommand.length > 1) { 185 | // To enable that kind of nested commands, we try to resolve those commands, before passing them to bower. 186 | for (var commandPos = 0; commandPos < nestedCommand.length; commandPos++) { 187 | if (bowerCommand) { 188 | // when the root command is already there, walk into the depth. 189 | bowerCommand = bowerCommand[nestedCommand[commandPos]]; 190 | } else { 191 | // the first time we look for the "root" commands available in bower 192 | bowerCommand = bower.commands[nestedCommand[commandPos]]; 193 | } 194 | } 195 | } else { 196 | // if the command isn't nested, just go ahead as usual 197 | bowerCommand = bower.commands[cmd]; 198 | } 199 | 200 | // try to give a good error description to the user when a bad command was passed 201 | if (bowerCommand === undefined) { 202 | throw new PluginError(PLUGIN_NAME, 'The command \'' + cmd + '\' is not available in the bower commands'); 203 | } 204 | 205 | return bowerCommand; 206 | } 207 | 208 | /** 209 | * Write stream to filesystem 210 | * 211 | * @param {object} opts options object 212 | * @param {object} stream file stream 213 | */ 214 | function writeStreamToFs(opts, stream) { 215 | var baseDir = path.join(opts.cwd, opts.directory); 216 | var walker = walk.walk(baseDir); 217 | 218 | walker.on('errors', function (root, stats, next) { 219 | stream.emit('error', new PluginError(PLUGIN_NAME, stats.error)); 220 | next(); 221 | }); 222 | walker.on('directory', function (root, stats, next) { 223 | next(); 224 | }); 225 | 226 | walker.on('file', function (root, stats, next) { 227 | var filePath = path.resolve(root, stats.name); 228 | 229 | fs.readFile(filePath, function (error, data) { 230 | if (error) { 231 | stream.emit('error', new PluginError(PLUGIN_NAME, error)); 232 | } else { 233 | stream.write(new Vinyl({ 234 | path: path.relative(baseDir, filePath), 235 | contents: data 236 | })); 237 | } 238 | 239 | next(); 240 | }); 241 | }); 242 | 243 | walker.on('end', function () { 244 | stream.emit('end'); 245 | stream.emit('finish'); 246 | }); 247 | } 248 | 249 | module.exports = gulpBower; 250 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-bower", 3 | "version": "0.0.15", 4 | "description": "Install Bower packages.", 5 | "main": "index.js", 6 | "dependencies": { 7 | "ansi-colors": "^1.0.1", 8 | "bower": "^1.3.12", 9 | "fancy-log": "^1.3.2", 10 | "inquirer": "^0.11.2", 11 | "plugin-error": "^0.1.2", 12 | "through2": "0.6.2", 13 | "vinyl": "^2.1.0", 14 | "walk": "2.3.3" 15 | }, 16 | "devDependencies": { 17 | "chai": "^3.4.1", 18 | "event-stream": "^3.3.2", 19 | "gulp": "latest", 20 | "gulp-codecov.io": "^1.0.1", 21 | "gulp-istanbul": "^0.10.3", 22 | "gulp-jshint": "latest", 23 | "gulp-mocha": "^2.2.0", 24 | "jshint": "^2.9.1", 25 | "mocha": "^2.3.4", 26 | "rimraf": "^2.5.0", 27 | "sinon": "^1.17.2", 28 | "sinon-chai": "^2.8.0", 29 | "stream-assert": "^2.0.3" 30 | }, 31 | "scripts": { 32 | "test": "node node_modules/gulp/bin/gulp.js post-coverage && node node_modules/gulp/bin/gulp.js lint" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git://github.com/zont/gulp-bower.git" 37 | }, 38 | "keywords": [ 39 | "gulpplugin", 40 | "bower" 41 | ], 42 | "author": "Alexander Zonov ", 43 | "license": "MIT", 44 | "bugs": { 45 | "url": "https://github.com/zont/gulp-bower/issues" 46 | }, 47 | "engines": { 48 | "node": ">=0.8" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /tests/fileSystemUtils.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var rimraf = require('rimraf'); 3 | 4 | var BOWERJSON = 'bower.json'; 5 | 6 | /** 7 | * Copy file 8 | * 9 | * @param {string} source path to source file 10 | * @param {string} target path to destination file 11 | * @param {Function} cb done callback 12 | */ 13 | function copyFile(source, target, cb) { 14 | var cbCalled = false; 15 | 16 | var rd = fs.createReadStream(source); 17 | rd.on("error", function (err) { 18 | done(err); 19 | }); 20 | var wr = fs.createWriteStream(target); 21 | wr.on("error", function (err) { 22 | done(err); 23 | }); 24 | wr.on("close", function (ex) { 25 | done(); 26 | }); 27 | rd.pipe(wr); 28 | 29 | function done(err) { 30 | if (typeof cb === "function") { 31 | cb(err); 32 | cbCalled = true; 33 | } 34 | } 35 | } 36 | 37 | /** 38 | * Write version conflicting bower.json to file 39 | * 40 | * @param {Function} done done callback 41 | */ 42 | function writeConflictJson(done) { 43 | copyFile('./tests/fixtures/bowerConflict.json', BOWERJSON, done); 44 | } 45 | 46 | /** 47 | * Write valid bower.json to file 48 | * 49 | * @param {Function} done done callback 50 | */ 51 | function writeValidJson(done) { 52 | copyFile('./tests/fixtures/bowerValid.json', BOWERJSON, done); 53 | } 54 | 55 | /** 56 | * Write valid .bowerrc to file 57 | * 58 | * @param {Function} done done callback 59 | */ 60 | function writeValidBowerrc(done) { 61 | copyFile('./tests/fixtures/bowerrcValid.json', './.bowerrc', done); 62 | } 63 | 64 | /** 65 | * Write empty .bowerrc to file 66 | * 67 | * @param {Function} done done callback 68 | */ 69 | function writeEmptyBowerrc(done) { 70 | copyFile('./tests/fixtures/bowerrcEmpty.json', './.bowerrc', done); 71 | } 72 | 73 | /** 74 | * Delete bower_components 75 | * 76 | * @param {string} path path to file or directory to delete 77 | * @param {Function} done done callback 78 | */ 79 | function deletePath(path, done) { 80 | rimraf(path, function (err) { 81 | if (err) throw (err); 82 | if (typeof done === 'function') done(); 83 | }); 84 | } 85 | 86 | /** 87 | * Delete bower.json if it exists 88 | * 89 | * @param {Function} done done callback 90 | */ 91 | function deleteBowerJson(done) { 92 | fs.stat(BOWERJSON, function (err, stats) { 93 | if (err) return done(); 94 | 95 | fs.unlink(BOWERJSON, function (err) { 96 | if (err) throw err; 97 | if (typeof done === 'function') done(); 98 | }); 99 | }) 100 | } 101 | 102 | module.exports = { 103 | writeConflictJson: writeConflictJson, 104 | writeValidJson: writeValidJson, 105 | writeValidBowerrc: writeValidBowerrc, 106 | writeEmptyBowerrc: writeEmptyBowerrc, 107 | deletePath: deletePath, 108 | deleteBowerJson: deleteBowerJson 109 | }; 110 | -------------------------------------------------------------------------------- /tests/fixtures/bowerConflict.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-bower-test", 3 | "description": "Temperary bower.json file for testing", 4 | "main": "index.js", 5 | "authors": [ 6 | "Crevil " 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "gulp", 11 | "gulp-bower" 12 | ], 13 | "homepage": "git://github.com/zont/gulp-bower.git", 14 | "moduleType": [], 15 | "private": true, 16 | "ignore": [ 17 | "**/.*", 18 | "node_modules", 19 | "bower_components", 20 | "test", 21 | "tests" 22 | ], 23 | "dependencies": { 24 | "bootstrap": "~3.3.6", 25 | "jquery": "1.8.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/fixtures/bowerValid.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-bower-test", 3 | "description": "Temperary bower.json file for testing", 4 | "main": "index.js", 5 | "authors": [ 6 | "Crevil " 7 | ], 8 | "license": "MIT", 9 | "keywords": [ 10 | "gulp", 11 | "gulp-bower" 12 | ], 13 | "homepage": "git://github.com/zont/gulp-bower.git", 14 | "moduleType": [], 15 | "private": true, 16 | "ignore": [ 17 | "**/.*", 18 | "node_modules", 19 | "bower_components", 20 | "test", 21 | "tests" 22 | ], 23 | "dependencies": { 24 | "log": "0.3.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/fixtures/bowerrcEmpty.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zont/gulp-bower/48c31b718ee5d9ab5c9dac58d100bb662a99173a/tests/fixtures/bowerrcEmpty.json -------------------------------------------------------------------------------- /tests/fixtures/bowerrcValid.json: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bowerrc_components" 3 | } 4 | -------------------------------------------------------------------------------- /tests/test.js: -------------------------------------------------------------------------------- 1 | /* global describe, xdescribe, it, xit, before, beforeEach, afterEach, after, process */ 2 | /* jshint expr: true */ 3 | 4 | var streamAssert = require('stream-assert'); 5 | var chai = require('chai'); 6 | var expect = require('chai').expect; 7 | var sinon = require('sinon'); 8 | var sinonChai = require('sinon-chai'); 9 | 10 | var inquirer = require('inquirer'); 11 | var fancyLog = require('fancy-log'); 12 | var fs = require('fs'); 13 | 14 | var fsUtil = require('./fileSystemUtils'); 15 | var bower = require('../index.js'); 16 | 17 | describe('gulp-bower', function () { 18 | var consoleStub; 19 | var consoleOutput = ''; 20 | 21 | before(function () { 22 | chai.use(sinonChai); 23 | }); 24 | 25 | beforeEach(function (done) { 26 | fsUtil.deletePath('bower_components/', function () { 27 | fsUtil.deleteBowerJson(function () { 28 | fsUtil.deletePath('.bowerrc', done); 29 | }); 30 | }); 31 | 32 | // stub fancyLog to suppress output in test results 33 | consoleStub = sinon.stub(fancyLog, 'info', function (val) { 34 | consoleOutput += val + '\n'; 35 | }); 36 | }); 37 | 38 | afterEach(function () { 39 | fancyLog.info.restore(); 40 | }); 41 | 42 | it('should emit error when dependency version can\'t be resolved', function (done) { 43 | fsUtil.writeConflictJson(function () { 44 | bower() 45 | .on('error', function (error) { 46 | try { 47 | expect(error.message).to.match(/resolve.*dependency/); 48 | done(); 49 | } catch (err) { 50 | done(err); 51 | } 52 | }); 53 | }); 54 | }); 55 | 56 | it('should pipe files to stream', function (done) { 57 | fsUtil.writeValidJson(function () { 58 | bower() 59 | .pipe(streamAssert.end(done)); 60 | }); 61 | }); 62 | 63 | describe('option', function () { 64 | describe('cmd', function () { 65 | it('should throw error on unknown command', function () { 66 | var command = 'notValidCommand'; 67 | expect(function () { 68 | bower({ cmd: command }); 69 | }).to.throw(/notValidCommand/); 70 | }); 71 | 72 | it('should handle multi letter commands', function () { 73 | var command = 'cache clean'; 74 | expect(function () { 75 | bower({ cmd: command, verbosity: 2 }); 76 | }).to.not.throw(); 77 | }); 78 | }); 79 | 80 | describe('directory', function () { 81 | it('should write to default directory', function (done) { 82 | fsUtil.writeValidJson(function () { 83 | bower() 84 | .on('end', function () { 85 | fs.stat('bower_components', function (err, stats) { 86 | expect(err).to.not.exist; 87 | done(); 88 | }); 89 | }); 90 | }); 91 | }); 92 | 93 | it('should write to explicit directory', function (done) { 94 | fsUtil.writeValidJson(function () { 95 | bower({ directory: 'lib' }) 96 | .on('end', function () { 97 | fs.stat('lib', function (err, stats) { 98 | expect(err).to.not.exist; 99 | fsUtil.deletePath('lib/', done); 100 | }); 101 | }); 102 | }); 103 | }); 104 | 105 | it('should write to explicit directory from string argument', function (done) { 106 | fsUtil.writeValidJson(function () { 107 | bower('lib') 108 | .on('end', function () { 109 | fs.stat('lib', function (err, stats) { 110 | expect(err).to.not.exist; 111 | fsUtil.deletePath('lib/', done); 112 | }); 113 | }); 114 | }); 115 | }); 116 | 117 | it('should use default directory when .bowerrc is empty', function (done) { 118 | fsUtil.writeValidJson(function () { 119 | fsUtil.writeEmptyBowerrc(function () { 120 | bower() 121 | .on('end', function () { 122 | fs.stat('bower_components', function (err, stats) { 123 | expect(err).to.not.exist; 124 | fsUtil.deletePath('.bowerrc', done); 125 | }); 126 | }); 127 | }); 128 | }); 129 | }); 130 | 131 | it('should get directory from .bowerrc', function (done) { 132 | fsUtil.writeValidJson(function () { 133 | fsUtil.writeValidBowerrc(function () { 134 | bower() 135 | .on('end', function () { 136 | fs.stat('bowerrc_components', function (err, stats) { 137 | expect(err).to.not.exist; 138 | fsUtil.deletePath('bowerrc_components/', function () { 139 | fsUtil.deletePath('.bowerrc', done); 140 | }); 141 | }); 142 | }); 143 | }); 144 | }); 145 | }); 146 | }); 147 | 148 | describe('interactive', function () { 149 | var promptStub; 150 | beforeEach(function () { 151 | // select first option when prompting 152 | promptStub = sinon.stub(inquirer, 'prompt', function (questions, cb) { 153 | setTimeout(function () { 154 | cb({ 155 | prompt: '1' 156 | }, 0); 157 | }); 158 | }); 159 | }); 160 | 161 | afterEach(function () { 162 | inquirer.prompt.restore(); 163 | }); 164 | 165 | it('should prompt for action when interactive is true', function (done) { 166 | fsUtil.writeConflictJson(function () { 167 | bower({ interactive: true }) 168 | .once('end', function () { 169 | try { 170 | expect(promptStub).to.have.been.called; 171 | done(); 172 | } catch (err) { 173 | done(err); 174 | } 175 | }); 176 | }); 177 | }); 178 | 179 | it('should not emit error when dependency version can\'t be resolved and interactive is true', function (done) { 180 | fsUtil.writeConflictJson(function () { 181 | var error = false; 182 | bower({ interactive: true }) 183 | .once('error', function () { 184 | error = true; 185 | }) 186 | .once('end', function () { 187 | try { 188 | expect(error).to.be.false; 189 | done(); 190 | } catch (err) { 191 | done(err); 192 | } 193 | }); 194 | }); 195 | }); 196 | }); 197 | 198 | describe('verbosity', function () { 199 | it('should output nothing when verbosity is 0', function (done) { 200 | fsUtil.writeValidJson(function () { 201 | bower({ verbosity: 0 }) 202 | .on('end', function () { 203 | try { 204 | expect(consoleStub).to.not.have.been.called; 205 | done(); 206 | } catch (err) { 207 | done(err); 208 | } 209 | }); 210 | }); 211 | }); 212 | 213 | it('should output nothing on errors when verbosity is 0', function (done) { 214 | fsUtil.writeConflictJson(function () { 215 | bower({ verbosity: 0 }) 216 | .on('error', function () { 217 | try { 218 | expect(consoleStub).to.not.have.been.called; 219 | done(); 220 | } catch (err) { 221 | done(err); 222 | } 223 | }); 224 | }); 225 | }); 226 | 227 | it('should output errors when verbosity is 1', function (done) { 228 | fsUtil.writeConflictJson(function () { 229 | bower({ verbosity: 1 }) 230 | .on('error', function () { 231 | try { 232 | expect(consoleStub).to.have.been.called; 233 | done(); 234 | } catch (err) { 235 | done(err); 236 | } 237 | }); 238 | }); 239 | }); 240 | 241 | it('should output info when verbosity is 2', function (done) { 242 | fsUtil.writeValidJson(function () { 243 | bower({ verbosity: 2 }) 244 | .on('end', function () { 245 | try { 246 | expect(consoleStub).to.have.been.called; 247 | done(); 248 | } catch (err) { 249 | done(err); 250 | } 251 | }); 252 | }); 253 | }); 254 | }); 255 | }); 256 | }); 257 | --------------------------------------------------------------------------------