Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/rules/prefer-mock-return-shorthand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,21 @@ export default createEslintRule<Options, MESSAGE_IDS>({
return
}

// check if we're using a non-constant variable
if (returnNode.type === AST_NODE_TYPES.Identifier) {
const scope = context.sourceCode.getScope(returnNode)

const isMutable = scope.through.some((v) =>
v.resolved?.defs.some(
(n) => n.type === 'Variable' && n.parent.kind !== 'const',
),
)

if (isMutable) {
return
}
}

context.report({
node: property,
messageId: 'useMockShorthand',
Expand Down
156 changes: 156 additions & 0 deletions tests/prefer-mock-return-shorthand.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,56 @@ ruleTester.run(RULE_NAME, rule, {
});
`,
'aVariable.mockReturnValue(Promise.all([1, 2, 3]));',
`
let currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => currentX);

// stuff happens

currentX++;

// more stuff happens
`,
`
let currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => currentX);
`,
`
let currentX = 0;
currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => currentX);
`,
`
var currentX = 0;
currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => currentX);
`,
`
var currentX = 0;
var currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => currentX);
`,
`
let doSomething = () => {};

jest.spyOn(X, getCount).mockImplementation(() => doSomething);
`,
`
let currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => {
currentX += 1;

return currentX;
});
`,
`
const currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => {
console.log('returning', currentX);

return currentX;
});
`,
],

invalid: [
Expand Down Expand Up @@ -404,5 +454,111 @@ ruleTester.run(RULE_NAME, rule, {
},
],
},
{
code: `
const currentX = 0;
jest.spyOn(X, getCount).mockImplementation(() => currentX);
`.trim(),
output: `
const currentX = 0;
jest.spyOn(X, getCount).mockReturnValue(currentX);
`.trim(),
errors: [
{
messageId: 'useMockShorthand',
data: { replacement: 'mockReturnValue' },
column: 33,
line: 2,
},
],
},
// currently we assume that exported stuff is immutable, since that
// is generally considered a bad idea especially when testing
{
code: `
import { currentX } from './elsewhere';
jest.spyOn(X, getCount).mockImplementation(() => currentX);
`.trim(),
output: `
import { currentX } from './elsewhere';
jest.spyOn(X, getCount).mockReturnValue(currentX);
`.trim(),
errors: [
{
messageId: 'useMockShorthand',
data: { replacement: 'mockReturnValue' },
column: 33,
line: 2,
},
],
},
{
code: `
const currentX = 0;

describe('some tests', () => {
it('works', () => {
jest.spyOn(X, getCount).mockImplementation(() => currentX);
});
});
`.trim(),
output: `
const currentX = 0;

describe('some tests', () => {
it('works', () => {
jest.spyOn(X, getCount).mockReturnValue(currentX);
});
});
`.trim(),
errors: [
{
messageId: 'useMockShorthand',
data: { replacement: 'mockReturnValue' },
column: 37,
line: 5,
},
],
},
{
code: `
function doSomething() {};

jest.spyOn(X, getCount).mockImplementation(() => doSomething);
`.trim(),
output: `
function doSomething() {};

jest.spyOn(X, getCount).mockReturnValue(doSomething);
`.trim(),
errors: [
{
messageId: 'useMockShorthand',
data: { replacement: 'mockReturnValue' },
column: 33,
line: 3,
},
],
},
{
code: `
const doSomething = () => {};

jest.spyOn(X, getCount).mockImplementation(() => doSomething);
`.trim(),
output: `
const doSomething = () => {};

jest.spyOn(X, getCount).mockReturnValue(doSomething);
`.trim(),
errors: [
{
messageId: 'useMockShorthand',
data: { replacement: 'mockReturnValue' },
column: 33,
line: 3,
},
],
},
],
})
Loading