Compare commits

..

48 Commits

Author SHA1 Message Date
Adam Stankiewicz
87cf578ba8 Update changelog 2015-12-11 21:51:30 +01:00
Adam Stankiewicz
3ead440c7c Update changelog 2015-12-11 21:50:50 +01:00
Adam Stankiewicz
e168c894a2 Bump to 1.7.1 2015-12-11 21:43:21 +01:00
Adam Stankiewicz
75e3661371 Update changelog 2015-12-11 21:42:34 +01:00
Adam Stankiewicz
baf8f7bf6b Fix missing parenthesis 2015-12-11 21:37:08 +01:00
Adam Stankiewicz
88758cd98c Revert "Add bower update --save functionality"
This reverts commit d2ba80e6e9.
2015-12-11 21:33:45 +01:00
Adam Stankiewicz
3bd2d62e67 Revert "Add failing tests for single package updates, optimize older tests"
This reverts commit 6616d09f47.
2015-12-11 21:32:47 +01:00
Adam Stankiewicz
d3eef5772a Revert "Only update packages requested by the user"
This reverts commit e3f402fc66.
2015-12-11 21:25:15 +01:00
Adam Stankiewicz
7c714901d4 Fix test for StandardRenderer 2015-12-11 20:33:54 +01:00
Adam Stankiewicz
7792b6d35d Use coveralls as npm script (fix certain versions of node) 2015-12-11 20:24:40 +01:00
Adam Stankiewicz
2db983dba3 Better formatting of help 2015-12-11 20:16:54 +01:00
Adam Stankiewicz
b9718bb309 Fix search command on no arguments, fixes #2066 2015-12-11 20:15:04 +01:00
Adam Stankiewicz
26f609e614 Ignore for now failing windows build on node 5 2015-12-10 21:25:01 +01:00
Adam Stankiewicz
4c2b56096b Merge pull request #2096 from contolini/readme-clean-up
Readme updates
2015-12-10 17:56:08 +01:00
Chris Contolini
5af929f0be Clean up readme 2015-12-09 20:08:44 -05:00
Adam Stankiewicz
686e883d87 Merge pull request #2094 from accommodavid/tar-test
Add test for tar archives
2015-12-09 11:34:57 +01:00
Adam Stankiewicz
f2767648e7 Merge pull request #2093 from contolini/hide-prereleases
Hide prerelease versions from `bower info`
2015-12-09 11:33:54 +01:00
Accommodavid
9e4bdd270d Add test for tar archives
Adds a test that checks if dependencies that point to tar archives (not
tar.gz) are handled and extracted correctly. Also removes a test from
`test/commands/install.js` that was duplicated.

Re-add postinstall test
2015-12-09 09:05:13 +01:00
Chris Contolini
7cb88ab49f Add renderer tests for prereleases 2015-12-08 17:59:21 -05:00
Chris Contolini
a532c55dca Hide prereleases when showing package info 2015-12-08 17:59:21 -05:00
Adam Stankiewicz
c559432c19 Properly call coveralls script 2015-12-08 20:05:04 +01:00
Adam Stankiewicz
322c49edf4 Get rid of STRICT_REQUIRE flag for coverage testing 2015-12-08 19:52:10 +01:00
Adam Stankiewicz
fe9b27a647 Try to fix appveyor build with npm-env 2015-12-08 19:15:06 +01:00
Adam Stankiewicz
1605374a25 Properly run code coverage on appveyor 2015-12-08 14:32:05 +01:00
Adam Stankiewicz
ac244a1400 Run coverage on appveyor as well 2015-12-08 14:21:05 +01:00
Adam Stankiewicz
d50e50f3b5 Add discord chat link, closes #2088 2015-12-08 11:14:33 +01:00
Adam Stankiewicz
3030469c59 Update update-notifier to 0.6.0 2015-12-08 11:00:51 +01:00
Adam Stankiewicz
977e0ddc52 Update changelog 2015-12-07 20:34:47 +01:00
Adam Stankiewicz
de3e1089da Better formatting of help message 2015-12-07 20:32:33 +01:00
Adam Stankiewicz
7897ad7dba Move bug reports to the top 2015-12-07 16:35:19 +01:00
Adam Stankiewicz
accdab3ece Link bug reports to wiki 2015-12-07 16:34:26 +01:00
David DeSandro
612aaa88eb add help menu for update --save, update --save-dev
Ref #2035
2015-12-07 08:42:17 -05:00
Adam Stankiewicz
338ac99080 Bump to 1.7.0 2015-12-07 13:34:01 +01:00
Adam Stankiewicz
9605bbea5f Bump bower-config to 1.3.0 2015-12-07 13:08:58 +01:00
Adam Stankiewicz
3791aee9d6 Merge pull request #2085 from pertrai1/feature/eslintrc
adding eslintrc for new ruleset option
2015-12-06 15:48:52 +01:00
Rob Simpson
20a223a959 adding eslintrc for new ruleset option 2015-12-06 06:10:13 -05:00
Adam Stankiewicz
ea5bd51327 Merge pull request #2083 from prometheansacrifice/updating-changelog
Adds changelog for release 1.7.0
2015-12-06 11:26:26 +01:00
Manas
b94c20b8da Release 1.7.0 2015-12-05 22:28:18 +05:30
Adam Stankiewicz
b81ba140e3 Bump to 1.6.9 and release 2015-12-04 22:28:09 +01:00
Adam Stankiewicz
4ffdb500b9 Update to npm version of fs-write-stream-atomic 2015-12-04 22:28:09 +01:00
Adam Stankiewicz
1696cde273 Merge pull request #2074 from eppeters/bower-search-prompt-before-listing-all
Prompt before listing all repos when running `bower search` without a query param
2015-12-03 00:21:57 +01:00
Adam Stankiewicz
94ffc35b25 Merge pull request #2070 from contolini/dont-update-all
Only update the packages requested by the user
2015-12-02 23:14:58 +01:00
Edward Peters
5a1e5eb9c7 Make 'bower search' show the help display when a user does not enter a
search term. Keep current behavior when running with config.json
enabled, or in non-interactive mode.

