Parent Elements | Bondar Academy
Course: Cypress UI Testing with JavaScript
Module: Interaction with Web Elements
Instructor: Artem Bondar
Lesson Summary
In this lesson, we explore how to find parent elements in Cypress , particularly when unique identifiers are not available. Here are the key points discussed: Identifying Elements When needing to select a specific button (e.g., Sign In ), and multiple buttons share the same color, look for unique elements around the button. Examples of unique elements include: Radio buttons Labels Input fields with unique ID Finding Parent Elements To locate a button based on an input field's ID : cy.get('#inputID').parents('form').find('button') This method travels up to the nearest form parent and then down to the button. Using cy.contains Another approach is using cy.contains to find elements by text. This can also return parent elements: cy.contains('text', { matchCase: false }) Chaining Methods You can chain multiple parent() calls to navigate up the DOM tree: cy.get('element').parent().parent().find('button') Using parentsUntil The parentsUntil method allows you to find all parent elements up to a specified element: cy.get('element').parentsUntil('form') This returns all parent elements before the specified element, which can be useful for complex DOM structures. In summary, use parents to find parent elements, parent for a single level up, and parentsUntil to collect elements up to a certain point in the DOM.
Video Transcript
All right, guys, in this lesson, we will talk about how to find parent elements in Cypress, so let's get into it. So this is our Form Layouts page and using the grid. And imagine the situation that you need to select this Sign In button, and both buttons on this page, this one and this one, has the same color. So you're not able to differentiate by the color, but you need somehow to identify this particular button and click on it. And also imagine that you don't have the header of the form using the grid. That previously in our examples was a unique identifier as a header and then we targeted element within the form. So what if you don't have both of those? What would you do? In the situations like that, you need to look for the unique, something unique about this form, some unique elements around the button that you want to click, and what it can be. So for example, in this form, we have two options for the radio buttons. They are unique for the entire page. Or this label radius, it's also unique and it also can be used as a starter locator that you are starting from. And also you can look deeper into the DOM and, for example, this form, the email input field has ID. And we know that ID usually for the page is unique and we can use this ID as our starting point. But the problem is that this input field is like a last element in this layout when you're digging into the form and then input field does not have a children element. So you cannot, from the input, find a button that is located below. To find this button based on this ID, you first need to travel up to the nearest parent that would include the entire form with this button. So for example, if we slowly going up, so this is the label for the email, then this is the div that combines the row for the email and the input field. And then the form, and here we go. So the form is the parent element for this input field that also includes sign-in button. And so we can find this ID. We can travel up in the DOM to the form tag, and then from the form tag, find the button. So let's do this. So I'm copying this ID, going back to the code. And here I already created a new test to work with the parent elements. So I type sciget, and first of all, we need to start with our key element, which we identify by ID, and we know that this is input element. Then to find the parent, you call method parents, this one. And as argument, you provide the locator for the element that will be parent in relation to this input field. And in example of our application, it will be the tag form, and I put it right here. And then from this form, I am looking for using method find. I'm looking for sign-in button, which is a single button, so I can use just a tag button. That's it, let's try to run it. So where's my Cypress? Running the test, and here we go. Look, first we identified the input field by ID, it's highlighted. Then we went up to the form level that includes sign-in button, and then we traveled down to the button itself, and button is selected. Pretty cool and pretty simple, so let's move on. So the second example, let's take the method CyContains with using the grid. Like this one, and I will remove nbcard from here. So we will search just by using the grid. And if I go back to Cypress, look, so it's looking for a header. But we want to find somehow the sign-in button. So again, we need to go just one level up, and then go down to this button. If you look into the DOM, you can see that, let me collapse this. So this is our using the grid, this is a header. And the nbcard body is the sibling element to nbcard header. So all we need to do here is just to go just one level up. We don't need to go all the way up, too far. All we need is just, okay, one step up. And to perform operations like that in Cypress, you can use a method .parent. Instead of parents, you call a parent. And then Cypress will find this element related to the user in the grid, then gonna make one step up. And then after that, we can safely travel down and select the button like this. Let's go back to the Cypress one more time, and here we go. Look, we found the header, then one parent up selected the entire form. And then one level down, we selected the button. And also, if we talk about this example with parent and child elements. So this expression, so this one that we just created with the parent, is exactly the same, is returning exactly the same result as this expression. So when you provide second argument, like a first argument as a locator into the method CyContains, this locator is technically what the CyContains will return you. So CyContains, even it's looking by the text, it will return you the element that you would put right here of the first argument. So this is nbcard is technically the parent element in relation to the text using the grid. So this expression and this expression are identical. And this feature about the CyContains is actually very, very powerful, because you don't need to combine CyContains and parent, like I showed you over here. You can just instead use a single expression with the two arguments, nbcard and then the text. And also, one of the features of the parent element, that you can infinitely chain the number of methods however you want. For example, if I type the parent one more time, we essentially go in one level up, and then one level up again, and only then going down. So you can put parent one, parent two, parent three. It's a rare case, I know, but technically, from the scripting perspective, it is possible. So just don't be afraid to experiment and chain the commands one by one. So you can put several parents if you want, slowly, level by level, move up in the DOM tree. All right, and the final example is when you want to find all parent elements on the way to your target element until that target element. Hold on, I will type this and then it's gonna make sense. So there is a third method, parentsUntil. And here, you need to provide allocator up to the place where you want to stop. So if I will provide the form like this, and we'll try to find the button from here. And then we go back to the Cypress, and look, my button was not found, why? Because Cypress in this example technically stopped one level before the form. So let's see, inspect, this is our button, and this is the form, here we go. So we set parentUntil the form. So it returned all parents that were before the form. And since our sign-in button is inside of the form, we were not able to select it. But instead, Cypress returned all parent elements before that. And before that was this div and this div, two of the elements. And if we go one level a little bit up, for example, nbCardBody, which is above the form, then our script will work again. So I will replace one level up, nbCardBody, and going back. And now test pass successfully. And look, parentsUntil found three elements, why is that? So just one more time, look at the DOM. So this is our starting element. First parent above is this div. The next parent above is this div. And then the next parent above is this form. So Cypress with this method returns the collection of the element that were before. And when you chain the next command, for example, find a child element from that element, it will essentially try a perfect match. Is it possible within those three elements, find that child element that you are looking for? I hope it makes sense. Okay, so that's it, and let's quickly summarize what we did in this lesson. When you want to find the parent elements from the current element, use method parents and the locator for the method that you're trying to find. If you want to go just a single level up in the DOM tree from the current element, use method parent. And if you want to return a list of the elements up to a certain element in the DOM tree from the target element, use method parents with the locator until you want to return the collection of those elements. All right, that's it, guys, and I'll see you in the next lesson.