Skip to content

Commit 9e68524

Browse files
committed
feat: add vitest mock env detection, closes #1181
1 parent c038699 commit 9e68524

File tree

6 files changed

+44
-0
lines changed

6 files changed

+44
-0
lines changed

eslint.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,4 +119,10 @@ export default tseslint.config(
119119
"local/avoid-multiline-template-expression": "off",
120120
},
121121
},
122+
{
123+
files: ["**/*.test.{ts,tsx}"],
124+
rules: {
125+
"@eslint-react/no-unnecessary-use-prefix": "off",
126+
},
127+
},
122128
);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as AST from "@eslint-react/ast";
2+
import type { RuleContext } from "@eslint-react/kit";
3+
import { AST_NODE_TYPES as T, type TSESTree } from "@typescript-eslint/types";
4+
5+
/**
6+
* Checks if the given node is inside a `vi.mock` callback.
7+
* @param context RuleContext
8+
* @param node The node to check
9+
* @returns `true` if the node is inside a `vi.mock` callback, otherwise `false`.
10+
* @internal
11+
*/
12+
export function isInViMockCallback(context: RuleContext, node: TSESTree.Node) {
13+
const found = AST.findParentNode(node, (n) => {
14+
if (!AST.isFunction(n)) return false;
15+
return n.parent.type === T.CallExpression
16+
&& n.parent.callee.type === T.MemberExpression
17+
&& n.parent.callee.object.type === T.Identifier
18+
&& n.parent.callee.object.name === "vi"
19+
&& n.parent.callee.property.type === T.Identifier
20+
&& n.parent.callee.property.name === "mock"
21+
&& n.parent.arguments[1] === n;
22+
});
23+
return found != null;
24+
}

packages/core/src/env/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./env-vitest";

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export * from "./component";
22
export type * from "./effect";
3+
export * from "./env";
34
export * from "./hook";
45
export * from "./jsx";
56
export type * from "./semantic";

packages/plugins/eslint-plugin-react-x/src/rules/no-unnecessary-use-prefix.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,5 +195,13 @@ ruleTester.run(RULE_NAME, rule, {
195195
}
196196
}
197197
`,
198+
// https://github.com/Rel1cx/eslint-react/issues/1181
199+
tsx`
200+
const mockUseSession = vi.fn().mockReturnValue(sessionUser);
201+
202+
vi.mock("src/components/session/session", () => ({
203+
useSession: () => mockUseSession(),
204+
}));
205+
`,
198206
],
199207
});

packages/plugins/eslint-plugin-react-x/src/rules/no-unnecessary-use-prefix.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ export function create(context: RuleContext<MessageID, []>): RuleListener {
6464
if (containsUseComments(context, node)) {
6565
continue;
6666
}
67+
// Skip hooks that are in a vi mock callback
68+
if (ER.isInViMockCallback(context, node)) {
69+
continue;
70+
}
6771
context.report({
6872
messageId: "noUnnecessaryUsePrefix",
6973
node: id ?? node,

0 commit comments

Comments
 (0)