eslint-plugin-playwright 0.22.2 → 1.0.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/README.md +12 -37
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +83 -52
- package/dist/index.mjs +97 -59
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -91,45 +91,19 @@ export default [
|
|
|
91
91
|
}
|
|
92
92
|
```
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
### Aliased Playwright Globals
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
- `additionalAssertFunctionNames`: an array of function names to treat as
|
|
100
|
-
assertion functions for the case of rules like `expect-expect`, which enforces
|
|
101
|
-
the presence of at least one assertion per test case. This allows such rules
|
|
102
|
-
to recognise custom assertion functions as valid assertions. The global
|
|
103
|
-
setting applies to all modules. The
|
|
104
|
-
[`expect-expect` rule accepts an option by the same name](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/expect-expect.md#additionalassertfunctionnames)
|
|
105
|
-
to enable per-module configuration (.e.g, for module-specific custom assert
|
|
106
|
-
functions).
|
|
107
|
-
|
|
108
|
-
You can configure these settings like so:
|
|
109
|
-
|
|
110
|
-
[Flat config](https://eslint.org/docs/latest/use/configure/configuration-files-new)
|
|
111
|
-
(**eslint.config.js**)
|
|
112
|
-
|
|
113
|
-
```javascript
|
|
114
|
-
export default [
|
|
115
|
-
{
|
|
116
|
-
settings: {
|
|
117
|
-
playwright: {
|
|
118
|
-
additionalAssertFunctionNames: ['assertCustomCondition'],
|
|
119
|
-
},
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
];
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
[Legacy config](https://eslint.org/docs/latest/use/configure/configuration-files)
|
|
126
|
-
(**.eslintrc**)
|
|
96
|
+
If you import Playwright globals (e.g. `test`, `expect`) with a custom name, you
|
|
97
|
+
can configure this plugin to be aware of these additional names.
|
|
127
98
|
|
|
128
99
|
```json
|
|
129
100
|
{
|
|
130
101
|
"settings": {
|
|
131
102
|
"playwright": {
|
|
132
|
-
"
|
|
103
|
+
"globalAliases": {
|
|
104
|
+
"test": ["myTest"],
|
|
105
|
+
"expect": ["myExpect"]
|
|
106
|
+
}
|
|
133
107
|
}
|
|
134
108
|
}
|
|
135
109
|
}
|
|
@@ -150,20 +124,21 @@ command line option.\
|
|
|
150
124
|
| ✔ | 🔧 | | [missing-playwright-await](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/missing-playwright-await.md) | Enforce Playwright APIs to be awaited |
|
|
151
125
|
| ✔ | | | [no-conditional-in-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-conditional-in-test.md) | Disallow conditional logic in tests |
|
|
152
126
|
| ✔ | | 💡 | [no-element-handle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-element-handle.md) | Disallow usage of element handles |
|
|
153
|
-
| ✔ | | | [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`
|
|
127
|
+
| ✔ | | | [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()` |
|
|
154
128
|
| ✔ | | 💡 | [no-focused-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-focused-test.md) | Disallow usage of `.only` annotation |
|
|
155
129
|
| ✔ | | | [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 |
|
|
156
130
|
| ✔ | | | [no-nested-step](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-nested-step.md) | Disallow nested `test.step()` methods |
|
|
157
131
|
| ✔ | | | [no-networkidle](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-networkidle.md) | Disallow usage of the `networkidle` option |
|
|
158
132
|
| | | | [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 |
|
|
159
|
-
| ✔ | | | [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md) | Disallow using `page.pause`
|
|
133
|
+
| ✔ | | | [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md) | Disallow using `page.pause()` |
|
|
134
|
+
| | 🔧 | | [no-get-by-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-get-by-title.md) | Disallow using `getByTitle()` |
|
|
160
135
|
| | | | [no-raw-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-raw-locators.md) | Disallow using raw locators |
|
|
161
136
|
| ✔ | 🔧 | | [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 |
|
|
162
137
|
| | | | [no-restricted-matchers](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers |
|
|
163
138
|
| ✔ | | 💡 | [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 |
|
|
164
139
|
| ✔ | 🔧 | | [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 |
|
|
165
|
-
| ✔ | | 💡 | [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`
|
|
166
|
-
| ✔ | | 💡 | [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`
|
|
140
|
+
| ✔ | | 💡 | [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()` |
|
|
141
|
+
| ✔ | | 💡 | [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()` |
|
|
167
142
|
| | | 💡 | [prefer-strict-equal](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-strict-equal.md) | Suggest using `toStrictEqual()` |
|
|
168
143
|
| | 🔧 | | [prefer-lowercase-title](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-lowercase-title.md) | Enforce lowercase test names |
|
|
169
144
|
| | 🔧 | | [prefer-to-be](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-to-be.md) | Suggest using `toBe()` |
|
package/dist/index.d.mts
CHANGED
|
@@ -18,6 +18,7 @@ declare const _default: {
|
|
|
18
18
|
'no-eval': eslint.Rule.RuleModule;
|
|
19
19
|
'no-focused-test': eslint.Rule.RuleModule;
|
|
20
20
|
'no-force-option': eslint.Rule.RuleModule;
|
|
21
|
+
'no-get-by-title': eslint.Rule.RuleModule;
|
|
21
22
|
'no-nested-step': eslint.Rule.RuleModule;
|
|
22
23
|
'no-networkidle': eslint.Rule.RuleModule;
|
|
23
24
|
'no-nth-methods': eslint.Rule.RuleModule;
|
|
@@ -67,6 +68,7 @@ declare const _default: {
|
|
|
67
68
|
'no-eval': eslint.Rule.RuleModule;
|
|
68
69
|
'no-focused-test': eslint.Rule.RuleModule;
|
|
69
70
|
'no-force-option': eslint.Rule.RuleModule;
|
|
71
|
+
'no-get-by-title': eslint.Rule.RuleModule;
|
|
70
72
|
'no-nested-step': eslint.Rule.RuleModule;
|
|
71
73
|
'no-networkidle': eslint.Rule.RuleModule;
|
|
72
74
|
'no-nth-methods': eslint.Rule.RuleModule;
|
|
@@ -203,6 +205,7 @@ declare const _default: {
|
|
|
203
205
|
'no-eval': eslint.Rule.RuleModule;
|
|
204
206
|
'no-focused-test': eslint.Rule.RuleModule;
|
|
205
207
|
'no-force-option': eslint.Rule.RuleModule;
|
|
208
|
+
'no-get-by-title': eslint.Rule.RuleModule;
|
|
206
209
|
'no-nested-step': eslint.Rule.RuleModule;
|
|
207
210
|
'no-networkidle': eslint.Rule.RuleModule;
|
|
208
211
|
'no-nth-methods': eslint.Rule.RuleModule;
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ declare const _default: {
|
|
|
18
18
|
'no-eval': eslint.Rule.RuleModule;
|
|
19
19
|
'no-focused-test': eslint.Rule.RuleModule;
|
|
20
20
|
'no-force-option': eslint.Rule.RuleModule;
|
|
21
|
+
'no-get-by-title': eslint.Rule.RuleModule;
|
|
21
22
|
'no-nested-step': eslint.Rule.RuleModule;
|
|
22
23
|
'no-networkidle': eslint.Rule.RuleModule;
|
|
23
24
|
'no-nth-methods': eslint.Rule.RuleModule;
|
|
@@ -67,6 +68,7 @@ declare const _default: {
|
|
|
67
68
|
'no-eval': eslint.Rule.RuleModule;
|
|
68
69
|
'no-focused-test': eslint.Rule.RuleModule;
|
|
69
70
|
'no-force-option': eslint.Rule.RuleModule;
|
|
71
|
+
'no-get-by-title': eslint.Rule.RuleModule;
|
|
70
72
|
'no-nested-step': eslint.Rule.RuleModule;
|
|
71
73
|
'no-networkidle': eslint.Rule.RuleModule;
|
|
72
74
|
'no-nth-methods': eslint.Rule.RuleModule;
|
|
@@ -203,6 +205,7 @@ declare const _default: {
|
|
|
203
205
|
'no-eval': eslint.Rule.RuleModule;
|
|
204
206
|
'no-focused-test': eslint.Rule.RuleModule;
|
|
205
207
|
'no-force-option': eslint.Rule.RuleModule;
|
|
208
|
+
'no-get-by-title': eslint.Rule.RuleModule;
|
|
206
209
|
'no-nested-step': eslint.Rule.RuleModule;
|
|
207
210
|
'no-networkidle': eslint.Rule.RuleModule;
|
|
208
211
|
'no-nth-methods': eslint.Rule.RuleModule;
|
package/dist/index.js
CHANGED
|
@@ -54,8 +54,11 @@ function isStringNode(node) {
|
|
|
54
54
|
function isPropertyAccessor(node, name) {
|
|
55
55
|
return getStringValue(node.property) === name;
|
|
56
56
|
}
|
|
57
|
-
function isTestIdentifier(node) {
|
|
58
|
-
|
|
57
|
+
function isTestIdentifier(context, node) {
|
|
58
|
+
const aliases = context.settings.playwright?.globalAliases?.test ?? [];
|
|
59
|
+
const testNames = ["test", ...aliases];
|
|
60
|
+
const regex = new RegExp(`^(${testNames.join("|")})$`);
|
|
61
|
+
return isIdentifier(node, regex) || node.type === "MemberExpression" && isIdentifier(node.object, regex);
|
|
59
62
|
}
|
|
60
63
|
var describeProperties = /* @__PURE__ */ new Set([
|
|
61
64
|
"parallel",
|
|
@@ -79,27 +82,31 @@ function findParent(node, type) {
|
|
|
79
82
|
return;
|
|
80
83
|
return node.parent.type === type ? node.parent : findParent(node.parent, type);
|
|
81
84
|
}
|
|
82
|
-
function isTestCall(node, modifiers) {
|
|
83
|
-
return isTestIdentifier(node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && ["ArrowFunctionExpression", "FunctionExpression"].includes(
|
|
85
|
+
function isTestCall(context, node, modifiers) {
|
|
86
|
+
return isTestIdentifier(context, node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && ["ArrowFunctionExpression", "FunctionExpression"].includes(
|
|
84
87
|
node.arguments[1].type
|
|
85
88
|
);
|
|
86
89
|
}
|
|
87
90
|
var testHooks = /* @__PURE__ */ new Set(["afterAll", "afterEach", "beforeAll", "beforeEach"]);
|
|
88
|
-
function isTestHook(node) {
|
|
89
|
-
return node.callee.type === "MemberExpression" &&
|
|
91
|
+
function isTestHook(context, node) {
|
|
92
|
+
return node.callee.type === "MemberExpression" && isTestIdentifier(context, node.callee.object) && testHooks.has(getStringValue(node.callee.property));
|
|
90
93
|
}
|
|
91
94
|
var expectSubCommands = /* @__PURE__ */ new Set(["soft", "poll"]);
|
|
92
|
-
function getExpectType(node) {
|
|
93
|
-
|
|
95
|
+
function getExpectType(context, node) {
|
|
96
|
+
const aliases = context.settings.playwright?.globalAliases?.expect ?? [];
|
|
97
|
+
const expectNames = ["expect", ...aliases];
|
|
98
|
+
const regex = new RegExp(`(^(${expectNames.join("|")})|Expect)$`);
|
|
99
|
+
if (isIdentifier(node.callee, regex)) {
|
|
94
100
|
return "standalone";
|
|
95
101
|
}
|
|
96
|
-
if (node.callee.type === "MemberExpression" &&
|
|
102
|
+
if (node.callee.type === "MemberExpression" && // TODO: Maybe
|
|
103
|
+
isIdentifier(node.callee.object, "expect")) {
|
|
97
104
|
const type = getStringValue(node.callee.property);
|
|
98
105
|
return expectSubCommands.has(type) ? type : void 0;
|
|
99
106
|
}
|
|
100
107
|
}
|
|
101
|
-
function isExpectCall(node) {
|
|
102
|
-
return !!getExpectType(node);
|
|
108
|
+
function isExpectCall(context, node) {
|
|
109
|
+
return !!getExpectType(context, node);
|
|
103
110
|
}
|
|
104
111
|
function getMatchers(node, chain = []) {
|
|
105
112
|
if (node.parent.type === "MemberExpression" && node.parent.object === node) {
|
|
@@ -117,26 +124,18 @@ function isPageMethod(node, name) {
|
|
|
117
124
|
return node.callee.type === "MemberExpression" && dig(node.callee.object, /(^(page|frame)|(Page|Frame)$)/) && isPropertyAccessor(node.callee, name);
|
|
118
125
|
}
|
|
119
126
|
|
|
120
|
-
// src/utils/misc.ts
|
|
121
|
-
var getAmountData = (amount) => ({
|
|
122
|
-
amount: amount.toString(),
|
|
123
|
-
s: amount === 1 ? "" : "s"
|
|
124
|
-
});
|
|
125
|
-
function getAdditionalAssertFunctionNames(context) {
|
|
126
|
-
const globalSettings = context.settings.playwright?.additionalAssertFunctionNames ?? [];
|
|
127
|
-
const ruleSettings = context.options[0]?.additionalAssertFunctionNames ?? [];
|
|
128
|
-
return [...globalSettings, ...ruleSettings];
|
|
129
|
-
}
|
|
130
|
-
|
|
131
127
|
// src/rules/expect-expect.ts
|
|
132
|
-
function isAssertionCall(node,
|
|
133
|
-
return isExpectCall(node) ||
|
|
128
|
+
function isAssertionCall(context, node, assertFunctionNames) {
|
|
129
|
+
return isExpectCall(context, node) || assertFunctionNames.find((name) => dig(node.callee, name));
|
|
134
130
|
}
|
|
135
131
|
var expect_expect_default = {
|
|
136
132
|
create(context) {
|
|
133
|
+
const options = {
|
|
134
|
+
assertFunctionNames: [],
|
|
135
|
+
...context.options?.[0] ?? {}
|
|
136
|
+
};
|
|
137
137
|
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
138
138
|
const unchecked = [];
|
|
139
|
-
const additionalAssertFunctionNames = getAdditionalAssertFunctionNames(context);
|
|
140
139
|
function checkExpressions(nodes) {
|
|
141
140
|
for (const node of nodes) {
|
|
142
141
|
const index2 = node.type === "CallExpression" ? unchecked.indexOf(node) : -1;
|
|
@@ -148,9 +147,9 @@ var expect_expect_default = {
|
|
|
148
147
|
}
|
|
149
148
|
return {
|
|
150
149
|
CallExpression(node) {
|
|
151
|
-
if (isTestCall(node, ["fixme", "only", "skip"])) {
|
|
150
|
+
if (isTestCall(context, node, ["fixme", "only", "skip"])) {
|
|
152
151
|
unchecked.push(node);
|
|
153
|
-
} else if (isAssertionCall(node,
|
|
152
|
+
} else if (isAssertionCall(context, node, options.assertFunctionNames)) {
|
|
154
153
|
const ancestors = sourceCode.getAncestors ? sourceCode.getAncestors(node) : context.getAncestors();
|
|
155
154
|
checkExpressions(ancestors);
|
|
156
155
|
}
|
|
@@ -176,7 +175,7 @@ var expect_expect_default = {
|
|
|
176
175
|
{
|
|
177
176
|
additionalProperties: false,
|
|
178
177
|
properties: {
|
|
179
|
-
|
|
178
|
+
assertFunctionNames: {
|
|
180
179
|
items: [{ type: "string" }],
|
|
181
180
|
type: "array"
|
|
182
181
|
}
|
|
@@ -302,11 +301,11 @@ var playwrightTestMatchers = [
|
|
|
302
301
|
"toBeAttached",
|
|
303
302
|
"toBeInViewport"
|
|
304
303
|
];
|
|
305
|
-
function getCallType(node, awaitableMatchers) {
|
|
304
|
+
function getCallType(context, node, awaitableMatchers) {
|
|
306
305
|
if (node.callee.type === "MemberExpression" && isIdentifier(node.callee.object, "test") && isPropertyAccessor(node.callee, "step")) {
|
|
307
306
|
return { messageId: "testStep", node };
|
|
308
307
|
}
|
|
309
|
-
const expectType = getExpectType(node);
|
|
308
|
+
const expectType = getExpectType(context, node);
|
|
310
309
|
if (!expectType)
|
|
311
310
|
return;
|
|
312
311
|
const [lastMatcher] = getMatchers(node).slice(-1);
|
|
@@ -355,7 +354,7 @@ var missing_playwright_await_default = {
|
|
|
355
354
|
}
|
|
356
355
|
return {
|
|
357
356
|
CallExpression(node) {
|
|
358
|
-
const result = getCallType(node, awaitableMatchers);
|
|
357
|
+
const result = getCallType(context, node, awaitableMatchers);
|
|
359
358
|
const isValid = result ? checkValidity(result.node) : false;
|
|
360
359
|
if (result && !isValid) {
|
|
361
360
|
context.report({
|
|
@@ -401,7 +400,7 @@ var no_conditional_in_test_default = {
|
|
|
401
400
|
create(context) {
|
|
402
401
|
function checkConditional(node) {
|
|
403
402
|
const call = findParent(node, "CallExpression");
|
|
404
|
-
if (call && isTestCall(call)) {
|
|
403
|
+
if (call && isTestCall(context, call)) {
|
|
405
404
|
context.report({ messageId: "conditionalInTest", node });
|
|
406
405
|
}
|
|
407
406
|
}
|
|
@@ -519,7 +518,7 @@ var no_focused_test_default = {
|
|
|
519
518
|
create(context) {
|
|
520
519
|
return {
|
|
521
520
|
CallExpression(node) {
|
|
522
|
-
if ((isTestCall(node) || isDescribeCall(node)) && node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "only")) {
|
|
521
|
+
if ((isTestCall(context, node) || isDescribeCall(node)) && node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "only")) {
|
|
523
522
|
const { callee } = node;
|
|
524
523
|
context.report({
|
|
525
524
|
messageId: "noFocusedTest",
|
|
@@ -602,6 +601,31 @@ var no_force_option_default = {
|
|
|
602
601
|
}
|
|
603
602
|
};
|
|
604
603
|
|
|
604
|
+
// src/rules/no-get-by-title.ts
|
|
605
|
+
var no_get_by_title_default = {
|
|
606
|
+
create(context) {
|
|
607
|
+
return {
|
|
608
|
+
CallExpression(node) {
|
|
609
|
+
if (isPageMethod(node, "getByTitle")) {
|
|
610
|
+
context.report({ messageId: "noGetByTitle", node });
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
},
|
|
615
|
+
meta: {
|
|
616
|
+
docs: {
|
|
617
|
+
category: "Best Practices",
|
|
618
|
+
description: "Disallows the usage of getByTitle()",
|
|
619
|
+
recommended: false,
|
|
620
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-get-by-title.md"
|
|
621
|
+
},
|
|
622
|
+
messages: {
|
|
623
|
+
noGetByTitle: "The HTML title attribute is not an accessible name. Prefer getByRole() or getByLabelText() instead."
|
|
624
|
+
},
|
|
625
|
+
type: "suggestion"
|
|
626
|
+
}
|
|
627
|
+
};
|
|
628
|
+
|
|
605
629
|
// src/rules/no-nested-step.ts
|
|
606
630
|
function isStepCall(node) {
|
|
607
631
|
const inner = node.type === "CallExpression" ? node.callee : node;
|
|
@@ -824,8 +848,8 @@ function getExpectArguments(node) {
|
|
|
824
848
|
const grandparent = node.parent.parent;
|
|
825
849
|
return grandparent.type === "CallExpression" ? grandparent.arguments : [];
|
|
826
850
|
}
|
|
827
|
-
function parseExpectCall(node) {
|
|
828
|
-
if (!isExpectCall(node)) {
|
|
851
|
+
function parseExpectCall(context, node) {
|
|
852
|
+
if (!isExpectCall(context, node)) {
|
|
829
853
|
return;
|
|
830
854
|
}
|
|
831
855
|
const members = getMatchers(node);
|
|
@@ -856,7 +880,7 @@ var no_restricted_matchers_default = {
|
|
|
856
880
|
const restrictedChains = context.options?.[0] ?? {};
|
|
857
881
|
return {
|
|
858
882
|
CallExpression(node) {
|
|
859
|
-
const expectCall = parseExpectCall(node);
|
|
883
|
+
const expectCall = parseExpectCall(context, node);
|
|
860
884
|
if (!expectCall)
|
|
861
885
|
return;
|
|
862
886
|
Object.entries(restrictedChains).map(([restriction, message]) => {
|
|
@@ -917,8 +941,8 @@ var no_skipped_test_default = {
|
|
|
917
941
|
const options = context.options[0] || {};
|
|
918
942
|
const allowConditional = !!options.allowConditional;
|
|
919
943
|
const { callee } = node;
|
|
920
|
-
if ((isTestIdentifier(callee) || isDescribeCall(node)) && callee.type === "MemberExpression" && isPropertyAccessor(callee, "skip")) {
|
|
921
|
-
const isHook = isTestCall(node) || isDescribeCall(node);
|
|
944
|
+
if ((isTestIdentifier(context, callee) || isDescribeCall(node)) && callee.type === "MemberExpression" && isPropertyAccessor(callee, "skip")) {
|
|
945
|
+
const isHook = isTestCall(context, node) || isDescribeCall(node);
|
|
922
946
|
if (!isHook && allowConditional && node.arguments.length) {
|
|
923
947
|
return;
|
|
924
948
|
}
|
|
@@ -1072,7 +1096,7 @@ var no_useless_not_default = {
|
|
|
1072
1096
|
create(context) {
|
|
1073
1097
|
return {
|
|
1074
1098
|
CallExpression(node) {
|
|
1075
|
-
const expectCall = parseExpectCall(node);
|
|
1099
|
+
const expectCall = parseExpectCall(context, node);
|
|
1076
1100
|
if (!expectCall)
|
|
1077
1101
|
return;
|
|
1078
1102
|
const notModifier = expectCall.modifiers.find(
|
|
@@ -1204,7 +1228,7 @@ var prefer_lowercase_title_default = {
|
|
|
1204
1228
|
let describeCount = 0;
|
|
1205
1229
|
return {
|
|
1206
1230
|
CallExpression(node) {
|
|
1207
|
-
const method = isDescribeCall(node) ? "test.describe" : isTestCall(node) ? "test" : null;
|
|
1231
|
+
const method = isDescribeCall(node) ? "test.describe" : isTestCall(context, node) ? "test" : null;
|
|
1208
1232
|
if (method === "test.describe") {
|
|
1209
1233
|
describeCount++;
|
|
1210
1234
|
if (ignoreTopLevelDescribe && describeCount === 1) {
|
|
@@ -1290,7 +1314,7 @@ var prefer_strict_equal_default = {
|
|
|
1290
1314
|
create(context) {
|
|
1291
1315
|
return {
|
|
1292
1316
|
CallExpression(node) {
|
|
1293
|
-
const expectCall = parseExpectCall(node);
|
|
1317
|
+
const expectCall = parseExpectCall(context, node);
|
|
1294
1318
|
if (expectCall?.matcherName === "toEqual") {
|
|
1295
1319
|
context.report({
|
|
1296
1320
|
messageId: "useToStrictEqual",
|
|
@@ -1364,7 +1388,7 @@ var prefer_to_be_default = {
|
|
|
1364
1388
|
create(context) {
|
|
1365
1389
|
return {
|
|
1366
1390
|
CallExpression(node) {
|
|
1367
|
-
const expectCall = parseExpectCall(node);
|
|
1391
|
+
const expectCall = parseExpectCall(context, node);
|
|
1368
1392
|
if (!expectCall)
|
|
1369
1393
|
return;
|
|
1370
1394
|
const notMatchers = ["toBeUndefined", "toBeDefined"];
|
|
@@ -1427,7 +1451,7 @@ var prefer_to_contain_default = {
|
|
|
1427
1451
|
create(context) {
|
|
1428
1452
|
return {
|
|
1429
1453
|
CallExpression(node) {
|
|
1430
|
-
const expectCall = parseExpectCall(node);
|
|
1454
|
+
const expectCall = parseExpectCall(context, node);
|
|
1431
1455
|
if (!expectCall || expectCall.args.length === 0)
|
|
1432
1456
|
return;
|
|
1433
1457
|
const { args, matcher, matcherName } = expectCall;
|
|
@@ -1497,7 +1521,7 @@ var prefer_to_have_count_default = {
|
|
|
1497
1521
|
create(context) {
|
|
1498
1522
|
return {
|
|
1499
1523
|
CallExpression(node) {
|
|
1500
|
-
const expectCall = parseExpectCall(node);
|
|
1524
|
+
const expectCall = parseExpectCall(context, node);
|
|
1501
1525
|
if (!expectCall || !matchers2.has(expectCall.matcherName)) {
|
|
1502
1526
|
return;
|
|
1503
1527
|
}
|
|
@@ -1553,7 +1577,7 @@ var prefer_to_have_length_default = {
|
|
|
1553
1577
|
create(context) {
|
|
1554
1578
|
return {
|
|
1555
1579
|
CallExpression(node) {
|
|
1556
|
-
const expectCall = parseExpectCall(node);
|
|
1580
|
+
const expectCall = parseExpectCall(context, node);
|
|
1557
1581
|
if (!expectCall || !lengthMatchers.has(expectCall.matcherName)) {
|
|
1558
1582
|
return;
|
|
1559
1583
|
}
|
|
@@ -1641,7 +1665,7 @@ var prefer_web_first_assertions_default = {
|
|
|
1641
1665
|
create(context) {
|
|
1642
1666
|
return {
|
|
1643
1667
|
CallExpression(node) {
|
|
1644
|
-
const expectCall = parseExpectCall(node);
|
|
1668
|
+
const expectCall = parseExpectCall(context, node);
|
|
1645
1669
|
if (!expectCall)
|
|
1646
1670
|
return;
|
|
1647
1671
|
const [arg] = node.arguments;
|
|
@@ -1742,7 +1766,7 @@ var require_soft_assertions_default = {
|
|
|
1742
1766
|
create(context) {
|
|
1743
1767
|
return {
|
|
1744
1768
|
CallExpression(node) {
|
|
1745
|
-
if (getExpectType(node) === "standalone") {
|
|
1769
|
+
if (getExpectType(context, node) === "standalone") {
|
|
1746
1770
|
context.report({
|
|
1747
1771
|
fix: (fixer) => fixer.insertTextAfter(node.callee, ".soft"),
|
|
1748
1772
|
messageId: "requireSoft",
|
|
@@ -1767,6 +1791,12 @@ var require_soft_assertions_default = {
|
|
|
1767
1791
|
}
|
|
1768
1792
|
};
|
|
1769
1793
|
|
|
1794
|
+
// src/utils/misc.ts
|
|
1795
|
+
var getAmountData = (amount) => ({
|
|
1796
|
+
amount: amount.toString(),
|
|
1797
|
+
s: amount === 1 ? "" : "s"
|
|
1798
|
+
});
|
|
1799
|
+
|
|
1770
1800
|
// src/rules/require-top-level-describe.ts
|
|
1771
1801
|
var require_top_level_describe_default = {
|
|
1772
1802
|
create(context) {
|
|
@@ -1791,9 +1821,9 @@ var require_top_level_describe_default = {
|
|
|
1791
1821
|
}
|
|
1792
1822
|
}
|
|
1793
1823
|
} else if (!describeCount) {
|
|
1794
|
-
if (isTestCall(node)) {
|
|
1824
|
+
if (isTestCall(context, node)) {
|
|
1795
1825
|
context.report({ messageId: "unexpectedTest", node: node.callee });
|
|
1796
|
-
} else if (isTestHook(node)) {
|
|
1826
|
+
} else if (isTestHook(context, node)) {
|
|
1797
1827
|
context.report({ messageId: "unexpectedHook", node: node.callee });
|
|
1798
1828
|
}
|
|
1799
1829
|
}
|
|
@@ -1854,9 +1884,9 @@ var valid_expect_default = {
|
|
|
1854
1884
|
const maxArgs = Math.max(options.minArgs, options.maxArgs);
|
|
1855
1885
|
return {
|
|
1856
1886
|
CallExpression(node) {
|
|
1857
|
-
if (!isExpectCall(node))
|
|
1887
|
+
if (!isExpectCall(context, node))
|
|
1858
1888
|
return;
|
|
1859
|
-
const expectCall = parseExpectCall(node);
|
|
1889
|
+
const expectCall = parseExpectCall(context, node);
|
|
1860
1890
|
if (!expectCall) {
|
|
1861
1891
|
context.report({ messageId: "matcherNotFound", node });
|
|
1862
1892
|
} else {
|
|
@@ -1973,7 +2003,7 @@ var valid_title_default = {
|
|
|
1973
2003
|
return {
|
|
1974
2004
|
CallExpression(node) {
|
|
1975
2005
|
const isDescribe = isDescribeCall(node);
|
|
1976
|
-
const isTest = isTestCall(node);
|
|
2006
|
+
const isTest = isTestCall(context, node);
|
|
1977
2007
|
if (!isDescribe && !isTest) {
|
|
1978
2008
|
return;
|
|
1979
2009
|
}
|
|
@@ -2142,6 +2172,7 @@ var index = {
|
|
|
2142
2172
|
"no-eval": no_eval_default,
|
|
2143
2173
|
"no-focused-test": no_focused_test_default,
|
|
2144
2174
|
"no-force-option": no_force_option_default,
|
|
2175
|
+
"no-get-by-title": no_get_by_title_default,
|
|
2145
2176
|
"no-nested-step": no_nested_step_default,
|
|
2146
2177
|
"no-networkidle": no_networkidle_default,
|
|
2147
2178
|
"no-nth-methods": no_nth_methods_default,
|
package/dist/index.mjs
CHANGED
|
@@ -33,8 +33,11 @@ function isStringNode(node) {
|
|
|
33
33
|
function isPropertyAccessor(node, name) {
|
|
34
34
|
return getStringValue(node.property) === name;
|
|
35
35
|
}
|
|
36
|
-
function isTestIdentifier(node) {
|
|
37
|
-
|
|
36
|
+
function isTestIdentifier(context, node) {
|
|
37
|
+
const aliases = context.settings.playwright?.globalAliases?.test ?? [];
|
|
38
|
+
const testNames = ["test", ...aliases];
|
|
39
|
+
const regex = new RegExp(`^(${testNames.join("|")})$`);
|
|
40
|
+
return isIdentifier(node, regex) || node.type === "MemberExpression" && isIdentifier(node.object, regex);
|
|
38
41
|
}
|
|
39
42
|
function isDescribeCall(node) {
|
|
40
43
|
const inner = node.type === "CallExpression" ? node.callee : node;
|
|
@@ -51,25 +54,29 @@ function findParent(node, type) {
|
|
|
51
54
|
return;
|
|
52
55
|
return node.parent.type === type ? node.parent : findParent(node.parent, type);
|
|
53
56
|
}
|
|
54
|
-
function isTestCall(node, modifiers) {
|
|
55
|
-
return isTestIdentifier(node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && ["ArrowFunctionExpression", "FunctionExpression"].includes(
|
|
57
|
+
function isTestCall(context, node, modifiers) {
|
|
58
|
+
return isTestIdentifier(context, node.callee) && !isDescribeCall(node) && (node.callee.type !== "MemberExpression" || !modifiers || modifiers?.includes(getStringValue(node.callee.property))) && node.arguments.length === 2 && ["ArrowFunctionExpression", "FunctionExpression"].includes(
|
|
56
59
|
node.arguments[1].type
|
|
57
60
|
);
|
|
58
61
|
}
|
|
59
|
-
function isTestHook(node) {
|
|
60
|
-
return node.callee.type === "MemberExpression" &&
|
|
62
|
+
function isTestHook(context, node) {
|
|
63
|
+
return node.callee.type === "MemberExpression" && isTestIdentifier(context, node.callee.object) && testHooks.has(getStringValue(node.callee.property));
|
|
61
64
|
}
|
|
62
|
-
function getExpectType(node) {
|
|
63
|
-
|
|
65
|
+
function getExpectType(context, node) {
|
|
66
|
+
const aliases = context.settings.playwright?.globalAliases?.expect ?? [];
|
|
67
|
+
const expectNames = ["expect", ...aliases];
|
|
68
|
+
const regex = new RegExp(`(^(${expectNames.join("|")})|Expect)$`);
|
|
69
|
+
if (isIdentifier(node.callee, regex)) {
|
|
64
70
|
return "standalone";
|
|
65
71
|
}
|
|
66
|
-
if (node.callee.type === "MemberExpression" &&
|
|
72
|
+
if (node.callee.type === "MemberExpression" && // TODO: Maybe
|
|
73
|
+
isIdentifier(node.callee.object, "expect")) {
|
|
67
74
|
const type = getStringValue(node.callee.property);
|
|
68
75
|
return expectSubCommands.has(type) ? type : void 0;
|
|
69
76
|
}
|
|
70
77
|
}
|
|
71
|
-
function isExpectCall(node) {
|
|
72
|
-
return !!getExpectType(node);
|
|
78
|
+
function isExpectCall(context, node) {
|
|
79
|
+
return !!getExpectType(context, node);
|
|
73
80
|
}
|
|
74
81
|
function getMatchers(node, chain = []) {
|
|
75
82
|
if (node.parent.type === "MemberExpression" && node.parent.object === node) {
|
|
@@ -104,38 +111,23 @@ var init_ast = __esm({
|
|
|
104
111
|
}
|
|
105
112
|
});
|
|
106
113
|
|
|
107
|
-
// src/utils/misc.ts
|
|
108
|
-
function getAdditionalAssertFunctionNames(context) {
|
|
109
|
-
const globalSettings = context.settings.playwright?.additionalAssertFunctionNames ?? [];
|
|
110
|
-
const ruleSettings = context.options[0]?.additionalAssertFunctionNames ?? [];
|
|
111
|
-
return [...globalSettings, ...ruleSettings];
|
|
112
|
-
}
|
|
113
|
-
var getAmountData;
|
|
114
|
-
var init_misc = __esm({
|
|
115
|
-
"src/utils/misc.ts"() {
|
|
116
|
-
"use strict";
|
|
117
|
-
getAmountData = (amount) => ({
|
|
118
|
-
amount: amount.toString(),
|
|
119
|
-
s: amount === 1 ? "" : "s"
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
|
|
124
114
|
// src/rules/expect-expect.ts
|
|
125
|
-
function isAssertionCall(node,
|
|
126
|
-
return isExpectCall(node) ||
|
|
115
|
+
function isAssertionCall(context, node, assertFunctionNames) {
|
|
116
|
+
return isExpectCall(context, node) || assertFunctionNames.find((name) => dig(node.callee, name));
|
|
127
117
|
}
|
|
128
118
|
var expect_expect_default;
|
|
129
119
|
var init_expect_expect = __esm({
|
|
130
120
|
"src/rules/expect-expect.ts"() {
|
|
131
121
|
"use strict";
|
|
132
122
|
init_ast();
|
|
133
|
-
init_misc();
|
|
134
123
|
expect_expect_default = {
|
|
135
124
|
create(context) {
|
|
125
|
+
const options = {
|
|
126
|
+
assertFunctionNames: [],
|
|
127
|
+
...context.options?.[0] ?? {}
|
|
128
|
+
};
|
|
136
129
|
const sourceCode = context.sourceCode ?? context.getSourceCode();
|
|
137
130
|
const unchecked = [];
|
|
138
|
-
const additionalAssertFunctionNames = getAdditionalAssertFunctionNames(context);
|
|
139
131
|
function checkExpressions(nodes) {
|
|
140
132
|
for (const node of nodes) {
|
|
141
133
|
const index = node.type === "CallExpression" ? unchecked.indexOf(node) : -1;
|
|
@@ -147,9 +139,9 @@ var init_expect_expect = __esm({
|
|
|
147
139
|
}
|
|
148
140
|
return {
|
|
149
141
|
CallExpression(node) {
|
|
150
|
-
if (isTestCall(node, ["fixme", "only", "skip"])) {
|
|
142
|
+
if (isTestCall(context, node, ["fixme", "only", "skip"])) {
|
|
151
143
|
unchecked.push(node);
|
|
152
|
-
} else if (isAssertionCall(node,
|
|
144
|
+
} else if (isAssertionCall(context, node, options.assertFunctionNames)) {
|
|
153
145
|
const ancestors = sourceCode.getAncestors ? sourceCode.getAncestors(node) : context.getAncestors();
|
|
154
146
|
checkExpressions(ancestors);
|
|
155
147
|
}
|
|
@@ -175,7 +167,7 @@ var init_expect_expect = __esm({
|
|
|
175
167
|
{
|
|
176
168
|
additionalProperties: false,
|
|
177
169
|
properties: {
|
|
178
|
-
|
|
170
|
+
assertFunctionNames: {
|
|
179
171
|
items: [{ type: "string" }],
|
|
180
172
|
type: "array"
|
|
181
173
|
}
|
|
@@ -258,11 +250,11 @@ var init_max_nested_describe = __esm({
|
|
|
258
250
|
});
|
|
259
251
|
|
|
260
252
|
// src/rules/missing-playwright-await.ts
|
|
261
|
-
function getCallType(node, awaitableMatchers) {
|
|
253
|
+
function getCallType(context, node, awaitableMatchers) {
|
|
262
254
|
if (node.callee.type === "MemberExpression" && isIdentifier(node.callee.object, "test") && isPropertyAccessor(node.callee, "step")) {
|
|
263
255
|
return { messageId: "testStep", node };
|
|
264
256
|
}
|
|
265
|
-
const expectType = getExpectType(node);
|
|
257
|
+
const expectType = getExpectType(context, node);
|
|
266
258
|
if (!expectType)
|
|
267
259
|
return;
|
|
268
260
|
const [lastMatcher] = getMatchers(node).slice(-1);
|
|
@@ -368,7 +360,7 @@ var init_missing_playwright_await = __esm({
|
|
|
368
360
|
}
|
|
369
361
|
return {
|
|
370
362
|
CallExpression(node) {
|
|
371
|
-
const result = getCallType(node, awaitableMatchers);
|
|
363
|
+
const result = getCallType(context, node, awaitableMatchers);
|
|
372
364
|
const isValid = result ? checkValidity(result.node) : false;
|
|
373
365
|
if (result && !isValid) {
|
|
374
366
|
context.report({
|
|
@@ -421,7 +413,7 @@ var init_no_conditional_in_test = __esm({
|
|
|
421
413
|
create(context) {
|
|
422
414
|
function checkConditional(node) {
|
|
423
415
|
const call = findParent(node, "CallExpression");
|
|
424
|
-
if (call && isTestCall(call)) {
|
|
416
|
+
if (call && isTestCall(context, call)) {
|
|
425
417
|
context.report({ messageId: "conditionalInTest", node });
|
|
426
418
|
}
|
|
427
419
|
}
|
|
@@ -560,7 +552,7 @@ var init_no_focused_test = __esm({
|
|
|
560
552
|
create(context) {
|
|
561
553
|
return {
|
|
562
554
|
CallExpression(node) {
|
|
563
|
-
if ((isTestCall(node) || isDescribeCall(node)) && node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "only")) {
|
|
555
|
+
if ((isTestCall(context, node) || isDescribeCall(node)) && node.callee.type === "MemberExpression" && isPropertyAccessor(node.callee, "only")) {
|
|
564
556
|
const { callee } = node;
|
|
565
557
|
context.report({
|
|
566
558
|
messageId: "noFocusedTest",
|
|
@@ -652,6 +644,38 @@ var init_no_force_option = __esm({
|
|
|
652
644
|
}
|
|
653
645
|
});
|
|
654
646
|
|
|
647
|
+
// src/rules/no-get-by-title.ts
|
|
648
|
+
var no_get_by_title_default;
|
|
649
|
+
var init_no_get_by_title = __esm({
|
|
650
|
+
"src/rules/no-get-by-title.ts"() {
|
|
651
|
+
"use strict";
|
|
652
|
+
init_ast();
|
|
653
|
+
no_get_by_title_default = {
|
|
654
|
+
create(context) {
|
|
655
|
+
return {
|
|
656
|
+
CallExpression(node) {
|
|
657
|
+
if (isPageMethod(node, "getByTitle")) {
|
|
658
|
+
context.report({ messageId: "noGetByTitle", node });
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
},
|
|
663
|
+
meta: {
|
|
664
|
+
docs: {
|
|
665
|
+
category: "Best Practices",
|
|
666
|
+
description: "Disallows the usage of getByTitle()",
|
|
667
|
+
recommended: false,
|
|
668
|
+
url: "https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-get-by-title.md"
|
|
669
|
+
},
|
|
670
|
+
messages: {
|
|
671
|
+
noGetByTitle: "The HTML title attribute is not an accessible name. Prefer getByRole() or getByLabelText() instead."
|
|
672
|
+
},
|
|
673
|
+
type: "suggestion"
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
});
|
|
678
|
+
|
|
655
679
|
// src/rules/no-nested-step.ts
|
|
656
680
|
function isStepCall(node) {
|
|
657
681
|
const inner = node.type === "CallExpression" ? node.callee : node;
|
|
@@ -908,8 +932,8 @@ function getExpectArguments(node) {
|
|
|
908
932
|
const grandparent = node.parent.parent;
|
|
909
933
|
return grandparent.type === "CallExpression" ? grandparent.arguments : [];
|
|
910
934
|
}
|
|
911
|
-
function parseExpectCall(node) {
|
|
912
|
-
if (!isExpectCall(node)) {
|
|
935
|
+
function parseExpectCall(context, node) {
|
|
936
|
+
if (!isExpectCall(context, node)) {
|
|
913
937
|
return;
|
|
914
938
|
}
|
|
915
939
|
const members = getMatchers(node);
|
|
@@ -954,7 +978,7 @@ var init_no_restricted_matchers = __esm({
|
|
|
954
978
|
const restrictedChains = context.options?.[0] ?? {};
|
|
955
979
|
return {
|
|
956
980
|
CallExpression(node) {
|
|
957
|
-
const expectCall = parseExpectCall(node);
|
|
981
|
+
const expectCall = parseExpectCall(context, node);
|
|
958
982
|
if (!expectCall)
|
|
959
983
|
return;
|
|
960
984
|
Object.entries(restrictedChains).map(([restriction, message]) => {
|
|
@@ -1022,8 +1046,8 @@ var init_no_skipped_test = __esm({
|
|
|
1022
1046
|
const options = context.options[0] || {};
|
|
1023
1047
|
const allowConditional = !!options.allowConditional;
|
|
1024
1048
|
const { callee } = node;
|
|
1025
|
-
if ((isTestIdentifier(callee) || isDescribeCall(node)) && callee.type === "MemberExpression" && isPropertyAccessor(callee, "skip")) {
|
|
1026
|
-
const isHook = isTestCall(node) || isDescribeCall(node);
|
|
1049
|
+
if ((isTestIdentifier(context, callee) || isDescribeCall(node)) && callee.type === "MemberExpression" && isPropertyAccessor(callee, "skip")) {
|
|
1050
|
+
const isHook = isTestCall(context, node) || isDescribeCall(node);
|
|
1027
1051
|
if (!isHook && allowConditional && node.arguments.length) {
|
|
1028
1052
|
return;
|
|
1029
1053
|
}
|
|
@@ -1199,7 +1223,7 @@ var init_no_useless_not = __esm({
|
|
|
1199
1223
|
create(context) {
|
|
1200
1224
|
return {
|
|
1201
1225
|
CallExpression(node) {
|
|
1202
|
-
const expectCall = parseExpectCall(node);
|
|
1226
|
+
const expectCall = parseExpectCall(context, node);
|
|
1203
1227
|
if (!expectCall)
|
|
1204
1228
|
return;
|
|
1205
1229
|
const notModifier = expectCall.modifiers.find(
|
|
@@ -1352,7 +1376,7 @@ var init_prefer_lowercase_title = __esm({
|
|
|
1352
1376
|
let describeCount = 0;
|
|
1353
1377
|
return {
|
|
1354
1378
|
CallExpression(node) {
|
|
1355
|
-
const method = isDescribeCall(node) ? "test.describe" : isTestCall(node) ? "test" : null;
|
|
1379
|
+
const method = isDescribeCall(node) ? "test.describe" : isTestCall(context, node) ? "test" : null;
|
|
1356
1380
|
if (method === "test.describe") {
|
|
1357
1381
|
describeCount++;
|
|
1358
1382
|
if (ignoreTopLevelDescribe && describeCount === 1) {
|
|
@@ -1446,7 +1470,7 @@ var init_prefer_strict_equal = __esm({
|
|
|
1446
1470
|
create(context) {
|
|
1447
1471
|
return {
|
|
1448
1472
|
CallExpression(node) {
|
|
1449
|
-
const expectCall = parseExpectCall(node);
|
|
1473
|
+
const expectCall = parseExpectCall(context, node);
|
|
1450
1474
|
if (expectCall?.matcherName === "toEqual") {
|
|
1451
1475
|
context.report({
|
|
1452
1476
|
messageId: "useToStrictEqual",
|
|
@@ -1529,7 +1553,7 @@ var init_prefer_to_be = __esm({
|
|
|
1529
1553
|
create(context) {
|
|
1530
1554
|
return {
|
|
1531
1555
|
CallExpression(node) {
|
|
1532
|
-
const expectCall = parseExpectCall(node);
|
|
1556
|
+
const expectCall = parseExpectCall(context, node);
|
|
1533
1557
|
if (!expectCall)
|
|
1534
1558
|
return;
|
|
1535
1559
|
const notMatchers = ["toBeUndefined", "toBeDefined"];
|
|
@@ -1600,7 +1624,7 @@ var init_prefer_to_contain = __esm({
|
|
|
1600
1624
|
create(context) {
|
|
1601
1625
|
return {
|
|
1602
1626
|
CallExpression(node) {
|
|
1603
|
-
const expectCall = parseExpectCall(node);
|
|
1627
|
+
const expectCall = parseExpectCall(context, node);
|
|
1604
1628
|
if (!expectCall || expectCall.args.length === 0)
|
|
1605
1629
|
return;
|
|
1606
1630
|
const { args, matcher, matcherName } = expectCall;
|
|
@@ -1679,7 +1703,7 @@ var init_prefer_to_have_count = __esm({
|
|
|
1679
1703
|
create(context) {
|
|
1680
1704
|
return {
|
|
1681
1705
|
CallExpression(node) {
|
|
1682
|
-
const expectCall = parseExpectCall(node);
|
|
1706
|
+
const expectCall = parseExpectCall(context, node);
|
|
1683
1707
|
if (!expectCall || !matchers2.has(expectCall.matcherName)) {
|
|
1684
1708
|
return;
|
|
1685
1709
|
}
|
|
@@ -1744,7 +1768,7 @@ var init_prefer_to_have_length = __esm({
|
|
|
1744
1768
|
create(context) {
|
|
1745
1769
|
return {
|
|
1746
1770
|
CallExpression(node) {
|
|
1747
|
-
const expectCall = parseExpectCall(node);
|
|
1771
|
+
const expectCall = parseExpectCall(context, node);
|
|
1748
1772
|
if (!expectCall || !lengthMatchers.has(expectCall.matcherName)) {
|
|
1749
1773
|
return;
|
|
1750
1774
|
}
|
|
@@ -1840,7 +1864,7 @@ var init_prefer_web_first_assertions = __esm({
|
|
|
1840
1864
|
create(context) {
|
|
1841
1865
|
return {
|
|
1842
1866
|
CallExpression(node) {
|
|
1843
|
-
const expectCall = parseExpectCall(node);
|
|
1867
|
+
const expectCall = parseExpectCall(context, node);
|
|
1844
1868
|
if (!expectCall)
|
|
1845
1869
|
return;
|
|
1846
1870
|
const [arg] = node.arguments;
|
|
@@ -1948,7 +1972,7 @@ var init_require_soft_assertions = __esm({
|
|
|
1948
1972
|
create(context) {
|
|
1949
1973
|
return {
|
|
1950
1974
|
CallExpression(node) {
|
|
1951
|
-
if (getExpectType(node) === "standalone") {
|
|
1975
|
+
if (getExpectType(context, node) === "standalone") {
|
|
1952
1976
|
context.report({
|
|
1953
1977
|
fix: (fixer) => fixer.insertTextAfter(node.callee, ".soft"),
|
|
1954
1978
|
messageId: "requireSoft",
|
|
@@ -1975,6 +1999,18 @@ var init_require_soft_assertions = __esm({
|
|
|
1975
1999
|
}
|
|
1976
2000
|
});
|
|
1977
2001
|
|
|
2002
|
+
// src/utils/misc.ts
|
|
2003
|
+
var getAmountData;
|
|
2004
|
+
var init_misc = __esm({
|
|
2005
|
+
"src/utils/misc.ts"() {
|
|
2006
|
+
"use strict";
|
|
2007
|
+
getAmountData = (amount) => ({
|
|
2008
|
+
amount: amount.toString(),
|
|
2009
|
+
s: amount === 1 ? "" : "s"
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
});
|
|
2013
|
+
|
|
1978
2014
|
// src/rules/require-top-level-describe.ts
|
|
1979
2015
|
var require_top_level_describe_default;
|
|
1980
2016
|
var init_require_top_level_describe = __esm({
|
|
@@ -2005,9 +2041,9 @@ var init_require_top_level_describe = __esm({
|
|
|
2005
2041
|
}
|
|
2006
2042
|
}
|
|
2007
2043
|
} else if (!describeCount) {
|
|
2008
|
-
if (isTestCall(node)) {
|
|
2044
|
+
if (isTestCall(context, node)) {
|
|
2009
2045
|
context.report({ messageId: "unexpectedTest", node: node.callee });
|
|
2010
|
-
} else if (isTestHook(node)) {
|
|
2046
|
+
} else if (isTestHook(context, node)) {
|
|
2011
2047
|
context.report({ messageId: "unexpectedHook", node: node.callee });
|
|
2012
2048
|
}
|
|
2013
2049
|
}
|
|
@@ -2077,9 +2113,9 @@ var init_valid_expect = __esm({
|
|
|
2077
2113
|
const maxArgs = Math.max(options.minArgs, options.maxArgs);
|
|
2078
2114
|
return {
|
|
2079
2115
|
CallExpression(node) {
|
|
2080
|
-
if (!isExpectCall(node))
|
|
2116
|
+
if (!isExpectCall(context, node))
|
|
2081
2117
|
return;
|
|
2082
|
-
const expectCall = parseExpectCall(node);
|
|
2118
|
+
const expectCall = parseExpectCall(context, node);
|
|
2083
2119
|
if (!expectCall) {
|
|
2084
2120
|
context.report({ messageId: "matcherNotFound", node });
|
|
2085
2121
|
} else {
|
|
@@ -2203,7 +2239,7 @@ var init_valid_title = __esm({
|
|
|
2203
2239
|
return {
|
|
2204
2240
|
CallExpression(node) {
|
|
2205
2241
|
const isDescribe = isDescribeCall(node);
|
|
2206
|
-
const isTest = isTestCall(node);
|
|
2242
|
+
const isTest = isTestCall(context, node);
|
|
2207
2243
|
if (!isDescribe && !isTest) {
|
|
2208
2244
|
return;
|
|
2209
2245
|
}
|
|
@@ -2374,6 +2410,7 @@ var require_src = __commonJS({
|
|
|
2374
2410
|
init_no_eval();
|
|
2375
2411
|
init_no_focused_test();
|
|
2376
2412
|
init_no_force_option();
|
|
2413
|
+
init_no_get_by_title();
|
|
2377
2414
|
init_no_nested_step();
|
|
2378
2415
|
init_no_networkidle();
|
|
2379
2416
|
init_no_nth_methods();
|
|
@@ -2407,6 +2444,7 @@ var require_src = __commonJS({
|
|
|
2407
2444
|
"no-eval": no_eval_default,
|
|
2408
2445
|
"no-focused-test": no_focused_test_default,
|
|
2409
2446
|
"no-force-option": no_force_option_default,
|
|
2447
|
+
"no-get-by-title": no_get_by_title_default,
|
|
2410
2448
|
"no-nested-step": no_nested_step_default,
|
|
2411
2449
|
"no-networkidle": no_networkidle_default,
|
|
2412
2450
|
"no-nth-methods": no_nth_methods_default,
|
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": "0.
|
|
4
|
+
"version": "1.0.1",
|
|
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",
|
|
@@ -35,9 +35,11 @@
|
|
|
35
35
|
"ts": "tsc --noEmit"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
+
"@jest/globals": "^29.7.0",
|
|
38
39
|
"@mskelton/eslint-config": "^8.4.0",
|
|
39
40
|
"@types/eslint": "^8.44.3",
|
|
40
41
|
"@types/estree": "^1.0.2",
|
|
42
|
+
"@types/node": "^20.11.17",
|
|
41
43
|
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
|
42
44
|
"@typescript-eslint/parser": "^6.7.3",
|
|
43
45
|
"dedent": "^1.5.1",
|