From f45ddad786160422e08b54ff518016ef496c996d Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 16:12:54 -0700 Subject: [PATCH 01/15] feat(core): Implement footer-contains rules --- .../core/src/library/ensure-contains.js | 9 +++++ .../core/src/library/ensure-contains.test.js | 17 ++++++++++ @commitlint/core/src/rules/footer-contains.js | 20 +++++++++++ .../core/src/rules/footer-contains.test.js | 33 +++++++++++++++++++ @commitlint/core/src/rules/index.js | 1 + 5 files changed, 80 insertions(+) create mode 100644 @commitlint/core/src/library/ensure-contains.js create mode 100644 @commitlint/core/src/library/ensure-contains.test.js create mode 100644 @commitlint/core/src/rules/footer-contains.js create mode 100644 @commitlint/core/src/rules/footer-contains.test.js diff --git a/@commitlint/core/src/library/ensure-contains.js b/@commitlint/core/src/library/ensure-contains.js new file mode 100644 index 0000000000..331f877ef3 --- /dev/null +++ b/@commitlint/core/src/library/ensure-contains.js @@ -0,0 +1,9 @@ +export default (value, regex) => { + if (value === undefined) { + return false; + } + if (!regex instanceof RegExp) { + return false; + } + return regex.test(value); +}; diff --git a/@commitlint/core/src/library/ensure-contains.test.js b/@commitlint/core/src/library/ensure-contains.test.js new file mode 100644 index 0000000000..fb78ffeb33 --- /dev/null +++ b/@commitlint/core/src/library/ensure-contains.test.js @@ -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); +}); \ No newline at end of file diff --git a/@commitlint/core/src/rules/footer-contains.js b/@commitlint/core/src/rules/footer-contains.js new file mode 100644 index 0000000000..de9bf8c746 --- /dev/null +++ b/@commitlint/core/src/rules/footer-contains.js @@ -0,0 +1,20 @@ +import ensureContains from '../library/ensure-contains'; +import message from '../library/message'; + +export default (parsed, when, value) => { + if (!parsed.scope) { + return [true, '']; + } + + const negated = when === 'never'; + const result = value.length === 0 || ensureContains(parsed.scope, value); + + return [ + negated ? !result : result, + message([ + `footer content must`, + negated ? `not` : null, + `pass the regular expression: ${value.toString()}` + ]) + ]; +}; diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js new file mode 100644 index 0000000000..e23f7782ba --- /dev/null +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -0,0 +1,33 @@ +import test from 'ava'; +import parse from '../library/parse'; +import footerContains from './footer-contains'; + +const messages = { + empty: 'foo(bar): baz', + matched: 'foo(bar): baz\n\nbody\n\nqux', + unmatched: 'foo(bar): baz\n\nbody\n\nquux' +}; + +const parsed = { + empty: parse(messages.empty), + matched: parse(messages.matched), + unmatched: parse(messages.unmatched) +}; + +test('footer-contains with no footer should not succeed', async t => { + const [actual] = footerContains(await parsed.empty, 'always', []); + const expected = false; + t.deepEqual(actual, expected); +}); + +test('footer-contains with matching footer should succeed', async t => { + const [actual] = footerContains(await parsed.matched, 'never', []); + 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, 'never', []); + const expected = false; + t.deepEqual(actual, expected); +}); \ No newline at end of file diff --git a/@commitlint/core/src/rules/index.js b/@commitlint/core/src/rules/index.js index 4d62e894b8..34d47ee25c 100644 --- a/@commitlint/core/src/rules/index.js +++ b/@commitlint/core/src/rules/index.js @@ -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'), From 8059f711504b374adae2f790258cd0cd2d7a8d94 Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 16:27:36 -0700 Subject: [PATCH 02/15] test: fix no-unsafe-negation violation --- @commitlint/core/src/library/ensure-contains.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/@commitlint/core/src/library/ensure-contains.js b/@commitlint/core/src/library/ensure-contains.js index 331f877ef3..55b7a0e279 100644 --- a/@commitlint/core/src/library/ensure-contains.js +++ b/@commitlint/core/src/library/ensure-contains.js @@ -2,7 +2,7 @@ export default (value, regex) => { if (value === undefined) { return false; } - if (!regex instanceof RegExp) { + if (!(regex instanceof RegExp)) { return false; } return regex.test(value); From fcb93f97ccfaec5f65d3ed9c61f3715666ec6a1b Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 16:38:41 -0700 Subject: [PATCH 03/15] test: fix broken tests --- @commitlint/core/src/rules/footer-contains.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index e23f7782ba..ac0eb21b44 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -15,19 +15,19 @@ const parsed = { }; test('footer-contains with no footer should not succeed', async t => { - const [actual] = footerContains(await parsed.empty, 'always', []); + 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, 'never', []); + const [actual] = footerContains(await parsed.matched, 'always', /^qux/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, 'never', []); + const [actual] = footerContains(await parsed.unmatched, 'always', /^qux/gi); const expected = false; t.deepEqual(actual, expected); }); \ No newline at end of file From 79008e1db1f1d583be325fbe19ceb3ae75338d7d Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 16:44:30 -0700 Subject: [PATCH 04/15] test: fix broken tests --- @commitlint/core/src/rules/footer-contains.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index ac0eb21b44..ae96e55bfe 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -15,19 +15,19 @@ const parsed = { }; test('footer-contains with no footer should not succeed', async t => { - const [actual] = footerContains(await parsed.empty, 'always', /^qux/gi); + 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', /^qux/gi); + const [actual] = footerContains(await parsed.matched, 'always', /qux/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 [actual] = footerContains(await parsed.unmatched, 'always', /qux/gi); const expected = false; t.deepEqual(actual, expected); }); \ No newline at end of file From 0e45d859b85f3c6f68fb68e3e7258ce840068dfe Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 17:09:09 -0700 Subject: [PATCH 05/15] test: fix broken tests --- @commitlint/core/src/rules/footer-contains.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index ae96e55bfe..fcd0391f3b 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -15,19 +15,19 @@ const parsed = { }; test('footer-contains with no footer should not succeed', async t => { - const [actual] = footerContains(await parsed.empty, 'always', /qux/gi); + 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', /qux/gi); + const [actual] = footerContains(await parsed.matched, 'always', /qux$/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 [actual] = footerContains(await parsed.unmatched, 'always', /qux$/gi); const expected = false; t.deepEqual(actual, expected); -}); \ No newline at end of file +}); From c6700a9caa00c638418b68067e00407a954c0c25 Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 17:15:48 -0700 Subject: [PATCH 06/15] test: debug broken test --- @commitlint/core/src/rules/footer-contains.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index fcd0391f3b..92769c6283 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -4,7 +4,7 @@ import footerContains from './footer-contains'; const messages = { empty: 'foo(bar): baz', - matched: 'foo(bar): baz\n\nbody\n\nqux', + matched: 'foo(bar): baz\n\nbody\nqux', unmatched: 'foo(bar): baz\n\nbody\n\nquux' }; @@ -22,8 +22,8 @@ test('footer-contains with no footer should not succeed', async t => { test('footer-contains with matching footer should succeed', async t => { const [actual] = footerContains(await parsed.matched, 'always', /qux$/gi); - const expected = true; - t.deepEqual(actual, expected); + // Const expected = true; + t.deepEqual(actual, await parsed.matched); }); test('footer-contains with non-matching footer should not succeed', async t => { From 884892052ea84b7249c80141a7387f2aff08cd7a Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 17:28:56 -0700 Subject: [PATCH 07/15] test: fix broken test --- @commitlint/core/src/rules/footer-contains.js | 6 +----- @commitlint/core/src/rules/footer-contains.test.js | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.js b/@commitlint/core/src/rules/footer-contains.js index de9bf8c746..6dc96681d8 100644 --- a/@commitlint/core/src/rules/footer-contains.js +++ b/@commitlint/core/src/rules/footer-contains.js @@ -2,12 +2,8 @@ import ensureContains from '../library/ensure-contains'; import message from '../library/message'; export default (parsed, when, value) => { - if (!parsed.scope) { - return [true, '']; - } - const negated = when === 'never'; - const result = value.length === 0 || ensureContains(parsed.scope, value); + const result = value.length === 0 || ensureContains(parsed.footer, value); return [ negated ? !result : result, diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index 92769c6283..ad69632237 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -4,7 +4,7 @@ import footerContains from './footer-contains'; const messages = { empty: 'foo(bar): baz', - matched: 'foo(bar): baz\n\nbody\nqux', + matched: 'foo(bar): baz\n\nbody\n\nqux', unmatched: 'foo(bar): baz\n\nbody\n\nquux' }; From 55a74b2036472455e2c82fc0ff63cdbf8e5316e9 Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 17:31:02 -0700 Subject: [PATCH 08/15] docs: update refrence-rules.md --- docs/reference-rules.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/reference-rules.md b/docs/reference-rules.md index ead3a886a5..118f015ed0 100644 --- a/docs/reference-rules.md +++ b/docs/reference-rules.md @@ -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` From a4b84081a4a85fb58dc98738bd09216992df9745 Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 17:37:45 -0700 Subject: [PATCH 09/15] test: fix broken test --- @commitlint/core/src/rules/footer-contains.test.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index ad69632237..2e8175ecbf 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -4,7 +4,11 @@ import footerContains from './footer-contains'; const messages = { empty: 'foo(bar): baz', - matched: 'foo(bar): baz\n\nbody\n\nqux', + matched: `foo(bar): baz + +body + +qux`, unmatched: 'foo(bar): baz\n\nbody\n\nquux' }; From af063fc3c264c20b639ff042b13bcf603a52f0f8 Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 18:23:46 -0700 Subject: [PATCH 10/15] test: fix broken test --- @commitlint/core/src/rules/footer-contains.test.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index 2e8175ecbf..629c7a05cc 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -5,11 +5,10 @@ import footerContains from './footer-contains'; const messages = { empty: 'foo(bar): baz', matched: `foo(bar): baz +bla bla bla -body - -qux`, - unmatched: 'foo(bar): baz\n\nbody\n\nquux' +PROJECT-001`, + unmatched: 'foo(bar): baz\n\nbody\n\nPROJEKT-001' }; const parsed = { From 1d38c3d97a98c61e59990029a171b9522afa7bef Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 18:34:02 -0700 Subject: [PATCH 11/15] test: fix broken test --- @commitlint/core/src/rules/footer-contains.test.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index 629c7a05cc..261fa20566 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -5,9 +5,10 @@ import footerContains from './footer-contains'; const messages = { empty: 'foo(bar): baz', matched: `foo(bar): baz -bla bla bla -PROJECT-001`, +qux + +Closes PROJECT-001`, unmatched: 'foo(bar): baz\n\nbody\n\nPROJEKT-001' }; From 0f871ca9b5e126ca57e97b3f04cb475b1bf639dd Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 18:49:08 -0700 Subject: [PATCH 12/15] test: fix broken test --- @commitlint/core/src/rules/footer-contains.test.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index 261fa20566..3f6b5fa3b1 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -4,11 +4,7 @@ import footerContains from './footer-contains'; const messages = { empty: 'foo(bar): baz', - matched: `foo(bar): baz - -qux - -Closes PROJECT-001`, + matched: 'chore: subject\nBREAKING CHANGE: something important', unmatched: 'foo(bar): baz\n\nbody\n\nPROJEKT-001' }; @@ -25,7 +21,11 @@ test('footer-contains with no footer should not succeed', async t => { }); test('footer-contains with matching footer should succeed', async t => { - const [actual] = footerContains(await parsed.matched, 'always', /qux$/gi); + const [actual] = footerContains( + await parsed.matched, + 'always', + /important$/gi + ); // Const expected = true; t.deepEqual(actual, await parsed.matched); }); From 762cdc55266ceeca3323656cd00b9e0d5416ac5d Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 18:54:31 -0700 Subject: [PATCH 13/15] test: fix broken test --- @commitlint/core/src/rules/footer-contains.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index 3f6b5fa3b1..041428d0ef 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -26,8 +26,8 @@ test('footer-contains with matching footer should succeed', async t => { 'always', /important$/gi ); - // Const expected = true; - t.deepEqual(actual, await parsed.matched); + const expected = true; + t.deepEqual(actual, expected); }); test('footer-contains with non-matching footer should not succeed', async t => { From c16b4ec948ed04326c413ad2e93b32d47edb4340 Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 19:03:06 -0700 Subject: [PATCH 14/15] test: add test for action footer --- @commitlint/core/src/rules/footer-contains.test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index 041428d0ef..f437c26f62 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -5,12 +5,15 @@ 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) }; @@ -30,6 +33,16 @@ test('footer-contains with matching footer should succeed', async t => { t.deepEqual(actual, expected); }); +test('footer-contains with alternate matching footer should succeed', async t => { + const [actual] = footerContains( + await parsed.matched, + '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; From 88336dd8672478ec23d39bd985d2ed53447a319e Mon Sep 17 00:00:00 2001 From: Nuri Hodges Date: Tue, 19 Sep 2017 22:02:07 -0700 Subject: [PATCH 15/15] test: fix test for action footer --- @commitlint/core/src/rules/footer-contains.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/@commitlint/core/src/rules/footer-contains.test.js b/@commitlint/core/src/rules/footer-contains.test.js index f437c26f62..59f1ad0eb9 100644 --- a/@commitlint/core/src/rules/footer-contains.test.js +++ b/@commitlint/core/src/rules/footer-contains.test.js @@ -35,7 +35,7 @@ test('footer-contains with matching footer should succeed', async t => { test('footer-contains with alternate matching footer should succeed', async t => { const [actual] = footerContains( - await parsed.matched, + await parsed.matchedAlt, 'always', /Closes #\d+$/gi );