eslint-plugin-playwright 2.3.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,20 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Max Schmitt
3
+ Copyright (c) 2024 Mark Skelton
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
11
 
12
12
  The above copyright notice and this permission notice shall be included in all
13
13
  copies or substantial portions of the Software.
14
14
 
15
15
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
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,
@@ -899,6 +921,9 @@ var no_conditional_expect_default = createRule({
899
921
  var no_conditional_in_test_default = createRule({
900
922
  create(context) {
901
923
  function checkConditional(node) {
924
+ if (node.type === "LogicalExpression" && node.operator === "??") {
925
+ return;
926
+ }
902
927
  const call = findParent(node, "CallExpression");
903
928
  if (!call)
904
929
  return;
@@ -1702,13 +1727,16 @@ var no_standalone_expect_default = createRule({
1702
1727
  if (call?.type === "hook") {
1703
1728
  callStack.push("hook");
1704
1729
  }
1730
+ if (node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "extend")) {
1731
+ callStack.push("fixture");
1732
+ }
1705
1733
  if (node.callee.type === "TaggedTemplateExpression") {
1706
1734
  callStack.push("template");
1707
1735
  }
1708
1736
  },
1709
1737
  "CallExpression:exit"(node) {
1710
1738
  const top = callStack.at(-1);
1711
- if (top === "test" && isTypeOfFnCall(context, node, ["test"]) && node.callee.type !== "MemberExpression" || top === "template" && node.callee.type === "TaggedTemplateExpression") {
1739
+ 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
1740
  callStack.pop();
1713
1741
  }
1714
1742
  }
package/package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "name": "eslint-plugin-playwright",
3
3
  "description": "ESLint plugin for Playwright testing.",
4
- "version": "2.3.0",
5
- "repository": "https://github.com/playwright-community/eslint-plugin-playwright",
4
+ "version": "2.4.1",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/mskelton/eslint-plugin-playwright.git"
8
+ },
6
9
  "author": "Mark Skelton <mark@mskelton.dev>",
10
+ "packageManager": "pnpm@8.12.0",
7
11
  "contributors": [
8
12
  "Max Schmitt <max@schmitt.mx>"
9
13
  ],
@@ -26,10 +30,33 @@
26
30
  "index.cjs",
27
31
  "index.d.ts"
28
32
  ],
33
+ "scripts": {
34
+ "build": "tsup src/index.ts --format cjs --out-dir dist",
35
+ "lint": "eslint .",
36
+ "format": "prettier --write .",
37
+ "format:check": "prettier --check .",
38
+ "test": "vitest --run --hideSkippedTests",
39
+ "test:watch": "vitest --reporter=dot --run",
40
+ "ts": "tsc --noEmit"
41
+ },
29
42
  "peerDependencies": {
30
43
  "eslint": ">=8.40.0"
31
44
  },
32
45
  "dependencies": {
33
46
  "globals": "^16.4.0"
47
+ },
48
+ "devDependencies": {
49
+ "@mskelton/eslint-config": "^9.0.1",
50
+ "@types/estree": "^1.0.6",
51
+ "@types/node": "^20.11.17",
52
+ "@typescript-eslint/parser": "^8.11.0",
53
+ "dedent": "^1.5.1",
54
+ "eslint": "^9.13.0",
55
+ "prettier": "^3.0.3",
56
+ "prettier-plugin-jsdoc": "^1.3.0",
57
+ "semantic-release": "^25.0.2",
58
+ "tsup": "^8.0.1",
59
+ "typescript": "^5.2.2",
60
+ "vitest": "^1.6.1"
34
61
  }
35
62
  }