Skip to content

Commit a65200b

Browse files
committed
feat: Add no-restricted-locators rule
Fixes #407
1 parent 261e188 commit a65200b

File tree

5 files changed

+484
-0
lines changed

5 files changed

+484
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ CLI option\
138138
| [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 | | | |
139139
| [no-page-pause](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-page-pause.md) | Disallow using `page.pause()` || | |
140140
| [no-raw-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-raw-locators.md) | Disallow using raw locators | | | |
141+
| [no-restricted-locators](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-restricted-locators.md) | Disallow specific locator methods | | | |
141142
| [no-restricted-matchers](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-restricted-matchers.md) | Disallow specific matchers & modifiers | | | |
142143
| [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 || | 💡 |
143144
| [no-slowed-test](https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/no-slowed-test.md) | Disallow usage of the `.slow` annotation | | | 💡 |
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
## Disallow specific locator methods (`no-restricted-locators`)
2+
3+
This rule bans specific locator methods from being used, and can suggest
4+
alternatives.
5+
6+
## Rule Details
7+
8+
Bans are expressed in the form of an array, where each element can be either:
9+
10+
- A string: the method name to restrict (uses default message)
11+
- An object: `{ type: "methodName", message: "Custom message" }` (optional
12+
message)
13+
14+
By default, the array is empty, meaning no locator methods are banned.
15+
16+
For example:
17+
18+
```json
19+
{
20+
"playwright/no-restricted-locators": [
21+
"error",
22+
[
23+
"getByTestId",
24+
{
25+
"type": "getByTitle",
26+
"message": "Prefer getByRole or getByLabel instead"
27+
}
28+
]
29+
]
30+
}
31+
```
32+
33+
Examples of **incorrect** code for this rule with the above configuration:
34+
35+
```javascript
36+
test('find button', async () => {
37+
await page.getByTestId('submit-button')
38+
})
39+
40+
test('find tooltip', async () => {
41+
await page.getByTitle('Additional info')
42+
})
43+
```
44+
45+
Examples of **correct** code for this rule with the above configuration:
46+
47+
```javascript
48+
test('find button', async () => {
49+
await page.getByRole('button', { name: 'Submit' })
50+
})
51+
52+
test('find tooltip', async () => {
53+
await page.getByLabel('Additional info')
54+
})
55+
```
56+
57+
## Options
58+
59+
The rule accepts an array where each element can be:
60+
61+
### String format
62+
63+
A simple string with the method name to restrict:
64+
65+
```json
66+
{
67+
"playwright/no-restricted-locators": ["error", ["getByTestId", "getByTitle"]]
68+
}
69+
```
70+
71+
### Object format
72+
73+
An object with `type` (required) and optional `message`:
74+
75+
```json
76+
{
77+
"playwright/no-restricted-locators": [
78+
"error",
79+
[
80+
{
81+
"type": "getByTestId",
82+
"message": "Prefer getByRole or getByLabel instead"
83+
},
84+
{ "type": "getByTitle" }
85+
]
86+
]
87+
}
88+
```
89+
90+
### Mixed format
91+
92+
You can mix string and object entries in the same array:
93+
94+
```json
95+
{
96+
"playwright/no-restricted-locators": [
97+
"error",
98+
[
99+
"getByTestId",
100+
{
101+
"type": "getByTitle",
102+
"message": "Prefer getByRole or getByLabel instead"
103+
}
104+
]
105+
]
106+
}
107+
```
108+
109+
## Common Locator Methods
110+
111+
Common locator methods that can be restricted:
112+
113+
- `getByTestId` - Find elements by test ID attribute
114+
- `getByTitle` - Find elements by title attribute
115+
- `getByAltText` - Find elements by alt text
116+
- `getByPlaceholder` - Find elements by placeholder text
117+
- `getByLabel` - Find elements by label
118+
- `getByRole` - Find elements by ARIA role
119+
- `getByText` - Find elements by text content
120+
121+
## When to Use This Rule
122+
123+
This rule is useful when:
124+
125+
- Your team wants to discourage certain locator methods (e.g., `getByTestId` for
126+
accessibility reasons)
127+
- You want to enforce consistent locator strategies across your test suite
128+
- You need to provide custom guidance on which alternatives to use

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import noNetworkidle from './rules/no-networkidle.js'
1818
import noNthMethods from './rules/no-nth-methods.js'
1919
import noPagePause from './rules/no-page-pause.js'
2020
import noRawLocators from './rules/no-raw-locators.js'
21+
import noRestrictedLocators from './rules/no-restricted-locators.js'
2122
import noRestrictedMatchers from './rules/no-restricted-matchers.js'
2223
import noSkippedTest from './rules/no-skipped-test.js'
2324
import noSlowedTest from './rules/no-slowed-test.js'
@@ -74,6 +75,7 @@ const index = {
7475
'no-nth-methods': noNthMethods,
7576
'no-page-pause': noPagePause,
7677
'no-raw-locators': noRawLocators,
78+
'no-restricted-locators': noRestrictedLocators,
7779
'no-restricted-matchers': noRestrictedMatchers,
7880
'no-skipped-test': noSkippedTest,
7981
'no-slowed-test': noSlowedTest,

0 commit comments

Comments
 (0)