Skip to content

Commit 782d8fa

Browse files
committed
fix(no-test-callback): provide suggestion instead of autofix
1 parent f70612d commit 782d8fa

File tree

2 files changed

+207
-98
lines changed

2 files changed

+207
-98
lines changed
+136-33
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TSESLint } from '@typescript-eslint/experimental-utils';
2+
import dedent from 'dedent';
23
import resolveFrom from 'resolve-from';
34
import rule from '../no-test-callback';
45

@@ -30,37 +31,127 @@ ruleTester.run('no-test-callback', rule, {
3031
},
3132
{
3233
code: 'test("something", done => {done();})',
33-
errors: [{ messageId: 'illegalTestCallback', line: 1, column: 19 }],
34-
output:
35-
'test("something", () => {return new Promise(done => {done();})})',
34+
errors: [
35+
{
36+
messageId: 'illegalTestCallback',
37+
line: 1,
38+
column: 19,
39+
suggestions: [
40+
{
41+
messageId: 'suggestWrappingInPromise',
42+
data: { callback: 'done' },
43+
output:
44+
'test("something", () => {return new Promise(done => {done();})})',
45+
},
46+
],
47+
},
48+
],
49+
},
50+
{
51+
code: 'test("something", finished => {finished();})',
52+
errors: [
53+
{
54+
messageId: 'illegalTestCallback',
55+
line: 1,
56+
column: 19,
57+
suggestions: [
58+
{
59+
messageId: 'suggestWrappingInPromise',
60+
data: { callback: 'finished' },
61+
output:
62+
'test("something", () => {return new Promise(finished => {finished();})})',
63+
},
64+
],
65+
},
66+
],
3667
},
3768
{
3869
code: 'test("something", (done) => {done();})',
39-
errors: [{ messageId: 'illegalTestCallback', line: 1, column: 20 }],
40-
output:
41-
'test("something", () => {return new Promise((done) => {done();})})',
70+
errors: [
71+
{
72+
messageId: 'illegalTestCallback',
73+
line: 1,
74+
column: 20,
75+
suggestions: [
76+
{
77+
messageId: 'suggestWrappingInPromise',
78+
data: { callback: 'done' },
79+
output:
80+
'test("something", () => {return new Promise((done) => {done();})})',
81+
},
82+
],
83+
},
84+
],
4285
},
4386
{
4487
code: 'test("something", done => done())',
45-
errors: [{ messageId: 'illegalTestCallback', line: 1, column: 19 }],
46-
output: 'test("something", () => new Promise(done => done()))',
88+
errors: [
89+
{
90+
messageId: 'illegalTestCallback',
91+
line: 1,
92+
column: 19,
93+
suggestions: [
94+
{
95+
messageId: 'suggestWrappingInPromise',
96+
data: { callback: 'done' },
97+
output: 'test("something", () => new Promise(done => done()))',
98+
},
99+
],
100+
},
101+
],
47102
},
48103
{
49104
code: 'test("something", (done) => done())',
50-
errors: [{ messageId: 'illegalTestCallback', line: 1, column: 20 }],
51-
output: 'test("something", () => new Promise((done) => done()))',
105+
errors: [
106+
{
107+
messageId: 'illegalTestCallback',
108+
line: 1,
109+
column: 20,
110+
suggestions: [
111+
{
112+
messageId: 'suggestWrappingInPromise',
113+
data: { callback: 'done' },
114+
output: 'test("something", () => new Promise((done) => done()))',
115+
},
116+
],
117+
},
118+
],
52119
},
53120
{
54121
code: 'test("something", function(done) {done();})',
55-
errors: [{ messageId: 'illegalTestCallback', line: 1, column: 28 }],
56-
output:
57-
'test("something", function() {return new Promise((done) => {done();})})',
122+
errors: [
123+
{
124+
messageId: 'illegalTestCallback',
125+
line: 1,
126+
column: 28,
127+
suggestions: [
128+
{
129+
messageId: 'suggestWrappingInPromise',
130+
data: { callback: 'done' },
131+
output:
132+
'test("something", function() {return new Promise((done) => {done();})})',
133+
},
134+
],
135+
},
136+
],
58137
},
59138
{
60139
code: 'test("something", function (done) {done();})',
61-
errors: [{ messageId: 'illegalTestCallback', line: 1, column: 29 }],
62-
output:
63-
'test("something", function () {return new Promise((done) => {done();})})',
140+
errors: [
141+
{
142+
messageId: 'illegalTestCallback',
143+
line: 1,
144+
column: 29,
145+
suggestions: [
146+
{
147+
messageId: 'suggestWrappingInPromise',
148+
data: { callback: 'done' },
149+
output:
150+
'test("something", function () {return new Promise((done) => {done();})})',
151+
},
152+
],
153+
},
154+
],
64155
},
65156
{
66157
code: 'test("something", async done => {done();})',
@@ -75,27 +166,39 @@ ruleTester.run('no-test-callback', rule, {
75166
errors: [{ messageId: 'useAwaitInsteadOfCallback', line: 1, column: 35 }],
76167
},
77168
{
78-
code: `
79-
test('my test', async (done) => {
80-
await myAsyncTask();
81-
expect(true).toBe(false);
82-
done();
83-
});
169+
code: dedent`
170+
test('my test', async (done) => {
171+
await myAsyncTask();
172+
expect(true).toBe(false);
173+
done();
174+
});
84175
`,
85-
errors: [{ messageId: 'useAwaitInsteadOfCallback', line: 2, column: 30 }],
176+
errors: [{ messageId: 'useAwaitInsteadOfCallback', line: 1, column: 24 }],
86177
},
87178
{
88-
code: `
89-
test('something', (done) => {
90-
done();
91-
});
92-
`,
93-
errors: [{ messageId: 'illegalTestCallback', line: 2, column: 26 }],
94-
output: `
95-
test('something', () => {return new Promise((done) => {
96-
done();
97-
})});
179+
code: dedent`
180+
test('something', (done) => {
181+
done();
182+
});
98183
`,
184+
errors: [
185+
{
186+
messageId: 'illegalTestCallback',
187+
line: 1,
188+
column: 20,
189+
suggestions: [
190+
{
191+
messageId: 'suggestWrappingInPromise',
192+
data: { callback: 'done' },
193+
output: dedent`
194+
test('something', () => {return new Promise((done) => {
195+
done();
196+
})});
197+
`,
198+
},
199+
],
200+
},
201+
],
99202
},
100203
],
101204
});

