mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 19:13:34 +08:00
When running a command with args against multiple targets, all targets should be given the args. As parseArguments was mutating the passed args array this wasn't the case. Fix by not mutating the array. This was especially noticeable when using the `ng lint --fix` command on a newly generated project, as files in the app target would be fixed, but e2e target would be only be linted (with no fix) Possibly closes #10657, #10656, #11005
242 lines
9.9 KiB
TypeScript
242 lines
9.9 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*
|
|
*/
|
|
// tslint:disable:no-global-tslint-disable no-big-function
|
|
import { logging } from '@angular-devkit/core';
|
|
import { Arguments, Option, OptionType } from './interface';
|
|
import { ParseArgumentException, parseArguments } from './parser';
|
|
|
|
describe('parseArguments', () => {
|
|
const options: Option[] = [
|
|
{ name: 'bool', aliases: [ 'b' ], type: OptionType.Boolean, description: '' },
|
|
{ name: 'num', aliases: [ 'n' ], type: OptionType.Number, description: '' },
|
|
{ name: 'str', aliases: [ 's' ], type: OptionType.String, description: '' },
|
|
{ name: 'strUpper', aliases: [ 'S' ], type: OptionType.String, description: '' },
|
|
{ name: 'helloWorld', aliases: [], type: OptionType.String, description: '' },
|
|
{ name: 'helloBool', aliases: [], type: OptionType.Boolean, description: '' },
|
|
{ name: 'arr', aliases: [ 'a' ], type: OptionType.Array, description: '' },
|
|
{ name: 'p1', positional: 0, aliases: [], type: OptionType.String, description: '' },
|
|
{ name: 'p2', positional: 1, aliases: [], type: OptionType.String, description: '' },
|
|
{ name: 'p3', positional: 2, aliases: [], type: OptionType.Number, description: '' },
|
|
{ name: 't1', aliases: [], type: OptionType.Boolean,
|
|
types: [OptionType.Boolean, OptionType.String], description: '' },
|
|
{ name: 't2', aliases: [], type: OptionType.Boolean,
|
|
types: [OptionType.Boolean, OptionType.Number], description: '' },
|
|
{ name: 't3', aliases: [], type: OptionType.Number,
|
|
types: [OptionType.Number, OptionType.Any], description: '' },
|
|
{ name: 'e1', aliases: [], type: OptionType.String, enum: ['hello', 'world'], description: '' },
|
|
{ name: 'e2', aliases: [], type: OptionType.String, enum: ['hello', ''], description: '' },
|
|
{ name: 'e3', aliases: [], type: OptionType.Boolean,
|
|
types: [OptionType.Boolean, OptionType.String], enum: ['json', true, false],
|
|
description: '' },
|
|
];
|
|
|
|
const tests: { [test: string]: Partial<Arguments> | ['!!!', Partial<Arguments>, string[]] } = {
|
|
'-S=b': { strUpper: 'b' },
|
|
'--bool': { bool: true },
|
|
'--bool=1': ['!!!', {}, ['--bool=1']],
|
|
'--bool ': { bool: true, p1: '' },
|
|
'-- --bool=1': { '--': ['--bool=1'] },
|
|
'--bool=yellow': ['!!!', {}, ['--bool=yellow']],
|
|
'--bool=true': { bool: true },
|
|
'--bool=false': { bool: false },
|
|
'--no-bool': { bool: false },
|
|
'--no-bool=true': { '--': ['--no-bool=true'] },
|
|
'--b=true': { bool: true },
|
|
'--b=false': { bool: false },
|
|
'--b true': { bool: true },
|
|
'--b false': { bool: false },
|
|
'--bool --num': { bool: true, num: 0 },
|
|
'--bool --num=true': ['!!!', { bool: true }, ['--num=true']],
|
|
'-- --bool --num=true': { '--': ['--bool', '--num=true'] },
|
|
'--bool=true --num': { bool: true, num: 0 },
|
|
'--bool true --num': { bool: true, num: 0 },
|
|
'--bool=false --num': { bool: false, num: 0 },
|
|
'--bool false --num': { bool: false, num: 0 },
|
|
'--str false --num': { str: 'false', num: 0 },
|
|
'--str=false --num': { str: 'false', num: 0 },
|
|
'--str=false --num1': { str: 'false', '--': ['--num1'] },
|
|
'--str=false val1 --num1': { str: 'false', p1: 'val1', '--': ['--num1'] },
|
|
'--str=false val1 val2': { str: 'false', p1: 'val1', p2: 'val2' },
|
|
'--str=false val1 val2 --num1': { str: 'false', p1: 'val1', p2: 'val2', '--': ['--num1'] },
|
|
'--str=false val1 --num1 val2': { str: 'false', p1: 'val1', '--': ['--num1', 'val2'] },
|
|
'--bool --bool=false': { bool: false },
|
|
'--bool --bool=false --bool': { bool: true },
|
|
'--num=1 --num=2 --num=3': { num: 3 },
|
|
'--str=1 --str=2 --str=3': { str: '3' },
|
|
'val1 --num=1 val2': { num: 1, p1: 'val1', p2: 'val2' },
|
|
'--p1=val1 --num=1 val2': { num: 1, p1: 'val1', p2: 'val2' },
|
|
'--p1=val1 --num=1 --p2=val2 val3': { num: 1, p1: 'val1', p2: 'val2', '--': ['val3'] },
|
|
'--bool val1 --etc --num val2 --v': [
|
|
'!!!',
|
|
{ bool: true, p1: 'val1', p2: 'val2', '--': ['--etc', '--v'] },
|
|
['--num' ],
|
|
],
|
|
'--bool val1 --etc --num=1 val2 --v': { bool: true, num: 1, p1: 'val1', p2: 'val2',
|
|
'--': ['--etc', '--v'] },
|
|
'--arr=a d': { arr: ['a'], p1: 'd' },
|
|
'--arr=a --arr=b --arr c d': { arr: ['a', 'b', 'c'], p1: 'd' },
|
|
'--arr=1 --arr --arr c d': { arr: ['1', '', 'c'], p1: 'd' },
|
|
'--arr=1 --arr --arr c d e': { arr: ['1', '', 'c'], p1: 'd', p2: 'e' },
|
|
'--str=1': { str: '1' },
|
|
'--str=': { str: '' },
|
|
'--str ': { str: '' },
|
|
'--str ': { str: '', p1: '' },
|
|
'--str ': { str: '', p1: '', p2: '', '--': [''] },
|
|
'--hello-world=1': { helloWorld: '1' },
|
|
'--hello-bool': { helloBool: true },
|
|
'--helloBool': { helloBool: true },
|
|
'--no-helloBool': { helloBool: false },
|
|
'--noHelloBool': { helloBool: false },
|
|
'--noBool': { bool: false },
|
|
'-b': { bool: true },
|
|
'-b=true': { bool: true },
|
|
'-sb': { bool: true, str: '' },
|
|
'-s=b': { str: 'b' },
|
|
'-bs': { bool: true, str: '' },
|
|
'--t1=true': { t1: true },
|
|
'--t1': { t1: true },
|
|
'--t1 --num': { t1: true, num: 0 },
|
|
'--no-t1': { t1: false },
|
|
'--t1=yellow': { t1: 'yellow' },
|
|
'--no-t1=true': { '--': ['--no-t1=true'] },
|
|
'--t1=123': { t1: '123' },
|
|
'--t2=true': { t2: true },
|
|
'--t2': { t2: true },
|
|
'--no-t2': { t2: false },
|
|
'--t2=yellow': ['!!!', {}, ['--t2=yellow']],
|
|
'--no-t2=true': { '--': ['--no-t2=true'] },
|
|
'--t2=123': { t2: 123 },
|
|
'--t3=a': { t3: 'a' },
|
|
'--t3': { t3: 0 },
|
|
'--t3 true': { t3: true },
|
|
'--e1 hello': { e1: 'hello' },
|
|
'--e1=hello': { e1: 'hello' },
|
|
'--e1 yellow': ['!!!', { p1: 'yellow' }, ['--e1']],
|
|
'--e1=yellow': ['!!!', {}, ['--e1=yellow']],
|
|
'--e1': ['!!!', {}, ['--e1']],
|
|
'--e1 true': ['!!!', { p1: 'true' }, ['--e1']],
|
|
'--e1=true': ['!!!', {}, ['--e1=true']],
|
|
'--e2 hello': { e2: 'hello' },
|
|
'--e2=hello': { e2: 'hello' },
|
|
'--e2 yellow': { p1: 'yellow', e2: '' },
|
|
'--e2=yellow': ['!!!', {}, ['--e2=yellow']],
|
|
'--e2': { e2: '' },
|
|
'--e2 true': { p1: 'true', e2: '' },
|
|
'--e2=true': ['!!!', {}, ['--e2=true']],
|
|
'--e3 json': { e3: 'json' },
|
|
'--e3=json': { e3: 'json' },
|
|
'--e3 yellow': { p1: 'yellow', e3: true },
|
|
'--e3=yellow': ['!!!', {}, ['--e3=yellow']],
|
|
'--e3': { e3: true },
|
|
'--e3 true': { e3: true },
|
|
'--e3=true': { e3: true },
|
|
'a b c 1': { p1: 'a', p2: 'b', '--': ['c', '1'] },
|
|
|
|
'-p=1 -c=prod': {'--': ['-p=1', '-c=prod'] },
|
|
'--p --c': {'--': ['--p', '--c'] },
|
|
'--p=123': {'--': ['--p=123'] },
|
|
'--p -c': {'--': ['--p', '-c'] },
|
|
'-p --c': {'--': ['-p', '--c'] },
|
|
'-p --c 123': {'--': ['-p', '--c', '123'] },
|
|
'--c 123 -p': {'--': ['--c', '123', '-p'] },
|
|
};
|
|
|
|
Object.entries(tests).forEach(([str, expected]) => {
|
|
it(`works for ${str}`, () => {
|
|
try {
|
|
const originalArgs = str.split(' ');
|
|
const args = originalArgs.slice();
|
|
|
|
const actual = parseArguments(args, options);
|
|
|
|
expect(Array.isArray(expected)).toBe(false);
|
|
expect(actual).toEqual(expected as Arguments);
|
|
expect(args).toEqual(originalArgs);
|
|
} catch (e) {
|
|
if (!(e instanceof ParseArgumentException)) {
|
|
throw e;
|
|
}
|
|
|
|
// The expected values are an array.
|
|
expect(Array.isArray(expected)).toBe(true);
|
|
expect(e.parsed).toEqual(expected[1] as Arguments);
|
|
expect(e.ignored).toEqual(expected[2] as string[]);
|
|
}
|
|
});
|
|
});
|
|
|
|
it('handles deprecation', () => {
|
|
const options = [
|
|
{ name: 'bool', aliases: [], type: OptionType.Boolean, description: '' },
|
|
{ name: 'depr', aliases: [], type: OptionType.Boolean, description: '', deprecated: true },
|
|
{ name: 'deprM', aliases: [], type: OptionType.Boolean, description: '', deprecated: 'ABCD' },
|
|
];
|
|
|
|
const logger = new logging.Logger('');
|
|
const messages: string[] = [];
|
|
|
|
logger.subscribe(entry => messages.push(entry.message));
|
|
|
|
let result = parseArguments(['--bool'], options, logger);
|
|
expect(result).toEqual({ bool: true });
|
|
expect(messages).toEqual([]);
|
|
|
|
result = parseArguments(['--depr'], options, logger);
|
|
expect(result).toEqual({ depr: true });
|
|
expect(messages.length).toEqual(1);
|
|
expect(messages[0]).toMatch(/\bdepr\b/);
|
|
messages.shift();
|
|
|
|
result = parseArguments(['--depr', '--bool'], options, logger);
|
|
expect(result).toEqual({ depr: true, bool: true });
|
|
expect(messages.length).toEqual(1);
|
|
expect(messages[0]).toMatch(/\bdepr\b/);
|
|
messages.shift();
|
|
|
|
result = parseArguments(['--depr', '--bool', '--deprM'], options, logger);
|
|
expect(result).toEqual({ depr: true, deprM: true, bool: true });
|
|
expect(messages.length).toEqual(2);
|
|
expect(messages[0]).toMatch(/\bdepr\b/);
|
|
expect(messages[1]).toMatch(/\bdeprM\b/);
|
|
expect(messages[1]).toMatch(/\bABCD\b/);
|
|
messages.shift();
|
|
});
|
|
|
|
it('handles a flag being added multiple times', () => {
|
|
const options = [
|
|
{ name: 'bool', aliases: [], type: OptionType.Boolean, description: '' },
|
|
];
|
|
|
|
const logger = new logging.Logger('');
|
|
const messages: string[] = [];
|
|
|
|
logger.subscribe(entry => messages.push(entry.message));
|
|
|
|
let result = parseArguments(['--bool'], options, logger);
|
|
expect(result).toEqual({ bool: true });
|
|
expect(messages).toEqual([]);
|
|
|
|
result = parseArguments(['--bool', '--bool'], options, logger);
|
|
expect(result).toEqual({ bool: true });
|
|
expect(messages).toEqual([]);
|
|
|
|
result = parseArguments(['--bool', '--bool=false'], options, logger);
|
|
expect(result).toEqual({ bool: false });
|
|
expect(messages.length).toEqual(1);
|
|
expect(messages[0]).toMatch(/\bbool\b.*\btrue\b.*\bfalse\b/);
|
|
messages.shift();
|
|
|
|
result = parseArguments(['--bool', '--bool=false', '--bool=false'], options, logger);
|
|
expect(result).toEqual({ bool: false });
|
|
expect(messages.length).toEqual(1);
|
|
expect(messages[0]).toMatch(/\bbool\b.*\btrue\b.*\bfalse\b/);
|
|
messages.shift();
|
|
});
|
|
});
|