Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): Implement footer-contains rules #76

Closed
wants to merge 15 commits into from
9 changes: 9 additions & 0 deletions @commitlint/core/src/library/ensure-contains.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export default (value, regex) => {
if (value === undefined) {
return false;
}
if (!(regex instanceof RegExp)) {
return false;
}
return regex.test(value);
};
17 changes: 17 additions & 0 deletions @commitlint/core/src/library/ensure-contains.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import test from 'ava';
import ensure from './ensure-contains';

test('false for no params', t => {
const actual = ensure();
t.is(actual, false);
});

test('true for /^foo/gi against foo', t => {
const actual = ensure('foo', /^foo/gi);
t.is(actual, true);
});

test('false for /^foo/gi against notfoo', t => {
const actual = ensure('notfoo', /^foo/gi);
t.is(actual, false);
});
16 changes: 16 additions & 0 deletions @commitlint/core/src/rules/footer-contains.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import ensureContains from '../library/ensure-contains';
import message from '../library/message';

export default (parsed, when, value) => {
const negated = when === 'never';
const result = value.length === 0 || ensureContains(parsed.footer, value);

return [
negated ? !result : result,
message([
`footer content must`,
negated ? `not` : null,
`pass the regular expression: ${value.toString()}`
])
];
};
50 changes: 50 additions & 0 deletions @commitlint/core/src/rules/footer-contains.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import test from 'ava';
import parse from '../library/parse';
import footerContains from './footer-contains';

const messages = {
empty: 'foo(bar): baz',
matched: 'chore: subject\nBREAKING CHANGE: something important',
matchedAlt:
'chore: subject\n\nsomething something fixed that issue\n\ncloses #1',
unmatched: 'foo(bar): baz\n\nbody\n\nPROJEKT-001'
};

const parsed = {
empty: parse(messages.empty),
matched: parse(messages.matched),
matchedAlt: parse(messages.matchedAlt),
unmatched: parse(messages.unmatched)
};

test('footer-contains with no footer should not succeed', async t => {
const [actual] = footerContains(await parsed.empty, 'always', /qux$/gi);
const expected = false;
t.deepEqual(actual, expected);
});

test('footer-contains with matching footer should succeed', async t => {
const [actual] = footerContains(
await parsed.matched,
'always',
/important$/gi
);
const expected = true;
t.deepEqual(actual, expected);
});

test('footer-contains with alternate matching footer should succeed', async t => {
const [actual] = footerContains(
await parsed.matchedAlt,
'always',
/Closes #\d+$/gi
);
const expected = true;
t.deepEqual(actual, expected);
});

test('footer-contains with non-matching footer should not succeed', async t => {
const [actual] = footerContains(await parsed.unmatched, 'always', /qux$/gi);
const expected = false;
t.deepEqual(actual, expected);
});
1 change: 1 addition & 0 deletions @commitlint/core/src/rules/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export default {
'body-max-length': require('./body-max-length'),
'body-min-length': require('./body-min-length'),
'body-tense': require('./body-tense'),
'footer-contains': require('./footer-contains'),
'footer-empty': require('./footer-empty'),
'footer-leading-blank': require('./footer-leading-blank'),
'footer-max-length': require('./footer-max-length'),
Expand Down
8 changes: 8 additions & 0 deletions docs/reference-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ Rule configurations are either of type `array` residing on a key with the rule's
]
```

#### footer-contains
* **condition**: `footer` matches regular expression
* **rules**: `always`
* **value**
```js
RegExp
```

#### footer-leading-blank
* **condition**: `footer` begins with blank line
* **rule**: `always`
Expand Down