eslint-plugin-playwright 2.3.0 → 2.4.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 CHANGED
@@ -38,19 +38,19 @@ file patterns.
38
38
  (**eslint.config.js**)
39
39
 
40
40
  ```javascript
41
+ import { defineConfig } from '@eslint/config'
41
42
  import playwright from 'eslint-plugin-playwright'
42
43
 
43
- export default [
44
+ export default defineConfig([
44
45
  {
45
- ...playwright.configs['flat/recommended'],
46
46
  files: ['tests/**'],
47
+ extends: [playwright.configs['flat/recommended']],
47
48
  rules: {
48
- ...playwright.configs['flat/recommended'].rules,
49
49
  // Customize Playwright rules
50
50
  // ...
51
51
  },
52
52
  },
53
- ]
53
+ ])
54
54
  ```
55
55
 
56
56
  [Legacy config](https://eslint.org/docs/latest/use/configure/configuration-files)
package/dist/index.cjs CHANGED
@@ -435,8 +435,12 @@ var expect_expect_default = createRule({
435
435
  create(context) {
436
436
  const options = {
437
437
  assertFunctionNames: [],
438
+ assertFunctionPatterns: [],
438
439
  ...context.options?.[0] ?? {}
439
440
  };
441
+ const patterns = options.assertFunctionPatterns.map(
442
+ (pattern) => new RegExp(pattern)
443
+ );
440
444
  const unchecked = [];
441
445
  function checkExpressions(nodes) {
442
446
  for (const node of nodes) {
@@ -447,12 +451,21 @@ var expect_expect_default = createRule({
447
451
  }
448
452
  }
449
453
  }
454
+ function matches(node) {
455
+ if (options.assertFunctionNames.some((name) => dig(node.callee, name))) {
456
+ return true;
457
+ }
458
+ if (patterns.some((pattern) => dig(node.callee, pattern))) {
459
+ return true;
460
+ }
461
+ return false;
462
+ }
450
463
  return {
451
464
  CallExpression(node) {
452
465
  const call = parseFnCall(context, node);
453
466
  if (call?.type === "test") {
454
467
  unchecked.push(node);
455
- } else if (call?.type === "expect" || options.assertFunctionNames.find((name) => dig(node.callee, name))) {
468
+ } else if (call?.type === "expect" || matches(node)) {
456
469
  const ancestors = context.sourceCode.getAncestors(node);
457
470
  checkExpressions(ancestors);
458
471
  }
@@ -481,6 +494,10 @@ var expect_expect_default = createRule({
481
494
  assertFunctionNames: {
482
495
  items: [{ type: "string" }],
483
496
  type: "array"
497
+ },
498
+ assertFunctionPatterns: {
499
+ items: [{ type: "string" }],
500
+ type: "array"
484
501
  }
485
502
  },
486
503
  type: "object"
@@ -693,14 +710,17 @@ var missing_playwright_await_default = createRule({
693
710
  // Add any custom matchers to the set
694
711
  ...options.customMatchers || []
695
712
  ]);
696
- function checkValidity(node) {
713
+ function checkValidity(node, visited) {
697
714
  const parent = getParent(node);
698
715
  if (!parent)
699
716
  return false;
717
+ if (visited.has(parent))
718
+ return false;
719
+ visited.add(parent);
700
720
  if (validTypes.has(parent.type))
701
721
  return true;
702
722
  if (parent.type === "ArrayExpression") {
703
- return checkValidity(parent);
723
+ return checkValidity(parent, visited);
704
724
  }
705
725
  if (parent.type === "CallExpression" && parent.callee.type === "MemberExpression" && isIdentifier(parent.callee.object, "Promise") && isIdentifier(parent.callee.property, "all")) {
706
726
  return true;
@@ -709,9 +729,11 @@ var missing_playwright_await_default = createRule({
709
729
  const scope = context.sourceCode.getScope(parent.parent);
710
730
  for (const ref of scope.references) {
711
731
  const refParent = ref.identifier.parent;
732
+ if (visited.has(refParent))
733
+ continue;
712
734
  if (validTypes.has(refParent.type))
713
735
  return true;
714
- if (checkValidity(refParent))
736
+ if (checkValidity(refParent, visited))
715
737
  return true;
716
738
  }
717
739
  }
@@ -723,7 +745,7 @@ var missing_playwright_await_default = createRule({
723
745
  if (call?.type !== "step" && call?.type !== "expect")
724
746
  return;
725
747
  const result = getCallType(call, awaitableMatchers);
726
- const isValid = result ? checkValidity(node) : false;
748
+ const isValid = result ? checkValidity(node, /* @__PURE__ */ new Set()) : false;
727
749
  if (result && !isValid) {
728
750
  context.report({
729
751
  data: result.data,
@@ -1702,13 +1724,16 @@ var no_standalone_expect_default = createRule({
1702
1724
  if (call?.type === "hook") {
1703
1725
  callStack.push("hook");
1704
1726
  }
1727
+ if (node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "extend")) {
1728
+ callStack.push("fixture");
1729
+ }
1705
1730
  if (node.callee.type === "TaggedTemplateExpression") {
1706
1731
  callStack.push("template");
1707
1732
  }
1708
1733
  },
1709
1734
  "CallExpression:exit"(node) {
1710
1735
  const top = callStack.at(-1);
1711
- if (top === "test" && isTypeOfFnCall(context, node, ["test"]) && node.callee.type !== "MemberExpression" || top === "template" && node.callee.type === "TaggedTemplateExpression") {
1736
+ if (top === "test" && isTypeOfFnCall(context, node, ["test"]) && node.callee.type !== "MemberExpression" || top === "template" && node.callee.type === "TaggedTemplateExpression" || top === "fixture" && node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "extend")) {
1712
1737
  callStack.pop();
1713
1738
  }
1714
1739
  }
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": "2.3.0",
4
+ "version": "2.4.0",
5
5
  "repository": "https://github.com/playwright-community/eslint-plugin-playwright",
6
6
  "author": "Mark Skelton <mark@mskelton.dev>",
7
7
  "contributors": [