eslint-plugin-playwright 1.1.2 → 1.3.0
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/README.md +53 -42
- package/dist/index.d.mts +39 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +752 -18
- package/dist/index.mjs +846 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -54,9 +54,12 @@ function isStringNode(node) {
|
|
|
54
54
|
function isPropertyAccessor(node, name) {
|
|
55
55
|
return getStringValue(node.property) === name;
|
|
56
56
|
}
|
|
57
|
-
function
|
|
57
|
+
function getTestNames(context) {
|
|
58
58
|
const aliases = context.settings.playwright?.globalAliases?.test ?? [];
|
|
59
|
-
|
|
59
|
+
return ["test", ...aliases];
|
|
60
|
+
}
|
|
61
|
+
function isTestIdentifier(context, node) {
|
|
62
|
+
const testNames = getTestNames(context);
|
|
60
63
|
const regex = new RegExp(`^(${testNames.join("|")})$`);
|
|
61
64
|
return isIdentifier(node, regex) || node.type === "MemberExpression" && isIdentifier(node.object, regex);
|
|
62
65
|
}
|
|
@@ -86,14 +89,34 @@ function findParent(node, type) {
|
|
|
86
89
|
return node.parent.type === type ? node.parent : findParent(node.parent, type);
|
|
87
90
|
}
|
|
88
91
|
function isTestCall(context, node, modifiers) {
|
|
89
|
-
return isTestIdentifier(context, node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && [
|
|
90
|
-
node.arguments[1].type
|
|
91
|
-
);
|
|
92
|
+
return isTestIdentifier(context, node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && isFunction(node.arguments[1]);
|
|
92
93
|
}
|
|
93
94
|
var testHooks = /* @__PURE__ */ new Set(["afterAll", "afterEach", "beforeAll", "beforeEach"]);
|
|
94
95
|
function isTestHook(context, node) {
|
|
95
96
|
return node.callee.type === "MemberExpression" && isTestIdentifier(context, node.callee.object) && testHooks.has(getStringValue(node.callee.property));
|
|
96
97
|
}
|
|
98
|
+
function parseFnCall(context, node) {
|
|
99
|
+
if (isTestCall(context, node)) {
|
|
100
|
+
return {
|
|
101
|
+
fn: node.arguments[1],
|
|
102
|
+
name: getStringValue(node.callee),
|
|
103
|
+
type: "test"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (node.callee.type === "MemberExpression" && isTestIdentifier(context, node.callee.object) && testHooks.has(getStringValue(node.callee.property))) {
|
|
107
|
+
return {
|
|
108
|
+
fn: node.arguments[0],
|
|
109
|
+
name: getStringValue(node.callee.property),
|
|
110
|
+
type: "hook"
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (isDescribeCall(node)) {
|
|
114
|
+
return {
|
|
115
|
+
name: getStringValue(node.callee),
|
|
116
|
+
type: "describe"
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
97
120
|
var expectSubCommands = /* @__PURE__ */ new Set(["soft", "poll"]);
|
|
98
121
|
function getExpectType(context, node) {
|
|
99
122
|
const aliases = context.settings.playwright?.globalAliases?.expect ?? [];
|
|
@@ -129,6 +152,7 @@ function isPageMethod(node, name) {
|
|
|
129
152
|
function isFunction(node) {
|
|
130
153
|
return node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression";
|
|
131
154
|
}
|
|
155
|
+
var equalityMatchers = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
132
156
|
|
|
133
157
|
// src/rules/expect-expect.ts
|
|
134
158
|
function isAssertionCall(context, node, assertFunctionNames) {
|
|
@@ -192,6 +216,69 @@ var expect_expect_default = {
|
|
|
192
216
|
}
|
|
193
217
|
};
|
|
194
218
|
|
|
219
|
+
// src/rules/max-expects.ts
|
|
220
|
+
var max_expects_default = {
|
|
221
|
+
create(context) {
|
|
222
|
+
const options = {
|
|
223
|
+
max: 5,
|
|
224
|
+
...context.options?.[0] ?? {}
|
|
225
|
+
};
|
|
226
|
+
let count = 0;
|
|
227
|
+
const maybeResetCount = (node) => {
|
|
228
|
+
const parent = getParent(node);
|
|
229
|
+
const isTestFn = parent?.type !== "CallExpression" || isTestCall(context, parent);
|
|
230
|
+
if (isTestFn) {
|
|
231
|
+
count = 0;
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
return {
|
|
235
|
+
ArrowFunctionExpression: maybeResetCount,
|
|
236
|
+
"ArrowFunctionExpression:exit": maybeResetCount,
|
|
237
|
+
CallExpression(node) {
|
|
238
|
+
if (!getExpectType(context, node))
|
|
239
|
+
return;
|
|
240
|
+
count += 1;
|
|
241
|
+
if (count > options.max) {
|
|
242
|
+
context.report({
|
|
243
|
+
data: {
|
|
244
|
+
count: count.toString(),
|
|
245
|
+
max: options.max.toString()
|
|
246
|
+
},
|
|
247
|
+
messageId: "exceededMaxAssertion",
|
|
248
|
+
node
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
FunctionExpression: maybeResetCount,
|
|
253
|
+
"FunctionExpression:exit": maybeResetCount
|
|
254
|
+
};
|
|
255
|
+
},
|
|
256
|
+
meta: {
|
|
257
|
+
docs: {
|
|
258
|
+
category: "Best Practices",
|
|
259
|
+
description: "Enforces a maximum number assertion calls in a test body",
|
|
260
|
+
recommended: false,
|
|
261
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-expects.md"
|
|
262
|
+
},
|
|
263
|
+
messages: {
|
|
264
|
+
exceededMaxAssertion: "Too many assertion calls ({{ count }}) - maximum allowed is {{ max }}"
|
|
265
|
+
},
|
|
266
|
+
schema: [
|
|
267
|
+
{
|
|
268
|
+
additionalProperties: false,
|
|
269
|
+
properties: {
|
|
270
|
+
max: {
|
|
271
|
+
minimum: 1,
|
|
272
|
+
type: "integer"
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
type: "object"
|
|
276
|
+
}
|
|
277
|
+
],
|
|
278
|
+
type: "suggestion"
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
195
282
|
// src/rules/max-nested-describe.ts
|
|
196
283
|
var max_nested_describe_default = {
|
|
197
284
|
create(context) {
|
|
@@ -399,6 +486,132 @@ var missing_playwright_await_default = {
|
|
|
399
486
|
}
|
|
400
487
|
};
|
|
401
488
|
|
|
489
|
+
// src/rules/no-commented-out-tests.ts
|
|
490
|
+
function hasTests(context, node) {
|
|
491
|
+
const testNames = getTestNames(context);
|
|
492
|
+
const names = testNames.join("|");
|
|
493
|
+
const regex = new RegExp(
|
|
494
|
+
`^\\s*(${names}|describe)(\\.\\w+|\\[['"]\\w+['"]\\])?\\s*\\(`,
|
|
495
|
+
"mu"
|
|
496
|
+
);
|
|
497
|
+
return regex.test(node.value);
|
|
498
|
+
}
|
|
499
|
+
var no_commented_out_tests_default = {
|
|
500
|
+
create(context) {
|
|
501
|
+
function checkNode(node) {
|
|
502
|
+
if (!hasTests(context, node))
|
|
503
|
+
return;
|
|
504
|
+
context.report({
|
|
505
|
+
messageId: "commentedTests",
|
|
506
|
+
node
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
return {
|
|
510
|
+
Program() {
|
|
511
|
+
context.sourceCode.getAllComments().forEach(checkNode);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
},
|
|
515
|
+
meta: {
|
|
516
|
+
docs: {
|
|
517
|
+
category: "Best Practices",
|
|
518
|
+
description: "Disallow commented out tests",
|
|
519
|
+
recommended: true,
|
|
520
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-commented-out-tests.md"
|
|
521
|
+
},
|
|
522
|
+
messages: {
|
|
523
|
+
commentedTests: "Some tests seem to be commented"
|
|
524
|
+
},
|
|
525
|
+
type: "problem"
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
// src/rules/no-conditional-expect.ts
|
|
530
|
+
var isCatchCall = (node) => node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "catch");
|
|
531
|
+
var getTestCallExpressionsFromDeclaredVariables = (context, declaredVariables) => {
|
|
532
|
+
return declaredVariables.reduce(
|
|
533
|
+
(acc, { references }) => [
|
|
534
|
+
...acc,
|
|
535
|
+
...references.map(({ identifier }) => getParent(identifier)).filter(
|
|
536
|
+
(node) => node?.type === "CallExpression" && isTestCall(context, node)
|
|
537
|
+
)
|
|
538
|
+
],
|
|
539
|
+
[]
|
|
540
|
+
);
|
|
541
|
+
};
|
|
542
|
+
var no_conditional_expect_default = {
|
|
543
|
+
create(context) {
|
|
544
|
+
let conditionalDepth = 0;
|
|
545
|
+
let inTestCase = false;
|
|
546
|
+
let inPromiseCatch = false;
|
|
547
|
+
const increaseConditionalDepth = () => inTestCase && conditionalDepth++;
|
|
548
|
+
const decreaseConditionalDepth = () => inTestCase && conditionalDepth--;
|
|
549
|
+
return {
|
|
550
|
+
CallExpression(node) {
|
|
551
|
+
if (isTestCall(context, node)) {
|
|
552
|
+
inTestCase = true;
|
|
553
|
+
}
|
|
554
|
+
if (isCatchCall(node)) {
|
|
555
|
+
inPromiseCatch = true;
|
|
556
|
+
}
|
|
557
|
+
const expectType = getExpectType(context, node);
|
|
558
|
+
if (inTestCase && expectType && conditionalDepth > 0) {
|
|
559
|
+
context.report({
|
|
560
|
+
messageId: "conditionalExpect",
|
|
561
|
+
node
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (inPromiseCatch && expectType) {
|
|
565
|
+
context.report({
|
|
566
|
+
messageId: "conditionalExpect",
|
|
567
|
+
node
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
"CallExpression:exit"(node) {
|
|
572
|
+
if (isTestCall(context, node)) {
|
|
573
|
+
inTestCase = false;
|
|
574
|
+
}
|
|
575
|
+
if (isCatchCall(node)) {
|
|
576
|
+
inPromiseCatch = false;
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
CatchClause: increaseConditionalDepth,
|
|
580
|
+
"CatchClause:exit": decreaseConditionalDepth,
|
|
581
|
+
ConditionalExpression: increaseConditionalDepth,
|
|
582
|
+
"ConditionalExpression:exit": decreaseConditionalDepth,
|
|
583
|
+
FunctionDeclaration(node) {
|
|
584
|
+
const declaredVariables = context.sourceCode.getDeclaredVariables(node);
|
|
585
|
+
const testCallExpressions = getTestCallExpressionsFromDeclaredVariables(
|
|
586
|
+
context,
|
|
587
|
+
declaredVariables
|
|
588
|
+
);
|
|
589
|
+
if (testCallExpressions.length > 0) {
|
|
590
|
+
inTestCase = true;
|
|
591
|
+
}
|
|
592
|
+
},
|
|
593
|
+
IfStatement: increaseConditionalDepth,
|
|
594
|
+
"IfStatement:exit": decreaseConditionalDepth,
|
|
595
|
+
LogicalExpression: increaseConditionalDepth,
|
|
596
|
+
"LogicalExpression:exit": decreaseConditionalDepth,
|
|
597
|
+
SwitchStatement: increaseConditionalDepth,
|
|
598
|
+
"SwitchStatement:exit": decreaseConditionalDepth
|
|
599
|
+
};
|
|
600
|
+
},
|
|
601
|
+
meta: {
|
|
602
|
+
docs: {
|
|
603
|
+
category: "Best Practices",
|
|
604
|
+
description: "Disallow calling `expect` conditionally",
|
|
605
|
+
recommended: true,
|
|
606
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-conditional-expect.md"
|
|
607
|
+
},
|
|
608
|
+
messages: {
|
|
609
|
+
conditionalExpect: "Avoid calling `expect` conditionally`"
|
|
610
|
+
},
|
|
611
|
+
type: "problem"
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
402
615
|
// src/rules/no-conditional-in-test.ts
|
|
403
616
|
var no_conditional_in_test_default = {
|
|
404
617
|
create(context) {
|
|
@@ -430,6 +643,51 @@ var no_conditional_in_test_default = {
|
|
|
430
643
|
}
|
|
431
644
|
};
|
|
432
645
|
|
|
646
|
+
// src/rules/no-duplicate-hooks.ts
|
|
647
|
+
var no_duplicate_hooks_default = {
|
|
648
|
+
create(context) {
|
|
649
|
+
const hookContexts = [{}];
|
|
650
|
+
return {
|
|
651
|
+
CallExpression(node) {
|
|
652
|
+
if (isDescribeCall(node)) {
|
|
653
|
+
hookContexts.push({});
|
|
654
|
+
}
|
|
655
|
+
if (!isTestHook(context, node)) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const currentLayer = hookContexts[hookContexts.length - 1];
|
|
659
|
+
const name = node.callee.type === "MemberExpression" ? getStringValue(node.callee.property) : "";
|
|
660
|
+
currentLayer[name] || (currentLayer[name] = 0);
|
|
661
|
+
currentLayer[name] += 1;
|
|
662
|
+
if (currentLayer[name] > 1) {
|
|
663
|
+
context.report({
|
|
664
|
+
data: { hook: name },
|
|
665
|
+
messageId: "noDuplicateHook",
|
|
666
|
+
node
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
},
|
|
670
|
+
"CallExpression:exit"(node) {
|
|
671
|
+
if (isDescribeCall(node)) {
|
|
672
|
+
hookContexts.pop();
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
},
|
|
677
|
+
meta: {
|
|
678
|
+
docs: {
|
|
679
|
+
category: "Best Practices",
|
|
680
|
+
description: "Disallow duplicate setup and teardown hooks",
|
|
681
|
+
recommended: false,
|
|
682
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-duplicate-hooks.md"
|
|
683
|
+
},
|
|
684
|
+
messages: {
|
|
685
|
+
noDuplicateHook: "Duplicate {{ hook }} in describe block"
|
|
686
|
+
},
|
|
687
|
+
type: "suggestion"
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
|
|
433
691
|
// src/rules/no-element-handle.ts
|
|
434
692
|
function getPropertyRange(node) {
|
|
435
693
|
return node.type === "Identifier" ? node.range : [node.range[0] + 1, node.range[1] - 1];
|
|
@@ -630,6 +888,52 @@ var no_get_by_title_default = {
|
|
|
630
888
|
}
|
|
631
889
|
};
|
|
632
890
|
|
|
891
|
+
// src/rules/no-hooks.ts
|
|
892
|
+
var no_hooks_default = {
|
|
893
|
+
create(context) {
|
|
894
|
+
const options = {
|
|
895
|
+
allow: [],
|
|
896
|
+
...context.options?.[0] ?? {}
|
|
897
|
+
};
|
|
898
|
+
return {
|
|
899
|
+
CallExpression(node) {
|
|
900
|
+
const call = parseFnCall(context, node);
|
|
901
|
+
if (call?.type === "hook" && !options.allow.includes(call.name)) {
|
|
902
|
+
context.report({
|
|
903
|
+
data: { hookName: call.name },
|
|
904
|
+
messageId: "unexpectedHook",
|
|
905
|
+
node
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
};
|
|
910
|
+
},
|
|
911
|
+
meta: {
|
|
912
|
+
docs: {
|
|
913
|
+
category: "Best Practices",
|
|
914
|
+
description: "Disallow setup and teardown hooks",
|
|
915
|
+
recommended: false,
|
|
916
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-hooks.md"
|
|
917
|
+
},
|
|
918
|
+
messages: {
|
|
919
|
+
unexpectedHook: "Unexpected '{{ hookName }}' hook"
|
|
920
|
+
},
|
|
921
|
+
schema: [
|
|
922
|
+
{
|
|
923
|
+
additionalProperties: false,
|
|
924
|
+
properties: {
|
|
925
|
+
allow: {
|
|
926
|
+
contains: ["beforeAll", "beforeEach", "afterAll", "afterEach"],
|
|
927
|
+
type: "array"
|
|
928
|
+
}
|
|
929
|
+
},
|
|
930
|
+
type: "object"
|
|
931
|
+
}
|
|
932
|
+
],
|
|
933
|
+
type: "suggestion"
|
|
934
|
+
}
|
|
935
|
+
};
|
|
936
|
+
|
|
633
937
|
// src/rules/no-nested-step.ts
|
|
634
938
|
function isStepCall(node) {
|
|
635
939
|
const inner = node.type === "CallExpression" ? node.callee : node;
|
|
@@ -997,6 +1301,95 @@ var no_skipped_test_default = {
|
|
|
997
1301
|
}
|
|
998
1302
|
};
|
|
999
1303
|
|
|
1304
|
+
// src/rules/no-standalone-expect.ts
|
|
1305
|
+
var getBlockType = (statement) => {
|
|
1306
|
+
const func = getParent(statement);
|
|
1307
|
+
if (!func) {
|
|
1308
|
+
throw new Error(
|
|
1309
|
+
`Unexpected BlockStatement. No parent defined. - please file a github issue at https://github.com/playwright-community/eslint-plugin-playwright`
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
if (func.type === "FunctionDeclaration") {
|
|
1313
|
+
return "function";
|
|
1314
|
+
}
|
|
1315
|
+
if (isFunction(func) && func.parent) {
|
|
1316
|
+
const expr = func.parent;
|
|
1317
|
+
if (expr.type === "VariableDeclarator" || expr.type === "MethodDefinition") {
|
|
1318
|
+
return "function";
|
|
1319
|
+
}
|
|
1320
|
+
if (expr.type === "CallExpression" && isDescribeCall(expr)) {
|
|
1321
|
+
return "describe";
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
return null;
|
|
1325
|
+
};
|
|
1326
|
+
var no_standalone_expect_default = {
|
|
1327
|
+
create(context) {
|
|
1328
|
+
const callStack = [];
|
|
1329
|
+
return {
|
|
1330
|
+
ArrowFunctionExpression(node) {
|
|
1331
|
+
if (node.parent?.type !== "CallExpression") {
|
|
1332
|
+
callStack.push("arrow");
|
|
1333
|
+
}
|
|
1334
|
+
},
|
|
1335
|
+
"ArrowFunctionExpression:exit"() {
|
|
1336
|
+
if (callStack[callStack.length - 1] === "arrow") {
|
|
1337
|
+
callStack.pop();
|
|
1338
|
+
}
|
|
1339
|
+
},
|
|
1340
|
+
BlockStatement(statement) {
|
|
1341
|
+
const blockType = getBlockType(statement);
|
|
1342
|
+
if (blockType) {
|
|
1343
|
+
callStack.push(blockType);
|
|
1344
|
+
}
|
|
1345
|
+
},
|
|
1346
|
+
"BlockStatement:exit"(statement) {
|
|
1347
|
+
if (callStack[callStack.length - 1] === getBlockType(statement)) {
|
|
1348
|
+
callStack.pop();
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
CallExpression(node) {
|
|
1352
|
+
if (getExpectType(context, node)) {
|
|
1353
|
+
const parent = callStack.at(-1);
|
|
1354
|
+
if (!parent || parent === "describe") {
|
|
1355
|
+
const root = findParent(node, "CallExpression");
|
|
1356
|
+
context.report({
|
|
1357
|
+
messageId: "unexpectedExpect",
|
|
1358
|
+
node: root ?? node
|
|
1359
|
+
});
|
|
1360
|
+
}
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (isTestCall(context, node)) {
|
|
1364
|
+
callStack.push("test");
|
|
1365
|
+
}
|
|
1366
|
+
if (node.callee.type === "TaggedTemplateExpression") {
|
|
1367
|
+
callStack.push("template");
|
|
1368
|
+
}
|
|
1369
|
+
},
|
|
1370
|
+
"CallExpression:exit"(node) {
|
|
1371
|
+
const top = callStack[callStack.length - 1];
|
|
1372
|
+
if (top === "test" && isTestCall(context, node) && node.callee.type !== "MemberExpression" || top === "template" && node.callee.type === "TaggedTemplateExpression") {
|
|
1373
|
+
callStack.pop();
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
};
|
|
1377
|
+
},
|
|
1378
|
+
meta: {
|
|
1379
|
+
docs: {
|
|
1380
|
+
category: "Best Practices",
|
|
1381
|
+
description: "Disallow using `expect` outside of `test` blocks",
|
|
1382
|
+
recommended: false,
|
|
1383
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-standalone-expect.md"
|
|
1384
|
+
},
|
|
1385
|
+
fixable: "code",
|
|
1386
|
+
messages: {
|
|
1387
|
+
unexpectedExpect: "Expect must be inside of a test block"
|
|
1388
|
+
},
|
|
1389
|
+
type: "suggestion"
|
|
1390
|
+
}
|
|
1391
|
+
};
|
|
1392
|
+
|
|
1000
1393
|
// src/utils/misc.ts
|
|
1001
1394
|
var getAmountData = (amount) => ({
|
|
1002
1395
|
amount: amount.toString(),
|
|
@@ -1319,6 +1712,258 @@ var no_wait_for_timeout_default = {
|
|
|
1319
1712
|
}
|
|
1320
1713
|
};
|
|
1321
1714
|
|
|
1715
|
+
// src/rules/prefer-comparison-matcher.ts
|
|
1716
|
+
var isString = (node) => {
|
|
1717
|
+
return isStringLiteral(node) || node.type === "TemplateLiteral";
|
|
1718
|
+
};
|
|
1719
|
+
var isComparingToString = (expression) => {
|
|
1720
|
+
return isString(expression.left) || isString(expression.right);
|
|
1721
|
+
};
|
|
1722
|
+
var invertedOperators = {
|
|
1723
|
+
"<": ">=",
|
|
1724
|
+
"<=": ">",
|
|
1725
|
+
">": "<=",
|
|
1726
|
+
">=": "<"
|
|
1727
|
+
};
|
|
1728
|
+
var operatorMatcher = {
|
|
1729
|
+
"<": "toBeLessThan",
|
|
1730
|
+
"<=": "toBeLessThanOrEqual",
|
|
1731
|
+
">": "toBeGreaterThan",
|
|
1732
|
+
">=": "toBeGreaterThanOrEqual"
|
|
1733
|
+
};
|
|
1734
|
+
var determineMatcher = (operator, negated) => {
|
|
1735
|
+
const op = negated ? invertedOperators[operator] : operator;
|
|
1736
|
+
return operatorMatcher[op] ?? null;
|
|
1737
|
+
};
|
|
1738
|
+
var prefer_comparison_matcher_default = {
|
|
1739
|
+
create(context) {
|
|
1740
|
+
return {
|
|
1741
|
+
CallExpression(node) {
|
|
1742
|
+
const expectCall = parseExpectCall(context, node);
|
|
1743
|
+
if (!expectCall || expectCall.args.length === 0)
|
|
1744
|
+
return;
|
|
1745
|
+
const { args, matcher } = expectCall;
|
|
1746
|
+
const [comparison] = node.arguments;
|
|
1747
|
+
const expectCallEnd = node.range[1];
|
|
1748
|
+
const [matcherArg] = args;
|
|
1749
|
+
if (comparison?.type !== "BinaryExpression" || isComparingToString(comparison) || !equalityMatchers.has(getStringValue(matcher)) || !isBooleanLiteral(matcherArg)) {
|
|
1750
|
+
return;
|
|
1751
|
+
}
|
|
1752
|
+
const hasNot = expectCall.modifiers.some(
|
|
1753
|
+
(node2) => getStringValue(node2) === "not"
|
|
1754
|
+
);
|
|
1755
|
+
const preferredMatcher = determineMatcher(
|
|
1756
|
+
comparison.operator,
|
|
1757
|
+
getRawValue(matcherArg) === hasNot.toString()
|
|
1758
|
+
);
|
|
1759
|
+
if (!preferredMatcher) {
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1762
|
+
context.report({
|
|
1763
|
+
data: { preferredMatcher },
|
|
1764
|
+
fix(fixer) {
|
|
1765
|
+
const [modifier] = expectCall.modifiers;
|
|
1766
|
+
const modifierText = modifier && getStringValue(modifier) !== "not" ? `.${getStringValue(modifier)}` : "";
|
|
1767
|
+
return [
|
|
1768
|
+
// Replace the comparison argument with the left-hand side of the comparison
|
|
1769
|
+
fixer.replaceText(
|
|
1770
|
+
comparison,
|
|
1771
|
+
context.sourceCode.getText(comparison.left)
|
|
1772
|
+
),
|
|
1773
|
+
// Replace the current matcher & modifier with the preferred matcher
|
|
1774
|
+
fixer.replaceTextRange(
|
|
1775
|
+
[expectCallEnd, getParent(matcher).range[1]],
|
|
1776
|
+
`${modifierText}.${preferredMatcher}`
|
|
1777
|
+
),
|
|
1778
|
+
// Replace the matcher argument with the right-hand side of the comparison
|
|
1779
|
+
fixer.replaceText(
|
|
1780
|
+
matcherArg,
|
|
1781
|
+
context.sourceCode.getText(comparison.right)
|
|
1782
|
+
)
|
|
1783
|
+
];
|
|
1784
|
+
},
|
|
1785
|
+
messageId: "useToBeComparison",
|
|
1786
|
+
node: matcher
|
|
1787
|
+
});
|
|
1788
|
+
}
|
|
1789
|
+
};
|
|
1790
|
+
},
|
|
1791
|
+
meta: {
|
|
1792
|
+
docs: {
|
|
1793
|
+
category: "Best Practices",
|
|
1794
|
+
description: "Suggest using the built-in comparison matchers",
|
|
1795
|
+
recommended: false
|
|
1796
|
+
},
|
|
1797
|
+
fixable: "code",
|
|
1798
|
+
messages: {
|
|
1799
|
+
useToBeComparison: "Prefer using `{{ preferredMatcher }}` instead"
|
|
1800
|
+
},
|
|
1801
|
+
type: "suggestion"
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
|
|
1805
|
+
// src/rules/prefer-equality-matcher.ts
|
|
1806
|
+
var prefer_equality_matcher_default = {
|
|
1807
|
+
create(context) {
|
|
1808
|
+
return {
|
|
1809
|
+
CallExpression(node) {
|
|
1810
|
+
const expectCall = parseExpectCall(context, node);
|
|
1811
|
+
if (!expectCall || expectCall.args.length === 0)
|
|
1812
|
+
return;
|
|
1813
|
+
const { args, matcher } = expectCall;
|
|
1814
|
+
const [comparison] = node.arguments;
|
|
1815
|
+
const expectCallEnd = node.range[1];
|
|
1816
|
+
const [matcherArg] = args;
|
|
1817
|
+
if (comparison?.type !== "BinaryExpression" || comparison.operator !== "===" && comparison.operator !== "!==" || !equalityMatchers.has(getStringValue(matcher)) || !isBooleanLiteral(matcherArg)) {
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
const matcherValue = getRawValue(matcherArg) === "true";
|
|
1821
|
+
const [modifier] = expectCall.modifiers;
|
|
1822
|
+
const hasNot = expectCall.modifiers.some(
|
|
1823
|
+
(node2) => getStringValue(node2) === "not"
|
|
1824
|
+
);
|
|
1825
|
+
const addNotModifier = (comparison.operator === "!==" ? !matcherValue : matcherValue) === hasNot;
|
|
1826
|
+
context.report({
|
|
1827
|
+
messageId: "useEqualityMatcher",
|
|
1828
|
+
node: matcher,
|
|
1829
|
+
suggest: [...equalityMatchers.keys()].map((equalityMatcher) => ({
|
|
1830
|
+
data: { matcher: equalityMatcher },
|
|
1831
|
+
fix(fixer) {
|
|
1832
|
+
let modifierText = modifier && getStringValue(modifier) !== "not" ? `.${getStringValue(modifier)}` : "";
|
|
1833
|
+
if (addNotModifier) {
|
|
1834
|
+
modifierText += `.not`;
|
|
1835
|
+
}
|
|
1836
|
+
return [
|
|
1837
|
+
// replace the comparison argument with the left-hand side of the comparison
|
|
1838
|
+
fixer.replaceText(
|
|
1839
|
+
comparison,
|
|
1840
|
+
context.sourceCode.getText(comparison.left)
|
|
1841
|
+
),
|
|
1842
|
+
// replace the current matcher & modifier with the preferred matcher
|
|
1843
|
+
fixer.replaceTextRange(
|
|
1844
|
+
[expectCallEnd, getParent(matcher).range[1]],
|
|
1845
|
+
`${modifierText}.${equalityMatcher}`
|
|
1846
|
+
),
|
|
1847
|
+
// replace the matcher argument with the right-hand side of the comparison
|
|
1848
|
+
fixer.replaceText(
|
|
1849
|
+
matcherArg,
|
|
1850
|
+
context.sourceCode.getText(comparison.right)
|
|
1851
|
+
)
|
|
1852
|
+
];
|
|
1853
|
+
},
|
|
1854
|
+
messageId: "suggestEqualityMatcher"
|
|
1855
|
+
}))
|
|
1856
|
+
});
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
},
|
|
1860
|
+
meta: {
|
|
1861
|
+
docs: {
|
|
1862
|
+
category: "Best Practices",
|
|
1863
|
+
description: "Suggest using the built-in equality matchers",
|
|
1864
|
+
recommended: false,
|
|
1865
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-equality-matcher.md"
|
|
1866
|
+
},
|
|
1867
|
+
hasSuggestions: true,
|
|
1868
|
+
messages: {
|
|
1869
|
+
suggestEqualityMatcher: "Use `{{ matcher }}`",
|
|
1870
|
+
useEqualityMatcher: "Prefer using one of the equality matchers instead"
|
|
1871
|
+
},
|
|
1872
|
+
type: "suggestion"
|
|
1873
|
+
}
|
|
1874
|
+
};
|
|
1875
|
+
|
|
1876
|
+
// src/rules/prefer-hooks-in-order.ts
|
|
1877
|
+
var HooksOrder = ["beforeAll", "beforeEach", "afterEach", "afterAll"];
|
|
1878
|
+
var prefer_hooks_in_order_default = {
|
|
1879
|
+
create(context) {
|
|
1880
|
+
let previousHookIndex = -1;
|
|
1881
|
+
let inHook = false;
|
|
1882
|
+
return {
|
|
1883
|
+
CallExpression(node) {
|
|
1884
|
+
if (inHook)
|
|
1885
|
+
return;
|
|
1886
|
+
if (!isTestHook(context, node)) {
|
|
1887
|
+
previousHookIndex = -1;
|
|
1888
|
+
return;
|
|
1889
|
+
}
|
|
1890
|
+
inHook = true;
|
|
1891
|
+
const currentHook = node.callee.type === "MemberExpression" ? getStringValue(node.callee.property) : "";
|
|
1892
|
+
const currentHookIndex = HooksOrder.indexOf(currentHook);
|
|
1893
|
+
if (currentHookIndex < previousHookIndex) {
|
|
1894
|
+
return context.report({
|
|
1895
|
+
data: {
|
|
1896
|
+
currentHook,
|
|
1897
|
+
previousHook: HooksOrder[previousHookIndex]
|
|
1898
|
+
},
|
|
1899
|
+
messageId: "reorderHooks",
|
|
1900
|
+
node
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
previousHookIndex = currentHookIndex;
|
|
1904
|
+
},
|
|
1905
|
+
"CallExpression:exit"(node) {
|
|
1906
|
+
if (isTestHook(context, node)) {
|
|
1907
|
+
inHook = false;
|
|
1908
|
+
return;
|
|
1909
|
+
}
|
|
1910
|
+
if (inHook) {
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
previousHookIndex = -1;
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
},
|
|
1917
|
+
meta: {
|
|
1918
|
+
docs: {
|
|
1919
|
+
category: "Best Practices",
|
|
1920
|
+
description: "Prefer having hooks in a consistent order",
|
|
1921
|
+
recommended: false,
|
|
1922
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-in-order.md"
|
|
1923
|
+
},
|
|
1924
|
+
messages: {
|
|
1925
|
+
reorderHooks: "`{{ currentHook }}` hooks should be before any `{{ previousHook }}` hooks"
|
|
1926
|
+
},
|
|
1927
|
+
type: "suggestion"
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
|
|
1931
|
+
// src/rules/prefer-hooks-on-top.ts
|
|
1932
|
+
var prefer_hooks_on_top_default = {
|
|
1933
|
+
create(context) {
|
|
1934
|
+
const stack = [false];
|
|
1935
|
+
return {
|
|
1936
|
+
CallExpression(node) {
|
|
1937
|
+
if (isTestCall(context, node)) {
|
|
1938
|
+
stack[stack.length - 1] = true;
|
|
1939
|
+
}
|
|
1940
|
+
if (stack.at(-1) && isTestHook(context, node)) {
|
|
1941
|
+
context.report({
|
|
1942
|
+
messageId: "noHookOnTop",
|
|
1943
|
+
node
|
|
1944
|
+
});
|
|
1945
|
+
}
|
|
1946
|
+
stack.push(false);
|
|
1947
|
+
},
|
|
1948
|
+
"CallExpression:exit"() {
|
|
1949
|
+
stack.pop();
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
},
|
|
1953
|
+
meta: {
|
|
1954
|
+
docs: {
|
|
1955
|
+
category: "Best Practices",
|
|
1956
|
+
description: "Suggest having hooks before any test cases",
|
|
1957
|
+
recommended: false,
|
|
1958
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-on-top.md"
|
|
1959
|
+
},
|
|
1960
|
+
messages: {
|
|
1961
|
+
noHookOnTop: "Hooks should come before test cases"
|
|
1962
|
+
},
|
|
1963
|
+
type: "suggestion"
|
|
1964
|
+
}
|
|
1965
|
+
};
|
|
1966
|
+
|
|
1322
1967
|
// src/rules/prefer-lowercase-title.ts
|
|
1323
1968
|
var prefer_lowercase_title_default = {
|
|
1324
1969
|
create(context) {
|
|
@@ -1506,9 +2151,8 @@ var prefer_to_be_default = {
|
|
|
1506
2151
|
notModifier
|
|
1507
2152
|
);
|
|
1508
2153
|
}
|
|
1509
|
-
const argumentMatchers = ["toBe", "toEqual", "toStrictEqual"];
|
|
1510
2154
|
const firstArg = expectCall.args[0];
|
|
1511
|
-
if (!
|
|
2155
|
+
if (!equalityMatchers.has(expectCall.matcherName) || !firstArg) {
|
|
1512
2156
|
return;
|
|
1513
2157
|
}
|
|
1514
2158
|
if (firstArg.type === "Literal" && firstArg.value === null) {
|
|
@@ -1548,7 +2192,6 @@ var prefer_to_be_default = {
|
|
|
1548
2192
|
};
|
|
1549
2193
|
|
|
1550
2194
|
// src/rules/prefer-to-contain.ts
|
|
1551
|
-
var matchers = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
1552
2195
|
var isFixableIncludesCallExpression = (node) => node.type === "CallExpression" && node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "includes") && node.arguments.length === 1 && node.arguments[0].type !== "SpreadElement";
|
|
1553
2196
|
var prefer_to_contain_default = {
|
|
1554
2197
|
create(context) {
|
|
@@ -1560,7 +2203,7 @@ var prefer_to_contain_default = {
|
|
|
1560
2203
|
const { args, matcher, matcherName } = expectCall;
|
|
1561
2204
|
const [includesCall] = node.arguments;
|
|
1562
2205
|
const [matcherArg] = args;
|
|
1563
|
-
if (!includesCall || matcherArg.type === "SpreadElement" || !
|
|
2206
|
+
if (!includesCall || matcherArg.type === "SpreadElement" || !equalityMatchers.has(matcherName) || !isBooleanLiteral(matcherArg) || !isFixableIncludesCallExpression(includesCall)) {
|
|
1564
2207
|
return;
|
|
1565
2208
|
}
|
|
1566
2209
|
const notModifier = expectCall.modifiers.find(
|
|
@@ -1618,13 +2261,12 @@ var prefer_to_contain_default = {
|
|
|
1618
2261
|
};
|
|
1619
2262
|
|
|
1620
2263
|
// src/rules/prefer-to-have-count.ts
|
|
1621
|
-
var matchers2 = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
1622
2264
|
var prefer_to_have_count_default = {
|
|
1623
2265
|
create(context) {
|
|
1624
2266
|
return {
|
|
1625
2267
|
CallExpression(node) {
|
|
1626
2268
|
const expectCall = parseExpectCall(context, node);
|
|
1627
|
-
if (!expectCall || !
|
|
2269
|
+
if (!expectCall || !equalityMatchers.has(expectCall.matcherName)) {
|
|
1628
2270
|
return;
|
|
1629
2271
|
}
|
|
1630
2272
|
const [argument] = node.arguments;
|
|
@@ -1674,13 +2316,12 @@ var prefer_to_have_count_default = {
|
|
|
1674
2316
|
};
|
|
1675
2317
|
|
|
1676
2318
|
// src/rules/prefer-to-have-length.ts
|
|
1677
|
-
var lengthMatchers = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
|
|
1678
2319
|
var prefer_to_have_length_default = {
|
|
1679
2320
|
create(context) {
|
|
1680
2321
|
return {
|
|
1681
2322
|
CallExpression(node) {
|
|
1682
2323
|
const expectCall = parseExpectCall(context, node);
|
|
1683
|
-
if (!expectCall || !
|
|
2324
|
+
if (!expectCall || !equalityMatchers.has(expectCall.matcherName)) {
|
|
1684
2325
|
return;
|
|
1685
2326
|
}
|
|
1686
2327
|
const [argument] = node.arguments;
|
|
@@ -1875,6 +2516,86 @@ var prefer_web_first_assertions_default = {
|
|
|
1875
2516
|
}
|
|
1876
2517
|
};
|
|
1877
2518
|
|
|
2519
|
+
// src/rules/require-hook.ts
|
|
2520
|
+
var isNullOrUndefined = (node) => {
|
|
2521
|
+
return node.type === "Literal" && node.value === null || isIdentifier(node, "undefined");
|
|
2522
|
+
};
|
|
2523
|
+
var shouldBeInHook = (context, node, allowedFunctionCalls = []) => {
|
|
2524
|
+
switch (node.type) {
|
|
2525
|
+
case "ExpressionStatement":
|
|
2526
|
+
return shouldBeInHook(context, node.expression, allowedFunctionCalls);
|
|
2527
|
+
case "CallExpression":
|
|
2528
|
+
return !(parseFnCall(context, node) || allowedFunctionCalls.includes(getStringValue(node.callee)));
|
|
2529
|
+
case "VariableDeclaration": {
|
|
2530
|
+
if (node.kind === "const") {
|
|
2531
|
+
return false;
|
|
2532
|
+
}
|
|
2533
|
+
return node.declarations.some(
|
|
2534
|
+
({ init }) => init != null && !isNullOrUndefined(init)
|
|
2535
|
+
);
|
|
2536
|
+
}
|
|
2537
|
+
default:
|
|
2538
|
+
return false;
|
|
2539
|
+
}
|
|
2540
|
+
};
|
|
2541
|
+
var require_hook_default = {
|
|
2542
|
+
create(context) {
|
|
2543
|
+
const options = {
|
|
2544
|
+
allowedFunctionCalls: [],
|
|
2545
|
+
...context.options?.[0] ?? {}
|
|
2546
|
+
};
|
|
2547
|
+
const checkBlockBody = (body) => {
|
|
2548
|
+
for (const statement of body) {
|
|
2549
|
+
if (shouldBeInHook(context, statement, options.allowedFunctionCalls)) {
|
|
2550
|
+
context.report({
|
|
2551
|
+
messageId: "useHook",
|
|
2552
|
+
node: statement
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
}
|
|
2556
|
+
};
|
|
2557
|
+
return {
|
|
2558
|
+
CallExpression(node) {
|
|
2559
|
+
if (!isDescribeCall(node) || node.arguments.length < 2) {
|
|
2560
|
+
return;
|
|
2561
|
+
}
|
|
2562
|
+
const [, testFn] = node.arguments;
|
|
2563
|
+
if (!isFunction(testFn) || testFn.body.type !== "BlockStatement") {
|
|
2564
|
+
return;
|
|
2565
|
+
}
|
|
2566
|
+
checkBlockBody(testFn.body.body);
|
|
2567
|
+
},
|
|
2568
|
+
Program(program) {
|
|
2569
|
+
checkBlockBody(program.body);
|
|
2570
|
+
}
|
|
2571
|
+
};
|
|
2572
|
+
},
|
|
2573
|
+
meta: {
|
|
2574
|
+
docs: {
|
|
2575
|
+
category: "Best Practices",
|
|
2576
|
+
description: "Require setup and teardown code to be within a hook",
|
|
2577
|
+
recommended: false,
|
|
2578
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-hook.md"
|
|
2579
|
+
},
|
|
2580
|
+
messages: {
|
|
2581
|
+
useHook: "This should be done within a hook"
|
|
2582
|
+
},
|
|
2583
|
+
schema: [
|
|
2584
|
+
{
|
|
2585
|
+
additionalProperties: false,
|
|
2586
|
+
properties: {
|
|
2587
|
+
allowedFunctionCalls: {
|
|
2588
|
+
items: { type: "string" },
|
|
2589
|
+
type: "array"
|
|
2590
|
+
}
|
|
2591
|
+
},
|
|
2592
|
+
type: "object"
|
|
2593
|
+
}
|
|
2594
|
+
],
|
|
2595
|
+
type: "suggestion"
|
|
2596
|
+
}
|
|
2597
|
+
};
|
|
2598
|
+
|
|
1878
2599
|
// src/rules/require-soft-assertions.ts
|
|
1879
2600
|
var require_soft_assertions_default = {
|
|
1880
2601
|
create(context) {
|
|
@@ -2071,17 +2792,17 @@ var compileMatcherPattern = (matcherMaybeWithMessage) => {
|
|
|
2071
2792
|
const [matcher, message] = Array.isArray(matcherMaybeWithMessage) ? matcherMaybeWithMessage : [matcherMaybeWithMessage];
|
|
2072
2793
|
return [new RegExp(matcher, "u"), message];
|
|
2073
2794
|
};
|
|
2074
|
-
var compileMatcherPatterns = (
|
|
2075
|
-
if (typeof
|
|
2076
|
-
const compiledMatcher = compileMatcherPattern(
|
|
2795
|
+
var compileMatcherPatterns = (matchers) => {
|
|
2796
|
+
if (typeof matchers === "string" || Array.isArray(matchers)) {
|
|
2797
|
+
const compiledMatcher = compileMatcherPattern(matchers);
|
|
2077
2798
|
return {
|
|
2078
2799
|
describe: compiledMatcher,
|
|
2079
2800
|
test: compiledMatcher
|
|
2080
2801
|
};
|
|
2081
2802
|
}
|
|
2082
2803
|
return {
|
|
2083
|
-
describe:
|
|
2084
|
-
test:
|
|
2804
|
+
describe: matchers.describe ? compileMatcherPattern(matchers.describe) : null,
|
|
2805
|
+
test: matchers.test ? compileMatcherPattern(matchers.test) : null
|
|
2085
2806
|
};
|
|
2086
2807
|
};
|
|
2087
2808
|
var MatcherAndMessageSchema = {
|
|
@@ -2273,14 +2994,19 @@ var index = {
|
|
|
2273
2994
|
configs: {},
|
|
2274
2995
|
rules: {
|
|
2275
2996
|
"expect-expect": expect_expect_default,
|
|
2997
|
+
"max-expects": max_expects_default,
|
|
2276
2998
|
"max-nested-describe": max_nested_describe_default,
|
|
2277
2999
|
"missing-playwright-await": missing_playwright_await_default,
|
|
3000
|
+
"no-commented-out-tests": no_commented_out_tests_default,
|
|
3001
|
+
"no-conditional-expect": no_conditional_expect_default,
|
|
2278
3002
|
"no-conditional-in-test": no_conditional_in_test_default,
|
|
3003
|
+
"no-duplicate-hooks": no_duplicate_hooks_default,
|
|
2279
3004
|
"no-element-handle": no_element_handle_default,
|
|
2280
3005
|
"no-eval": no_eval_default,
|
|
2281
3006
|
"no-focused-test": no_focused_test_default,
|
|
2282
3007
|
"no-force-option": no_force_option_default,
|
|
2283
3008
|
"no-get-by-title": no_get_by_title_default,
|
|
3009
|
+
"no-hooks": no_hooks_default,
|
|
2284
3010
|
"no-nested-step": no_nested_step_default,
|
|
2285
3011
|
"no-networkidle": no_networkidle_default,
|
|
2286
3012
|
"no-nth-methods": no_nth_methods_default,
|
|
@@ -2288,11 +3014,16 @@ var index = {
|
|
|
2288
3014
|
"no-raw-locators": no_raw_locators_default,
|
|
2289
3015
|
"no-restricted-matchers": no_restricted_matchers_default,
|
|
2290
3016
|
"no-skipped-test": no_skipped_test_default,
|
|
3017
|
+
"no-standalone-expect": no_standalone_expect_default,
|
|
2291
3018
|
"no-unsafe-references": no_unsafe_references_default,
|
|
2292
3019
|
"no-useless-await": no_useless_await_default,
|
|
2293
3020
|
"no-useless-not": no_useless_not_default,
|
|
2294
3021
|
"no-wait-for-selector": no_wait_for_selector_default,
|
|
2295
3022
|
"no-wait-for-timeout": no_wait_for_timeout_default,
|
|
3023
|
+
"prefer-comparison-matcher": prefer_comparison_matcher_default,
|
|
3024
|
+
"prefer-equality-matcher": prefer_equality_matcher_default,
|
|
3025
|
+
"prefer-hooks-in-order": prefer_hooks_in_order_default,
|
|
3026
|
+
"prefer-hooks-on-top": prefer_hooks_on_top_default,
|
|
2296
3027
|
"prefer-lowercase-title": prefer_lowercase_title_default,
|
|
2297
3028
|
"prefer-strict-equal": prefer_strict_equal_default,
|
|
2298
3029
|
"prefer-to-be": prefer_to_be_default,
|
|
@@ -2300,6 +3031,7 @@ var index = {
|
|
|
2300
3031
|
"prefer-to-have-count": prefer_to_have_count_default,
|
|
2301
3032
|
"prefer-to-have-length": prefer_to_have_length_default,
|
|
2302
3033
|
"prefer-web-first-assertions": prefer_web_first_assertions_default,
|
|
3034
|
+
"require-hook": require_hook_default,
|
|
2303
3035
|
"require-soft-assertions": require_soft_assertions_default,
|
|
2304
3036
|
"require-top-level-describe": require_top_level_describe_default,
|
|
2305
3037
|
"valid-expect": valid_expect_default,
|
|
@@ -2312,6 +3044,7 @@ var sharedConfig = {
|
|
|
2312
3044
|
"playwright/expect-expect": "warn",
|
|
2313
3045
|
"playwright/max-nested-describe": "warn",
|
|
2314
3046
|
"playwright/missing-playwright-await": "error",
|
|
3047
|
+
"playwright/no-conditional-expect": "warn",
|
|
2315
3048
|
"playwright/no-conditional-in-test": "warn",
|
|
2316
3049
|
"playwright/no-element-handle": "warn",
|
|
2317
3050
|
"playwright/no-eval": "warn",
|
|
@@ -2321,6 +3054,7 @@ var sharedConfig = {
|
|
|
2321
3054
|
"playwright/no-networkidle": "error",
|
|
2322
3055
|
"playwright/no-page-pause": "warn",
|
|
2323
3056
|
"playwright/no-skipped-test": "warn",
|
|
3057
|
+
"playwright/no-standalone-expect": "error",
|
|
2324
3058
|
"playwright/no-unsafe-references": "error",
|
|
2325
3059
|
"playwright/no-useless-await": "warn",
|
|
2326
3060
|
"playwright/no-useless-not": "warn",
|