Skip to content

Commit b8c93c2

Browse files
committed
no-unknown-modifiers: Forbid .always without after/afterEach
Fixes #139
1 parent e80bcdf commit b8c93c2

3 files changed

Lines changed: 100 additions & 12 deletions

File tree

docs/rules/no-unknown-modifiers.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ import test from 'ava';
2020
test.onlu(t => {}); //
2121
test.only(t => {}); //
2222

23-
test.seril(t => {}); //
23+
test.seril(t => {}); //
2424
test.serial(t => {}); //
2525

2626
test.beforeeach(t => {}); //
2727
test.beforeEach(t => {}); //
2828

2929
test.unknown(t => {}); //
30+
31+
test.always(t => {}); // ❌ `.always` requires `after` or `afterEach`
32+
test.after.always(t => {}); //
33+
34+
test.before.always(t => {}); // ❌ `.always` requires `after` or `afterEach`
35+
test.afterEach.always(t => {}); //
3036
```

rules/no-unknown-modifiers.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import createAvaRule from '../create-ava-rule.js';
44

55
const MESSAGE_ID = 'no-unknown-modifiers';
66
const MESSAGE_ID_SUGGESTION = 'no-unknown-modifiers-suggestion';
7+
const MESSAGE_ID_ALWAYS = 'always-without-after';
8+
const MESSAGE_ID_ALWAYS_SUGGESTION = 'always-without-after-suggestion';
79

8-
const modifiers = new Set([
10+
const knownModifiers = new Set([
911
'after',
1012
'afterEach',
1113
'always',
@@ -20,9 +22,6 @@ const modifiers = new Set([
2022
'macro',
2123
]);
2224

23-
const unknownModifiers = node => util.getTestModifiers(node)
24-
.filter(modifier => !modifiers.has(modifier.name));
25-
2625
const create = context => {
2726
const ava = createAvaRule();
2827

@@ -31,16 +30,37 @@ const create = context => {
3130
ava.isInTestFile,
3231
ava.isTestNode,
3332
])(node => {
34-
for (const modifier of unknownModifiers(node)) {
33+
const testModifiers = util.getTestModifiers(node);
34+
35+
for (const modifier of testModifiers) {
36+
if (!knownModifiers.has(modifier.name)) {
37+
context.report({
38+
node: modifier,
39+
messageId: MESSAGE_ID,
40+
data: {name: modifier.name},
41+
suggest: [{
42+
messageId: MESSAGE_ID_SUGGESTION,
43+
data: {name: modifier.name},
44+
fix: fixer => fixer.replaceTextRange(...util.removeTestModifier({
45+
modifier: modifier.name,
46+
node,
47+
context,
48+
})),
49+
}],
50+
});
51+
}
52+
}
53+
54+
const alwaysModifier = testModifiers.find(modifier => modifier.name === 'always');
55+
56+
if (alwaysModifier && !testModifiers.some(modifier => modifier.name === 'after' || modifier.name === 'afterEach')) {
3557
context.report({
36-
node: modifier,
37-
messageId: MESSAGE_ID,
38-
data: {name: modifier.name},
58+
node: alwaysModifier,
59+
messageId: MESSAGE_ID_ALWAYS,
3960
suggest: [{
40-
messageId: MESSAGE_ID_SUGGESTION,
41-
data: {name: modifier.name},
61+
messageId: MESSAGE_ID_ALWAYS_SUGGESTION,
4262
fix: fixer => fixer.replaceTextRange(...util.removeTestModifier({
43-
modifier: modifier.name,
63+
modifier: 'always',
4464
node,
4565
context,
4666
})),
@@ -65,6 +85,8 @@ export default {
6585
messages: {
6686
[MESSAGE_ID]: 'Unknown test modifier `.{{name}}`.',
6787
[MESSAGE_ID_SUGGESTION]: 'Remove the `.{{name}}` modifier.',
88+
[MESSAGE_ID_ALWAYS]: 'The `.always` modifier can only be used with `after` and `afterEach` hooks.',
89+
[MESSAGE_ID_ALWAYS_SUGGESTION]: 'Remove the `.always` modifier.',
6890
},
6991
},
7092
};

test/no-unknown-modifiers.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ ruleTester.run('no-unknown-modifiers', rule, {
2828
`${header}test.todo(t => {});`,
2929
`${header}test.after.always(t => {});`,
3030
`${header}test.afterEach.always(t => {});`,
31+
`${header}test.after.always.skip(t => {});`,
3132
`${header}test.failing(t => {});`,
3233
`${header}test.macro(t => {});`,
3334
// Shouldn't be triggered since it's not a test file
@@ -120,5 +121,64 @@ ruleTester.run('no-unknown-modifiers', rule, {
120121
}],
121122
}],
122123
},
124+
{
125+
code: `${header}test.always(t => {});`,
126+
errors: [{
127+
messageId: 'always-without-after',
128+
suggestions: [{
129+
messageId: 'always-without-after-suggestion',
130+
output: `${header}test(t => {});`,
131+
}],
132+
}],
133+
},
134+
{
135+
code: `${header}test.before.always(t => {});`,
136+
errors: [{
137+
messageId: 'always-without-after',
138+
suggestions: [{
139+
messageId: 'always-without-after-suggestion',
140+
output: `${header}test.before(t => {});`,
141+
}],
142+
}],
143+
},
144+
{
145+
code: `${header}test.beforeEach.always(t => {});`,
146+
errors: [{
147+
messageId: 'always-without-after',
148+
suggestions: [{
149+
messageId: 'always-without-after-suggestion',
150+
output: `${header}test.beforeEach(t => {});`,
151+
}],
152+
}],
153+
},
154+
{
155+
code: `${header}test.serial.always(t => {});`,
156+
errors: [{
157+
messageId: 'always-without-after',
158+
suggestions: [{
159+
messageId: 'always-without-after-suggestion',
160+
output: `${header}test.serial(t => {});`,
161+
}],
162+
}],
163+
},
164+
{
165+
code: `${header}test.foo.always(t => {});`,
166+
errors: [
167+
{
168+
messageId: 'no-unknown-modifiers',
169+
suggestions: [{
170+
messageId: 'no-unknown-modifiers-suggestion',
171+
output: `${header}test.always(t => {});`,
172+
}],
173+
},
174+
{
175+
messageId: 'always-without-after',
176+
suggestions: [{
177+
messageId: 'always-without-after-suggestion',
178+
output: `${header}test.foo(t => {});`,
179+
}],
180+
},
181+
],
182+
},
123183
],
124184
});

0 commit comments

Comments
 (0)