src/rules/no-test-callback.ts

+71-65
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export default createRule({
1111
},
1212
messages: {
1313
illegalTestCallback: 'Illegal usage of test callback',
14+
suggestWrappingInPromise: 'Wrap in `new Promise({{ callback }} => ...`',
1415
useAwaitInsteadOfCallback:
1516
'Use await instead of callback in async functions',
1617
},
@@ -55,71 +56,76 @@ export default createRule({
5556
context.report({
5657
node: argument,
5758
messageId: 'illegalTestCallback',
58-
fix(fixer) {
59-
const { body } = callback;
60-
61-
/* istanbul ignore if https://github.com/typescript-eslint/typescript-eslint/issues/734 */
62-
if (!body) {
63-
throw new Error(
64-
`Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`,
65-
);
66-
}
67-
68-
const sourceCode = context.getSourceCode();
69-
const firstBodyToken = sourceCode.getFirstToken(body);
70-
const lastBodyToken = sourceCode.getLastToken(body);
71-
const tokenBeforeArgument = sourceCode.getTokenBefore(argument);
72-
const tokenAfterArgument = sourceCode.getTokenAfter(argument);
73-
74-
/* istanbul ignore if */
75-
if (
76-
!('name' in argument) ||
77-
!firstBodyToken ||
78-
!lastBodyToken ||
79-
!tokenBeforeArgument ||
80-
!tokenAfterArgument
81-
) {
82-
throw new Error(
83-
`Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`,
84-
);
85-
}
86-
87-
const argumentInParens =
88-
tokenBeforeArgument.value === '(' &&
89-
tokenAfterArgument.value === ')';
90-
91-
let argumentFix = fixer.replaceText(argument, '()');
92-
93-
if (argumentInParens) {
94-
argumentFix = fixer.remove(argument);
95-
}
96-
97-
let newCallback = argument.name;
98-
99-
if (argumentInParens) {
100-
newCallback = `(${newCallback})`;
101-
}
102-
103-
let beforeReplacement = `new Promise(${newCallback} => `;
104-
let afterReplacement = ')';
105-
let replaceBefore = true;
106-
107-
if (body.type === AST_NODE_TYPES.BlockStatement) {
108-
const keyword = 'return';
109-
110-
beforeReplacement = `${keyword} ${beforeReplacement}{`;
111-
afterReplacement += '}';
112-
replaceBefore = false;
113-
}
114-
115-
return [
116-
argumentFix,
117-
replaceBefore
118-
? fixer.insertTextBefore(firstBodyToken, beforeReplacement)
119-
: fixer.insertTextAfter(firstBodyToken, beforeReplacement),
120-
fixer.insertTextAfter(lastBodyToken, afterReplacement),
121-
];
122-
},
59+
suggest: [
60+
{
61+
messageId: 'suggestWrappingInPromise',
62+
data: { callback: argument.name },
63+
fix(fixer) {
64+
const { body } = callback;
65+
66+
/* istanbul ignore if https://github.com/typescript-eslint/typescript-eslint/issues/734 */
67+
if (!body) {
68+
throw new Error(
69+
`Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`,
70+
);
71+
}
72+
73+
const sourceCode = context.getSourceCode();
74+
const firstBodyToken = sourceCode.getFirstToken(body);
75+
const lastBodyToken = sourceCode.getLastToken(body);
76+
const tokenBeforeArgument = sourceCode.getTokenBefore(argument);
77+
const tokenAfterArgument = sourceCode.getTokenAfter(argument);
78+
79+
/* istanbul ignore if */
80+
if (
81+
!firstBodyToken ||
82+
!lastBodyToken ||
83+
!tokenBeforeArgument ||
84+
!tokenAfterArgument
85+
) {
86+
throw new Error(
87+
`Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`,
88+
);
89+
}
90+
91+
const argumentInParens =
92+
tokenBeforeArgument.value === '(' &&
93+
tokenAfterArgument.value === ')';
94+
95+
let argumentFix = fixer.replaceText(argument, '()');
96+
97+
if (argumentInParens) {
98+
argumentFix = fixer.remove(argument);
99+
}
100+
101+
let newCallback = argument.name;
102+
103+
if (argumentInParens) {
104+
newCallback = `(${newCallback})`;
105+
}
106+
107+
let beforeReplacement = `new Promise(${newCallback} => `;
108+
let afterReplacement = ')';
109+
let replaceBefore = true;
110+
111+
if (body.type === AST_NODE_TYPES.BlockStatement) {
112+
const keyword = 'return';
113+
114+
beforeReplacement = `${keyword} ${beforeReplacement}{`;
115+
afterReplacement += '}';
116+
replaceBefore = false;
117+
}
118+
119+
return [
120+
argumentFix,
121+
replaceBefore
122+
? fixer.insertTextBefore(firstBodyToken, beforeReplacement)
123+
: fixer.insertTextAfter(firstBodyToken, beforeReplacement),
124+
fixer.insertTextAfter(lastBodyToken, afterReplacement),
125+
];
126+
},
127+
},
128+
],
123129
});
124130
},
125131
};

0 commit comments

Comments
 (0)