Skip to content

Commit 9636ae8

Browse files
authored
fix(prefer-mock-return-shorthand): don't report mutable implementations (#1908) (#855)
1 parent 1881ed0 commit 9636ae8

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

src/rules/prefer-mock-return-shorthand.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@ export default createEslintRule<Options, MESSAGE_IDS>({
7878
return
7979
}
8080

81+
// check if we're using a non-constant variable
82+
if (returnNode.type === AST_NODE_TYPES.Identifier) {
83+
const scope = context.sourceCode.getScope(returnNode)
84+
85+
const isMutable = scope.through.some((v) =>
86+
v.resolved?.defs.some(
87+
(n) => n.type === 'Variable' && n.parent.kind !== 'const',
88+
),
89+
)
90+
91+
if (isMutable) {
92+
return
93+
}
94+
}
95+
8196
context.report({
8297
node: property,
8398
messageId: 'useMockShorthand',

tests/prefer-mock-return-shorthand.test.ts

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,56 @@ ruleTester.run(RULE_NAME, rule, {
9595
});
9696
`,
9797
'aVariable.mockReturnValue(Promise.all([1, 2, 3]));',
98+
`
99+
let currentX = 0;
100+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
101+
102+
// stuff happens
103+
104+
currentX++;
105+
106+
// more stuff happens
107+
`,
108+
`
109+
let currentX = 0;
110+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
111+
`,
112+
`
113+
let currentX = 0;
114+
currentX = 0;
115+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
116+
`,
117+
`
118+
var currentX = 0;
119+
currentX = 0;
120+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
121+
`,
122+
`
123+
var currentX = 0;
124+
var currentX = 0;
125+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
126+
`,
127+
`
128+
let doSomething = () => {};
129+
130+
jest.spyOn(X, getCount).mockImplementation(() => doSomething);
131+
`,
132+
`
133+
let currentX = 0;
134+
jest.spyOn(X, getCount).mockImplementation(() => {
135+
currentX += 1;
136+
137+
return currentX;
138+
});
139+
`,
140+
`
141+
const currentX = 0;
142+
jest.spyOn(X, getCount).mockImplementation(() => {
143+
console.log('returning', currentX);
144+
145+
return currentX;
146+
});
147+
`,
98148
],
99149

100150
invalid: [
@@ -444,5 +494,111 @@ ruleTester.run(RULE_NAME, rule, {
444494
},
445495
],
446496
},
497+
{
498+
code: `
499+
const currentX = 0;
500+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
501+
`.trim(),
502+
output: `
503+
const currentX = 0;
504+
jest.spyOn(X, getCount).mockReturnValue(currentX);
505+
`.trim(),
506+
errors: [
507+
{
508+
messageId: 'useMockShorthand',
509+
data: { replacement: 'mockReturnValue' },
510+
column: 33,
511+
line: 2,
512+
},
513+
],
514+
},
515+
// currently we assume that exported stuff is immutable, since that
516+
// is generally considered a bad idea especially when testing
517+
{
518+
code: `
519+
import { currentX } from './elsewhere';
520+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
521+
`.trim(),
522+
output: `
523+
import { currentX } from './elsewhere';
524+
jest.spyOn(X, getCount).mockReturnValue(currentX);
525+
`.trim(),
526+
errors: [
527+
{
528+
messageId: 'useMockShorthand',
529+
data: { replacement: 'mockReturnValue' },
530+
column: 33,
531+
line: 2,
532+
},
533+
],
534+
},
535+
{
536+
code: `
537+
const currentX = 0;
538+
539+
describe('some tests', () => {
540+
it('works', () => {
541+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
542+
});
543+
});
544+
`.trim(),
545+
output: `
546+
const currentX = 0;
547+
548+
describe('some tests', () => {
549+
it('works', () => {
550+
jest.spyOn(X, getCount).mockReturnValue(currentX);
551+
});
552+
});
553+
`.trim(),
554+
errors: [
555+
{
556+
messageId: 'useMockShorthand',
557+
data: { replacement: 'mockReturnValue' },
558+
column: 37,
559+
line: 5,
560+
},
561+
],
562+
},
563+
{
564+
code: `
565+
function doSomething() {};
566+
567+
jest.spyOn(X, getCount).mockImplementation(() => doSomething);
568+
`.trim(),
569+
output: `
570+
function doSomething() {};
571+
572+
jest.spyOn(X, getCount).mockReturnValue(doSomething);
573+
`.trim(),
574+
errors: [
575+
{
576+
messageId: 'useMockShorthand',
577+
data: { replacement: 'mockReturnValue' },
578+
column: 33,
579+
line: 3,
580+
},
581+
],
582+
},
583+
{
584+
code: `
585+
const doSomething = () => {};
586+
587+
jest.spyOn(X, getCount).mockImplementation(() => doSomething);
588+
`.trim(),
589+
output: `
590+
const doSomething = () => {};
591+
592+
jest.spyOn(X, getCount).mockReturnValue(doSomething);
593+
`.trim(),
594+
errors: [
595+
{
596+
messageId: 'useMockShorthand',
597+
data: { replacement: 'mockReturnValue' },
598+
column: 33,
599+
line: 3,
600+
},
601+
],
602+
},
447603
],
448604
})

0 commit comments

Comments
 (0)