Skip to content

Commit

Permalink
- move aliases to unsupported aliases
Browse files Browse the repository at this point in the history
- tests properly camelised comand
- tests properly command with hyphen
- move generation of documentation in src/cli/commands/index.js
- move every command related stuff in src/cli/commands/index.js
- tests some corner cases
- delete every camelCase use in src/cli/commands/index.js and
src/cli/commands/help.js
  • Loading branch information
voxsim committed Apr 10, 2017
1 parent fb40251 commit e5a91fa
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 140 deletions.
32 changes: 0 additions & 32 deletions __tests__/cli/aliases.js

This file was deleted.

32 changes: 32 additions & 0 deletions __tests__/cli/unsupported-aliases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* @flow */

import unsupportedAliases from '../../src/cli/unsupported-aliases.js';

test('shorthands and affordances', () => {
expect(unsupportedAliases['run-script']).toBe('run');
expect(unsupportedAliases['c']).toBe('config');
expect(unsupportedAliases['i']).toBe('install');
expect(unsupportedAliases['ls']).toBe('list');
expect(unsupportedAliases['rb']).toBe('rebuild');
expect(unsupportedAliases['runScript']).toBe('run');
expect(unsupportedAliases['t']).toBe('test');
expect(unsupportedAliases['tst']).toBe('test');
expect(unsupportedAliases['un']).toBe('remove');
expect(unsupportedAliases['up']).toBe('upgrade');
expect(unsupportedAliases['v']).toBe('version');
expect(unsupportedAliases['add-user']).toBe('login');
expect(unsupportedAliases['dist-tag']).toBe('tag');
expect(unsupportedAliases['dist-tags']).toBe('tag');
expect(unsupportedAliases['adduser']).toBe('login');
expect(unsupportedAliases['author']).toBe('owner');
expect(unsupportedAliases['isntall']).toBe('install');
expect(unsupportedAliases['la']).toBe('list');
expect(unsupportedAliases['ll']).toBe('list');
expect(unsupportedAliases['r']).toBe('remove');
expect(unsupportedAliases['rm']).toBe('remove');
expect(unsupportedAliases['show']).toBe('info');
expect(unsupportedAliases['uninstall']).toBe('remove');
expect(unsupportedAliases['update']).toBe('upgrade');
expect(unsupportedAliases['verison']).toBe('version');
expect(unsupportedAliases['view']).toBe('info');
});
5 changes: 5 additions & 0 deletions __tests__/fixtures/index/run-generate-lock-entry/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "test_generate_lock_entry",
"version": "1.0.0",
"license": "UNLICENSED"
}
45 changes: 43 additions & 2 deletions __tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,20 +200,26 @@ test.concurrent('should install if first arg looks like a flag', async () => {
expect(stdout[stdout.length - 1]).toEqual('{"type":"success","data":"Saved lockfile."}');
});