Rewrite bower search tests to cover the different cases of using the
command without a query parameter (interactive w/o config.json,
interactive w/ config.json, and non-interactive)
2015-12-02 17:07:27 -05:00
Chris Contolini
8c1f30b1c8 Format test files to comply with new jscs rules 2015-12-02 14:10:33 -05:00
Chris Contolini
e3f402fc66 Only update packages requested by the user 2015-12-02 14:10:28 -05:00
Chris Contolini
6616d09f47 Add failing tests for single package updates, optimize older tests 2015-12-02 14:10:28 -05:00
Adam Stankiewicz
25ad2ef946 Merge pull request #2076 from prometheansacrifice/instructions-for-squashing-commits
Adds instructions for squashing commits
2015-12-02 13:51:13 +01:00
Manas
ba4a1a9d45 Adds instructions for squashing commits 2015-12-02 13:30:45 +05:30
25 changed files with 484 additions and 478 deletions

45
.eslintrc Normal file
View File

@@ -0,0 +1,45 @@
env:
node: true
# enable ECMAScript features
ecmaFeatures:
arrowFunctions: true
binaryLiterals: true
blockBindings: true
classes: true
forOf: true
generators: true
objectLiteralShorthandMethods: true
objectLiteralShorthandProperties: true
octalLiterals: true
templateStrings: true
rules:
no-debugger: 2
no-dupe-args: 2
no-dupe-keys: 2
no-duplicate-case: 2
no-ex-assign: 2
no-reserved-keys: 2
no-unreachable: 2
valid-typeof: 2
no-fallthrough: 2
quotes: [2, "single", "avoid-escape"]
indent: [2, 2]
comma-spacing: 2
semi: 2
space-infix-ops: 2
space-return-throw-case: 2
space-before-function-paren: [2, "never"]
space-before-blocks: [2, "always"]
new-parens: 2
max-len: [2, 80, 2]
no-multiple-empty-lines: [2, {max: 2}]
eol-last: 2
no-trailing-spaces: 2
space-after-keywords: 2
# ECMAScript 6
prefer-const: 2
strict: [2, "global"]
no-undef: 2

View File

