-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Support xpath support for cy.get() and .find() #1274
Comments
I don't know the full depth of the complexity of the implementation of this, but this is definitely possible.
|
+1 for XPath support |
This comment has been minimized.
This comment has been minimized.
+1, this would make migrating from an existing selenium framework significantly easier. |
These things already exist. You can use off the shelf tools to convert xpath to css selectors. There are a few NPM modules you can just install and require in cypress. |
I'm pretty sure xpath is a super-set of css, so any translator from xpath to css would be incomplete. Part of the reason I want xpath is that it's more powerful. |
for example, in xpath you can select a node depending upon its children, or its text content. |
This comment has been minimized.
This comment has been minimized.
3 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
+1, although i got what I needed with |
This comment has been minimized.
This comment has been minimized.
+1. Even in cases where CSS is enough, having Xpath would make some migrations from other frameworks so much easier. |
Yeah I've just ran into an issue, where a |
+1. Adding a data-cy attribute is a nice way, but we should be allowed to use xpath as well if we don't want to add any code specifically for testing. |
Yes, searching by text content would be great with xpath, since that cannot be done with CSS selectors (it doesn't allow Edit: just found this: https://docs.cypress.io/api/commands/contains.html#Content |
This comment has been minimized.
This comment has been minimized.
I'd love that. I use CSS selectors whenever possible, but sometimes XPath is necessary. One example of a selector that is hugely useful in XPath, but not possible in CSS, is selecting a table cell based on the header. For instance, to get a cell in row 3 in column with a label "Age", you can use:
Not exactly a trivial selector, but I still prefer it over doing this programmatically. Here's a corresponding table: <table>
<thead>
<tr>
<th>Username</th>
<th>Email address</th>
<th>Age</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mary</td>
<td>[email protected]</td>
<td>62</td>
</tr>
<tr>
<td>John</td>
<td>[email protected]</td>
<td>60</td>
</tr>
<tr>
<td>Kate</td>
<td>[email protected]</td>
<td>20</td>
</tr>
</tbody>
</table> |
Am averse to 'me toos' and +1's but xpath capability it a must. There are a few scenarios where css will not work; the primary one being pointed out by fringd. Even if it is the XPath 1.0 engine, it would make Cypress fully usable for any webpage... |
@kamituel in your example above why couldn't you just do this? // find the cell containing the content
cy.contains('td', '20')
// or you could find a higher up element if you wanted to
cy.contains('tr', '20') The vast majority of use cases I've seen are for XPath related to an element containing text and you can accomplish that with |
I just looked it up and apparently there is already a You should already be able to do this with Cypress with a custom command. https://developer.mozilla.org/en-US/docs/Web/API/Document/evaluate At the very least, adding this to the query methods of Cypress may not be that difficult afterall. |
@bryantabaird went back through to review comments. Per my comment here: you can use We've found |
@brian-mann To follow a real example, I'm working on a web application that has several large tables (for reporting purposes), that can easily have 20-30 columns. In some test cases, I want to assert on contents of just a few out of those 20-30 columns. Using:
Let's assume, still following my example, that I want to assert on contents of the first and third column, and I'm not interested in the contents of the 2nd: cy.contains('td', '20')
cy.contains('td', 'Kate') This code will match: <tr>
<td>Kate</td>
<td>[email protected]</td>
<td>20</td>
</tr> but it'll also match:
So I can start adding some more specific selectors, or use cy.contains('td:nth-of-type(3)', '20')
cy.contains('td:nth-of-type(1)', 'Kate') But it gets tricky quickly - I'll have to update tests as the table grows, or when I remove a column, etc... Compare it to (a hypothetical code): cy.get(cell(3, 'Age')).contains('20');
cy.get(cell(3, 'Username')).contains('Kate');
// With a helper function:
function cell(rowNumber, columnHeader) {
return `//table
/tbody
/tr[position()=${ rowNumber }]
/td[count(//table/thead/tr/th[text()='${ columnHeader }']/preceding-sibling::th) + 1]`;
} Sure, the helper function uses a fairly complex XPath selector, but it's not that bad once one gets used to XPath, and it's still simpler than a helper function/command would be without XPath. Plus, it leads to simple, readable and maintainable test code. In general, I prefer CSS over XPath any day, as it leads to shorter selectors whose syntax everyone is familiar with. But when given a choice of a complex helper function that would need to iterate over a number of DOM nodes, versus a declarative XPath selector, I strongly prefer XPath. Also, yes, there is javascript:(window.find_all = function (query) { var nodes = []; var iterator = document.evaluate(query, document); try { var node = iterator.iterateNext(); while (node) { nodes.push(node); node = iterator.iterateNext(); } } catch (e) { console.error("Document tree modified during iteration", e); return null; } return nodes; })(); Usage: find_all(xpath_selector); I would imagine in Cypress, we could accept XPath selectors prefixed with some character. Like in |
What I'm saying is that with Cypress you already have native DOM access to your window/document. Just use the code you wrote just now and put it in a custom command so that it finds you the DOM element and then pass that off to |
You mean write a custom command that'll accept an XPath selector and yield a DOM element? Sure, we can do that. And I'm pretty sure I eventually will, as we slowly (but surely) go about migrating our Selenium tests to Cypress ;) Question is - should Cypress' built-in I'd estimate that maybe 5% of selectors I would write in Selenium are XPath. Apparently, 20+ people who upvoted the OP have somewhat similar experiences. Is it enough to warrant having it built into Cypress itself? Not for me do decide :) If you, the Cypress' core team, will decide it's not worth the effort, would you accept a PR that adds XPath support to |
@kamituel We would certainly accept a PR that adds support for XPath! We are not against supporting XPath considering the demand from users here. Unfortunately, we are a small team, so it is not within our roadmap at this moment to work on this - so @brian-mann suggestions were to help you all with a workaround to use now. We also feature custom commands in our plugins, so if that's an easier option than doing a PR - let us know and we can share it there. |
No, but you can chain cy.get, cy.contains and find elements by text, no xpath necessary Sent from my iPhoneOn Aug 9, 2023, at 11:37, Moji ***@***.***> wrote:
@bahmutov but cy.contains cannot handle xpath or it can? Isn't it easier to bring back cypress-xpath again?
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
@bahmutov It is true when I'm starting a project, but in our case transitioning from xpath in our existing tests means we should rewrite pretty much all the tests which it doesn't make any sense(it does make sense if we get more value but simply we don't). |
What about //parent::div ? |
First of all "contains" is so useless when you have multiple similar elements and second -> chain commands are kinda broken, especially with .get command. |
+1 from me, even more now that cypress/xpath is no longer supported. |
+1 for xpath please |
+1 for xpath support |
1+ for xpath support. |
+1 for xpath support |
A very large part of the Cypress users will appreciate that this is prioritized. Thanks! |
+1 for xpath support. It's realy helps a lot while integrating with UI elements. |
+1 for xpath support |
+1 for xpath support. |
+1
The xpath that would do it
It allows the button to be targeted leaving the DOM to be able to change in all possible ways, except changes to data-w-component attribute, or changes to the title of the panel, or changes to the text of the button. |
It can do something close. For the example in above post the below code clicks the desired button. This Cypress test will break if another panel is nested around the title, whereas the Selenium/XPath test would keep passing.
|
how has this not been prioritized since the xpath package has been deprecated? |
+1 for Cypress to be able to support the use of xpath natively. It seems that the Cy team’s thinking is only geared towards development, where only the simplest and fastest is considered. Xpath is undoubtedly a selector infinitely more powerful than the CSS Selector. Not to mention teams that would like to migrate from other frameworks and already use xpath and won’t break their heads to change all selectors to CSS. |
As Salesforce Lightning element testing requires xpath (#29294) and the xpath package has been deprecated, I give +1 for this issue |
I've been having same issues as @alexsch01 here with testing Salesforce Lightning Elements and sometimes the shadow elements are not recognized so we have to use xpath. @bahmutov, @jennifer-shehane as Salesforce is custom LWC made by salesforce which will not have data-testids and use a ton of shadow containers is there any support for this? |
Shadow support is different from xpath. On the personal note regarding xpath selectors: don’t use them. Sent from my iPhoneOn Apr 9, 2024, at 10:14, dqiubread ***@***.***> wrote:
I've been having same issues as @alexsch01 here with testing Salesforce Lightning Elements and sometimes the shadow elements are not recognized so we have to use Cypress. @bahmutov, @jennifer-shehane as Salesforce is custom LWC made by salesforce which will not have data-testids and use a ton of shadow containers is there any support for this?
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
@bahmutov, the problem for us is that in our salesforce application its really hard to tell what is and isnt a shadow dom element since salesforce does not explicitly tell you if the element type is inside a shadow element. Instead of for me requesting for a feature on shadow dom elements where idk where the issue is coming from, it would be easier to get xpath support as developer tools already supports it so to me it feels more of a universal solution. |
Can’t you set cypress option to traverse the shadow borders by default?Sent from my iPhoneOn Apr 9, 2024, at 10:41, dqiubread ***@***.***> wrote:
@bahmutov, the problem for us is that in our salesforce application its really hard to tell what is and isnt a shadow dom element since salesforce does not explicitly tell you if the element type is inside a shadow element. Instead of for me requesting for a feature on shadow dom elements where idk where the issue is coming from, it would be easier to get xpath support as developer tools already supports it so to me it feels more of a universal solution.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: ***@***.***>
|
@bahmutov, I turned the includeShadowDom to true to try to resolve the issue, but for some reason for some of the elements like these elements where they have an aura class or aura id in salesforce, it sometimes fails to get the element by the classname or id. I was told that the elements are alls built from salesforce so not sure how much custom stuff the development team has done. The reason my team uses xpath is we are able to get these elements that have these aura classes which cy.get and cy.contains for some reason is not able to handle for Saleforce |
Seems we can add the now removed @cypress/xpath code to our commands.js to get back the
|
I'm not totally understanding. Wasn't .get and .find never supported? Also Cypress xpath has been removed from the master branch, do you mean we can just make a custom command using what existed of the xpath functionality from before? |
Yes, copy&paste the full content of the @cypress/xpath index.js linked above (which is linked to the commit before they removed the content) into your command.js and it appears to restore |
@DMaguireKane despite it has been deprecated, is still available for download in the npmjs, why do you suggest we do this to use |
@jgonzalezalbisu Ah, I somehow assumed that it was removed because it no longer worked. Apologies for the wasted notifications. Installing |
@DMaguireKane nothing to apologize for! |
Current behavior:
.get('//div') doesn't work
.find('p/span') also doesn't work
Desired behavior:
It gets the element using document.evaluate just like get and find currently uses document.querySelector.
or to avoid collisions we add getXpath and findXpath or something.
Motivation
xpath is fairly standard in integration tests, and is much more powerful than css selectors are, and I'm working on a shared library of xpath selectors for use with selenium, puppeteer, and ideally, cypress.
I'm happy to help with writing this code if people agree it's a useful feature that would be likely to get merged.
The text was updated successfully, but these errors were encountered: