eslint-plugin-playwright 1.6.0 → 1.6.2

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
@@ -45,7 +45,7 @@ import playwright from 'eslint-plugin-playwright'
45
45
 
46
46
  export default [
47
47
  {
48
- ...playwright.configs['flat/playwright'],
48
+ ...playwright.configs['flat/recommended'],
49
49
  files: ['tests/**'],
50
50
  },
51
51
  {
@@ -174,18 +174,18 @@ CLI option\
174
174
  | [no-eval](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-eval.md) | Disallow usage of `page.$eval()` and `page.$$eval()` | ✅ | | |
175
175
  | [no-focused-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-focused-test.md) | Disallow usage of `.only` annotation | ✅ | | 💡 |
176
176
  | [no-force-option](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-force-option.md) | Disallow usage of the `{ force: true }` option | ✅ | | |
177
+ | [no-get-by-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-get-by-title.md) | Disallow using `getByTitle()` | | 🔧 | |
177
178
  | [no-hooks](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-hooks.md) | Disallow setup and teardown hooks | | | |
178
179
  | [no-nested-step](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nested-step.md) | Disallow nested `test.step()` methods | ✅ | | |
179
180
  | [no-networkidle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-networkidle.md) | Disallow usage of the `networkidle` option | ✅ | | |
180
181
  | [no-nth-methods](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nth-methods.md) | Disallow usage of `first()`, `last()`, and `nth()` methods | | | |
181
182
  | [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md) | Disallow using `page.pause()` | ✅ | | |
182
- | [no-unsafe-references](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-unsafe-references.md) | Prevent unsafe variable references in `page.evaluate()` | ✅ | 🔧 | |
183
- | [no-get-by-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-get-by-title.md) | Disallow using `getByTitle()` | | 🔧 | |
184
183
  | [no-raw-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-raw-locators.md) | Disallow using raw locators | | | |
185
- | [no-useless-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-await.md) | Disallow unnecessary `await`s for Playwright methods | ✅ | 🔧 | |
186
184
  | [no-restricted-matchers](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | | |
187
185
  | [no-skipped-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-skipped-test.md) | Disallow usage of the `.skip` annotation | ✅ | | 💡 |
188
186
  | [no-standalone-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-standalone-expect.md) | Disallow using expect outside of `test` blocks | ✅ | | |
187
+ | [no-unsafe-references](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-unsafe-references.md) | Prevent unsafe variable references in `page.evaluate()` | ✅ | 🔧 | |
188
+ | [no-useless-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-await.md) | Disallow unnecessary `await`s for Playwright methods | ✅ | 🔧 | |
189
189
  | [no-useless-not](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-useless-not.md) | Disallow usage of `not` matchers when a specific matcher exists | ✅ | 🔧 | |
190
190
  | [no-wait-for-selector](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-wait-for-selector.md) | Disallow usage of `page.waitForSelector()` | ✅ | | 💡 |
191
191
  | [no-wait-for-timeout](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-wait-for-timeout.md) | Disallow usage of `page.waitForTimeout()` | ✅ | | 💡 |
@@ -193,18 +193,18 @@ CLI option\
193
193
  | [prefer-equality-matcher](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-equality-matcher.md) | Suggest using the built-in equality matchers | | | 💡 |
194
194
  | [prefer-hooks-in-order](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-in-order.md) | Prefer having hooks in a consistent order | | | |
195
195
  | [prefer-hooks-on-top](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-hooks-on-top.md) | Suggest having hooks before any test cases | | | |
196
- | [prefer-strict-equal](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | | 💡 |
197
196
  | [prefer-lowercase-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names | | 🔧 | |
197
+ | [prefer-strict-equal](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` | | | 💡 |
198
198
  | [prefer-to-be](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-be.md) | Suggest using `toBe()` | | 🔧 | |
199
199
  | [prefer-to-contain](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-contain.md) | Suggest using `toContain()` | | 🔧 | |
200
200
  | [prefer-to-have-count](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-have-count.md) | Suggest using `toHaveCount()` | | 🔧 | |
201
201
  | [prefer-to-have-length](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-have-length.md) | Suggest using `toHaveLength()` | | 🔧 | |
202
202
  | [prefer-web-first-assertions](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-web-first-assertions.md) | Suggest using web first assertions | ✅ | 🔧 | |
203
203
  | [require-hook](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-hook.md) | Require setup and teardown code to be within a hook | | | |
204
- | [require-top-level-describe](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `test.describe` block | | | |
205
204
  | [require-soft-assertions](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-soft-assertions.md) | Require assertions to use `expect.soft()` | | 🔧 | |
205
+ | [require-to-throw-message](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | | |
206
+ | [require-top-level-describe](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-top-level-describe.md) | Require test cases and hooks to be inside a `test.describe` block | | | |
206
207
  | [valid-describe-callback](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-describe-callback.md) | Enforce valid `describe()` callback | ✅ | | |
207
- | [valid-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ✅ | | |
208
208
  | [valid-expect-in-promise](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect-in-promise.md) | Require promises that have expectations in their chain to be valid | ✅ | | |
209
+ | [valid-expect](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-expect.md) | Enforce valid `expect()` usage | ✅ | | |
209
210
  | [valid-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/valid-title.md) | Enforce valid titles | ✅ | 🔧 | |
210
- | [require-to-throw-message](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/require-to-throw-message.md) | Require a message for `toThrow()` | | | |
package/dist/index.js CHANGED
@@ -329,6 +329,24 @@ function getNodeName(node) {
329
329
  }
330
330
  return null;
331
331
  }
332
+ var isVariableDeclarator = (node) => node.type === "VariableDeclarator";
333
+ var isAssignmentExpression = (node) => node.type === "AssignmentExpression";
334
+ function isNodeLastAssignment(node, assignment) {
335
+ if (node.range && assignment.range && node.range[0] < assignment.range[1]) {
336
+ return false;
337
+ }
338
+ return assignment.left.type === "Identifier" && assignment.left.name === node.name;
339
+ }
340
+ function dereference(context, node) {
341
+ if (node?.type !== "Identifier") {
342
+ return node;
343
+ }
344
+ const scope = context.sourceCode.getScope(node);
345
+ const parents = scope.references.map((ref) => ref.identifier).map((ident) => ident.parent);
346
+ const decl = parents.filter(isVariableDeclarator).find((p) => p.id.type === "Identifier" && p.id.name === node.name);
347
+ const expr = parents.filter(isAssignmentExpression).reverse().find((assignment) => isNodeLastAssignment(node, assignment));
348
+ return expr?.right ?? decl?.init;
349
+ }
332
350
 
333
351
  // src/utils/createRule.ts
334
352
  function interpolate(str, data) {
@@ -2534,7 +2552,7 @@ var prefer_to_have_count_default = createRule({
2534
2552
  if (call?.type !== "expect" || !equalityMatchers.has(call.matcherName)) {
2535
2553
  return;
2536
2554
  }
2537
- const [argument] = call.args;
2555
+ const argument = dereference(context, call.args[0]);
2538
2556
  if (argument?.type !== "AwaitExpression" || argument.argument.type !== "CallExpression" || argument.argument.callee.type !== "MemberExpression" || !isPropertyAccessor(argument.argument.callee, "count")) {
2539
2557
  return;
2540
2558
  }
@@ -2669,18 +2687,6 @@ var supportedMatchers = /* @__PURE__ */ new Set([
2669
2687
  "toBeTruthy",
2670
2688
  "toBeFalsy"
2671
2689
  ]);
2672
- function dereference(context, node) {
2673
- if (node?.type !== "Identifier") {
2674
- return node;
2675
- }
2676
- const scope = context.sourceCode.getScope(node);
2677
- for (const ref of scope.references) {
2678
- const refParent = ref.identifier.parent;
2679
- if (refParent.type === "VariableDeclarator") {
2680
- return refParent.init;
2681
- }
2682
- }
2683
- }
2684
2690
  var prefer_web_first_assertions_default = createRule({
2685
2691
  create(context) {
2686
2692
  return {
package/dist/index.mjs CHANGED
@@ -313,7 +313,23 @@ function getNodeName(node) {
313
313
  }
314
314
  return null;
315
315
  }
316
- var isTemplateLiteral, equalityMatchers, joinNames;
316
+ function isNodeLastAssignment(node, assignment) {
317
+ if (node.range && assignment.range && node.range[0] < assignment.range[1]) {
318
+ return false;
319
+ }
320
+ return assignment.left.type === "Identifier" && assignment.left.name === node.name;
321
+ }
322
+ function dereference(context, node) {
323
+ if (node?.type !== "Identifier") {
324
+ return node;
325
+ }
326
+ const scope = context.sourceCode.getScope(node);
327
+ const parents = scope.references.map((ref) => ref.identifier).map((ident) => ident.parent);
328
+ const decl = parents.filter(isVariableDeclarator).find((p) => p.id.type === "Identifier" && p.id.name === node.name);
329
+ const expr = parents.filter(isAssignmentExpression).reverse().find((assignment) => isNodeLastAssignment(node, assignment));
330
+ return expr?.right ?? decl?.init;
331
+ }
332
+ var isTemplateLiteral, equalityMatchers, joinNames, isVariableDeclarator, isAssignmentExpression;
317
333
  var init_ast = __esm({
318
334
  "src/utils/ast.ts"() {
319
335
  "use strict";
@@ -322,6 +338,8 @@ var init_ast = __esm({
322
338
  (value === void 0 || node.quasis[0].value.raw === value);
323
339
  equalityMatchers = /* @__PURE__ */ new Set(["toBe", "toEqual", "toStrictEqual"]);
324
340
  joinNames = (a, b) => a && b ? `${a}.${b}` : null;
341
+ isVariableDeclarator = (node) => node.type === "VariableDeclarator";
342
+ isAssignmentExpression = (node) => node.type === "AssignmentExpression";
325
343
  }
326
344
  });
327
345
 
@@ -2855,7 +2873,7 @@ var init_prefer_to_have_count = __esm({
2855
2873
  if (call?.type !== "expect" || !equalityMatchers.has(call.matcherName)) {
2856
2874
  return;
2857
2875
  }
2858
- const [argument] = call.args;
2876
+ const argument = dereference(context, call.args[0]);
2859
2877
  if (argument?.type !== "AwaitExpression" || argument.argument.type !== "CallExpression" || argument.argument.callee.type !== "MemberExpression" || !isPropertyAccessor(argument.argument.callee, "count")) {
2860
2878
  return;
2861
2879
  }
@@ -2961,18 +2979,6 @@ var init_prefer_to_have_length = __esm({
2961
2979
  });
2962
2980
 
2963
2981
  // src/rules/prefer-web-first-assertions.ts
2964
- function dereference(context, node) {
2965
- if (node?.type !== "Identifier") {
2966
- return node;
2967
- }
2968
- const scope = context.sourceCode.getScope(node);
2969
- for (const ref of scope.references) {
2970
- const refParent = ref.identifier.parent;
2971
- if (refParent.type === "VariableDeclarator") {
2972
- return refParent.init;
2973
- }
2974
- }
2975
- }
2976
2982
  var methods3, supportedMatchers, prefer_web_first_assertions_default;
2977
2983
  var init_prefer_web_first_assertions = __esm({
2978
2984
  "src/rules/prefer-web-first-assertions.ts"() {
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.6.0",
4
+ "version": "1.6.2",
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",