@vitest/eslint-plugin 1.1.19 → 1.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/index.cjs +121 -173
- package/dist/index.d.cts +7 -206
- package/dist/index.d.mts +7 -206
- package/dist/index.d.ts +7 -206
- package/dist/index.mjs +120 -172
- package/package.json +14 -15
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { isAbsolute, posix } from 'node:path';
|
|
|
4
4
|
import ts from 'typescript';
|
|
5
5
|
import { createRequire } from 'node:module';
|
|
6
6
|
|
|
7
|
-
const version = "1.1.
|
|
7
|
+
const version = "1.1.20";
|
|
8
8
|
|
|
9
9
|
function createEslintRule(rule) {
|
|
10
10
|
const createRule = ESLintUtils.RuleCreator(
|
|
@@ -15,8 +15,7 @@ function createEslintRule(rule) {
|
|
|
15
15
|
const joinNames = (a, b) => a && b ? `${a}.${b}` : null;
|
|
16
16
|
const isFunction = (node) => node.type === AST_NODE_TYPES.FunctionExpression || node.type === AST_NODE_TYPES.ArrowFunctionExpression;
|
|
17
17
|
function getNodeName(node) {
|
|
18
|
-
if (isSupportedAccessor(node))
|
|
19
|
-
return getAccessorValue(node);
|
|
18
|
+
if (isSupportedAccessor(node)) return getAccessorValue(node);
|
|
20
19
|
switch (node.type) {
|
|
21
20
|
case AST_NODE_TYPES.TaggedTemplateExpression:
|
|
22
21
|
return getNodeName(node.tag);
|
|
@@ -83,6 +82,8 @@ var HookName = /* @__PURE__ */ ((HookName2) => {
|
|
|
83
82
|
return HookName2;
|
|
84
83
|
})(HookName || {});
|
|
85
84
|
var ModifierName = /* @__PURE__ */ ((ModifierName2) => {
|
|
85
|
+
ModifierName2["to"] = "to";
|
|
86
|
+
ModifierName2["have"] = "have";
|
|
86
87
|
ModifierName2["not"] = "not";
|
|
87
88
|
ModifierName2["rejects"] = "rejects";
|
|
88
89
|
ModifierName2["resolves"] = "resolves";
|
|
@@ -155,10 +156,10 @@ const findModifiersAndMatcher = (members) => {
|
|
|
155
156
|
if (!ModifierName.hasOwnProperty(name))
|
|
156
157
|
return "modifier-unknown";
|
|
157
158
|
} else if (modifiers.length === 1) {
|
|
158
|
-
if (name !== ModifierName.not)
|
|
159
|
+
if (name !== ModifierName.not && name != ModifierName.have)
|
|
159
160
|
return "modifier-unknown";
|
|
160
161
|
const firstModifier = getAccessorValue(modifiers[0]);
|
|
161
|
-
if (firstModifier !== ModifierName.resolves && firstModifier !== ModifierName.rejects)
|
|
162
|
+
if (firstModifier !== ModifierName.resolves && firstModifier !== ModifierName.rejects && firstModifier !== ModifierName.to)
|
|
162
163
|
return "modifier-unknown";
|
|
163
164
|
} else {
|
|
164
165
|
return "modifier-unknown";
|
|
@@ -325,6 +326,8 @@ const describeImportDefAsImport = (def) => {
|
|
|
325
326
|
return null;
|
|
326
327
|
if (def.node.type !== AST_NODE_TYPES.ImportSpecifier)
|
|
327
328
|
return null;
|
|
329
|
+
if (def.node.imported.type != AST_NODE_TYPES.Identifier)
|
|
330
|
+
return null;
|
|
328
331
|
if (def.parent.importKind === "type")
|
|
329
332
|
return null;
|
|
330
333
|
return {
|
|
@@ -448,8 +451,7 @@ const lowerCaseTitle = createEslintRule({
|
|
|
448
451
|
return {
|
|
449
452
|
CallExpression(node) {
|
|
450
453
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
451
|
-
if (!vitestFnCall || !hasStringAsFirstArgument)
|
|
452
|
-
return;
|
|
454
|
+
if (!vitestFnCall || !hasStringAsFirstArgument) return;
|
|
453
455
|
if (vitestFnCall?.type === "describe") {
|
|
454
456
|
numberOfDescribeBlocks++;
|
|
455
457
|
if (ignoreTopLevelDescribe && numberOfDescribeBlocks === 1)
|
|
@@ -459,13 +461,10 @@ const lowerCaseTitle = createEslintRule({
|
|
|
459
461
|
}
|
|
460
462
|
const [firstArgument] = node.arguments;
|
|
461
463
|
const description = getStringValue(firstArgument);
|
|
462
|
-
if (typeof description !== "string")
|
|
463
|
-
|
|
464
|
-
if (allowedPrefixes.some((prefix) => description.startsWith(prefix)))
|
|
465
|
-
return;
|
|
464
|
+
if (typeof description !== "string") return;
|
|
465
|
+
if (allowedPrefixes.some((prefix) => description.startsWith(prefix))) return;
|
|
466
466
|
const firstCharacter = description.charAt(0);
|
|
467
|
-
if (ignores.includes(vitestFnCall.name) || lowercaseFirstCharacterOnly && (!firstCharacter || firstCharacter === firstCharacter.toLowerCase()) || !lowercaseFirstCharacterOnly && description === description.toLowerCase())
|
|
468
|
-
return;
|
|
467
|
+
if (ignores.includes(vitestFnCall.name) || lowercaseFirstCharacterOnly && (!firstCharacter || firstCharacter === firstCharacter.toLowerCase()) || !lowercaseFirstCharacterOnly && description === description.toLowerCase()) return;
|
|
469
468
|
context.report({
|
|
470
469
|
messageId: lowercaseFirstCharacterOnly ? "lowerCaseTitle" : "fullyLowerCaseTitle",
|
|
471
470
|
node: node.arguments[0],
|
|
@@ -523,8 +522,7 @@ const maxNestedDescribe = createEslintRule({
|
|
|
523
522
|
create(context, [{ max }]) {
|
|
524
523
|
const stack = [];
|
|
525
524
|
function pushStack(node) {
|
|
526
|
-
if (node.parent?.type !== "CallExpression")
|
|
527
|
-
return;
|
|
525
|
+
if (node.parent?.type !== "CallExpression") return;
|
|
528
526
|
if (node.parent.callee.type !== "Identifier" || node.parent.callee.name !== "describe")
|
|
529
527
|
return;
|
|
530
528
|
stack.push(0);
|
|
@@ -536,8 +534,7 @@ const maxNestedDescribe = createEslintRule({
|
|
|
536
534
|
}
|
|
537
535
|
}
|
|
538
536
|
function popStack(node) {
|
|
539
|
-
if (node.parent?.type !== "CallExpression")
|
|
540
|
-
return;
|
|
537
|
+
if (node.parent?.type !== "CallExpression") return;
|
|
541
538
|
if (node.parent.callee.type !== "Identifier" || node.parent.callee.name !== "describe")
|
|
542
539
|
return;
|
|
543
540
|
stack.pop();
|
|
@@ -663,8 +660,7 @@ const noFocusedTests = createEslintRule({
|
|
|
663
660
|
}
|
|
664
661
|
if (callee.type === "TaggedTemplateExpression") {
|
|
665
662
|
const tagCall = callee.tag.type === "MemberExpression" ? callee.tag.object : null;
|
|
666
|
-
if (!tagCall)
|
|
667
|
-
return;
|
|
663
|
+
if (!tagCall) return;
|
|
668
664
|
if (tagCall.type === "MemberExpression" && isTestOrDescribe(tagCall.object) && isOnly(tagCall.property)) {
|
|
669
665
|
context.report({
|
|
670
666
|
node: tagCall.property,
|
|
@@ -738,18 +734,6 @@ function parsePluginSettings(settings) {
|
|
|
738
734
|
}
|
|
739
735
|
|
|
740
736
|
const RULE_NAME$U = "expect-expect";
|
|
741
|
-
function matchesAssertFunctionName(nodeName, patterns) {
|
|
742
|
-
return patterns.some(
|
|
743
|
-
(p) => new RegExp(
|
|
744
|
-
`^${p.split(".").map((x) => {
|
|
745
|
-
if (x === "**")
|
|
746
|
-
return "[a-z\\d\\.]*";
|
|
747
|
-
return x.replace(/\*/gu, "[a-z\\d]*");
|
|
748
|
-
}).join("\\.")}(\\.|$)`,
|
|
749
|
-
"ui"
|
|
750
|
-
).test(nodeName)
|
|
751
|
-
);
|
|
752
|
-
}
|
|
753
737
|
const expectExpect = createEslintRule({
|
|
754
738
|
name: RULE_NAME$U,
|
|
755
739
|
meta: {
|
|
@@ -782,8 +766,8 @@ const expectExpect = createEslintRule({
|
|
|
782
766
|
create(context, [{ assertFunctionNames = ["expect"], additionalTestBlockFunctions = [] }]) {
|
|
783
767
|
const unchecked = [];
|
|
784
768
|
const settings = parsePluginSettings(context.settings);
|
|
785
|
-
if (settings.typecheck)
|
|
786
|
-
|
|
769
|
+
if (settings.typecheck) assertFunctionNames.push("expectTypeOf", "assertType");
|
|
770
|
+
const assertFunctionRegexps = assertFunctionNames.map(buildPatternRegexp);
|
|
787
771
|
function checkCallExpression(nodes) {
|
|
788
772
|
for (const node of nodes) {
|
|
789
773
|
const index = node.type === AST_NODE_TYPES.CallExpression ? unchecked.indexOf(node) : -1;
|
|
@@ -808,10 +792,9 @@ const expectExpect = createEslintRule({
|
|
|
808
792
|
return;
|
|
809
793
|
const name = getNodeName(node) ?? "";
|
|
810
794
|
if (isTypeOfVitestFnCall(node, context, ["test"]) || additionalTestBlockFunctions.includes(name)) {
|
|
811
|
-
if (node.callee.type === AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property, "todo"))
|
|
812
|
-
return;
|
|
795
|
+
if (node.callee.type === AST_NODE_TYPES.MemberExpression && isSupportedAccessor(node.callee.property, "todo")) return;
|
|
813
796
|
unchecked.push(node);
|
|
814
|
-
} else if (
|
|
797
|
+
} else if (assertFunctionRegexps.some((p) => p.test(name))) {
|
|
815
798
|
checkCallExpression(context.sourceCode.getAncestors(node));
|
|
816
799
|
}
|
|
817
800
|
},
|
|
@@ -826,6 +809,17 @@ const expectExpect = createEslintRule({
|
|
|
826
809
|
};
|
|
827
810
|
}
|
|
828
811
|
});
|
|
812
|
+
function buildPatternRegexp(pattern) {
|
|
813
|
+
const parts = pattern.split(".").map((x) => {
|
|
814
|
+
if (x === "**")
|
|
815
|
+
return "[_a-z\\d\\.]*";
|
|
816
|
+
return x.replace(/\*/gu, "[a-z\\d]*");
|
|
817
|
+
});
|
|
818
|
+
return new RegExp(
|
|
819
|
+
`^${parts.join("\\.")}(\\.|$)`,
|
|
820
|
+
"ui"
|
|
821
|
+
);
|
|
822
|
+
}
|
|
829
823
|
|
|
830
824
|
const RULE_NAME$T = "consistent-test-it";
|
|
831
825
|
const buildFixer = (callee, nodeName, preferredTestKeyword) => (fixer) => [
|
|
@@ -891,6 +885,8 @@ const consistentTestIt = createEslintRule({
|
|
|
891
885
|
for (const specifier of node.specifiers) {
|
|
892
886
|
if (specifier.type !== "ImportSpecifier")
|
|
893
887
|
continue;
|
|
888
|
+
if (specifier.imported.type !== "Identifier")
|
|
889
|
+
continue;
|
|
894
890
|
if (specifier.local.name !== specifier.imported.name)
|
|
895
891
|
continue;
|
|
896
892
|
if (specifier.local.name === oppositeTestKeyword) {
|
|
@@ -910,8 +906,7 @@ const consistentTestIt = createEslintRule({
|
|
|
910
906
|
if (node.callee.type === AST_NODE_TYPES.Identifier && node.callee.name === "bench")
|
|
911
907
|
return;
|
|
912
908
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
913
|
-
if (!vitestFnCall)
|
|
914
|
-
return;
|
|
909
|
+
if (!vitestFnCall) return;
|
|
915
910
|
if (vitestFnCall.type === "describe") {
|
|
916
911
|
describeNestingLevel++;
|
|
917
912
|
return;
|
|
@@ -1477,8 +1472,7 @@ const noDisabledTests = createEslintRule({
|
|
|
1477
1472
|
return {
|
|
1478
1473
|
CallExpression(node) {
|
|
1479
1474
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
1480
|
-
if (!vitestFnCall)
|
|
1481
|
-
return;
|
|
1475
|
+
if (!vitestFnCall) return;
|
|
1482
1476
|
if (vitestFnCall.type === "describe")
|
|
1483
1477
|
suiteDepth++;
|
|
1484
1478
|
if (vitestFnCall.type === "test") {
|
|
@@ -1558,16 +1552,13 @@ const noDoneCallback = createEslintRule({
|
|
|
1558
1552
|
if (isVitestEach && node.callee.type !== AST_NODE_TYPES.TaggedTemplateExpression)
|
|
1559
1553
|
return;
|
|
1560
1554
|
const isInsideConcurrentTestOrDescribe = context.sourceCode.getAncestors(node).some((ancestor) => {
|
|
1561
|
-
if (ancestor.type !== AST_NODE_TYPES.CallExpression)
|
|
1562
|
-
return false;
|
|
1555
|
+
if (ancestor.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
1563
1556
|
const isNotInsideDescribeOrTest = !isTypeOfVitestFnCall(ancestor, context, ["describe", "test"]);
|
|
1564
|
-
if (isNotInsideDescribeOrTest)
|
|
1565
|
-
return false;
|
|
1557
|
+
if (isNotInsideDescribeOrTest) return false;
|
|
1566
1558
|
const isTestRunningConcurrently = ancestor.callee.type === AST_NODE_TYPES.MemberExpression && isSupportedAccessor(ancestor.callee.property, "concurrent");
|
|
1567
1559
|
return isTestRunningConcurrently;
|
|
1568
1560
|
});
|
|
1569
|
-
if (isInsideConcurrentTestOrDescribe)
|
|
1570
|
-
return;
|
|
1561
|
+
if (isInsideConcurrentTestOrDescribe) return;
|
|
1571
1562
|
const callback = findCallbackArg(node, isVitestEach, context);
|
|
1572
1563
|
const callbackArgIndex = Number(isVitestEach);
|
|
1573
1564
|
if (!callback || !isFunction(callback) || callback.params.length !== 1 + callbackArgIndex)
|
|
@@ -1654,14 +1645,13 @@ const noDuplicateHooks = createEslintRule({
|
|
|
1654
1645
|
const hooksContexts = [{}];
|
|
1655
1646
|
return {
|
|
1656
1647
|
CallExpression(node) {
|
|
1657
|
-
var _a;
|
|
1658
1648
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
1659
1649
|
if (vitestFnCall?.type === "describe")
|
|
1660
1650
|
hooksContexts.push({});
|
|
1661
1651
|
if (vitestFnCall?.type !== "hook")
|
|
1662
1652
|
return;
|
|
1663
1653
|
const currentLayer = hooksContexts[hooksContexts.length - 1];
|
|
1664
|
-
currentLayer[
|
|
1654
|
+
currentLayer[vitestFnCall.name] ||= 0;
|
|
1665
1655
|
currentLayer[vitestFnCall.name] += 1;
|
|
1666
1656
|
if (currentLayer[vitestFnCall.name] > 1) {
|
|
1667
1657
|
context.report({
|
|
@@ -2055,18 +2045,15 @@ const noTestReturnStatement = createEslintRule({
|
|
|
2055
2045
|
return;
|
|
2056
2046
|
const body = getBody(node.arguments);
|
|
2057
2047
|
const returnStmt = body.find((stmt) => stmt.type === AST_NODE_TYPES.ReturnStatement);
|
|
2058
|
-
if (!returnStmt)
|
|
2059
|
-
return;
|
|
2048
|
+
if (!returnStmt) return;
|
|
2060
2049
|
context.report({ messageId: "noTestReturnStatement", node: returnStmt });
|
|
2061
2050
|
},
|
|
2062
2051
|
FunctionDeclaration(node) {
|
|
2063
2052
|
const declaredVariables = context.sourceCode.getDeclaredVariables(node);
|
|
2064
2053
|
const testCallExpressions = getTestCallExpressionsFromDeclaredVariables(declaredVariables, context);
|
|
2065
|
-
if (testCallExpressions.length === 0)
|
|
2066
|
-
return;
|
|
2054
|
+
if (testCallExpressions.length === 0) return;
|
|
2067
2055
|
const returnStmt = node.body.body.find((stmt) => stmt.type === AST_NODE_TYPES.ReturnStatement);
|
|
2068
|
-
if (!returnStmt)
|
|
2069
|
-
return;
|
|
2056
|
+
if (!returnStmt) return;
|
|
2070
2057
|
context.report({ messageId: "noTestReturnStatement", node: returnStmt });
|
|
2071
2058
|
}
|
|
2072
2059
|
};
|
|
@@ -2093,8 +2080,7 @@ const preferCalledWith = createEslintRule({
|
|
|
2093
2080
|
return {
|
|
2094
2081
|
CallExpression(node) {
|
|
2095
2082
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
2096
|
-
if (vitestFnCall?.type !== "expect")
|
|
2097
|
-
return;
|
|
2083
|
+
if (vitestFnCall?.type !== "expect") return;
|
|
2098
2084
|
if (vitestFnCall.modifiers.some(
|
|
2099
2085
|
(node2) => getAccessorValue(node2) === "not"
|
|
2100
2086
|
))
|
|
@@ -2137,8 +2123,7 @@ function isFunctionType(type) {
|
|
|
2137
2123
|
}
|
|
2138
2124
|
function isClassType(type) {
|
|
2139
2125
|
const symbol = type.getSymbol();
|
|
2140
|
-
if (!symbol)
|
|
2141
|
-
return false;
|
|
2126
|
+
if (!symbol) return false;
|
|
2142
2127
|
return symbol.getDeclarations()?.some((declaration) => ts.isClassDeclaration(declaration) || ts.isClassExpression(declaration)) ?? false;
|
|
2143
2128
|
}
|
|
2144
2129
|
const compileMatcherPatterns = (matchers) => {
|
|
@@ -2237,17 +2222,15 @@ const validTitle = createEslintRule({
|
|
|
2237
2222
|
return {
|
|
2238
2223
|
CallExpression(node) {
|
|
2239
2224
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
2240
|
-
if (vitestFnCall?.type !== "describe" && vitestFnCall?.type !== "test" && vitestFnCall?.type !== "it")
|
|
2241
|
-
|
|
2225
|
+
if (vitestFnCall?.type !== "describe" && vitestFnCall?.type !== "test" && vitestFnCall?.type !== "it") return;
|
|
2226
|
+
if (vitestFnCall.members.some((m) => m.type == AST_NODE_TYPES.Identifier && m.name == "extend")) return;
|
|
2242
2227
|
const [argument] = node.arguments;
|
|
2243
2228
|
if (settings.typecheck) {
|
|
2244
2229
|
const services = ESLintUtils.getParserServices(context);
|
|
2245
2230
|
const type = services.getTypeAtLocation(argument);
|
|
2246
|
-
if (isFunctionType(type) || isClassType(type))
|
|
2247
|
-
return;
|
|
2231
|
+
if (isFunctionType(type) || isClassType(type)) return;
|
|
2248
2232
|
}
|
|
2249
|
-
if (!argument || allowArguments && argument.type === AST_NODE_TYPES.Identifier)
|
|
2250
|
-
return;
|
|
2233
|
+
if (!argument || allowArguments && argument.type === AST_NODE_TYPES.Identifier) return;
|
|
2251
2234
|
if (!isStringNode(argument)) {
|
|
2252
2235
|
if (argument.type === AST_NODE_TYPES.BinaryExpression && doesBinaryExpressionContainStringNode(argument))
|
|
2253
2236
|
return;
|
|
@@ -2481,6 +2464,8 @@ const validExpect = createEslintRule({
|
|
|
2481
2464
|
return;
|
|
2482
2465
|
} else if (vitestFnCall?.type !== "expect") {
|
|
2483
2466
|
return;
|
|
2467
|
+
} else if (vitestFnCall.modifiers.some((mod) => mod.type === AST_NODE_TYPES.Identifier && mod.name == "to")) {
|
|
2468
|
+
return;
|
|
2484
2469
|
}
|
|
2485
2470
|
const { parent: expect } = vitestFnCall.head.node;
|
|
2486
2471
|
if (expect?.type !== AST_NODE_TYPES.CallExpression)
|
|
@@ -2689,8 +2674,7 @@ const preferToBeTruthy = createEslintRule({
|
|
|
2689
2674
|
return {
|
|
2690
2675
|
CallExpression(node) {
|
|
2691
2676
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
2692
|
-
if (!(vitestFnCall?.type === "expect" || vitestFnCall?.type === "expectTypeOf"))
|
|
2693
|
-
return;
|
|
2677
|
+
if (!(vitestFnCall?.type === "expect" || vitestFnCall?.type === "expectTypeOf")) return;
|
|
2694
2678
|
if (vitestFnCall.args.length === 1 && isTrueLiteral(getFirstMatcherArg(vitestFnCall)) && EqualityMatcher.hasOwnProperty(getAccessorValue(vitestFnCall.matcher))) {
|
|
2695
2679
|
context.report({
|
|
2696
2680
|
node: vitestFnCall.matcher,
|
|
@@ -2727,8 +2711,7 @@ const preferToBeFalsy = createEslintRule({
|
|
|
2727
2711
|
return {
|
|
2728
2712
|
CallExpression(node) {
|
|
2729
2713
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
2730
|
-
if (!(vitestFnCall?.type === "expect" || vitestFnCall?.type === "expectTypeOf"))
|
|
2731
|
-
return;
|
|
2714
|
+
if (!(vitestFnCall?.type === "expect" || vitestFnCall?.type === "expectTypeOf")) return;
|
|
2732
2715
|
if (vitestFnCall.args.length === 1 && isFalseLiteral(getFirstMatcherArg(vitestFnCall)) && EqualityMatcher.hasOwnProperty(getAccessorValue(vitestFnCall.matcher))) {
|
|
2733
2716
|
context.report({
|
|
2734
2717
|
node: vitestFnCall.matcher,
|
|
@@ -2889,8 +2872,7 @@ const preferStrictEqual = createEslintRule({
|
|
|
2889
2872
|
return {
|
|
2890
2873
|
CallExpression(node) {
|
|
2891
2874
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
2892
|
-
if (vitestFnCall?.type !== "expect")
|
|
2893
|
-
return;
|
|
2875
|
+
if (vitestFnCall?.type !== "expect") return;
|
|
2894
2876
|
const { matcher } = vitestFnCall;
|
|
2895
2877
|
if (isSupportedAccessor(matcher, "toEqual")) {
|
|
2896
2878
|
context.report({
|
|
@@ -2930,8 +2912,7 @@ const preferExpectResolves = createEslintRule({
|
|
|
2930
2912
|
create: (context) => ({
|
|
2931
2913
|
CallExpression(node) {
|
|
2932
2914
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
2933
|
-
if (vitestFnCall?.type !== "expect")
|
|
2934
|
-
return;
|
|
2915
|
+
if (vitestFnCall?.type !== "expect") return;
|
|
2935
2916
|
const { parent } = vitestFnCall.head.node;
|
|
2936
2917
|
if (parent?.type !== AST_NODE_TYPES.CallExpression)
|
|
2937
2918
|
return;
|
|
@@ -2980,13 +2961,11 @@ const preferEach = createEslintRule({
|
|
|
2980
2961
|
return "describe";
|
|
2981
2962
|
};
|
|
2982
2963
|
const enterForLoop = () => {
|
|
2983
|
-
if (vitestFnCalls.length === 0 || inTestCaseCall)
|
|
2984
|
-
return;
|
|
2964
|
+
if (vitestFnCalls.length === 0 || inTestCaseCall) return;
|
|
2985
2965
|
vitestFnCalls.length = 0;
|
|
2986
2966
|
};
|
|
2987
2967
|
const exitForLoop = (node) => {
|
|
2988
|
-
if (vitestFnCalls.length === 0 || inTestCaseCall)
|
|
2989
|
-
return;
|
|
2968
|
+
if (vitestFnCalls.length === 0 || inTestCaseCall) return;
|
|
2990
2969
|
context.report({
|
|
2991
2970
|
node,
|
|
2992
2971
|
messageId: "preferEach",
|
|
@@ -3074,8 +3053,7 @@ const preferHooksInOrder = createEslintRule({
|
|
|
3074
3053
|
let inHook = false;
|
|
3075
3054
|
return {
|
|
3076
3055
|
CallExpression(node) {
|
|
3077
|
-
if (inHook)
|
|
3078
|
-
return;
|
|
3056
|
+
if (inHook) return;
|
|
3079
3057
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
3080
3058
|
if (vitestFnCall?.type !== "hook") {
|
|
3081
3059
|
previousHookIndex = -1;
|
|
@@ -3139,8 +3117,7 @@ const preferMockPromiseShorthand = createEslintRule({
|
|
|
3139
3117
|
defaultOptions: [],
|
|
3140
3118
|
create(context) {
|
|
3141
3119
|
const report = (property, isOnce, outerArgNode, innerArgNode = outerArgNode) => {
|
|
3142
|
-
if (innerArgNode?.type !== AST_NODE_TYPES.CallExpression)
|
|
3143
|
-
return;
|
|
3120
|
+
if (innerArgNode?.type !== AST_NODE_TYPES.CallExpression) return;
|
|
3144
3121
|
const argName = getNodeName(innerArgNode);
|
|
3145
3122
|
if (argName !== "Promise.resolve" && argName !== "Promise.reject")
|
|
3146
3123
|
return;
|
|
@@ -3246,13 +3223,10 @@ const preferViMocked = createEslintRule({
|
|
|
3246
3223
|
create(context) {
|
|
3247
3224
|
function check(node) {
|
|
3248
3225
|
const { typeAnnotation } = node;
|
|
3249
|
-
if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference)
|
|
3250
|
-
return;
|
|
3226
|
+
if (typeAnnotation.type !== AST_NODE_TYPES.TSTypeReference) return;
|
|
3251
3227
|
const { typeName } = typeAnnotation;
|
|
3252
|
-
if (typeName.type !== AST_NODE_TYPES.Identifier)
|
|
3253
|
-
|
|
3254
|
-
if (!mockTypes.includes(typeName.name))
|
|
3255
|
-
return;
|
|
3228
|
+
if (typeName.type !== AST_NODE_TYPES.Identifier) return;
|
|
3229
|
+
if (!mockTypes.includes(typeName.name)) return;
|
|
3256
3230
|
const fnName = context.sourceCode.text.slice(
|
|
3257
3231
|
...followTypeAssertionChain(node.expression).range
|
|
3258
3232
|
);
|
|
@@ -3266,8 +3240,7 @@ const preferViMocked = createEslintRule({
|
|
|
3266
3240
|
}
|
|
3267
3241
|
return {
|
|
3268
3242
|
TSAsExpression(node) {
|
|
3269
|
-
if (node.parent.type === AST_NODE_TYPES.TSAsExpression)
|
|
3270
|
-
return;
|
|
3243
|
+
if (node.parent.type === AST_NODE_TYPES.TSAsExpression) return;
|
|
3271
3244
|
check(node);
|
|
3272
3245
|
},
|
|
3273
3246
|
TSTypeAssertion(node) {
|
|
@@ -3281,12 +3254,10 @@ const RULE_NAME$j = "prefer-snapshot-hint";
|
|
|
3281
3254
|
const snapshotMatchers = ["toMatchSnapshot", "toThrowErrorMatchingSnapshot"];
|
|
3282
3255
|
const snapshotMatcherNames = snapshotMatchers;
|
|
3283
3256
|
const isSnapshotMatcherWithoutHint = (expectFnCall) => {
|
|
3284
|
-
if (expectFnCall.args.length === 0)
|
|
3285
|
-
return true;
|
|
3257
|
+
if (expectFnCall.args.length === 0) return true;
|
|
3286
3258
|
if (!isSupportedAccessor(expectFnCall.matcher, "toMatchSnapshot"))
|
|
3287
3259
|
return expectFnCall.args.length !== 1;
|
|
3288
|
-
if (expectFnCall.args.length === 2)
|
|
3289
|
-
return false;
|
|
3260
|
+
if (expectFnCall.args.length === 2) return false;
|
|
3290
3261
|
const [arg] = expectFnCall.args;
|
|
3291
3262
|
return !isStringNode(arg);
|
|
3292
3263
|
};
|
|
@@ -3361,8 +3332,7 @@ const preferSnapshotHint = createEslintRule({
|
|
|
3361
3332
|
return;
|
|
3362
3333
|
}
|
|
3363
3334
|
const matcherName = getAccessorValue(vitestFnCall.matcher);
|
|
3364
|
-
if (!snapshotMatcherNames.includes(matcherName))
|
|
3365
|
-
return;
|
|
3335
|
+
if (!snapshotMatcherNames.includes(matcherName)) return;
|
|
3366
3336
|
snapshotMatchers2.push(vitestFnCall);
|
|
3367
3337
|
}
|
|
3368
3338
|
};
|
|
@@ -3383,8 +3353,7 @@ const hasNonEachMembersAndParams = (vitestFnCall, functionExpression) => {
|
|
|
3383
3353
|
};
|
|
3384
3354
|
const reportUnexpectedReturnInDescribe = (blockStatement, context) => {
|
|
3385
3355
|
blockStatement.body.forEach((node) => {
|
|
3386
|
-
if (node.type !== AST_NODE_TYPES.ReturnStatement)
|
|
3387
|
-
return;
|
|
3356
|
+
if (node.type !== AST_NODE_TYPES.ReturnStatement) return;
|
|
3388
3357
|
context.report({
|
|
3389
3358
|
messageId: "unexpectedReturnInDescribe",
|
|
3390
3359
|
node
|
|
@@ -3412,8 +3381,7 @@ const validDescribeCallback = createEslintRule({
|
|
|
3412
3381
|
return {
|
|
3413
3382
|
CallExpression(node) {
|
|
3414
3383
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
3415
|
-
if (vitestFnCall?.type !== "describe")
|
|
3416
|
-
return;
|
|
3384
|
+
if (vitestFnCall?.type !== "describe") return;
|
|
3417
3385
|
if (vitestFnCall?.members[0]?.type === AST_NODE_TYPES.Identifier && vitestFnCall.members[0].name === "todo")
|
|
3418
3386
|
return;
|
|
3419
3387
|
if (node.arguments.length < 1) {
|
|
@@ -3510,8 +3478,7 @@ const requireTopLevelDescribe = createEslintRule({
|
|
|
3510
3478
|
return {
|
|
3511
3479
|
CallExpression(node) {
|
|
3512
3480
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
3513
|
-
if (!vitestFnCall)
|
|
3514
|
-
return;
|
|
3481
|
+
if (!vitestFnCall) return;
|
|
3515
3482
|
if (vitestFnCall.type === "describe") {
|
|
3516
3483
|
numberOfDescribeBlocks++;
|
|
3517
3484
|
if (numberOfDescribeBlocks === 1) {
|
|
@@ -3565,8 +3532,7 @@ const requireToThrowMessage = createEslintRule({
|
|
|
3565
3532
|
return {
|
|
3566
3533
|
CallExpression(node) {
|
|
3567
3534
|
const vitestFnCall = parseVitestFnCall(node, context);
|
|
3568
|
-
if (vitestFnCall?.type !== "expect")
|
|
3569
|
-
return;
|
|
3535
|
+
if (vitestFnCall?.type !== "expect") return;
|
|
3570
3536
|
const { matcher } = vitestFnCall;
|
|
3571
3537
|
const matcherName = getAccessorValue(matcher);
|
|
3572
3538
|
if (vitestFnCall.args.length === 0 && ["toThrow", "toThrowError"].includes(matcherName) && !vitestFnCall.modifiers.some((nod) => getAccessorValue(nod) === "not")) {
|
|
@@ -3653,11 +3619,9 @@ const requireHook = createEslintRule({
|
|
|
3653
3619
|
checkBlockBody(program.body);
|
|
3654
3620
|
},
|
|
3655
3621
|
CallExpression(node) {
|
|
3656
|
-
if (!isTypeOfVitestFnCall(node, context, ["describe"]) || node.arguments.length < 2)
|
|
3657
|
-
return;
|
|
3622
|
+
if (!isTypeOfVitestFnCall(node, context, ["describe"]) || node.arguments.length < 2) return;
|
|
3658
3623
|
const [, testFn] = node.arguments;
|
|
3659
|
-
if (!isFunction(testFn) || testFn.body.type !== AST_NODE_TYPES.BlockStatement)
|
|
3660
|
-
return;
|
|
3624
|
+
if (!isFunction(testFn) || testFn.body.type !== AST_NODE_TYPES.BlockStatement) return;
|
|
3661
3625
|
checkBlockBody(testFn.body.body);
|
|
3662
3626
|
}
|
|
3663
3627
|
};
|
|
@@ -3697,19 +3661,15 @@ const requireLocalTestContextForConcurrentSnapshots = createEslintRule({
|
|
|
3697
3661
|
"toThrowErrorMatchingInlineSnapshot"
|
|
3698
3662
|
// @ts-ignore
|
|
3699
3663
|
].includes(node.callee?.property.name);
|
|
3700
|
-
if (isNotASnapshotAssertion)
|
|
3701
|
-
return;
|
|
3664
|
+
if (isNotASnapshotAssertion) return;
|
|
3702
3665
|
const isInsideSequentialDescribeOrTest = !context.sourceCode.getAncestors(node).some((ancestor) => {
|
|
3703
|
-
if (ancestor.type !== AST_NODE_TYPES.CallExpression)
|
|
3704
|
-
return false;
|
|
3666
|
+
if (ancestor.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
3705
3667
|
const isNotInsideDescribeOrTest = !isTypeOfVitestFnCall(ancestor, context, ["describe", "test"]);
|
|
3706
|
-
if (isNotInsideDescribeOrTest)
|
|
3707
|
-
return false;
|
|
3668
|
+
if (isNotInsideDescribeOrTest) return false;
|
|
3708
3669
|
const isTestRunningConcurrently = ancestor.callee.type === AST_NODE_TYPES.MemberExpression && isSupportedAccessor(ancestor.callee.property, "concurrent");
|
|
3709
3670
|
return isTestRunningConcurrently;
|
|
3710
3671
|
});
|
|
3711
|
-
if (isInsideSequentialDescribeOrTest)
|
|
3712
|
-
return;
|
|
3672
|
+
if (isInsideSequentialDescribeOrTest) return;
|
|
3713
3673
|
context.report({
|
|
3714
3674
|
node,
|
|
3715
3675
|
messageId: "requireLocalTestContext"
|
|
@@ -3721,8 +3681,7 @@ const requireLocalTestContextForConcurrentSnapshots = createEslintRule({
|
|
|
3721
3681
|
|
|
3722
3682
|
const RULE_NAME$d = "prefer-todo";
|
|
3723
3683
|
const isTargetedTestCase = (vitestFnCall) => {
|
|
3724
|
-
if (vitestFnCall.members.some((s) => getAccessorValue(s) !== "skip"))
|
|
3725
|
-
return false;
|
|
3684
|
+
if (vitestFnCall.members.some((s) => getAccessorValue(s) !== "skip")) return false;
|
|
3726
3685
|
if (vitestFnCall.name.startsWith("x"))
|
|
3727
3686
|
return false;
|
|
3728
3687
|
return !vitestFnCall.name.startsWith("f");
|
|
@@ -3828,11 +3787,9 @@ const preferSpyOn = createEslintRule({
|
|
|
3828
3787
|
return {
|
|
3829
3788
|
AssignmentExpression(node) {
|
|
3830
3789
|
const { left, right } = node;
|
|
3831
|
-
if (left.type !== AST_NODE_TYPES.MemberExpression)
|
|
3832
|
-
return;
|
|
3790
|
+
if (left.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
3833
3791
|
const vitestFnCall = getVitestFnCall(right);
|
|
3834
|
-
if (!vitestFnCall)
|
|
3835
|
-
return;
|
|
3792
|
+
if (!vitestFnCall) return;
|
|
3836
3793
|
context.report({
|
|
3837
3794
|
node,
|
|
3838
3795
|
messageId: "useViSpayOn",
|
|
@@ -3913,8 +3870,7 @@ const preferComparisonMatcher = createEslintRule({
|
|
|
3913
3870
|
if (vitestFnCall?.type !== "expect" || vitestFnCall.args.length === 0)
|
|
3914
3871
|
return;
|
|
3915
3872
|
const { parent: expect } = vitestFnCall.head.node;
|
|
3916
|
-
if (expect?.type !== AST_NODE_TYPES.CallExpression)
|
|
3917
|
-
return;
|
|
3873
|
+
if (expect?.type !== AST_NODE_TYPES.CallExpression) return;
|
|
3918
3874
|
const {
|
|
3919
3875
|
arguments: [comparison],
|
|
3920
3876
|
range: [, expectCallEnd]
|
|
@@ -3926,8 +3882,7 @@ const preferComparisonMatcher = createEslintRule({
|
|
|
3926
3882
|
const [modifier] = vitestFnCall.modifiers;
|
|
3927
3883
|
const hasNot = vitestFnCall.modifiers.some((nod) => getAccessorValue(nod) === "not");
|
|
3928
3884
|
const preferredMatcher = determineMatcher(comparison.operator, matcherArg.value === hasNot);
|
|
3929
|
-
if (!preferredMatcher)
|
|
3930
|
-
return;
|
|
3885
|
+
if (!preferredMatcher) return;
|
|
3931
3886
|
context.report({
|
|
3932
3887
|
fix(fixer) {
|
|
3933
3888
|
const { sourceCode } = context;
|
|
@@ -3980,8 +3935,7 @@ const preferToContain = createEslintRule({
|
|
|
3980
3935
|
if (vitestFnCall?.type !== "expect" || vitestFnCall.args.length === 0)
|
|
3981
3936
|
return;
|
|
3982
3937
|
const { parent: expect } = vitestFnCall.head.node;
|
|
3983
|
-
if (expect?.type !== AST_NODE_TYPES.CallExpression)
|
|
3984
|
-
return;
|
|
3938
|
+
if (expect?.type !== AST_NODE_TYPES.CallExpression) return;
|
|
3985
3939
|
const {
|
|
3986
3940
|
arguments: [includesCall],
|
|
3987
3941
|
range: [, expectCallEnd]
|
|
@@ -4229,8 +4183,7 @@ var StatementType = /* @__PURE__ */ ((StatementType2) => {
|
|
|
4229
4183
|
const paddingAlwaysTester = (prevNode, nextNode, paddingContext) => {
|
|
4230
4184
|
const { sourceCode, ruleContext } = paddingContext;
|
|
4231
4185
|
const paddingLines = getPaddingLineSequences(prevNode, nextNode, sourceCode);
|
|
4232
|
-
if (paddingLines.length > 0)
|
|
4233
|
-
return;
|
|
4186
|
+
if (paddingLines.length > 0) return;
|
|
4234
4187
|
ruleContext.report({
|
|
4235
4188
|
node: nextNode,
|
|
4236
4189
|
messageId: "missingPadding",
|
|
@@ -4345,8 +4298,7 @@ const testPadding = (prevNode, nextNode, paddingContext) => {
|
|
|
4345
4298
|
};
|
|
4346
4299
|
const verifyNode = (node, paddingContext) => {
|
|
4347
4300
|
const { scopeInfo } = paddingContext;
|
|
4348
|
-
if (!isValidParent(node?.parent.type))
|
|
4349
|
-
return;
|
|
4301
|
+
if (!isValidParent(node?.parent.type)) return;
|
|
4350
4302
|
if (scopeInfo.prevNode) {
|
|
4351
4303
|
testPadding(scopeInfo.prevNode, node, paddingContext);
|
|
4352
4304
|
}
|
|
@@ -4976,48 +4928,6 @@ const plugin = {
|
|
|
4976
4928
|
[RULE_NAME$2]: paddingAroundTestBlocks,
|
|
4977
4929
|
[RULE_NAME]: validExpectInPromise
|
|
4978
4930
|
},
|
|
4979
|
-
configs: {
|
|
4980
|
-
"legacy-recommended": createConfigLegacy(recommended),
|
|
4981
|
-
"legacy-all": createConfigLegacy(allRules),
|
|
4982
|
-
"recommended": {
|
|
4983
|
-
plugins: {
|
|
4984
|
-
get vitest() {
|
|
4985
|
-
return plugin;
|
|
4986
|
-
}
|
|
4987
|
-
},
|
|
4988
|
-
rules: createConfig(recommended)
|
|
4989
|
-
},
|
|
4990
|
-
"all": {
|
|
4991
|
-
plugins: {
|
|
4992
|
-
get vitest() {
|
|
4993
|
-
return plugin;
|
|
4994
|
-
}
|
|
4995
|
-
},
|
|
4996
|
-
rules: createConfig(allRules)
|
|
4997
|
-
},
|
|
4998
|
-
"env": {
|
|
4999
|
-
languageOptions: {
|
|
5000
|
-
globals: {
|
|
5001
|
-
suite: "writable",
|
|
5002
|
-
test: "writable",
|
|
5003
|
-
describe: "writable",
|
|
5004
|
-
it: "writable",
|
|
5005
|
-
expectTypeOf: "writable",
|
|
5006
|
-
assertType: "writable",
|
|
5007
|
-
expect: "writable",
|
|
5008
|
-
assert: "writable",
|
|
5009
|
-
vitest: "writable",
|
|
5010
|
-
vi: "writable",
|
|
5011
|
-
beforeAll: "writable",
|
|
5012
|
-
afterAll: "writable",
|
|
5013
|
-
beforeEach: "writable",
|
|
5014
|
-
afterEach: "writable",
|
|
5015
|
-
onTestFailed: "writable",
|
|
5016
|
-
onTestFinished: "writable"
|
|
5017
|
-
}
|
|
5018
|
-
}
|
|
5019
|
-
}
|
|
5020
|
-
},
|
|
5021
4931
|
environments: {
|
|
5022
4932
|
env: {
|
|
5023
4933
|
globals: {
|
|
@@ -5041,5 +4951,43 @@ const plugin = {
|
|
|
5041
4951
|
}
|
|
5042
4952
|
}
|
|
5043
4953
|
};
|
|
4954
|
+
plugin.configs = {
|
|
4955
|
+
"legacy-recommended": createConfigLegacy(recommended),
|
|
4956
|
+
"legacy-all": createConfigLegacy(allRules),
|
|
4957
|
+
"recommended": {
|
|
4958
|
+
plugins: {
|
|
4959
|
+
["vitest"]: plugin
|
|
4960
|
+
},
|
|
4961
|
+
rules: createConfig(recommended)
|
|
4962
|
+
},
|
|
4963
|
+
"all": {
|
|
4964
|
+
plugins: {
|
|
4965
|
+
["vitest"]: plugin
|
|
4966
|
+
},
|
|
4967
|
+
rules: createConfig(allRules)
|
|
4968
|
+
},
|
|
4969
|
+
"env": {
|
|
4970
|
+
languageOptions: {
|
|
4971
|
+
globals: {
|
|
4972
|
+
suite: "writable",
|
|
4973
|
+
test: "writable",
|
|
4974
|
+
describe: "writable",
|
|
4975
|
+
it: "writable",
|
|
4976
|
+
expectTypeOf: "writable",
|
|
4977
|
+
assertType: "writable",
|
|
4978
|
+
expect: "writable",
|
|
4979
|
+
assert: "writable",
|
|
4980
|
+
vitest: "writable",
|
|
4981
|
+
vi: "writable",
|
|
4982
|
+
beforeAll: "writable",
|
|
4983
|
+
afterAll: "writable",
|
|
4984
|
+
beforeEach: "writable",
|
|
4985
|
+
afterEach: "writable",
|
|
4986
|
+
onTestFailed: "writable",
|
|
4987
|
+
onTestFinished: "writable"
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
}
|
|
4991
|
+
};
|
|
5044
4992
|
|
|
5045
4993
|
export { plugin as default };
|