@@ -1,5 +1,32 @@
# Changelog
## 1.7.1 - 2015-12-11
- Rollback "Add `bower update --save` functionality", it causes issues and needs more testing
- Fix backward-compatibility of `bower search --json` ([#2066](https://github.com/bower/bower/issues/2066))
- Ignore prerelease versions from `bower info` output
- Update update-notifier to 0.6.0
- Better formatting of help messages (https://github.com/bower/bower/commit/de3e1089da80f47ea3667c5ab80d301cddfd8c3e)
- Add help menu for update `--save` and `update --save-dev` (https://github.com/bower/bower/commit/612aaa88eb4d4b268b2d8665c338ac086af3a5b0)
## 1.7.0 - 2015-12-07
- Add `bower update --save` functionality ([#2035](https://github.com/bower/bower/issues/2035))
- `bower search` shows help message when no package name is specified ([#2066](https://github.com/bower/bower/issues/2066))
- Update only those packages that are explicitly requested by the user. Related Issues
- [#256](https://github.com/bower/bower/issues/256)
- [#924](https://github.com/bower/bower/issues/924)
- [#1770](https://github.com/bower/bower/issues/1770)
- Allow for @ in username for SVN on windows ([#1650](https://github.com/bower/bower/issues/1650))
- Update bower config
- Loads the .bowerrc file from the cwd specified on the command line
- Allow the use of environment variables in .bowerrc ([#41](https://github.com/bower/config/issues/41))
- Allow for array notation in ENV variables ([#44](https://github.com/bower/config/issues/44))
## 1.6.9 - 2015-12-04
- Change git version of fs-write-stream-atomic back to npm version ([#2079](https://github.com/bower/bower/issues/2079))
## 1.6.8 - 2015-11-27
- Use fs-write-stream-atomic for downloads

View File

@@ -2,6 +2,9 @@
Bower is a large community project with many different developers contributing at all levels to the project. We're **actively** looking for more contributors right now. If you're interested in becoming Bower maintainer or supporting in in any way, please full the following form: http://goo.gl/forms/P1ndzCNoiG. There is more information about [contributing](https://github.com/bower/bower/wiki/Contributor-Guidelines) in the Wiki.
<a name="bugs"></a>
## 🐛 [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)
## Casual Involvement
* Improve the bower.io site ([tickets](https://github.com/bower/bower.github.io/issues))
@@ -35,48 +38,6 @@ requests](#pull-requests), but please respect the following restrictions:
* Please **do not** derail or troll issues. Keep the discussion on topic and
respect the opinions of others.
<a name="bugs"></a>
## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository.
Good bug reports are extremely helpful - thank you!
Guidelines for bug reports:
1. **Use the GitHub issue search** &mdash; check if the issue has already been
reported.
2. **Check if the issue has been fixed** &mdash; try to reproduce it using the
latest `master` or development branch in the repository.
3. **Isolate the problem** &mdash; ideally create a [reduced test
case](http://css-tricks.com/6263-reduced-test-cases/).
A good bug report shouldn't leave others needing to chase you up for more
information. Please try to be as detailed as possible in your report. What is
your environment? What steps will reproduce the issue? What OS experiences the
problem? What would you expect to be the outcome? All these details will help
people to fix any potential bugs.
Example:
> Short and descriptive example bug report title
>
> A summary of the issue and the browser/OS environment in which it occurs. If
> suitable, include the steps required to reproduce the bug.
>
> 1. This is the first step
> 2. This is the second step
> 3. Further steps, etc.
>
> `<url>` - a link to the reduced test case
>
> Any other information you want to share that is relevant to the issue being
> reported. This might include the lines of code that you have identified as
> causing the bug, and potential solutions (and your opinions on their
> merits).
<a name="features"></a>
## Feature requests
@@ -160,6 +121,8 @@ included in the project:
force push to your remote feature branch. You may also be asked to squash
commits.
10. If you are asked to squash your commits, then please use `git rebase -i master`. It will ask you to pick your commits - pick the major commits and squash the rest.
**IMPORTANT**: By submitting a patch, you agree to license your work under the
same license as that used by the project.

View File

@@ -55,10 +55,10 @@ module.exports = function (grunt) {
command: 'node test/packages.js --force && node test/packages-svn.js --force'
},
cover: {
command: 'STRICT_REQUIRE=1 node node_modules/istanbul/lib/cli.js cover --dir ./test/reports node_modules/mocha/bin/_mocha -- --timeout 30000 -R dot test/test.js'
command: 'node node_modules/istanbul/lib/cli.js cover --dir ./test/reports node_modules/mocha/bin/_mocha -- --timeout 30000 -R dot test/test.js'
},
coveralls: {
command: 'node node_modules/.bin/coveralls < test/reports/lcov.info'
command: 'npm run coveralls < test/reports/lcov.info'
}
},
watch: {
@@ -68,7 +68,7 @@ module.exports = function (grunt) {
});
grunt.registerTask('assets', ['exec:assets-force']);
grunt.registerTask('test', ['jshint', 'jscs', 'exec:assets', 'simplemocha:full']);
grunt.registerTask('test', ['jscs', 'jshint', 'exec:assets', 'simplemocha:full']);
grunt.registerTask('cover', 'exec:cover');
grunt.registerTask('travis', ['jshint', 'exec:assets', 'exec:cover', 'exec:coveralls']);
grunt.registerTask('default', 'test');

View File

@@ -1,11 +1,11 @@
# Bower - A package manager for the web
> Bower needs resources for its maintenance. Please fill [<strong>Support Declaration</strong>](http://goo.gl/forms/P1ndzCNoiG) if you think you can help.
> Bower needs resources for its maintenance. Please see [our blog](http://bower.io/blog/) if you think you can help.
[![Build Status](https://travis-ci.org/bower/bower.svg?branch=master)](https://travis-ci.org/bower/bower)
[![Windows Build](https://ci.appveyor.com/api/projects/status/jr6vfra8w84plh2g/branch/master?svg=true)](https://ci.appveyor.com/project/sheerun/bower/history)
[![Coverage Status](https://img.shields.io/coveralls/bower/bower.svg)](https://coveralls.io/r/bower/bower?branch=master)
[![Join the chat at https://gitter.im/bower/bower](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bower/bower?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Discord chat](https://img.shields.io/badge/discord-join%20chat%20%E2%86%92-brightgreen.svg?style=flat)](https://discord.gg/0fFM7QF0KpZRh2cY)
[![Issue Stats](http://issuestats.com/github/bower/bower/badge/pr?style=flat)](http://issuestats.com/github/bower/bower)
[![Issue Stats](http://issuestats.com/github/bower/bower/badge/issue?style=flat)](http://issuestats.com/github/bower/bower)
@@ -52,7 +52,7 @@ $ bower install <package>#<version> --save
We discourage using bower components statically for performance and security reasons (if component has an `upload.php` file that is not ignored, that can be easily exploited to do malicious stuff).
The best approach is to process components installed by bower with build tool (like [Grunt](http://gruntjs.com/) or [gulp](http://gulpjs.com/)), and serve them concatenated or using module loader (like [RequireJS](http://requirejs.org/)).
The best approach is to process components installed by bower with build tool (like [Grunt](http://gruntjs.com/) or [gulp](http://gulpjs.com/)), and serve them concatenated or using a module loader (like [RequireJS](http://requirejs.org/)).
### Uninstalling packages
@@ -68,7 +68,7 @@ On `prezto` or `oh-my-zsh`, do not forget to `alias bower='noglob bower'` or `bo
### Never run Bower with sudo
Bower is a user command, there is no need to execute it with superuser permissions.
Bower is a user command; there is no need to execute it with superuser permissions.
### Windows users
@@ -100,6 +100,7 @@ Bower can be configured using JSON in a `.bowerrc` file. Read over available opt
## Support
* [Discord chat](https://discord.gg/0fFM7QF0KpZRh2cY)
* [StackOverflow](http://stackoverflow.com/questions/tagged/bower)
* [Mailinglist](http://groups.google.com/group/twitter-bower) - twitter-bower@googlegroups.com
* [\#bower](http://webchat.freenode.net/?channels=bower) on Freenode
@@ -107,8 +108,7 @@ Bower can be configured using JSON in a `.bowerrc` file. Read over available opt
## Contributing
We welcome [contributions](https://github.com/bower/bower/graphs/contributors) of all kinds from anyone. Please take a moment to
review the [guidelines for contributing](CONTRIBUTING.md).
We welcome [contributions](https://github.com/bower/bower/graphs/contributors) of all kinds from anyone. Please take a moment to review the [guidelines for contributing](CONTRIBUTING.md).
* [Bug reports](https://github.com/bower/bower/wiki/Report-a-Bug)
* [Feature requests](CONTRIBUTING.md#features)

View File

@@ -18,6 +18,7 @@ environment:
matrix:
allow_failures:
- nodejs_version: "0.10"
- nodejs_version: "5"
# Install scripts. (runs after repo cloning)
install:
@@ -33,7 +34,7 @@ install:
# Post-install test scripts.
test_script:
- cmd: npm test
- cmd: npm run ci
# Don't actually build.
build: off

View File

@@ -99,30 +99,40 @@ analytics.setup(bower.config).then(function () {
// Get the renderer and configure it with the executed command
renderer = cli.getRenderer(command, logger.json, bower.config);
logger
.on('end', function (data) {
if (!bower.config.silent && !bower.config.quiet) {
renderer.end(data);
}
})
.on('error', function (err) {
if (levels.error >= loglevel) {
renderer.error(err);
}
function handleLogger(logger, renderer) {
logger
.on('end', function (data) {
if (!bower.config.silent && !bower.config.quiet) {
renderer.end(data);
}
})
.on('error', function (err) {
if (command !== 'help' && err.code === cli.READ_OPTIONS_ERROR_CODE) {
logger = bower.commands.help(command);
renderer = cli.getRenderer('help', logger.json, bower.config);
handleLogger(logger, renderer);
} else {
if (levels.error >= loglevel) {
renderer.error(err);
}
process.exit(1);
})
.on('log', function (log) {
if (levels[log.level] >= loglevel) {
renderer.log(log);
}
})
.on('prompt', function (prompt, callback) {
renderer.prompt(prompt)
.then(function (answer) {
callback(answer);
process.exit(1);
}
})
.on('log', function (log) {
if (levels[log.level] >= loglevel) {
renderer.log(log);
}
})
.on('prompt', function (prompt, callback) {
renderer.prompt(prompt)
.then(function (answer) {
callback(answer);
});
});
});
}
handleLogger(logger, renderer);
// Warn if HOME is not SET
if (!userHome) {

View File

@@ -10,24 +10,24 @@ var config = require('../config');
* return as soon as possible and load and execute the command asynchronously.
*/
function commandFactory(id) {
if (process.env.STRICT_REQUIRE) {
require(id);
}
function command() {
function runApi() {
var command = require(id);
var commandArgs = [].slice.call(arguments);
return withLogger(function (logger) {
commandArgs.unshift(logger);
return require(id).apply(undefined, commandArgs);
return command.apply(undefined, commandArgs);
});
}
function runFromArgv(argv) {
return withLogger(function (logger) {
var command = require(id);
var commandArgs;
var command = require(id);
var commandArgs = command.readOptions(argv);
commandArgs = command.readOptions(argv);
return withLogger(function (logger) {
commandArgs.unshift(logger);
return command.apply(undefined, commandArgs);
@@ -38,7 +38,7 @@ function commandFactory(id) {
var logger = new Logger();
Q.try(func, logger)
.done(function () {
.then(function () {
config.restore();
var args = [].slice.call(arguments);
args.unshift('end');
@@ -51,9 +51,9 @@ function commandFactory(id) {
return logger;
}
command.line = runFromArgv;
runApi.line = runFromArgv;
return command;
return runApi;
}

View File

@@ -2,33 +2,41 @@ var Q = require('q');
var RegistryClient = require('bower-registry-client');
var Tracker = require('../util/analytics').Tracker;
var defaultConfig = require('../config');
var cli = require('../util/cli');
function search(logger, name, config) {
var registryClient;
var tracker;
var json = config ? config.json : undefined;
config = defaultConfig(config);
config.json = config.json || json; // Hack until bower-config is fixed...
config.cache = config.storage.registry;
registryClient = new RegistryClient(config, logger);
tracker = new Tracker(config);
tracker.track('search', name);
// If no name was specified, list all packages
if (!name) {
return Q.nfcall(registryClient.list.bind(registryClient));
// Otherwise search it
} else {
if (name) {
return Q.nfcall(registryClient.search.bind(registryClient), name);
} else {
// List all packages when in interactive mode + json enabled, and
// always when in non-interactive mode
if (config.interactive && !config.json) {
throw cli.createReadOptionsError('search');
}
return Q.nfcall(registryClient.list.bind(registryClient));
}
}
// -------------------
search.readOptions = function (argv) {
var cli = require('../util/cli');
var options = cli.readOptions(argv);
var name = options.argv.remain.slice(1).join(' ');
var terms = options.argv.remain.slice(1);
var name = terms.join(' ');
return [name];
};

View File

@@ -23,9 +23,7 @@ update.readOptions = function (argv) {
var options = cli.readOptions({
'force-latest': { type: Boolean, shorthand: 'F' },
'production': { type: Boolean, shorthand: 'p' },
'save': { type: Boolean, shorthand: 'S' },
'save-dev': { type: Boolean, shorthand: 'D' }
'production': { type: Boolean, shorthand: 'p' }
}, argv);
var names = options.argv.remain.slice(1);

View File

@@ -197,27 +197,6 @@ Project.prototype.update = function (names, options) {
return that._manager.install(that._json);
})
.then(function (installed) {
if (that._options.save || that._options.saveDev) {
// Cycle through the specified endpoints
targets.forEach(function (target) {
// Abort if current and new version are identical
if (target.target === target.pkgMeta.version) {
return false;
}
var jsonEndpoint = endpointParser.decomposed2json(target);
// Bower uses the ~ range specifier for new installs
jsonEndpoint[target.name] = '~' + target.pkgMeta.version;
if (that._options.saveDev && mout.object.has(that._json, 'devDependencies.' + target.name)) {
that._json.devDependencies = mout.object.mixIn(that._json.devDependencies || {}, jsonEndpoint);
}
if (that._options.save && mout.object.has(that._json, 'dependencies.' + target.name)) {
that._json.dependencies = mout.object.mixIn(that._json.dependencies || {}, jsonEndpoint);
}
});
}
// Save JSON, might contain changes to resolutions
return that.saveJson()
.then(function () {

View File

@@ -5,6 +5,7 @@ var archy = require('archy');
var Q = require('q');
var stringifyObject = require('stringify-object');
var os = require('os');
var semverUtils = require('semver-utils');
var pkg = require(path.join(__dirname, '../..', 'package.json'));
var template = require('../util/template');
@@ -209,6 +210,19 @@ StandardRenderer.prototype._info = function (data) {
// Render the versions at the end
if (includeVersions) {
data.hidePreReleases = false;
data.numPreReleases = 0;
// If output isn't verbose, hide prereleases
if (!this._config.verbose) {
data.versions = mout.array.filter(data.versions, function(version) {
version = semverUtils.parse(version);
if (!version.release && !version.build) {
return true;
}
data.numPreReleases++;
});
data.hidePreReleases = !!data.numPreReleases;
}
str += '\n' + template.render('std/info.std', data);
}

View File

@@ -1,6 +1,9 @@
var mout = require('mout');
var nopt = require('nopt');
var renderers = require('../renderers');
var createError = require('./createError');
var READ_OPTIONS_ERROR_CODE = 'EREADOPTIONS';
function readOptions(options, argv) {
var types;
@@ -37,6 +40,16 @@ function readOptions(options, argv) {
return parsedOptions;
}
/**
* Creates an error for the case where a command has trouble parsing command
* line options.
**/
function createReadOptionsError(commandName) {
var errorString = commandName + ' syntax error';
return createError(errorString, READ_OPTIONS_ERROR_CODE);
}
function getRenderer(command, json, config) {
if (config.json || json) {
return new renderers.Json(command, config);
@@ -47,3 +60,6 @@ function getRenderer(command, json, config) {
module.exports.readOptions = readOptions;
module.exports.getRenderer = getRenderer;
module.exports.createReadOptionsError = createReadOptionsError;
module.exports.READ_OPTIONS_ERROR_CODE = READ_OPTIONS_ERROR_CODE;

View File

@@ -1,6 +1,6 @@
{
"name": "bower",
"version": "1.6.8",
"version": "1.7.1",
"description": "The browser package manager",
"author": "Twitter",
"license": "MIT",
@@ -16,7 +16,7 @@
"dependencies": {
"abbrev": "^1.0.5",
"archy": "1.0.0",
"bower-config": "^1.2.3",
"bower-config": "^1.3.0",
"bower-endpoint-parser": "^0.2.2",
"bower-json": "^0.4.0",
"bower-logger": "^0.2.2",
@@ -27,7 +27,7 @@
"configstore": "^0.3.2",
"decompress-zip": "^0.1.0",
"destroy": "^1.0.3",
"fs-write-stream-atomic": "^1.0.4",
"fs-write-stream-atomic": "^1.0.5",
"fstream": "^1.0.3",
"fstream-ignore": "^1.0.2",
"github": "^0.2.3",
@@ -53,11 +53,12 @@
"retry": "0.6.1",
"rimraf": "^2.2.8",
"semver": "^2.3.0",
"semver-utils": "^1.1.1",
"shell-quote": "^1.4.2",
"stringify-object": "^1.0.0",
"tar-fs": "^1.4.1",
"tmp": "0.0.24",
"update-notifier": "^0.3.0",
"update-notifier": "^0.6.0",
"user-home": "^1.1.0",
"which": "^1.0.8"
},
@@ -130,7 +131,9 @@
"which"
],
"scripts": {
"test": "grunt test"
"test": "grunt test",
"ci": "grunt travis",
"coveralls": "coveralls"
},
"bin": "bin/bower",
"files": [

View File

@@ -2,7 +2,6 @@
"command": "search",
"description": "Finds all packages or a specific package.",
"usage": [
"search [<options>]",
"search <name> [<options>]"
],
"options": [

View File

@@ -19,6 +19,16 @@
"shorthand": "-p",
"flag": "--production",
"description": "Do not install project devDependencies"
},
{
"shorthand": "-S",
"flag": "--save",
"description": "Update dependencies in bower.json"
},
{
"shorthand": "-D",
"flag": "--save-dev",
"description": "Update devDependencies in bower.json"
}
]
}

View File

@@ -7,6 +7,7 @@ Usage:
{{/each}}
{{/condense}}
Options:
{{#condense}}
@@ -20,3 +21,4 @@ Options:
Description:
{{#indent level="4"}}{{description}}{{/indent}}

View File

@@ -24,3 +24,4 @@ Options:
{{/condense}}
See 'bower help <command>' for more information on a specific command.

View File

@@ -5,6 +5,10 @@
{{/versions}}
{{/condense}}
{{#if hidePreReleases}}
Show {{numPreReleases}} additional prereleases with bower info {{name}} --verbose
{{/if}}
You can request info for a specific version with 'bower info {{name}}#<version>'
{{else}}No versions available.
{{/if}}

BIN
test/assets/package-tar.tar Normal file

Binary file not shown.

View File

@@ -1,36 +1,43 @@
var expect = require('expect.js');
var path = require('path');
var helpers = require('../helpers');
var nock = require('nock');
var fs = require('../../lib/util/fs');
describe('bower install', function () {
describe('bower install', function() {
var tempDir = new helpers.TempDir();
var install = helpers.command('install', { cwd: tempDir.path });
var install = helpers.command('install', {
cwd: tempDir.path
});
it('correctly reads arguments', function() {
expect(install.readOptions(['jquery', 'angular', '-F', '-p', '-S', '-D', '-E']))
.to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
.to.eql([
['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}
]);
});
it('correctly reads long arguments', function() {
expect(install.readOptions([
'jquery', 'angular',
'--force-latest', '--production', '--save', '--save-dev', '--save-exact'
])).to.eql([['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}]);
'jquery', 'angular',
'--force-latest', '--production', '--save', '--save-dev', '--save-exact'
])).to.eql([
['jquery', 'angular'], {
forceLatest: true,
production: true,
save: true,
saveDev: true,
saveExact: true
}
]);
});
var mainPackage = new helpers.TempDir({
@@ -41,7 +48,22 @@ describe('bower install', function () {
var gitPackage = new helpers.TempDir();
it('writes to bower.json if --save flag is used', function () {
gitPackage.prepareGit({
'1.0.0': {
'bower.json': {
name: 'package'
},
'version.txt': '1.0.0'
},
'1.0.1': {
'bower.json': {
name: 'package'
},
'version.txt': '1.0.1'
}
});
it('writes to bower.json if --save flag is used', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -50,12 +72,16 @@ describe('bower install', function () {
}
});
return helpers.run(install, [[mainPackage.path], { save: true }]).then(function() {
return helpers.run(install, [
[mainPackage.path], {
save: true
}
]).then(function() {
expect(tempDir.read('bower.json')).to.contain('dependencies');
});
});
it('writes an exact version number to dependencies in bower.json if --save --save-exact flags are used', function () {
it('writes an exact version number to dependencies in bower.json if --save --save-exact flags are used', function() {
mainPackage.prepare({
'bower.json': {
name: 'package',
@@ -70,14 +96,16 @@ describe('bower install', function () {
});
return helpers.run(install, [
[mainPackage.path],
{ saveExact: true, save: true }
]).then(function() {
expect(tempDir.readJson('bower.json').dependencies.package).to.equal(mainPackage.path + '#1.2.3');
});
[mainPackage.path], {
saveExact: true,
save: true
}
]).then(function() {
expect(tempDir.readJson('bower.json').dependencies.package).to.equal(mainPackage.path + '#1.2.3');
});
});
it('writes an exact version number to devDependencies in bower.json if --save-dev --save-exact flags are used', function () {
it('writes an exact version number to devDependencies in bower.json if --save-dev --save-exact flags are used', function() {
mainPackage.prepare({
'bower.json': {
name: 'package',
@@ -92,18 +120,24 @@ describe('bower install', function () {
});
return helpers.run(install, [
[mainPackage.path],
{ saveExact: true, saveDev: true }
]).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.package).to.equal(mainPackage.path + '#0.1.0');
});
[mainPackage.path], {
saveExact: true,
saveDev: true
}
]).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.package).to.equal(mainPackage.path + '#0.1.0');
});
});
it('reads .bowerrc from cwd', function () {
mainPackage.prepare({ foo: 'bar' });
it('reads .bowerrc from cwd', function() {
mainPackage.prepare({
foo: 'bar'
});
tempDir.prepare({
'.bowerrc': { directory: 'assets' },
'.bowerrc': {
directory: 'assets'
},
'bower.json': {
name: 'test',
dependencies: {
@@ -117,7 +151,7 @@ describe('bower install', function () {
});
});
it('runs preinstall hook', function () {
it('runs preinstall hook', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -139,7 +173,7 @@ describe('bower install', function () {
});
});
it('runs preinstall hook', function () {
it('runs postinstall hook', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -162,7 +196,7 @@ describe('bower install', function () {
});
// To be discussed, but that's the implementation now
it('does not run hooks if nothing is installed', function () {
it('does not run hooks if nothing is installed', function() {
tempDir.prepare({
'bower.json': {
name: 'test'
@@ -180,7 +214,7 @@ describe('bower install', function () {
});
});
it('runs postinstall after bower.json is written', function () {
it('runs postinstall after bower.json is written', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -194,12 +228,16 @@ describe('bower install', function () {
}
});
return helpers.run(install, [[mainPackage.path], { save: true }]).then(function() {
return helpers.run(install, [
[mainPackage.path], {
save: true
}
]).then(function() {
expect(tempDir.read('hook.txt')).to.contain('dependencies');
});
});
it('display the output of hook scripts', function (next) {
it('display the output of hook scripts', function(next) {
mainPackage.prepare();
tempDir.prepare({
@@ -217,37 +255,36 @@ describe('bower install', function () {
});
var lastAction = null;
helpers.run(install).logger.intercept(function (log) {
helpers.run(install).logger.intercept(function(log) {
if (log.level === 'action') {
lastAction = log;
}
}).on('end', function () {
}).on('end', function() {
expect(lastAction.message).to.be('foobar');
next();
});
});
it('skips components not installed by bower', function () {
mainPackage.prepare({
'.git': {} //Make a dummy file instead of using slower gitPrepare()
});
it('skips components not installed by bower', function() {
mainPackage.prepare({
'.git': {} //Make a dummy file instead of using slower gitPrepare()
});
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
}
}
});
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: mainPackage.path
}
}
});
return helpers.run(install).then(function() {
var packageFiles = fs.readdirSync(mainPackage.path);
//presence of .git file implies folder was not overwritten
expect(packageFiles).to.contain('.git');
});
});
return helpers.run(install).then(function() {
var packageFiles = fs.readdirSync(mainPackage.path);
//presence of .git file implies folder was not overwritten
expect(packageFiles).to.contain('.git');
});
});
it('works for git repositories', function () {
gitPackage.prepareGit({
@@ -279,6 +316,22 @@ describe('bower install', function () {
});
});
it('works for dependencies that point to tar files', function() {
var packageDir = path.join(__dirname, '../assets/package-tar.tar');
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package: packageDir
}
}
});
return helpers.run(install).then(function() {
expect(tempDir.read('bower_components/package/index.txt')).to.contain('1.0.0');
});
});
it('does not install ignored dependencies', function() {
mainPackage.prepare();
var package2 = new helpers.TempDir({
@@ -313,7 +366,6 @@ describe('bower install', function () {
expect(tempDir.exists('bower_components/package')).to.be(false);
expect(tempDir.exists('bower_components/package2')).to.be(true);
});
});
it('does not install ignored dependencies if run multiple times', function() {
@@ -351,10 +403,9 @@ describe('bower install', function () {
expect(tempDir.exists('bower_components/package2')).to.be(true);
});
});
});
it('recognizes proxy option in config', function (done) {
it('recognizes proxy option in config', function(done) {
this.timeout(10000);
tempDir.prepare({
@@ -371,22 +422,21 @@ describe('bower install', function () {
});
nock('http://dummy.local')
.get('http://github.com/yahoo/pure/archive/v0.6.0.tar.gz')
.reply(500);
.get('http://github.com/yahoo/pure/archive/v0.6.0.tar.gz')
.reply(500);
return helpers.run(install, [
undefined,
undefined,
{ proxy: 'http://dummy.local/' }
])
.fail(function(error) {
expect(error.message).to.equal('Status code of 500');
done();
});
.fail(function(error) {
expect(error.message).to.equal('Status code of 500');
done();
});
});
it('errors if the components directory is not a directory', function () {
it('errors if the components directory is not a directory', function() {
tempDir.prepare({
'.bowerrc': {
directory: '.bowerrc'

View File

@@ -27,7 +27,9 @@ describe('bower search', function () {
});
});
it('lists all repositories if no query given', function () {
it('lists all repositories when no query given in non-interactive mode', function () {
var nonInteractiveConfig = { interactive: false };
return Q.Promise(function(resolve) {
var search = helpers.command('search', {
'bower-registry-client': function() {
@@ -37,8 +39,45 @@ describe('bower search', function () {
}
});
helpers.run(search, [], {});
helpers.run(search, [null, nonInteractiveConfig]);
});
});
it('lists all repositories when no query given and config.json is enabled in interactive mode', function () {
var interactiveConfig = { interactive: true, json: true };
var search = helpers.command('search', {
'bower-registry-client': function() {
return {
list: function (cb) { return cb(null, 'foobar'); }
};
}
});
return helpers.run(search, [null, interactiveConfig])
.spread(function(result) {
expect(result).to.be('foobar');
});
});
it('does not list any repositories in interactive mode if no query given and config.json is disabled', function () {
var interactiveConfig = { interactive: true };
var search = helpers.command('search', {
'bower-registry-client': function() {
return {
list: function() { throw 'list called'; },
search: function() { throw 'search called'; }
};
}
});
return helpers.run(search, [null, interactiveConfig])
.then(function(commandResult) {
expect().fail('should fail');
})
.catch(function(e) {
expect(e.code).to.be('EREADOPTIONS');
});
});
});

View File

@@ -1,6 +1,5 @@
var expect = require('expect.js');
var object = require('mout').object;
var semver = require('semver');
var helpers = require('../helpers');
var updateCmd = helpers.command('update');
@@ -8,6 +7,7 @@ var commands = helpers.require('lib/index').commands;
describe('bower update', function () {
this.timeout(10000);
var tempDir = new helpers.TempDir();
var subPackage = new helpers.TempDir({
@@ -42,14 +42,16 @@ describe('bower update', function () {
}
}).prepare();
var update = function(packages, options, config) {
var updateLogger = function(packages, options, config) {
config = object.merge(config || {}, {
cwd: tempDir.path
});
var logger = commands.update(
packages, options, config
);
return commands.update(packages, options, config);
};
var update = function(packages, options, config) {
var logger = updateLogger(packages, options, config);
return helpers.expectEvent(logger, 'end');
};
@@ -67,16 +69,11 @@ describe('bower update', function () {
};
it('correctly reads arguments', function() {
expect(updateCmd.readOptions(['jquery', '-F', '-p', '-S', '-D']))
.to.eql([['jquery'], {
forceLatest: true,
production: true,
save: true,
saveDev: true
}]);
expect(updateCmd.readOptions(['jquery', '-F', '-p']))
.to.eql([['jquery'], { forceLatest: true, production: true }]);
});
it('install missing packages', function () {
it('install missing packages', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -96,77 +93,76 @@ describe('bower update', function () {
it('does not install ignored dependencies', function() {
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3'
}
}).prepare();
'bower.json': {
name: 'package3'
}
}).prepare();
var package2 = new helpers.TempDir({
'bower.json': {
name: 'package2',
dependencies: {
package3: package3.path
}
}
}).prepare();
'bower.json': {
name: 'package2',
dependencies: {
package3: package3.path
}
}
}).prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
return update().then(function() {
expect(tempDir.exists('bower_components/package2/bower.json')).to.equal(true);
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
expect(tempDir.exists('bower_components/package2/bower.json')).to.equal(true);
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
});
it('does not install ignored dependencies if run multiple times', function() {
var package3 = new helpers.TempDir({
'bower.json': {
name: 'package3'
}
}).prepare();
'bower.json': {
name: 'package3'
}
}).prepare();
var package2 = new helpers.TempDir({
'bower.json': {
name: 'package2',
dependencies: {
package3: package3.path
}
}
}).prepare();
'bower.json': {
name: 'package2',
dependencies: {
package3: package3.path
}
}
}).prepare();
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
'bower.json': {
name: 'test',
dependencies: {
package2: package2.path
}
},
'.bowerrc': {
ignoredDependencies: ['package3']
}
});
return update().then(function() {
return update().then(function() {
expect(tempDir.exists('bower_components/package2/bower.json')).to.equal(true);
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
});
return update().then(function() {
expect(tempDir.exists('bower_components/package2/bower.json')).to.equal(true);
expect(tempDir.exists('bower_components/package3')).to.equal(false);
});
});
});
it('runs preinstall hook when installing missing package', function () {
it('runs preinstall hook when installing missing package', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -188,7 +184,7 @@ describe('bower update', function () {
});
});
it('runs postinstall hook when installing missing package', function () {
it('runs postinstall hook when installing missing package', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -210,7 +206,7 @@ describe('bower update', function () {
});
});
it('doesn\'t runs postinstall when no package is update', function () {
it('doesn\'t runs postinstall when no package is update', function() {
mainPackage.prepare();
tempDir.prepare({
@@ -236,7 +232,7 @@ describe('bower update', function () {
});
});
it('updates a package', function () {
it('updates a package', function() {
tempDir.prepare({
'bower.json': {
name: 'test',
@@ -265,213 +261,6 @@ describe('bower update', function () {
});
});
it('doesn\'t update extraneous packages', function () {
tempDir.prepare({
'bower.json': {
name: 'test'
}
});
return install(['underscore#1.5.0']).then(function() {
expect(tempDir.readJson('bower_components/underscore/package.json').version).to.equal('1.5.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower_components/underscore/package.json').version).to.equal('1.5.0');
expect(tempDir.readJson('bower.json')).to.not.have.property('dependencies');
});
});
});
it('updates bower.json dep after updating with --save flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '~1.5.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.2');
});
});
});
it('updates bower.json dev dep after updating with --save-dev flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
devDependencies: {
underscore: '~1.5.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.0');
return update(null, {saveDev: true}).then(function() {
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.2');
});
});
});
it('replaces "any" range with latest version', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '*'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('*');
return update(null, {save: true}).then(function() {
var version = semver.gte(tempDir.readJson('bower.json').dependencies.underscore.replace('~', ''), '1.8.3');
expect(version).to.be.ok();
});
});
});
it('updates multiple components in bower.json after updating with --save flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '~1.5.0',
lodash: '~1.0.0'
},
devDependencies: {
neat: '~1.5.0'
},
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.0');
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('~1.0.0');
expect(tempDir.readJson('bower.json').devDependencies.neat).to.equal('~1.5.0');
return update(null, {save: true}).then(function() {
// Normal deps should have changed
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~1.5.2');
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('~1.0.2');
// Dev deps should not have changed
expect(tempDir.readJson('bower.json').devDependencies.neat).to.equal('~1.5.0');
});
});
});
it('updates multiple components in bower.json after updating with --save-dev flag', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
neat: '~1.5.0'
},
devDependencies: {
underscore: '~1.5.0',
lodash: '~1.0.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.neat).to.equal('~1.5.0');
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.0');
expect(tempDir.readJson('bower.json').devDependencies.lodash).to.equal('~1.0.0');
return update(null, {saveDev: true}).then(function() {
// Normal deps should not have changed
expect(tempDir.readJson('bower.json').dependencies.neat).to.equal('~1.5.0');
// Dev deps should have changed
expect(tempDir.readJson('bower.json').devDependencies.underscore).to.equal('~1.5.2');
expect(tempDir.readJson('bower.json').devDependencies.lodash).to.equal('~1.0.2');
});
});
});
it('correctly interprets semver range specifier pre-1.0', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '^0.1.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('^0.1.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('~0.1.1');
});
});
});
it('correctly interprets semver range specifier post-1.0', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
lodash: '^1.0.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('^1.0.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.lodash).to.equal('~1.3.1');
});
});
});
it('doesn\'t update bower.json if versions are identical', function () {
tempDir.prepare({
'bower.json': {
name: 'test',
dependencies: {
underscore: '1.5.0'
}
}
});
return install().then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('1.5.0');
return update(null, {save: true}).then(function() {
expect(tempDir.readJson('bower.json').dependencies.underscore).to.equal('1.5.0');
});
});
});
it('does not install ignored dependencies when updating a package', function () {
var package3 = new helpers.TempDir({
'bower.json': {
@@ -536,7 +325,7 @@ describe('bower update', function () {
});
});
it('runs preinstall hook when updating a package', function () {
it('runs preinstall hook when updating a package', function() {
tempDir.prepare({
'bower.json': {
name: 'test',
@@ -568,7 +357,7 @@ describe('bower update', function () {
});
});
it('runs postinstall hook when updating a package', function () {
it('runs postinstall hook when updating a package', function() {
tempDir.prepare({
'bower.json': {
name: 'test',

View File

@@ -220,7 +220,7 @@ exports.command = function (command, stubs) {
};
exports.run = function (command, args) {
var logger = command.apply(command, args || []);
var logger = command.apply(null, args || []);
// Hack so we can intercept prompring for data
logger.prompt = function(data) {
@@ -310,4 +310,4 @@ exports.runBin = function (args) {
afterEach(function () {
nock.cleanAll();
});
});

View File

@@ -613,7 +613,11 @@ describe('StandardRenderer', function () {
versions: [
'1.2.0',
'1.2.1',
'1.2.2'
'1.2.2',
'1.2.3+build-1234',
'1.2.8-build.2098+sha.cb9c0f2',
'1.3.0-rc.5',
'1.3.0-beta.18'
]
});
}).spread(function(stdout, stderr) {
@@ -627,6 +631,48 @@ describe('StandardRenderer', function () {
- 1.2.0
- 1.2.1
- 1.2.2
Show 4 additional prereleases with bower info foo --verbose
You can request info for a specific version with 'bower info foo#<version>'
*/}));
});
});
it('outputs full info command log with prereleases', function() {
return helpers.capture(function() {
var renderer = new StandardRenderer('info', { verbose: true });
renderer.end({
name: 'foo',
latest: {
version: '1.2.3'
},
versions: [
'1.2.0',
'1.2.1',
'1.2.2',
'1.2.3+build-1234',
'1.2.8-build.2098+sha.cb9c0f2',
'1.3.0-rc.5',
'1.3.0-beta.18'
]
});
}).spread(function(stdout, stderr) {
expect(stdout).to.equal(multiline(function() {/*
{
version: '1.2.3'
}
Available versions:
- 1.2.0
- 1.2.1
- 1.2.2
- 1.2.3+build-1234
- 1.2.8-build.2098+sha.cb9c0f2
- 1.3.0-rc.5
- 1.3.0-beta.18
You can request info for a specific version with 'bower info foo#<version>'
*/}));
@@ -784,6 +830,7 @@ describe('StandardRenderer', function () {
Usage:
bower uninstall <name> [<name> ..] [<options>]
Options:
-h, --help Show this help message
@@ -795,6 +842,7 @@ describe('StandardRenderer', function () {
Uninstalls a package locally from your bower_components directory
*/}));
});
});