test.concurrent('should interpolate aliases', async () => {
test.concurrent('should interpolate unsopported aliases', async () => {
await expectAnErrorMessage(
execCommand('i', [], 'run-add', true),
'Did you mean `yarn install`?',
);
});

test.concurrent('should display correct documentation link for aliases', async () => {
test.concurrent('should display correct documentation link for unsopported aliases', async () => {
await expectAnInfoMessageAfterError(
execCommand('i', [], 'run-add', true),
'Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.',
);
});

test.concurrent('should show help and ignore unsopported aliases', async () => {
const stdout = await execCommand('i', ['--help'], 'run-help');
expect(stdout[stdout.length - 1])
.toEqual('Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.');
});

test.concurrent('should run help of run command if --help is before --', async () => {
const stdout = await execCommand('run', ['custom-script', '--help', '--'], 'run-custom-script-with-arguments');
expect(stdout[0]).toEqual('Usage: yarn [command] [flags]');
Expand Down Expand Up @@ -275,3 +281,38 @@ test.concurrent('should throws missing command for constructor command', async (
'Command \"constructor\" not found',
);
});

test.concurrent('should show help and ignore constructor command', async () => {
const stdout = await execCommand('constructor', ['--help'], 'run-help');
expectHelpOutput(stdout);
});

test.concurrent('should run command with hyphens', async () => {
const stdout = await execCommand('generate-lock-entry', [], 'run-generate-lock-entry');
expect(stdout[0]).toMatch(/# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY./);
expect(stdout[1]).toMatch(/# yarn lockfile v1/);
});

test.concurrent('should run camelised command for command with hyphens', async () => {
const stdout = await execCommand('generateLockEntry', [], 'run-generate-lock-entry');
expect(stdout[0]).toMatch(/# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY./);
expect(stdout[1]).toMatch(/# yarn lockfile v1/);
});

test.concurrent('should run help for command with hyphens', async () => {
const stdout = await execCommand('generate-lock-entry', ['--help'], 'run-generate-lock-entry');
const lastLines = stdout.slice(stdout.length - 4);
expect(lastLines[0]).toMatch(/yarn generate-lock-entry/);
expect(lastLines[1]).toMatch(/yarn generate-lock-entry --use-manifest .\/package.json/);
expect(lastLines[2]).toMatch(/yarn generate-lock-entry --resolved local-file.tgz#hash/);
expect(lastLines[3]).toMatch(/Visit https:\/\/yarnpkg.com\/en\/docs\/cli\/generate-lock-entry/);
});

test.concurrent('should run help for camelised command', async () => {
const stdout = await execCommand('generateLockEntry', ['--help'], 'run-generate-lock-entry');
const lastLines = stdout.slice(stdout.length - 4);
expect(lastLines[0]).toMatch(/yarn generate-lock-entry/);
expect(lastLines[1]).toMatch(/yarn generate-lock-entry --use-manifest .\/package.json/);
expect(lastLines[2]).toMatch(/yarn generate-lock-entry --resolved local-file.tgz#hash/);
expect(lastLines[3]).toMatch(/Visit https:\/\/yarnpkg.com\/en\/docs\/cli\/generate-lock-entry/);
});
39 changes: 3 additions & 36 deletions src/cli/aliases.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,6 @@
/* @flow */

const shorthands: { [key: string]: string } = {
c: 'config',
i: 'install',
la: 'list',
ll: 'list',
ln: 'link',
ls: 'list',
r: 'remove',
rb: 'rebuild',
rm: 'remove',
t: 'test',
tst: 'test',
un: 'remove',
up: 'upgrade',
v: 'version',
};

const affordances: { [key: string]: string } = {
'add-user': 'login',
adduser: 'login',
author: 'owner',
'dist-tag': 'tag',
'dist-tags': 'tag',
isntall: 'install',
'run-script': 'run',
runScript: 'run',
show: 'info',
uninstall: 'remove',
update: 'upgrade',
verison: 'version',
view: 'info',
};

export default ({
...shorthands,
...affordances,
export default({
'upgrade-interactive': 'upgradeInteractive',
'generate-lock-entry': 'generateLockEntry',
}: { [key: string]: string });
17 changes: 6 additions & 11 deletions src/cli/commands/help.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
/* @flow */

import * as commands from './index.js';
import commands from './index.js';
import * as constants from '../../constants.js';
import type {Reporter} from '../../reporters/index.js';
import type Config from '../../config.js';
import {sortAlpha, hyphenate, camelCase} from '../../util/misc.js';
import {sortAlpha, hyphenate} from '../../util/misc.js';
const chalk = require('chalk');

export function hasWrapper(): boolean {
Expand All @@ -17,15 +17,10 @@ export function run(
commander: Object,
args: Array<string>,
): Promise<void> {
const getDocsLink = (name) => `${constants.YARN_DOCS}${name || ''}`;
const getDocsInfo = (name) => 'Visit ' + chalk.bold(getDocsLink(name)) + ' for documentation about this command.';

if (args.length) {
const commandName = camelCase(args.shift());

if (commandName) {
const commandName = args.shift();
if (Object.prototype.hasOwnProperty.call(commands, commandName)) {
const command = commands[commandName];

if (command) {
if (typeof command.setFlags === 'function') {
command.setFlags(commander);
Expand All @@ -41,15 +36,15 @@ export function run(
console.log();
});
}
commander.on('--help', () => console.log(' ' + getDocsInfo(commandName) + '\n'));

commander.on('--help', () => console.log(' ' + command.getDocsInfo + '\n'));
commander.help();
return Promise.resolve();
}
}
}

commander.on('--help', () => {
const getDocsLink = (name) => `${constants.YARN_DOCS}${name || ''}`;
console.log(' Commands:\n');
for (const name of Object.keys(commands).sort(sortAlpha)) {
if (commands[name].useless) {
Expand Down
109 changes: 73 additions & 36 deletions src/cli/commands/index.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,86 @@
/* @flow */
import {ConsoleReporter, JSONReporter} from '../../reporters/index.js';
import * as constants from '../../constants.js';
import {MessageError} from '../../errors.js';
import Config from '../../config.js';

import * as access from './access.js'; export {access};
import * as add from './add.js'; export {add};
import * as bin from './bin.js'; export {bin};
import * as cache from './cache.js'; export {cache};
import * as check from './check.js'; export {check};
import * as clean from './clean.js'; export {clean};
import * as config from './config.js'; export {config};
import * as generateLockEntry from './generate-lock-entry.js'; export {generateLockEntry};
import * as global from './global.js'; export {global};
import * as help from './help.js'; export {help};
import * as import_ from './import.js'; export {import_ as import};
import * as info from './info.js'; export {info};
import * as init from './init.js'; export {init};
import * as install from './install.js'; export {install};
import * as licenses from './licenses.js'; export {licenses};
import * as link from './link.js'; export {link};
import * as login from './login.js'; export {login};
import * as logout from './logout.js'; export {logout};
import * as list from './list.js'; export {list};
import * as outdated from './outdated.js'; export {outdated};
import * as owner from './owner.js'; export {owner};
import * as pack from './pack.js'; export {pack};
import * as publish from './publish.js'; export {publish};
import * as remove from './remove.js'; export {remove};
import * as run from './run.js'; export {run};
import * as tag from './tag.js'; export {tag};
import * as team from './team.js'; export {team};
import * as unlink from './unlink.js'; export {unlink};
import * as upgrade from './upgrade.js'; export {upgrade};
import * as version from './version.js'; export {version};
import * as versions from './versions.js'; export {versions};
import * as why from './why.js'; export {why};
import * as upgradeInteractive from './upgrade-interactive.js'; export {upgradeInteractive};
const chalk = require('chalk');

const getDocsLink = (name) => `${constants.YARN_DOCS}${name || ''}`;
const getDocsInfo = (name) => 'Visit ' + chalk.bold(getDocsLink(name)) + ' for documentation about this command.';

const commands = {};

import * as access from './access.js'; commands['access'] = access;
import * as add from './add.js'; commands['add'] = add;
import * as bin from './bin.js'; commands['bin'] = bin;
import * as cache from './cache.js'; commands['cache'] = cache;
import * as check from './check.js'; commands['check'] = check;
import * as clean from './clean.js'; commands['clean'] = clean;
import * as config from './config.js'; commands['config'] = config;
import * as generateLockEntry from './generate-lock-entry.js'; commands['generateLockEntry'] = generateLockEntry;
import * as global from './global.js'; commands['global'] = global;
import * as help from './help.js'; commands['help'] = help;
import * as import_ from './import.js'; commands['import'] = import_;
import * as info from './info.js'; commands['info'] = info;
import * as init from './init.js'; commands['init'] = init;
import * as install from './install.js'; commands['install'] = install;
import * as licenses from './licenses.js'; commands['licenses'] = licenses;
import * as link from './link.js'; commands['link'] = link;
import * as login from './login.js'; commands['login'] = login;
import * as logout from './logout.js'; commands['logout'] = logout;
import * as list from './list.js'; commands['list'] = list;
import * as outdated from './outdated.js'; commands['outdated'] = outdated;
import * as owner from './owner.js'; commands['owner'] = owner;
import * as pack from './pack.js'; commands['pack'] = pack;
import * as publish from './publish.js'; commands['publish'] = publish;
import * as remove from './remove.js'; commands['remove'] = remove;
import * as run from './run.js'; commands['run'] = run;
import * as tag from './tag.js'; commands['tag'] = tag;
import * as team from './team.js'; commands['team'] = team;
import * as unlink from './unlink.js'; commands['unlink'] = unlink;
import * as upgrade from './upgrade.js'; commands['upgrade'] = upgrade;
import * as version from './version.js'; commands['version'] = version;
import * as versions from './versions.js'; commands['versions'] = versions;
import * as why from './why.js'; commands['why'] = why;
import * as upgradeInteractive from './upgrade-interactive.js'; commands['upgradeInteractive'] = upgradeInteractive;

import buildUseless from './_useless.js';

export const lockfile = buildUseless(
commands['lockfile'] = buildUseless(
"The lockfile command isn't necessary. `yarn install` will produce a lockfile.",
);

export const dedupe = buildUseless(
commands['dedupe'] = buildUseless(
"The dedupe command isn't necessary. `yarn install` will already dedupe.",
);

export const prune = buildUseless(
commands['prune'] = buildUseless(
"The prune command isn't necessary. `yarn install` will prune extraneous packages.",
);

for (const key in commands) {
commands[key].getDocsInfo = getDocsInfo(key);
}

import aliases from '../aliases.js';

for (const key in aliases) {
commands[key] = commands[aliases[key]];
commands[key].getDocsInfo = getDocsInfo(key);
}

import unsupportedAliases from '../unsupported-aliases.js';

for (const key in unsupportedAliases) {
commands[key] = {
run(config: Config, reporter: ConsoleReporter | JSONReporter): Promise<void> {
throw new MessageError(`Did you mean \`yarn ${unsupportedAliases[key]}\`?`);
},
getDocsInfo: getDocsInfo(unsupportedAliases[key]),
};
}

export default ({
...commands,
}: { [key: string]: Object });
Loading

0 comments on commit e5a91fa

Please sign in to comment.