Skip to content

Commit 6ae2bd5

Browse files
committed
Add the test-title-format rule
Fix avajs#157
1 parent ed2c1dc commit 6ae2bd5

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed

docs/rules/test-title-format.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Ensure tests have a correct title format
2+
3+
Translations:
4+
5+
Tests should have a title matching the format option.
6+
7+
8+
## Fail
9+
10+
```js
11+
/*eslint ava/test-title: ["error", {regexp: "^Should"}]*/
12+
import test from 'ava';
13+
14+
test("Not starting with 'Should'", t => {
15+
t.pass();
16+
});
17+
18+
/*eslint ava/test-title: ["error", {regexp: "\\.$"}]*/
19+
import test from 'ava';
20+
21+
test('Doesn\'t end with a dot', t => {
22+
t.pass();
23+
});
24+
```
25+
26+
27+
## Pass
28+
29+
```js
30+
/*eslint ava/test-title: ["error", {regexp: "^Should"}]*/
31+
import test from 'ava';
32+
33+
test('Should pass tests', t => {
34+
t.pass();
35+
});
36+
37+
test('Should behave as expected', t => {
38+
t.pass();
39+
});
40+
41+
/*eslint ava/test-title: ["error", {regexp: "\\.$"}]*/
42+
import test from 'ava';
43+
44+
test('End with a dot.', t => {
45+
t.pass();
46+
});
47+
```
48+
49+
## Options
50+
51+
This rule supports the following options:
52+
53+
`regexp`: A regular expression string to match against the test titles. Overrides the default and the configuration found in the `package.json` or `ava.config.js` files.
54+
55+
You can set the options like this:
56+
57+
```js
58+
"ava/test-title-format": ["error", {"regexp": "^Should"}]
59+
```

rules/test-title-format.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
const {visitIf} = require('enhance-visitors');
3+
const createAvaRule = require('../create-ava-rule');
4+
const util = require('../util');
5+
6+
const create = context => {
7+
const ava = createAvaRule();
8+
let titleRegExp;
9+
try {
10+
if (context.options[0] && context.options[0].regexp) {
11+
titleRegExp = new RegExp(context.options[0].regexp);
12+
}
13+
} catch (error) {
14+
console.warn(error);
15+
}
16+
17+
return ava.merge({
18+
CallExpression: visitIf([
19+
ava.isInTestFile,
20+
ava.isTestNode,
21+
ava.hasNoHookModifier
22+
])(node => {
23+
const requiredLength = ava.hasTestModifier('todo') ? 1 : 2;
24+
const hasTitle = node.arguments.length >= requiredLength;
25+
26+
if (hasTitle && titleRegExp) {
27+
const title = node.arguments[0];
28+
if (title.type === 'Literal' && !titleRegExp.test(title.value)) {
29+
context.report({
30+
node,
31+
message: 'Title doesn\'t match required format.'
32+
});
33+
}
34+
}
35+
})
36+
});
37+
};
38+
39+
module.exports = {
40+
create,
41+
meta: {
42+
docs: {
43+
url: util.getDocsUrl(__filename)
44+
}
45+
}
46+
};

test/test-title-format.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import test from 'ava';
2+
import avaRuleTester from 'eslint-ava-rule-tester';
3+
import rule from '../rules/test-title-format';
4+
5+
const ruleTester = avaRuleTester(test, {
6+
env: {
7+
es6: true
8+
}
9+
});
10+
11+
const errors = [{ruleId: 'test-title-format'}];
12+
const header = 'const test = require(\'ava\');\n';
13+
14+
ruleTester.run('test-title-format', rule, {
15+
valid: [
16+
header + 'test("Foo", t => { t.pass(); });',
17+
{
18+
code: header + 'test("Foo", t => { t.pass(); });',
19+
options: [{regexp: '.'}]
20+
},
21+
{
22+
code: header + 'test("Should pass tests.", t => { t.pass(); });',
23+
options: [{regexp: '^Should .+\\.$'}]
24+
},
25+
{
26+
code: header + 'test.todo("Should pass tests.");',
27+
options: [{regexp: '^Should .+\\.$'}]
28+
},
29+
{
30+
code: header + 'test(t => { t.pass(); });',
31+
options: [{regexp: '^Should'}]
32+
},
33+
{
34+
code: header + 'test("Foo", t => { t.pass(); });',
35+
options: [{regexp: '(]'}] // Invalid regexp
36+
},
37+
{
38+
code: header + 'notTest("Foo", t => { t.pass(); });',
39+
options: [{regexp: '^Should'}]
40+
},
41+
{
42+
code: header + 'test(macro, t => { t.pass(); });',
43+
options: [{regexp: '^Should'}]
44+
},
45+
// Shouldn't be triggered since it's not a test file
46+
{
47+
code: 'test("Test", t => { t.pass(); });',
48+
options: [{regexp: '^Should'}]
49+
}
50+
],
51+
invalid: [
52+
{
53+
code: header + 'test("Test something", t => { t.pass(); });',
54+
options: [{regexp: '^Should'}],
55+
errors
56+
},
57+
{
58+
code: header + 'test.todo("Test something");',
59+
options: [{regexp: '^Should'}],
60+
errors
61+
},
62+
]
63+
});

0 commit comments

Comments
 (0)