Skip to content

Commit aaa65fe

Browse files
committed
fix(prefer-mock-return-shorthand): don't report mutable implementations (#1908)
1 parent 48aa682 commit aaa65fe

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
@@ -75,6 +75,21 @@ export default createEslintRule<Options, MESSAGE_IDS>({
7575
return
7676
}
7777

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

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

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,56 @@ ruleTester.run(RULE_NAME, rule, {
5757
});
5858
`,
5959
'aVariable.mockReturnValue(Promise.all([1, 2, 3]));',
60+
`
61+
let currentX = 0;
62+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
63+
64+
// stuff happens
65+
66+
currentX++;
67+
68+
// more stuff happens
69+
`,
70+
`
71+
let currentX = 0;
72+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
73+
`,
74+
`
75+
let currentX = 0;
76+
currentX = 0;
77+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
78+
`,
79+
`
80+
var currentX = 0;
81+
currentX = 0;
82+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
83+
`,
84+
`
85+
var currentX = 0;
86+
var currentX = 0;
87+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
88+
`,
89+
`
90+
let doSomething = () => {};
91+
92+
jest.spyOn(X, getCount).mockImplementation(() => doSomething);
93+
`,
94+
`
95+
let currentX = 0;
96+
jest.spyOn(X, getCount).mockImplementation(() => {
97+
currentX += 1;
98+
99+
return currentX;
100+
});
101+
`,
102+
`
103+
const currentX = 0;
104+
jest.spyOn(X, getCount).mockImplementation(() => {
105+
console.log('returning', currentX);
106+
107+
return currentX;
108+
});
109+
`,
60110
],
61111

62112
invalid: [
@@ -404,5 +454,111 @@ ruleTester.run(RULE_NAME, rule, {
404454
},
405455
],
406456
},
457+
{
458+
code: `
459+
const currentX = 0;
460+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
461+
`.trim(),
462+
output: `
463+
const currentX = 0;
464+
jest.spyOn(X, getCount).mockReturnValue(currentX);
465+
`.trim(),
466+
errors: [
467+
{
468+
messageId: 'useMockShorthand',
469+
data: { replacement: 'mockReturnValue' },
470+
column: 33,
471+
line: 2,
472+
},
473+
],
474+
},
475+
// currently we assume that exported stuff is immutable, since that
476+
// is generally considered a bad idea especially when testing
477+
{
478+
code: `
479+
import { currentX } from './elsewhere';
480+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
481+
`.trim(),
482+
output: `
483+
import { currentX } from './elsewhere';
484+
jest.spyOn(X, getCount).mockReturnValue(currentX);
485+
`.trim(),
486+
errors: [
487+
{
488+
messageId: 'useMockShorthand',
489+
data: { replacement: 'mockReturnValue' },
490+
column: 33,
491+
line: 2,
492+
},
493+
],
494+
},
495+
{
496+
code: `
497+
const currentX = 0;
498+
499+
describe('some tests', () => {
500+
it('works', () => {
501+
jest.spyOn(X, getCount).mockImplementation(() => currentX);
502+
});
503+
});
504+
`.trim(),
505+
output: `
506+
const currentX = 0;
507+
508+
describe('some tests', () => {
509+
it('works', () => {
510+
jest.spyOn(X, getCount).mockReturnValue(currentX);
511+
});
512+
});
513+
`.trim(),
514+
errors: [
515+
{
516+
messageId: 'useMockShorthand',
517+
data: { replacement: 'mockReturnValue' },
518+
column: 37,
519+
line: 5,
520+
},
521+
],
522+
},
523+
{
524+
code: `
525+
function doSomething() {};
526+
527+
jest.spyOn(X, getCount).mockImplementation(() => doSomething);
528+
`.trim(),
529+
output: `
530+
function doSomething() {};
531+
532+
jest.spyOn(X, getCount).mockReturnValue(doSomething);
533+
`.trim(),
534+
errors: [
535+
{
536+
messageId: 'useMockShorthand',
537+
data: { replacement: 'mockReturnValue' },
538+
column: 33,
539+
line: 3,
540+
},
541+
],
542+
},
543+
{
544+
code: `
545+
const doSomething = () => {};
546+
547+
jest.spyOn(X, getCount).mockImplementation(() => doSomething);
548+
`.trim(),
549+
output: `
550+
const doSomething = () => {};
551+
552+
jest.spyOn(X, getCount).mockReturnValue(doSomething);
553+
`.trim(),
554+
errors: [
555+
{
556+
messageId: 'useMockShorthand',
557+
data: { replacement: 'mockReturnValue' },
558+
column: 33,
559+
line: 3,
560+
},
561+
],
562+
},
407563
],
408564
})

0 commit comments

Comments
 (0)