Skip to content

Commit 8eabdf9

Browse files
Merge pull request #9 from xeptore/master
fix(scope-maker): exclude skip choice when required
2 parents 2ba90df + de49e6e commit 8eabdf9

File tree

2 files changed

+67
-9
lines changed

2 files changed

+67
-9
lines changed

src/prompts/scope-maker.test.ts

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { ListQuestion } from 'inquirer';
22
import { Rule, Case, Level, Rules } from '@commitlint/load';
3-
import { scopeMaker, filterFactory, validatorFactory } from './scope-maker';
3+
import { scopeMaker, filterFactory, validatorFactory, choicesFactory } from './scope-maker';
44

55
describe('scopeMaker', () => {
66
describe('validatorFactory', () => {
@@ -54,7 +54,7 @@ describe('scopeMaker', () => {
5454
});
5555

5656
describe('choices', () => {
57-
test('should display choices if array scope enum is present', () => {
57+
it('should display choices if array scope enum is present', () => {
5858
const scopeConfig = scopeMaker([], { 'scope-enum': [2, 'always', ['foo', 'bar']] })[0] as ListQuestion;
5959

6060
if (scopeConfig.choices) {
@@ -76,6 +76,38 @@ describe('scopeMaker', () => {
7676
});
7777
});
7878

79+
describe('choicesFactory', () => {
80+
it('should not allow non-empty scope when empty scope is required', () => {
81+
const scopeConfig = choicesFactory({
82+
'scope-empty': [2, 'always', undefined]
83+
});
84+
85+
expect(scopeConfig).toEqual([{ name: ':skip', value: '' }]);
86+
});
87+
88+
it('should not allow skipping scope when is required', () => {
89+
const scopeConfig = choicesFactory({
90+
'scope-empty': [2, 'never', undefined]
91+
});
92+
93+
expect(scopeConfig).not.toContainEqual({ name: ':skip', value: '' });
94+
});
95+
});
96+
97+
it('should allow skipping scope when "scope-empty" severity is "warn"', () => {
98+
const scopeConfig = choicesFactory({
99+
'scope-empty': [1, 'always', undefined]
100+
});
101+
102+
expect(scopeConfig).toContainEqual({ name: ':skip', value: '' });
103+
});
104+
105+
it('should allow skipping scope when "scope-empty" rule is not set', () => {
106+
const scopeConfig = choicesFactory({});
107+
108+
expect(scopeConfig).toContainEqual({ name: ':skip', value: '' });
109+
});
110+
79111
describe('filterFactory', () => {
80112
test.each<[Rule<Case>, string, string]>([
81113
[[Level.Error, 'always', 'camel-case'], 'FOO_BAR', 'fooBar'],

src/prompts/scope-maker.ts

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Rules } from '@commitlint/load';
1+
import { Rules, Level } from '@commitlint/load';
22
import { ChoiceOptions } from 'inquirer';
33
import { whenFactory } from '../when';
44
import { caseValidator, emptyValidator, maxLengthValidator, minLengthValidator, validate } from '../validators';
@@ -36,14 +36,40 @@ export function validatorFactory(rules: Rules) {
3636
};
3737
}
3838

39-
export function choicesFactory(rules: Rules) {
40-
let choices: ChoiceOptions[] | undefined;
41-
if (rules['scope-enum']) {
42-
const [, , scopeEnum] = rules['scope-enum'];
43-
if (scopeEnum && scopeEnum.length > 0) {
44-
choices = [...scopeEnum.map(scope => ({ name: scope, value: scope })), { name: ':skip', value: '' }];
39+
function parseEmptyScopeRule(rule: Rules['scope-empty']): [boolean, ChoiceOptions | undefined] {
40+
const skipChoice: ChoiceOptions = { name: ':skip', value: '' };
41+
if (rule !== undefined) {
42+
const [level, applicability] = rule;
43+
if (level === Level.Error) {
44+
if (applicability === 'always') {
45+
return [true, skipChoice];
46+
}
47+
return [false, undefined];
4548
}
4649
}
50+
return [true, skipChoice];
51+
}
52+
53+
function parseScopeEnumRule(rule: Rules['scope-enum']): [boolean, ChoiceOptions[] | undefined] {
54+
if (rule !== undefined) {
55+
const [, , scopeEnum] = rule;
56+
return [true, scopeEnum.map(scope => ({ name: scope, value: scope }))];
57+
}
58+
return [false, undefined];
59+
}
60+
61+
export function choicesFactory(rules: Rules): ChoiceOptions[] | undefined {
62+
const choices: ChoiceOptions[] = [];
63+
64+
const [containsSkipChoice, skipChoice] = parseEmptyScopeRule(rules['scope-empty']);
65+
if (containsSkipChoice) {
66+
choices.push(skipChoice as ChoiceOptions);
67+
}
68+
69+
const [containsScopeEnumChoices, scopeEnumChoices] = parseScopeEnumRule(rules['scope-enum']);
70+
if (containsScopeEnumChoices) {
71+
choices.unshift(...(scopeEnumChoices as ChoiceOptions[]));
72+
}
4773

4874
return choices;
4975
}

0 commit comments

Comments
 (0)