eslint-plugin-playwright 1.1.2 → 1.2.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 +8 -1
- package/dist/index.d.mts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +429 -5
- package/dist/index.mjs +485 -5
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -33,9 +33,12 @@ function isStringNode(node) {
|
|
|
33
33
|
function isPropertyAccessor(node, name) {
|
|
34
34
|
return getStringValue(node.property) === name;
|
|
35
35
|
}
|
|
36
|
-
function
|
|
36
|
+
function getTestNames(context) {
|
|
37
37
|
const aliases = context.settings.playwright?.globalAliases?.test ?? [];
|
|
38
|
-
|
|
38
|
+
return ["test", ...aliases];
|
|
39
|
+
}
|
|
40
|
+
function isTestIdentifier(context, node) {
|
|
41
|
+
const testNames = getTestNames(context);
|
|
39
42
|
const regex = new RegExp(`^(${testNames.join("|")})$`);
|
|
40
43
|
return isIdentifier(node, regex) || node.type === "MemberExpression" && isIdentifier(node.object, regex);
|
|
41
44
|
}
|
|
@@ -58,9 +61,7 @@ function findParent(node, type) {
|
|
|
58
61
|
return node.parent.type === type ? node.parent : findParent(node.parent, type);
|
|
59
62
|
}
|
|
60
63
|
function isTestCall(context, node, modifiers) {
|
|
61
|
-
return isTestIdentifier(context, node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && [
|
|
62
|
-
node.arguments[1].type
|
|
63
|
-
);
|
|
64
|
+
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]);
|
|
64
65
|
}
|
|
65
66
|
function isTestHook(context, node) {
|
|
66
67
|
return node.callee.type === "MemberExpression" && isTestIdentifier(context, node.callee.object) && testHooks.has(getStringValue(node.callee.property));
|
|
@@ -186,6 +187,76 @@ var init_expect_expect = __esm({
|
|
|
186
187
|
}
|
|
187
188
|
});
|
|
188
189
|
|
|
190
|
+
// src/rules/max-expects.ts
|
|
191
|
+
var max_expects_default;
|
|
192
|
+
var init_max_expects = __esm({
|
|
193
|
+
"src/rules/max-expects.ts"() {
|
|
194
|
+
"use strict";
|
|
195
|
+
init_ast();
|
|
196
|
+
max_expects_default = {
|
|
197
|
+
create(context) {
|
|
198
|
+
const options = {
|
|
199
|
+
max: 5,
|
|
200
|
+
...context.options?.[0] ?? {}
|
|
201
|
+
};
|
|
202
|
+
let count = 0;
|
|
203
|
+
const maybeResetCount = (node) => {
|
|
204
|
+
const parent = getParent(node);
|
|
205
|
+
const isTestFn = parent?.type !== "CallExpression" || isTestCall(context, parent);
|
|
206
|
+
if (isTestFn) {
|
|
207
|
+
count = 0;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
ArrowFunctionExpression: maybeResetCount,
|
|
212
|
+
"ArrowFunctionExpression:exit": maybeResetCount,
|
|
213
|
+
CallExpression(node) {
|
|
214
|
+
if (!getExpectType(context, node))
|
|
215
|
+
return;
|
|
216
|
+
count += 1;
|
|
217
|
+
if (count > options.max) {
|
|
218
|
+
context.report({
|
|
219
|
+
data: {
|
|
220
|
+
count: count.toString(),
|
|
221
|
+
max: options.max.toString()
|
|
222
|
+
},
|
|
223
|
+
messageId: "exceededMaxAssertion",
|
|
224
|
+
node
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
FunctionExpression: maybeResetCount,
|
|
229
|
+
"FunctionExpression:exit": maybeResetCount
|
|
230
|
+
};
|
|
231
|
+
},
|
|
232
|
+
meta: {
|
|
233
|
+
docs: {
|
|
234
|
+
category: "Best Practices",
|
|
235
|
+
description: "Enforces a maximum number assertion calls in a test body",
|
|
236
|
+
recommended: false,
|
|
237
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/max-expects.md"
|
|
238
|
+
},
|
|
239
|
+
messages: {
|
|
240
|
+
exceededMaxAssertion: "Too many assertion calls ({{ count }}) - maximum allowed is {{ max }}"
|
|
241
|
+
},
|
|
242
|
+
schema: [
|
|
243
|
+
{
|
|
244
|
+
additionalProperties: false,
|
|
245
|
+
properties: {
|
|
246
|
+
max: {
|
|
247
|
+
minimum: 1,
|
|
248
|
+
type: "integer"
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
type: "object"
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
type: "suggestion"
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
189
260
|
// src/rules/max-nested-describe.ts
|
|
190
261
|
var max_nested_describe_default;
|
|
191
262
|
var init_max_nested_describe = __esm({
|
|
@@ -407,6 +478,146 @@ var init_missing_playwright_await = __esm({
|
|
|
407
478
|
}
|
|
408
479
|
});
|
|
409
480
|
|
|
481
|
+
// src/rules/no-commented-out-tests.ts
|
|
482
|
+
function hasTests(context, node) {
|
|
483
|
+
const testNames = getTestNames(context);
|
|
484
|
+
const names = testNames.join("|");
|
|
485
|
+
const regex = new RegExp(
|
|
486
|
+
`^\\s*(${names}|describe)(\\.\\w+|\\[['"]\\w+['"]\\])?\\s*\\(`,
|
|
487
|
+
"mu"
|
|
488
|
+
);
|
|
489
|
+
return regex.test(node.value);
|
|
490
|
+
}
|
|
491
|
+
var no_commented_out_tests_default;
|
|
492
|
+
var init_no_commented_out_tests = __esm({
|
|
493
|
+
"src/rules/no-commented-out-tests.ts"() {
|
|
494
|
+
"use strict";
|
|
495
|
+
init_ast();
|
|
496
|
+
no_commented_out_tests_default = {
|
|
497
|
+
create(context) {
|
|
498
|
+
function checkNode(node) {
|
|
499
|
+
if (!hasTests(context, node))
|
|
500
|
+
return;
|
|
501
|
+
context.report({
|
|
502
|
+
messageId: "commentedTests",
|
|
503
|
+
node
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
return {
|
|
507
|
+
Program() {
|
|
508
|
+
context.sourceCode.getAllComments().forEach(checkNode);
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
},
|
|
512
|
+
meta: {
|
|
513
|
+
docs: {
|
|
514
|
+
category: "Best Practices",
|
|
515
|
+
description: "Disallow commented out tests",
|
|
516
|
+
recommended: true,
|
|
517
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-commented-out-tests.md"
|
|
518
|
+
},
|
|
519
|
+
messages: {
|
|
520
|
+
commentedTests: "Some tests seem to be commented"
|
|
521
|
+
},
|
|
522
|
+
type: "problem"
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// src/rules/no-conditional-expect.ts
|
|
529
|
+
var isCatchCall, getTestCallExpressionsFromDeclaredVariables, no_conditional_expect_default;
|
|
530
|
+
var init_no_conditional_expect = __esm({
|
|
531
|
+
"src/rules/no-conditional-expect.ts"() {
|
|
532
|
+
"use strict";
|
|
533
|
+
init_ast();
|
|
534
|
+
isCatchCall = (node) => node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "catch");
|
|
535
|
+
getTestCallExpressionsFromDeclaredVariables = (context, declaredVariables) => {
|
|
536
|
+
return declaredVariables.reduce(
|
|
537
|
+
(acc, { references }) => [
|
|
538
|
+
...acc,
|
|
539
|
+
...references.map(({ identifier }) => getParent(identifier)).filter(
|
|
540
|
+
(node) => node?.type === "CallExpression" && isTestCall(context, node)
|
|
541
|
+
)
|
|
542
|
+
],
|
|
543
|
+
[]
|
|
544
|
+
);
|
|
545
|
+
};
|
|
546
|
+
no_conditional_expect_default = {
|
|
547
|
+
create(context) {
|
|
548
|
+
let conditionalDepth = 0;
|
|
549
|
+
let inTestCase = false;
|
|
550
|
+
let inPromiseCatch = false;
|
|
551
|
+
const increaseConditionalDepth = () => inTestCase && conditionalDepth++;
|
|
552
|
+
const decreaseConditionalDepth = () => inTestCase && conditionalDepth--;
|
|
553
|
+
return {
|
|
554
|
+
CallExpression(node) {
|
|
555
|
+
if (isTestCall(context, node)) {
|
|
556
|
+
inTestCase = true;
|
|
557
|
+
}
|
|
558
|
+
if (isCatchCall(node)) {
|
|
559
|
+
inPromiseCatch = true;
|
|
560
|
+
}
|
|
561
|
+
const expectType = getExpectType(context, node);
|
|
562
|
+
if (inTestCase && expectType && conditionalDepth > 0) {
|
|
563
|
+
context.report({
|
|
564
|
+
messageId: "conditionalExpect",
|
|
565
|
+
node
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
if (inPromiseCatch && expectType) {
|
|
569
|
+
context.report({
|
|
570
|
+
messageId: "conditionalExpect",
|
|
571
|
+
node
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
"CallExpression:exit"(node) {
|
|
576
|
+
if (isTestCall(context, node)) {
|
|
577
|
+
inTestCase = false;
|
|
578
|
+
}
|
|
579
|
+
if (isCatchCall(node)) {
|
|
580
|
+
inPromiseCatch = false;
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
CatchClause: increaseConditionalDepth,
|
|
584
|
+
"CatchClause:exit": decreaseConditionalDepth,
|
|
585
|
+
ConditionalExpression: increaseConditionalDepth,
|
|
586
|
+
"ConditionalExpression:exit": decreaseConditionalDepth,
|
|
587
|
+
FunctionDeclaration(node) {
|
|
588
|
+
const declaredVariables = context.sourceCode.getDeclaredVariables(node);
|
|
589
|
+
const testCallExpressions = getTestCallExpressionsFromDeclaredVariables(
|
|
590
|
+
context,
|
|
591
|
+
declaredVariables
|
|
592
|
+
);
|
|
593
|
+
if (testCallExpressions.length > 0) {
|
|
594
|
+
inTestCase = true;
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
IfStatement: increaseConditionalDepth,
|
|
598
|
+
"IfStatement:exit": decreaseConditionalDepth,
|
|
599
|
+
LogicalExpression: increaseConditionalDepth,
|
|
600
|
+
"LogicalExpression:exit": decreaseConditionalDepth,
|
|
601
|
+
SwitchStatement: increaseConditionalDepth,
|
|
602
|
+
"SwitchStatement:exit": decreaseConditionalDepth
|
|
603
|
+
};
|
|
604
|
+
},
|
|
605
|
+
meta: {
|
|
606
|
+
docs: {
|
|
607
|
+
category: "Best Practices",
|
|
608
|
+
description: "Disallow calling `expect` conditionally",
|
|
609
|
+
recommended: true,
|
|
610
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-conditional-expect.md"
|
|
611
|
+
},
|
|
612
|
+
messages: {
|
|
613
|
+
conditionalExpect: "Avoid calling `expect` conditionally`"
|
|
614
|
+
},
|
|
615
|
+
type: "problem"
|
|
616
|
+
}
|
|
617
|
+
};
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
|
|
410
621
|
// src/rules/no-conditional-in-test.ts
|
|
411
622
|
var no_conditional_in_test_default;
|
|
412
623
|
var init_no_conditional_in_test = __esm({
|
|
@@ -445,6 +656,58 @@ var init_no_conditional_in_test = __esm({
|
|
|
445
656
|
}
|
|
446
657
|
});
|
|
447
658
|
|
|
659
|
+
// src/rules/no-duplicate-hooks.ts
|
|
660
|
+
var no_duplicate_hooks_default;
|
|
661
|
+
var init_no_duplicate_hooks = __esm({
|
|
662
|
+
"src/rules/no-duplicate-hooks.ts"() {
|
|
663
|
+
"use strict";
|
|
664
|
+
init_ast();
|
|
665
|
+
no_duplicate_hooks_default = {
|
|
666
|
+
create(context) {
|
|
667
|
+
const hookContexts = [{}];
|
|
668
|
+
return {
|
|
669
|
+
CallExpression(node) {
|
|
670
|
+
if (isDescribeCall(node)) {
|
|
671
|
+
hookContexts.push({});
|
|
672
|
+
}
|
|
673
|
+
if (!isTestHook(context, node)) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const currentLayer = hookContexts[hookContexts.length - 1];
|
|
677
|
+
const name = node.callee.type === "MemberExpression" ? getStringValue(node.callee.property) : "";
|
|
678
|
+
currentLayer[name] || (currentLayer[name] = 0);
|
|
679
|
+
currentLayer[name] += 1;
|
|
680
|
+
if (currentLayer[name] > 1) {
|
|
681
|
+
context.report({
|
|
682
|
+
data: { hook: name },
|
|
683
|
+
messageId: "noDuplicateHook",
|
|
684
|
+
node
|
|
685
|
+
});
|
|
686
|
+
}
|
|
687
|
+
},
|
|
688
|
+
"CallExpression:exit"(node) {
|
|
689
|
+
if (isDescribeCall(node)) {
|
|
690
|
+
hookContexts.pop();
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
};
|
|
694
|
+
},
|
|
695
|
+
meta: {
|
|
696
|
+
docs: {
|
|
697
|
+
category: "Best Practices",
|
|
698
|
+
description: "Disallow duplicate setup and teardown hooks",
|
|
699
|
+
recommended: false,
|
|
700
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-duplicate-hooks.md"
|
|
701
|
+
},
|
|
702
|
+
messages: {
|
|
703
|
+
noDuplicateHook: "Duplicate {{ hook }} in describe block"
|
|
704
|
+
},
|
|
705
|
+
type: "suggestion"
|
|
706
|
+
}
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
|
|
448
711
|
// src/rules/no-element-handle.ts
|
|
449
712
|
function getPropertyRange(node) {
|
|
450
713
|
return node.type === "Identifier" ? node.range : [node.range[0] + 1, node.range[1] - 1];
|
|
@@ -1104,6 +1367,102 @@ var init_no_skipped_test = __esm({
|
|
|
1104
1367
|
}
|
|
1105
1368
|
});
|
|
1106
1369
|
|
|
1370
|
+
// src/rules/no-standalone-expect.ts
|
|
1371
|
+
var getBlockType, no_standalone_expect_default;
|
|
1372
|
+
var init_no_standalone_expect = __esm({
|
|
1373
|
+
"src/rules/no-standalone-expect.ts"() {
|
|
1374
|
+
"use strict";
|
|
1375
|
+
init_ast();
|
|
1376
|
+
getBlockType = (statement) => {
|
|
1377
|
+
const func = getParent(statement);
|
|
1378
|
+
if (!func) {
|
|
1379
|
+
throw new Error(
|
|
1380
|
+
`Unexpected BlockStatement. No parent defined. - please file a github issue at https://github.com/jest-community/eslint-plugin-jest`
|
|
1381
|
+
);
|
|
1382
|
+
}
|
|
1383
|
+
if (func.type === "FunctionDeclaration") {
|
|
1384
|
+
return "function";
|
|
1385
|
+
}
|
|
1386
|
+
if (isFunction(func) && func.parent) {
|
|
1387
|
+
const expr = func.parent;
|
|
1388
|
+
if (expr.type === "VariableDeclarator") {
|
|
1389
|
+
return "function";
|
|
1390
|
+
}
|
|
1391
|
+
if (expr.type === "CallExpression" && isDescribeCall(expr)) {
|
|
1392
|
+
return "describe";
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
return null;
|
|
1396
|
+
};
|
|
1397
|
+
no_standalone_expect_default = {
|
|
1398
|
+
create(context) {
|
|
1399
|
+
const callStack = [];
|
|
1400
|
+
return {
|
|
1401
|
+
ArrowFunctionExpression(node) {
|
|
1402
|
+
if (node.parent?.type !== "CallExpression") {
|
|
1403
|
+
callStack.push("arrow");
|
|
1404
|
+
}
|
|
1405
|
+
},
|
|
1406
|
+
"ArrowFunctionExpression:exit"() {
|
|
1407
|
+
if (callStack[callStack.length - 1] === "arrow") {
|
|
1408
|
+
callStack.pop();
|
|
1409
|
+
}
|
|
1410
|
+
},
|
|
1411
|
+
BlockStatement(statement) {
|
|
1412
|
+
const blockType = getBlockType(statement);
|
|
1413
|
+
if (blockType) {
|
|
1414
|
+
callStack.push(blockType);
|
|
1415
|
+
}
|
|
1416
|
+
},
|
|
1417
|
+
"BlockStatement:exit"(statement) {
|
|
1418
|
+
if (callStack[callStack.length - 1] === getBlockType(statement)) {
|
|
1419
|
+
callStack.pop();
|
|
1420
|
+
}
|
|
1421
|
+
},
|
|
1422
|
+
CallExpression(node) {
|
|
1423
|
+
if (getExpectType(context, node)) {
|
|
1424
|
+
const parent = callStack.at(-1);
|
|
1425
|
+
if (!parent || parent === "describe") {
|
|
1426
|
+
const root = findParent(node, "CallExpression");
|
|
1427
|
+
context.report({
|
|
1428
|
+
messageId: "unexpectedExpect",
|
|
1429
|
+
node: root ?? node
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
if (isTestCall(context, node)) {
|
|
1435
|
+
callStack.push("test");
|
|
1436
|
+
}
|
|
1437
|
+
if (node.callee.type === "TaggedTemplateExpression") {
|
|
1438
|
+
callStack.push("template");
|
|
1439
|
+
}
|
|
1440
|
+
},
|
|
1441
|
+
"CallExpression:exit"(node) {
|
|
1442
|
+
const top = callStack[callStack.length - 1];
|
|
1443
|
+
if (top === "test" && isTestCall(context, node) && node.callee.type !== "MemberExpression" || top === "template" && node.callee.type === "TaggedTemplateExpression") {
|
|
1444
|
+
callStack.pop();
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
};
|
|
1448
|
+
},
|
|
1449
|
+
meta: {
|
|
1450
|
+
docs: {
|
|
1451
|
+
category: "Best Practices",
|
|
1452
|
+
description: "Disallow using `expect` outside of `test` blocks",
|
|
1453
|
+
recommended: false,
|
|
1454
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-contain.md"
|
|
1455
|
+
},
|
|
1456
|
+
fixable: "code",
|
|
1457
|
+
messages: {
|
|
1458
|
+
unexpectedExpect: "Expect must be inside of a test block"
|
|
1459
|
+
},
|
|
1460
|
+
type: "suggestion"
|
|
1461
|
+
}
|
|
1462
|
+
};
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1465
|
+
|
|
1107
1466
|
// src/utils/misc.ts
|
|
1108
1467
|
var getAmountData, truthy;
|
|
1109
1468
|
var init_misc = __esm({
|
|
@@ -1476,6 +1835,111 @@ var init_no_wait_for_timeout = __esm({
|
|
|
1476
1835
|
}
|
|
1477
1836
|
});
|
|
1478
1837
|
|
|
1838
|
+
// src/rules/prefer-hooks-in-order.ts
|
|
1839
|
+
var HooksOrder, prefer_hooks_in_order_default;
|
|
1840
|
+
var init_prefer_hooks_in_order = __esm({
|
|
1841
|
+
"src/rules/prefer-hooks-in-order.ts"() {
|
|
1842
|
+
"use strict";
|
|
1843
|
+
init_ast();
|
|
1844
|
+
HooksOrder = ["beforeAll", "beforeEach", "afterEach", "afterAll"];
|
|
1845
|
+
prefer_hooks_in_order_default = {
|
|
1846
|
+
create(context) {
|
|
1847
|
+
let previousHookIndex = -1;
|
|
1848
|
+
let inHook = false;
|
|
1849
|
+
return {
|
|
1850
|
+
CallExpression(node) {
|
|
1851
|
+
if (inHook)
|
|
1852
|
+
return;
|
|
1853
|
+
if (!isTestHook(context, node)) {
|
|
1854
|
+
previousHookIndex = -1;
|
|
1855
|
+
return;
|
|
1856
|
+
}
|
|
1857
|
+
inHook = true;
|
|
1858
|
+
const currentHook = node.callee.type === "MemberExpression" ? getStringValue(node.callee.property) : "";
|
|
1859
|
+
const currentHookIndex = HooksOrder.indexOf(currentHook);
|
|
1860
|
+
if (currentHookIndex < previousHookIndex) {
|
|
1861
|
+
return context.report({
|
|
1862
|
+
data: {
|
|
1863
|
+
currentHook,
|
|
1864
|
+
previousHook: HooksOrder[previousHookIndex]
|
|
1865
|
+
},
|
|
1866
|
+
messageId: "reorderHooks",
|
|
1867
|
+
node
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
previousHookIndex = currentHookIndex;
|
|
1871
|
+
},
|
|
1872
|
+
"CallExpression:exit"(node) {
|
|
1873
|
+
if (isTestHook(context, node)) {
|
|
1874
|
+
inHook = false;
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
if (inHook) {
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
previousHookIndex = -1;
|
|
1881
|
+
}
|
|
1882
|
+
};
|
|
1883
|
+
},
|
|
1884
|
+
meta: {
|
|
1885
|
+
docs: {
|
|
1886
|
+
category: "Best Practices",
|
|
1887
|
+
description: "Prefer having hooks in a consistent order",
|
|
1888
|
+
recommended: false,
|
|
1889
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-in-order.md"
|
|
1890
|
+
},
|
|
1891
|
+
messages: {
|
|
1892
|
+
reorderHooks: "`{{ currentHook }}` hooks should be before any `{{ previousHook }}` hooks"
|
|
1893
|
+
},
|
|
1894
|
+
type: "suggestion"
|
|
1895
|
+
}
|
|
1896
|
+
};
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
|
|
1900
|
+
// src/rules/prefer-hooks-on-top.ts
|
|
1901
|
+
var prefer_hooks_on_top_default;
|
|
1902
|
+
var init_prefer_hooks_on_top = __esm({
|
|
1903
|
+
"src/rules/prefer-hooks-on-top.ts"() {
|
|
1904
|
+
"use strict";
|
|
1905
|
+
init_ast();
|
|
1906
|
+
prefer_hooks_on_top_default = {
|
|
1907
|
+
create(context) {
|
|
1908
|
+
const stack = [false];
|
|
1909
|
+
return {
|
|
1910
|
+
CallExpression(node) {
|
|
1911
|
+
if (isTestCall(context, node)) {
|
|
1912
|
+
stack[stack.length - 1] = true;
|
|
1913
|
+
}
|
|
1914
|
+
if (stack.at(-1) && isTestHook(context, node)) {
|
|
1915
|
+
context.report({
|
|
1916
|
+
messageId: "noHookOnTop",
|
|
1917
|
+
node
|
|
1918
|
+
});
|
|
1919
|
+
}
|
|
1920
|
+
stack.push(false);
|
|
1921
|
+
},
|
|
1922
|
+
"CallExpression:exit"() {
|
|
1923
|
+
stack.pop();
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
},
|
|
1927
|
+
meta: {
|
|
1928
|
+
docs: {
|
|
1929
|
+
category: "Best Practices",
|
|
1930
|
+
description: "Suggest having hooks before any test cases",
|
|
1931
|
+
recommended: false,
|
|
1932
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-on-top.md"
|
|
1933
|
+
},
|
|
1934
|
+
messages: {
|
|
1935
|
+
noHookOnTop: "Hooks should come before test cases"
|
|
1936
|
+
},
|
|
1937
|
+
type: "suggestion"
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
}
|
|
1941
|
+
});
|
|
1942
|
+
|
|
1479
1943
|
// src/rules/prefer-lowercase-title.ts
|
|
1480
1944
|
var prefer_lowercase_title_default;
|
|
1481
1945
|
var init_prefer_lowercase_title = __esm({
|
|
@@ -2519,9 +2983,13 @@ import globals from "globals";
|
|
|
2519
2983
|
var require_src = __commonJS({
|
|
2520
2984
|
"src/index.ts"(exports, module) {
|
|
2521
2985
|
init_expect_expect();
|
|
2986
|
+
init_max_expects();
|
|
2522
2987
|
init_max_nested_describe();
|
|
2523
2988
|
init_missing_playwright_await();
|
|
2989
|
+
init_no_commented_out_tests();
|
|
2990
|
+
init_no_conditional_expect();
|
|
2524
2991
|
init_no_conditional_in_test();
|
|
2992
|
+
init_no_duplicate_hooks();
|
|
2525
2993
|
init_no_element_handle();
|
|
2526
2994
|
init_no_eval();
|
|
2527
2995
|
init_no_focused_test();
|
|
@@ -2534,11 +3002,14 @@ var require_src = __commonJS({
|
|
|
2534
3002
|
init_no_raw_locators();
|
|
2535
3003
|
init_no_restricted_matchers();
|
|
2536
3004
|
init_no_skipped_test();
|
|
3005
|
+
init_no_standalone_expect();
|
|
2537
3006
|
init_no_unsafe_references();
|
|
2538
3007
|
init_no_useless_await();
|
|
2539
3008
|
init_no_useless_not();
|
|
2540
3009
|
init_no_wait_for_selector();
|
|
2541
3010
|
init_no_wait_for_timeout();
|
|
3011
|
+
init_prefer_hooks_in_order();
|
|
3012
|
+
init_prefer_hooks_on_top();
|
|
2542
3013
|
init_prefer_lowercase_title();
|
|
2543
3014
|
init_prefer_strict_equal();
|
|
2544
3015
|
init_prefer_to_be();
|
|
@@ -2554,9 +3025,13 @@ var require_src = __commonJS({
|
|
|
2554
3025
|
configs: {},
|
|
2555
3026
|
rules: {
|
|
2556
3027
|
"expect-expect": expect_expect_default,
|
|
3028
|
+
"max-expects": max_expects_default,
|
|
2557
3029
|
"max-nested-describe": max_nested_describe_default,
|
|
2558
3030
|
"missing-playwright-await": missing_playwright_await_default,
|
|
3031
|
+
"no-commented-out-tests": no_commented_out_tests_default,
|
|
3032
|
+
"no-conditional-expect": no_conditional_expect_default,
|
|
2559
3033
|
"no-conditional-in-test": no_conditional_in_test_default,
|
|
3034
|
+
"no-duplicate-hooks": no_duplicate_hooks_default,
|
|
2560
3035
|
"no-element-handle": no_element_handle_default,
|
|
2561
3036
|
"no-eval": no_eval_default,
|
|
2562
3037
|
"no-focused-test": no_focused_test_default,
|
|
@@ -2569,11 +3044,14 @@ var require_src = __commonJS({
|
|
|
2569
3044
|
"no-raw-locators": no_raw_locators_default,
|
|
2570
3045
|
"no-restricted-matchers": no_restricted_matchers_default,
|
|
2571
3046
|
"no-skipped-test": no_skipped_test_default,
|
|
3047
|
+
"no-standalone-expect": no_standalone_expect_default,
|
|
2572
3048
|
"no-unsafe-references": no_unsafe_references_default,
|
|
2573
3049
|
"no-useless-await": no_useless_await_default,
|
|
2574
3050
|
"no-useless-not": no_useless_not_default,
|
|
2575
3051
|
"no-wait-for-selector": no_wait_for_selector_default,
|
|
2576
3052
|
"no-wait-for-timeout": no_wait_for_timeout_default,
|
|
3053
|
+
"prefer-hooks-in-order": prefer_hooks_in_order_default,
|
|
3054
|
+
"prefer-hooks-on-top": prefer_hooks_on_top_default,
|
|
2577
3055
|
"prefer-lowercase-title": prefer_lowercase_title_default,
|
|
2578
3056
|
"prefer-strict-equal": prefer_strict_equal_default,
|
|
2579
3057
|
"prefer-to-be": prefer_to_be_default,
|
|
@@ -2593,6 +3071,7 @@ var require_src = __commonJS({
|
|
|
2593
3071
|
"playwright/expect-expect": "warn",
|
|
2594
3072
|
"playwright/max-nested-describe": "warn",
|
|
2595
3073
|
"playwright/missing-playwright-await": "error",
|
|
3074
|
+
"playwright/no-conditional-expect": "warn",
|
|
2596
3075
|
"playwright/no-conditional-in-test": "warn",
|
|
2597
3076
|
"playwright/no-element-handle": "warn",
|
|
2598
3077
|
"playwright/no-eval": "warn",
|
|
@@ -2602,6 +3081,7 @@ var require_src = __commonJS({
|
|
|
2602
3081
|
"playwright/no-networkidle": "error",
|
|
2603
3082
|
"playwright/no-page-pause": "warn",
|
|
2604
3083
|
"playwright/no-skipped-test": "warn",
|
|
3084
|
+
"playwright/no-standalone-expect": "error",
|
|
2605
3085
|
"playwright/no-unsafe-references": "error",
|
|
2606
3086
|
"playwright/no-useless-await": "warn",
|
|
2607
3087
|
"playwright/no-useless-not": "warn",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-playwright",
|
|
3
3
|
"description": "ESLint plugin for Playwright testing.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"repository": "https://github.com/playwright-community/eslint-plugin-playwright",
|
|
6
6
|
"author": "Mark Skelton <mark@mskelton.dev>",
|
|
7
7
|
"packageManager": "pnpm@8.12.0",
|