-
Notifications
You must be signed in to change notification settings - Fork 42
feat(prefer-locator): Add rule to suggest not using page methods #315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
mskelton
merged 9 commits into
playwright-community:main
from
carlbray:feature/prefer-page-locator-fill
Sep 19, 2024
Merged
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
78000e7
Add prefer-page-locator-fill
3b380c7
Rename rule
6425539
Add set of methods to check against
a879690
Update docs too
3a5ca3f
Fix formatting
b66f87d
Change descriptons, add more tests and examples
ef612d6
Switch to CallExpression
2ff8637
Add examples without await
99bc2aa
Use test from rule-tester
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Suggest using `page.locator()` (`prefer-locator`) | ||
|
||
Suggest using locators and their associated methods instead of page methods for | ||
performing actions. | ||
|
||
## Rule details | ||
|
||
This rule triggers a warning if page methods are used, instead of locators. | ||
|
||
The following patterns are considered warnings: | ||
|
||
```javascript | ||
page.click('css=button') | ||
await page.click('css=button') | ||
await page.dblclick('xpath=//button') | ||
await page.fill('input[type="password"]', 'password') | ||
|
||
await page.frame('frame-name').click('css=button') | ||
``` | ||
|
||
The following pattern are **not** warnings: | ||
|
||
```javascript | ||
const locator = page.locator('css=button') | ||
await page.getByRole('password').fill('password') | ||
await page.getByLabel('User Name').fill('John') | ||
await page.getByRole('button', { name: 'Sign in' }).click() | ||
await page.locator('input[type="password"]').fill('password') | ||
await page.locator('css=button').click() | ||
await page.locator('xpath=//button').dblclick() | ||
|
||
await page.frameLocator('#my-iframe').getByText('Submit').click() | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import { runRuleTester, test } from '../utils/rule-tester' | ||
import rule from './prefer-locator' | ||
|
||
runRuleTester('prefer-locator', rule, { | ||
invalid: [ | ||
{ | ||
code: test(`await page.fill('input[type="password"]', 'password')`), | ||
errors: [ | ||
{ | ||
column: 34, | ||
endColumn: 81, | ||
endLine: 1, | ||
line: 1, | ||
messageId: 'preferLocator', | ||
}, | ||
], | ||
output: null, | ||
}, | ||
{ | ||
code: test(`await page.dblclick('xpath=//button')`), | ||
errors: [ | ||
{ | ||
column: 34, | ||
endColumn: 65, | ||
endLine: 1, | ||
line: 1, | ||
messageId: 'preferLocator', | ||
}, | ||
], | ||
output: null, | ||
}, | ||
{ | ||
code: `page.click('xpath=//button')`, | ||
errors: [ | ||
{ | ||
column: 1, | ||
endColumn: 29, | ||
endLine: 1, | ||
line: 1, | ||
messageId: 'preferLocator', | ||
}, | ||
], | ||
output: null, | ||
}, | ||
{ | ||
code: test(`await page.frame('frame-name').click('css=button')`), | ||
errors: [ | ||
{ | ||
column: 34, | ||
endColumn: 78, | ||
endLine: 1, | ||
line: 1, | ||
messageId: 'preferLocator', | ||
}, | ||
], | ||
output: null, | ||
}, | ||
{ | ||
code: `page.frame('frame-name').click('css=button')`, | ||
errors: [ | ||
{ | ||
column: 1, | ||
endColumn: 45, | ||
endLine: 1, | ||
line: 1, | ||
messageId: 'preferLocator', | ||
}, | ||
], | ||
output: null, | ||
}, | ||
], | ||
valid: [ | ||
{ | ||
code: `const locator = page.locator('input[type="password"]')`, | ||
}, | ||
{ | ||
code: test( | ||
`await page.locator('input[type="password"]').fill('password')`, | ||
), | ||
}, | ||
{ | ||
code: test(`await page.locator('xpath=//button').dblclick()`), | ||
}, | ||
{ | ||
code: `page.locator('xpath=//button').click()`, | ||
}, | ||
{ | ||
code: test( | ||
`await page.frameLocator('#my-iframe').locator('css=button').click()`, | ||
), | ||
}, | ||
{ | ||
code: test(`await page.evaluate('1 + 2')`), | ||
}, | ||
{ | ||
code: `page.frame('frame-name')`, | ||
}, | ||
], | ||
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import ESTree from 'estree' | ||
import { getStringValue, isPageMethod } from '../utils/ast' | ||
import { createRule } from '../utils/createRule' | ||
|
||
const pageMethods = new Set([ | ||
'click', | ||
'dblclick', | ||
'dispatchEvent', | ||
'fill', | ||
'focus', | ||
'getAttribute', | ||
'hover', | ||
'innerHTML', | ||
'innerText', | ||
'inputValue', | ||
'isChecked', | ||
'isDisabled', | ||
'isEditable', | ||
'isEnabled', | ||
'isHidden', | ||
'isVisible', | ||
'press', | ||
'selectOption', | ||
'setChecked', | ||
'setInputFiles', | ||
'tap', | ||
'textContent', | ||
'uncheck', | ||
]) | ||
|
||
function isSupportedMethod(node: ESTree.CallExpression) { | ||
if (node.callee.type !== 'MemberExpression') return false | ||
|
||
const name = getStringValue(node.callee.property) | ||
return pageMethods.has(name) && isPageMethod(node, name) | ||
mskelton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
export default createRule({ | ||
create(context) { | ||
return { | ||
CallExpression(node) { | ||
// Must be a method we care about | ||
if (!isSupportedMethod(node)) return | ||
|
||
context.report({ | ||
messageId: 'preferLocator', | ||
node, | ||
}) | ||
}, | ||
} | ||
}, | ||
meta: { | ||
docs: { | ||
category: 'Best Practices', | ||
description: 'Suggest locators over page methods', | ||
recommended: false, | ||
url: 'https://github.com/playwright-community/eslint-plugin-playwright/tree/main/docs/rules/prefer-locator.md', | ||
}, | ||
messages: { | ||
preferLocator: 'Prefer locator methods instead of page methods', | ||
}, | ||
schema: [], | ||
type: 'suggestion', | ||
}, | ||
}) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.