playwright
playwright copied to clipboard
[Feature] codegen: choose between multiple generated selectors
In some cases the generated selector isn't stable enough for rerunning the code.
Having multiple selectors per element could solve this, similar to how testim.io does this - https://help.testim.io/docs/working-with-locators#:~:text=Testim%20Smart%20Locators%20are%20a,application%20to%20write%20the%20tests.
The main goal of the codegen
tool is to help users learn the Playwright API. We don't aim at creating re-runnable scripts that are production-ready. That's why we emit them into terminal rather than write into the live IDE. Having said that, it should be relatively easy for us to offer several version of the selector, preferring one aspect or the other for user to pick from.
The QA world is split on the self-healing topic (some prefer to assert behavior, others to keep test running in a best effort manner). We don't have an opinion on this matter, we consider this to be a higher-up-the-stack decision.
Maybe another cool approach for this would be: https://playwright.dev/docs/selectors#selecting-elements-based-on-layout
In v1.10, generated selectors overall work pretty good. If there are any specific instances where the selector is really bad, please file a separate issue with repro steps.
I am renaming this issue to be about generating multiple selectors and choosing one of them (as suggested in the original request).
As a user would like an option to explicitly define or influence what properties the recorder looks for and uses for the selectors in the generated code emitted by the recorder.
Personally, not a big fan of tools second guessing and assuming they know what is best, would assert there are "data-XXX" defined in the HTML spec that could be used for this purpose. Would assert it would actually make it easier and more often since we as users know and understand our specific code bases, might make it easier for all involved. Cases where the selector fails because multiple items match... Fine easy to understand and fix up my code as needed and handle thos cases needed, but at least we get what we needed.
What I am doing now is to add an eventlistener to elements with the attribute I want to record, for example:
<button testid="buybutton">Buy</button>
and then console.log the actual selector that I want. I can imagine that something like this would be helpful:
- make an input field in the codegen option for an attribute you want to search for when you click something.
- Add an eventlistener that searches for the closest it can find (https://developer.mozilla.org/en-US/docs/Web/API/Element/closest)
- Spit out that css selector to the codegen window, if it cant find one, spit out the regular one.
Hello, just wanting to bring attention to this thread again because it is also something my team would like implemented.
The selectors codegen generates are not always the ideal selectors for our codebase. For example, they use class names or aria labels that change more frequently rather than more stable elements such as data-unique-id. Having the option to choose would greatly improve the usefulness of codegen. Any updates on if this feature will get development?
I think to be fair, when entering my comment before, it seemed the recorder wouldn't pick up the data-test-id, running with 1.21 i'm seeing if data-test-id is present it is using it. Was hard to justify asking the devs to go to the trouble of putting the id's in the product code but they would be used... From my simple test, it appears data-test-id will be used.
Based on id, data-testid, data-test-id, data-test selectors and a short test it seems that npx playwright codegen <url>
allready uses data-test
as a selector.
This markup
<label>Name<input type="text" data-test="trader_search_by_name" data-val="true"
data-val-required="The Name field is required."
id="Name" name="Name" >
</label>
resulted in
await page.locator('[data-test="trader_search_by_name"]').fill('Foo');
Based on id, data-testid, data-test-id, data-test selectors and a short test it seems that
npx playwright codegen <url>
allready usesdata-test
as a selector.This markup
<label>Name<input type="text" data-test="trader_search_by_name" data-val="true" data-val-required="The Name field is required." id="Name" name="Name" > </label>
resulted in
await page.locator('[data-test="trader_search_by_name"]').fill('Foo');
Is this behavior something we can count on @dgozman @pavelfeldman? We have been interested in providing codegen a hint to use a data attribute as well. This would save immense time.
Is this behavior something we can count on @dgozman @pavelfeldman? We have been interested in providing codegen a hint to use a data attribute as well. This would save immense time.
@Jojoshua Yes, codegen always checks and suggests test ids.
Would love to see this feature implemented (see my issue linked by dgozman above for another way it could be implemented)
Even just being able to exclude id from the codegen would be a big help (our app uses dynamic id's throughout).
Yes please. That would be quite useful!
I would also find it very useful to be able to define an order of precedence for attributes to use as selectors through codegen.
Another idea: Add a configuration option that adds all the alternative selectors as commented-out code in the generated code.
+1 on adding an option to prefer user-facing locators.
Playwright comes with multiple built-in locators. To make tests resilient, we recommend prioritizing user-facing attributes and explicit contracts such as page.getByRole().
Related: https://github.com/microsoft/playwright/issues/9015 @dgozman: This seems to have been completed. How do I use it to generate multiple selectors to choose from?
@dgozman : Thanks to a colleague, We found this
- It looks to be set to false for the microsoft repo - https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/server/injected/recorder/recorder.ts#L135
- However, set to true for the fork - https://github.com/dgozman/playwright/blob/434ac3327ca76ef582d68a30a59acc9a3eb5f430/packages/playwright-core/src/server/injected/recorder/recorder.ts#L134
How does multiple: true ever get passed in? I tried upgrading playwright to 1.44 and still can't use this feature.
Also, I tried downloading the source code and I tried to hardcode the value
export function generateSelector(injectedScript: InjectedScript, targetElement: Element, options: GenerateSelectorOptions): { selector: string, selectors: string[], elements: Element[] } {
injectedScript._evaluator.begin();
options.multiple = true;
beginAriaCaches();
Then
npm run build
Then
npx playwright codegen
But still don't see multiple selectors. I don't know if it's running the code I changed or not since the only breakpoints I can trigger are in packages\playwright\lib
but I need to trigger bps in packages/playwright-core/src/server/injected/recorder/recorder.ts
. Please help me to either get the changes from the source code to work or how to run using installed playwright
Thank you in advance
@esther-86 This feature was disabled, as it was deemed not yet ready. Sorry for confusion. Let me reopen the issue.
ah... sad to see it go for now, i had been using it in a forked repo as well. what was not ready about the feature? (as it was really usefull to the team)