@saasmakers/eslint 1.0.26 → 1.0.27
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/dist/index.cjs +146 -10
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +146 -10
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -63,7 +63,7 @@ function checkUnion(context, node, maxLineLength, minItems) {
|
|
|
63
63
|
function collapseBlankLine(text) {
|
|
64
64
|
return text.replace(/\n[^\S\n]*\n[^\S\n]*/, "\n");
|
|
65
65
|
}
|
|
66
|
-
function expressionStartsWithIdentifier(node, identifier) {
|
|
66
|
+
function expressionStartsWithIdentifier$1(node, identifier) {
|
|
67
67
|
if (node.type === index$1.distExports.AST_NODE_TYPES.Identifier && node.name === identifier) {
|
|
68
68
|
return true;
|
|
69
69
|
}
|
|
@@ -73,17 +73,17 @@ function expressionStartsWithIdentifier(node, identifier) {
|
|
|
73
73
|
return true;
|
|
74
74
|
}
|
|
75
75
|
if (callee.type === index$1.distExports.AST_NODE_TYPES.MemberExpression) {
|
|
76
|
-
return expressionStartsWithIdentifier(callee.object, identifier);
|
|
76
|
+
return expressionStartsWithIdentifier$1(callee.object, identifier);
|
|
77
77
|
}
|
|
78
78
|
if (callee.type === index$1.distExports.AST_NODE_TYPES.ChainExpression) {
|
|
79
|
-
return expressionStartsWithIdentifier(callee.expression, identifier);
|
|
79
|
+
return expressionStartsWithIdentifier$1(callee.expression, identifier);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
if (node.type === index$1.distExports.AST_NODE_TYPES.MemberExpression) {
|
|
83
|
-
return expressionStartsWithIdentifier(node.object, identifier);
|
|
83
|
+
return expressionStartsWithIdentifier$1(node.object, identifier);
|
|
84
84
|
}
|
|
85
85
|
if (node.type === index$1.distExports.AST_NODE_TYPES.ChainExpression) {
|
|
86
|
-
return expressionStartsWithIdentifier(node.expression, identifier);
|
|
86
|
+
return expressionStartsWithIdentifier$1(node.expression, identifier);
|
|
87
87
|
}
|
|
88
88
|
return false;
|
|
89
89
|
}
|
|
@@ -211,10 +211,10 @@ function hasLineCommentBetween(prevNode, nextNode, sourceCode) {
|
|
|
211
211
|
});
|
|
212
212
|
}
|
|
213
213
|
function isAssertExpression(expression) {
|
|
214
|
-
return expressionStartsWithIdentifier(expression, "assert");
|
|
214
|
+
return expressionStartsWithIdentifier$1(expression, "assert");
|
|
215
215
|
}
|
|
216
216
|
function isConsoleExpression(expression) {
|
|
217
|
-
return expressionStartsWithIdentifier(expression, "console");
|
|
217
|
+
return expressionStartsWithIdentifier$1(expression, "console");
|
|
218
218
|
}
|
|
219
219
|
function isDirectivePrologue(node) {
|
|
220
220
|
if (node.expression.type !== index$1.distExports.AST_NODE_TYPES.Literal) {
|
|
@@ -223,7 +223,7 @@ function isDirectivePrologue(node) {
|
|
|
223
223
|
return typeof node.expression.value === "string";
|
|
224
224
|
}
|
|
225
225
|
function isExpectExpression(expression) {
|
|
226
|
-
return expressionStartsWithIdentifier(expression, "expect");
|
|
226
|
+
return expressionStartsWithIdentifier$1(expression, "expect");
|
|
227
227
|
}
|
|
228
228
|
function isOwnLineComment(comment, sourceCode) {
|
|
229
229
|
if (comment.type !== "Line") {
|
|
@@ -403,6 +403,7 @@ const rule$4 = {
|
|
|
403
403
|
}
|
|
404
404
|
};
|
|
405
405
|
|
|
406
|
+
const teardownViMethods = /* @__PURE__ */ new Set(["restoreAllMocks", "unstubAllGlobals", "useRealTimers"]);
|
|
406
407
|
function compareTests(testA, testB) {
|
|
407
408
|
const functionA = getFunctionName(testA);
|
|
408
409
|
const functionB = getFunctionName(testB);
|
|
@@ -418,6 +419,40 @@ function compareTests(testA, testB) {
|
|
|
418
419
|
const specificNameB = getSpecificName(testB);
|
|
419
420
|
return specificNameA.localeCompare(specificNameB);
|
|
420
421
|
}
|
|
422
|
+
function expressionStartsWithIdentifier(node, identifier) {
|
|
423
|
+
if (node.type === index$1.distExports.AST_NODE_TYPES.Identifier && node.name === identifier) {
|
|
424
|
+
return true;
|
|
425
|
+
}
|
|
426
|
+
if (node.type === index$1.distExports.AST_NODE_TYPES.CallExpression) {
|
|
427
|
+
const { callee } = node;
|
|
428
|
+
if (callee.type === index$1.distExports.AST_NODE_TYPES.Identifier && callee.name === identifier) {
|
|
429
|
+
return true;
|
|
430
|
+
}
|
|
431
|
+
if (callee.type === index$1.distExports.AST_NODE_TYPES.MemberExpression) {
|
|
432
|
+
return expressionStartsWithIdentifier(callee.object, identifier);
|
|
433
|
+
}
|
|
434
|
+
if (callee.type === index$1.distExports.AST_NODE_TYPES.ChainExpression) {
|
|
435
|
+
return expressionStartsWithIdentifier(callee.expression, identifier);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
if (node.type === index$1.distExports.AST_NODE_TYPES.MemberExpression) {
|
|
439
|
+
return expressionStartsWithIdentifier(node.object, identifier);
|
|
440
|
+
}
|
|
441
|
+
if (node.type === index$1.distExports.AST_NODE_TYPES.ChainExpression) {
|
|
442
|
+
return expressionStartsWithIdentifier(node.expression, identifier);
|
|
443
|
+
}
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
function getExpressionFromStatement(statement) {
|
|
447
|
+
if (statement.type !== index$1.distExports.AST_NODE_TYPES.ExpressionStatement) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
let { expression } = statement;
|
|
451
|
+
if (expression.type === index$1.distExports.AST_NODE_TYPES.AwaitExpression) {
|
|
452
|
+
expression = expression.argument;
|
|
453
|
+
}
|
|
454
|
+
return expression;
|
|
455
|
+
}
|
|
421
456
|
function getFunctionName(testName) {
|
|
422
457
|
const parts = testName.split(".");
|
|
423
458
|
return parts.slice(0, 2).join(".");
|
|
@@ -431,6 +466,20 @@ function getSpecificName(testName) {
|
|
|
431
466
|
}
|
|
432
467
|
return parts.slice(specialIndex + 1).join(".");
|
|
433
468
|
}
|
|
469
|
+
function getTestCallbackBlockBody(node) {
|
|
470
|
+
const callback = node.arguments[1];
|
|
471
|
+
if (!callback) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
if (callback.type !== index$1.distExports.AST_NODE_TYPES.FunctionExpression && callback.type !== index$1.distExports.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
const { body } = callback;
|
|
478
|
+
if (body.type !== index$1.distExports.AST_NODE_TYPES.BlockStatement) {
|
|
479
|
+
return null;
|
|
480
|
+
}
|
|
481
|
+
return body;
|
|
482
|
+
}
|
|
434
483
|
function getTestName(node) {
|
|
435
484
|
const firstArgument = node.arguments[0];
|
|
436
485
|
if (firstArgument?.type === index$1.distExports.AST_NODE_TYPES.Literal && typeof firstArgument.value === "string") {
|
|
@@ -451,12 +500,78 @@ function getTestPriority(testName) {
|
|
|
451
500
|
return 1;
|
|
452
501
|
}
|
|
453
502
|
}
|
|
503
|
+
function hasAssertMethodCall(expression) {
|
|
504
|
+
if (expression.type !== index$1.distExports.AST_NODE_TYPES.CallExpression) {
|
|
505
|
+
return false;
|
|
506
|
+
}
|
|
507
|
+
const { callee } = expression;
|
|
508
|
+
if (callee.type === index$1.distExports.AST_NODE_TYPES.MemberExpression && callee.property.type === index$1.distExports.AST_NODE_TYPES.Identifier && callee.property.name.startsWith("assert")) {
|
|
509
|
+
if (callee.object.type === index$1.distExports.AST_NODE_TYPES.Identifier && callee.object.name === "expect") {
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
return true;
|
|
513
|
+
}
|
|
514
|
+
return false;
|
|
515
|
+
}
|
|
516
|
+
function isAssertionCountExpression(expression) {
|
|
517
|
+
if (expression.type !== index$1.distExports.AST_NODE_TYPES.CallExpression) {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
const { callee } = expression;
|
|
521
|
+
if (callee.type !== index$1.distExports.AST_NODE_TYPES.MemberExpression || callee.object.type !== index$1.distExports.AST_NODE_TYPES.Identifier || callee.property.type !== index$1.distExports.AST_NODE_TYPES.Identifier) {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
if (callee.object.name === "expect" && (callee.property.name === "assertions" || callee.property.name === "hasAssertions")) {
|
|
525
|
+
return true;
|
|
526
|
+
}
|
|
527
|
+
return callee.object.name === "assert" && callee.property.name === "plan";
|
|
528
|
+
}
|
|
529
|
+
function isAssertionCountStatement(statement) {
|
|
530
|
+
const expression = getExpressionFromStatement(statement);
|
|
531
|
+
if (!expression) {
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
return isAssertionCountExpression(expression);
|
|
535
|
+
}
|
|
536
|
+
function isAssertionExpression(expression) {
|
|
537
|
+
if (isAssertionCountExpression(expression)) {
|
|
538
|
+
return false;
|
|
539
|
+
}
|
|
540
|
+
if (expressionStartsWithIdentifier(expression, "assert") || expressionStartsWithIdentifier(expression, "expect")) {
|
|
541
|
+
return true;
|
|
542
|
+
}
|
|
543
|
+
return hasAssertMethodCall(expression);
|
|
544
|
+
}
|
|
545
|
+
function isAssertionStatement(statement) {
|
|
546
|
+
const expression = getExpressionFromStatement(statement);
|
|
547
|
+
if (!expression) {
|
|
548
|
+
return false;
|
|
549
|
+
}
|
|
550
|
+
return isAssertionExpression(expression);
|
|
551
|
+
}
|
|
552
|
+
function isTeardownStatement(statement) {
|
|
553
|
+
const expression = getExpressionFromStatement(statement);
|
|
554
|
+
if (!expression || expression.type !== index$1.distExports.AST_NODE_TYPES.CallExpression) {
|
|
555
|
+
return false;
|
|
556
|
+
}
|
|
557
|
+
const { callee } = expression;
|
|
558
|
+
if (callee.type === index$1.distExports.AST_NODE_TYPES.Identifier && callee.name === "cleanup") {
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
if (callee.type === index$1.distExports.AST_NODE_TYPES.MemberExpression && callee.object.type === index$1.distExports.AST_NODE_TYPES.Identifier && callee.object.name === "vi" && callee.property.type === index$1.distExports.AST_NODE_TYPES.Identifier && teardownViMethods.has(callee.property.name)) {
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
return false;
|
|
565
|
+
}
|
|
454
566
|
const rule$3 = {
|
|
455
567
|
defaultOptions: [],
|
|
456
568
|
meta: {
|
|
457
|
-
docs: { description: "Enforce sorted test functions
|
|
569
|
+
docs: { description: "Enforce sorted test functions and setup-before-assertions layout in test bodies" },
|
|
458
570
|
fixable: "code",
|
|
459
|
-
messages: {
|
|
571
|
+
messages: {
|
|
572
|
+
setupAfterAssertion: "Setup statements must appear before assertions in test bodies.",
|
|
573
|
+
sortError: "Test functions should be grouped by method with sorted metrics, errors, exceptions and middlewares."
|
|
574
|
+
},
|
|
460
575
|
schema: [],
|
|
461
576
|
type: "suggestion"
|
|
462
577
|
},
|
|
@@ -464,6 +579,25 @@ const rule$3 = {
|
|
|
464
579
|
if (!context.filename.endsWith(".spec.ts") && !context.filename.endsWith(".test.ts")) {
|
|
465
580
|
return {};
|
|
466
581
|
}
|
|
582
|
+
function handleTestBody(node) {
|
|
583
|
+
const callbackBody = getTestCallbackBlockBody(node);
|
|
584
|
+
if (!callbackBody) {
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
const firstAssertionIndex = callbackBody.body.findIndex(isAssertionStatement);
|
|
588
|
+
if (firstAssertionIndex === -1) {
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
for (const statement of callbackBody.body.slice(firstAssertionIndex + 1)) {
|
|
592
|
+
if (isAssertionStatement(statement) || isAssertionCountStatement(statement) || isTeardownStatement(statement)) {
|
|
593
|
+
continue;
|
|
594
|
+
}
|
|
595
|
+
context.report({
|
|
596
|
+
messageId: "setupAfterAssertion",
|
|
597
|
+
node: statement
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
467
601
|
function handleTestGroup(node) {
|
|
468
602
|
const testGroup = node.arguments[0];
|
|
469
603
|
if (!testGroup || !node.arguments[1]) {
|
|
@@ -512,6 +646,8 @@ const rule$3 = {
|
|
|
512
646
|
}
|
|
513
647
|
return {
|
|
514
648
|
'CallExpression[callee.name="describe"]': handleTestGroup,
|
|
649
|
+
'CallExpression[callee.name="it"]': handleTestBody,
|
|
650
|
+
'CallExpression[callee.name="test"]': handleTestBody,
|
|
515
651
|
'CallExpression[callee.object.name="describe"][callee.property.name="concurrent"]': handleTestGroup,
|
|
516
652
|
'CallExpression[callee.object.name="test"][callee.property.name="group"]': handleTestGroup
|
|
517
653
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -5198,7 +5198,7 @@ declare const _default: {
|
|
|
5198
5198
|
maxLineLength?: number;
|
|
5199
5199
|
minItems?: number;
|
|
5200
5200
|
} | undefined)?], unknown, RuleListener>;
|
|
5201
|
-
'ts-format-tests': RuleModule<"sortError", [], unknown, RuleListener>;
|
|
5201
|
+
'ts-format-tests': RuleModule<"setupAfterAssertion" | "sortError", [], unknown, RuleListener>;
|
|
5202
5202
|
'vue-format-i18n': RuleModule<"sortError" | "indentError" | "invalidJson" | "invalidLocale" | "missingLocale" | "missingTranslations" | "unusedString", [({
|
|
5203
5203
|
locales?: string[];
|
|
5204
5204
|
} | undefined)?], unknown, RuleListener>;
|
package/dist/index.d.mts
CHANGED
|
@@ -5198,7 +5198,7 @@ declare const _default: {
|
|
|
5198
5198
|
maxLineLength?: number;
|
|
5199
5199
|
minItems?: number;
|
|
5200
5200
|
} | undefined)?], unknown, RuleListener>;
|
|
5201
|
-
'ts-format-tests': RuleModule<"sortError", [], unknown, RuleListener>;
|
|
5201
|
+
'ts-format-tests': RuleModule<"setupAfterAssertion" | "sortError", [], unknown, RuleListener>;
|
|
5202
5202
|
'vue-format-i18n': RuleModule<"sortError" | "indentError" | "invalidJson" | "invalidLocale" | "missingLocale" | "missingTranslations" | "unusedString", [({
|
|
5203
5203
|
locales?: string[];
|
|
5204
5204
|
} | undefined)?], unknown, RuleListener>;
|
package/dist/index.d.ts
CHANGED
|
@@ -5198,7 +5198,7 @@ declare const _default: {
|
|
|
5198
5198
|
maxLineLength?: number;
|
|
5199
5199
|
minItems?: number;
|
|
5200
5200
|
} | undefined)?], unknown, RuleListener>;
|
|
5201
|
-
'ts-format-tests': RuleModule<"sortError", [], unknown, RuleListener>;
|
|
5201
|
+
'ts-format-tests': RuleModule<"setupAfterAssertion" | "sortError", [], unknown, RuleListener>;
|
|
5202
5202
|
'vue-format-i18n': RuleModule<"sortError" | "indentError" | "invalidJson" | "invalidLocale" | "missingLocale" | "missingTranslations" | "unusedString", [({
|
|
5203
5203
|
locales?: string[];
|
|
5204
5204
|
} | undefined)?], unknown, RuleListener>;
|
package/dist/index.mjs
CHANGED
|
@@ -61,7 +61,7 @@ function checkUnion(context, node, maxLineLength, minItems) {
|
|
|
61
61
|
function collapseBlankLine(text) {
|
|
62
62
|
return text.replace(/\n[^\S\n]*\n[^\S\n]*/, "\n");
|
|
63
63
|
}
|
|
64
|
-
function expressionStartsWithIdentifier(node, identifier) {
|
|
64
|
+
function expressionStartsWithIdentifier$1(node, identifier) {
|
|
65
65
|
if (node.type === distExports.AST_NODE_TYPES.Identifier && node.name === identifier) {
|
|
66
66
|
return true;
|
|
67
67
|
}
|
|
@@ -71,17 +71,17 @@ function expressionStartsWithIdentifier(node, identifier) {
|
|
|
71
71
|
return true;
|
|
72
72
|
}
|
|
73
73
|
if (callee.type === distExports.AST_NODE_TYPES.MemberExpression) {
|
|
74
|
-
return expressionStartsWithIdentifier(callee.object, identifier);
|
|
74
|
+
return expressionStartsWithIdentifier$1(callee.object, identifier);
|
|
75
75
|
}
|
|
76
76
|
if (callee.type === distExports.AST_NODE_TYPES.ChainExpression) {
|
|
77
|
-
return expressionStartsWithIdentifier(callee.expression, identifier);
|
|
77
|
+
return expressionStartsWithIdentifier$1(callee.expression, identifier);
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
if (node.type === distExports.AST_NODE_TYPES.MemberExpression) {
|
|
81
|
-
return expressionStartsWithIdentifier(node.object, identifier);
|
|
81
|
+
return expressionStartsWithIdentifier$1(node.object, identifier);
|
|
82
82
|
}
|
|
83
83
|
if (node.type === distExports.AST_NODE_TYPES.ChainExpression) {
|
|
84
|
-
return expressionStartsWithIdentifier(node.expression, identifier);
|
|
84
|
+
return expressionStartsWithIdentifier$1(node.expression, identifier);
|
|
85
85
|
}
|
|
86
86
|
return false;
|
|
87
87
|
}
|
|
@@ -209,10 +209,10 @@ function hasLineCommentBetween(prevNode, nextNode, sourceCode) {
|
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
211
|
function isAssertExpression(expression) {
|
|
212
|
-
return expressionStartsWithIdentifier(expression, "assert");
|
|
212
|
+
return expressionStartsWithIdentifier$1(expression, "assert");
|
|
213
213
|
}
|
|
214
214
|
function isConsoleExpression(expression) {
|
|
215
|
-
return expressionStartsWithIdentifier(expression, "console");
|
|
215
|
+
return expressionStartsWithIdentifier$1(expression, "console");
|
|
216
216
|
}
|
|
217
217
|
function isDirectivePrologue(node) {
|
|
218
218
|
if (node.expression.type !== distExports.AST_NODE_TYPES.Literal) {
|
|
@@ -221,7 +221,7 @@ function isDirectivePrologue(node) {
|
|
|
221
221
|
return typeof node.expression.value === "string";
|
|
222
222
|
}
|
|
223
223
|
function isExpectExpression(expression) {
|
|
224
|
-
return expressionStartsWithIdentifier(expression, "expect");
|
|
224
|
+
return expressionStartsWithIdentifier$1(expression, "expect");
|
|
225
225
|
}
|
|
226
226
|
function isOwnLineComment(comment, sourceCode) {
|
|
227
227
|
if (comment.type !== "Line") {
|
|
@@ -401,6 +401,7 @@ const rule$4 = {
|
|
|
401
401
|
}
|
|
402
402
|
};
|
|
403
403
|
|
|
404
|
+
const teardownViMethods = /* @__PURE__ */ new Set(["restoreAllMocks", "unstubAllGlobals", "useRealTimers"]);
|
|
404
405
|
function compareTests(testA, testB) {
|
|
405
406
|
const functionA = getFunctionName(testA);
|
|
406
407
|
const functionB = getFunctionName(testB);
|
|
@@ -416,6 +417,40 @@ function compareTests(testA, testB) {
|
|
|
416
417
|
const specificNameB = getSpecificName(testB);
|
|
417
418
|
return specificNameA.localeCompare(specificNameB);
|
|
418
419
|
}
|
|
420
|
+
function expressionStartsWithIdentifier(node, identifier) {
|
|
421
|
+
if (node.type === distExports.AST_NODE_TYPES.Identifier && node.name === identifier) {
|
|
422
|
+
return true;
|
|
423
|
+
}
|
|
424
|
+
if (node.type === distExports.AST_NODE_TYPES.CallExpression) {
|
|
425
|
+
const { callee } = node;
|
|
426
|
+
if (callee.type === distExports.AST_NODE_TYPES.Identifier && callee.name === identifier) {
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
if (callee.type === distExports.AST_NODE_TYPES.MemberExpression) {
|
|
430
|
+
return expressionStartsWithIdentifier(callee.object, identifier);
|
|
431
|
+
}
|
|
432
|
+
if (callee.type === distExports.AST_NODE_TYPES.ChainExpression) {
|
|
433
|
+
return expressionStartsWithIdentifier(callee.expression, identifier);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
if (node.type === distExports.AST_NODE_TYPES.MemberExpression) {
|
|
437
|
+
return expressionStartsWithIdentifier(node.object, identifier);
|
|
438
|
+
}
|
|
439
|
+
if (node.type === distExports.AST_NODE_TYPES.ChainExpression) {
|
|
440
|
+
return expressionStartsWithIdentifier(node.expression, identifier);
|
|
441
|
+
}
|
|
442
|
+
return false;
|
|
443
|
+
}
|
|
444
|
+
function getExpressionFromStatement(statement) {
|
|
445
|
+
if (statement.type !== distExports.AST_NODE_TYPES.ExpressionStatement) {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
let { expression } = statement;
|
|
449
|
+
if (expression.type === distExports.AST_NODE_TYPES.AwaitExpression) {
|
|
450
|
+
expression = expression.argument;
|
|
451
|
+
}
|
|
452
|
+
return expression;
|
|
453
|
+
}
|
|
419
454
|
function getFunctionName(testName) {
|
|
420
455
|
const parts = testName.split(".");
|
|
421
456
|
return parts.slice(0, 2).join(".");
|
|
@@ -429,6 +464,20 @@ function getSpecificName(testName) {
|
|
|
429
464
|
}
|
|
430
465
|
return parts.slice(specialIndex + 1).join(".");
|
|
431
466
|
}
|
|
467
|
+
function getTestCallbackBlockBody(node) {
|
|
468
|
+
const callback = node.arguments[1];
|
|
469
|
+
if (!callback) {
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
if (callback.type !== distExports.AST_NODE_TYPES.FunctionExpression && callback.type !== distExports.AST_NODE_TYPES.ArrowFunctionExpression) {
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
const { body } = callback;
|
|
476
|
+
if (body.type !== distExports.AST_NODE_TYPES.BlockStatement) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
return body;
|
|
480
|
+
}
|
|
432
481
|
function getTestName(node) {
|
|
433
482
|
const firstArgument = node.arguments[0];
|
|
434
483
|
if (firstArgument?.type === distExports.AST_NODE_TYPES.Literal && typeof firstArgument.value === "string") {
|
|
@@ -449,12 +498,78 @@ function getTestPriority(testName) {
|
|
|
449
498
|
return 1;
|
|
450
499
|
}
|
|
451
500
|
}
|
|
501
|
+
function hasAssertMethodCall(expression) {
|
|
502
|
+
if (expression.type !== distExports.AST_NODE_TYPES.CallExpression) {
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
const { callee } = expression;
|
|
506
|
+
if (callee.type === distExports.AST_NODE_TYPES.MemberExpression && callee.property.type === distExports.AST_NODE_TYPES.Identifier && callee.property.name.startsWith("assert")) {
|
|
507
|
+
if (callee.object.type === distExports.AST_NODE_TYPES.Identifier && callee.object.name === "expect") {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
return false;
|
|
513
|
+
}
|
|
514
|
+
function isAssertionCountExpression(expression) {
|
|
515
|
+
if (expression.type !== distExports.AST_NODE_TYPES.CallExpression) {
|
|
516
|
+
return false;
|
|
517
|
+
}
|
|
518
|
+
const { callee } = expression;
|
|
519
|
+
if (callee.type !== distExports.AST_NODE_TYPES.MemberExpression || callee.object.type !== distExports.AST_NODE_TYPES.Identifier || callee.property.type !== distExports.AST_NODE_TYPES.Identifier) {
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
if (callee.object.name === "expect" && (callee.property.name === "assertions" || callee.property.name === "hasAssertions")) {
|
|
523
|
+
return true;
|
|
524
|
+
}
|
|
525
|
+
return callee.object.name === "assert" && callee.property.name === "plan";
|
|
526
|
+
}
|
|
527
|
+
function isAssertionCountStatement(statement) {
|
|
528
|
+
const expression = getExpressionFromStatement(statement);
|
|
529
|
+
if (!expression) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
return isAssertionCountExpression(expression);
|
|
533
|
+
}
|
|
534
|
+
function isAssertionExpression(expression) {
|
|
535
|
+
if (isAssertionCountExpression(expression)) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
if (expressionStartsWithIdentifier(expression, "assert") || expressionStartsWithIdentifier(expression, "expect")) {
|
|
539
|
+
return true;
|
|
540
|
+
}
|
|
541
|
+
return hasAssertMethodCall(expression);
|
|
542
|
+
}
|
|
543
|
+
function isAssertionStatement(statement) {
|
|
544
|
+
const expression = getExpressionFromStatement(statement);
|
|
545
|
+
if (!expression) {
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
548
|
+
return isAssertionExpression(expression);
|
|
549
|
+
}
|
|
550
|
+
function isTeardownStatement(statement) {
|
|
551
|
+
const expression = getExpressionFromStatement(statement);
|
|
552
|
+
if (!expression || expression.type !== distExports.AST_NODE_TYPES.CallExpression) {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
const { callee } = expression;
|
|
556
|
+
if (callee.type === distExports.AST_NODE_TYPES.Identifier && callee.name === "cleanup") {
|
|
557
|
+
return true;
|
|
558
|
+
}
|
|
559
|
+
if (callee.type === distExports.AST_NODE_TYPES.MemberExpression && callee.object.type === distExports.AST_NODE_TYPES.Identifier && callee.object.name === "vi" && callee.property.type === distExports.AST_NODE_TYPES.Identifier && teardownViMethods.has(callee.property.name)) {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
452
564
|
const rule$3 = {
|
|
453
565
|
defaultOptions: [],
|
|
454
566
|
meta: {
|
|
455
|
-
docs: { description: "Enforce sorted test functions
|
|
567
|
+
docs: { description: "Enforce sorted test functions and setup-before-assertions layout in test bodies" },
|
|
456
568
|
fixable: "code",
|
|
457
|
-
messages: {
|
|
569
|
+
messages: {
|
|
570
|
+
setupAfterAssertion: "Setup statements must appear before assertions in test bodies.",
|
|
571
|
+
sortError: "Test functions should be grouped by method with sorted metrics, errors, exceptions and middlewares."
|
|
572
|
+
},
|
|
458
573
|
schema: [],
|
|
459
574
|
type: "suggestion"
|
|
460
575
|
},
|
|
@@ -462,6 +577,25 @@ const rule$3 = {
|
|
|
462
577
|
if (!context.filename.endsWith(".spec.ts") && !context.filename.endsWith(".test.ts")) {
|
|
463
578
|
return {};
|
|
464
579
|
}
|
|
580
|
+
function handleTestBody(node) {
|
|
581
|
+
const callbackBody = getTestCallbackBlockBody(node);
|
|
582
|
+
if (!callbackBody) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
const firstAssertionIndex = callbackBody.body.findIndex(isAssertionStatement);
|
|
586
|
+
if (firstAssertionIndex === -1) {
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
for (const statement of callbackBody.body.slice(firstAssertionIndex + 1)) {
|
|
590
|
+
if (isAssertionStatement(statement) || isAssertionCountStatement(statement) || isTeardownStatement(statement)) {
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
context.report({
|
|
594
|
+
messageId: "setupAfterAssertion",
|
|
595
|
+
node: statement
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
}
|
|
465
599
|
function handleTestGroup(node) {
|
|
466
600
|
const testGroup = node.arguments[0];
|
|
467
601
|
if (!testGroup || !node.arguments[1]) {
|
|
@@ -510,6 +644,8 @@ const rule$3 = {
|
|
|
510
644
|
}
|
|
511
645
|
return {
|
|
512
646
|
'CallExpression[callee.name="describe"]': handleTestGroup,
|
|
647
|
+
'CallExpression[callee.name="it"]': handleTestBody,
|
|
648
|
+
'CallExpression[callee.name="test"]': handleTestBody,
|
|
513
649
|
'CallExpression[callee.object.name="describe"][callee.property.name="concurrent"]': handleTestGroup,
|
|
514
650
|
'CallExpression[callee.object.name="test"][callee.property.name="group"]': handleTestGroup
|
|
515
651
|
};
|