Web Table Loops | Bondar Academy
Course: Cypress UI Testing with JavaScript
Module: Automation of User Interfaces
Instructor: Artem Bondar
Lesson Summary
In this lesson, we explore how to validate each row in a web table based on a specific value, such as age. The goal is to automate the filtering of table rows and validate the displayed results. Key Steps in the Automation Process Filter the Table: Input a value (e.g., age) to filter the rows. For instance, typing 20 should display only rows with that age. Locate Elements: Use placeholder.age as a locator to input the age. Loop Through Rows: Retrieve all table rows using tbody.tr and loop through them with the each method. Validation: Check if the last column of each row contains the expected age value. Troubleshooting Common Issues During testing, an error may occur stating "subject no longer attached to the DOM." This happens when Cypress attempts to access elements before the DOM has updated after an input. To resolve this: Implement a CyWait command to introduce a delay, allowing the table to update before querying it. Note that using CyWait is generally discouraged and should be a last resort. Testing Multiple Values We can enhance the automation by testing multiple ages using an array: const ages = [20, 30, 40, 200]; For each age, validate the corresponding table rows. If an age has no corresponding data (e.g., 200 ), assert that the message "no data found" is displayed. In summary, this lesson demonstrates how to effectively loop through table rows, validate values, and handle timing issues in Cypress testing.
Video Transcript
Hey guys, in this lesson, we'll continue working with the web tables. In this lesson, I will show you one more interesting scenario, how to validate every row in the table with some particular value. Let's jump into it. This is our web table and let's automate the following scenario. So we can filter the values in this table by any value. Let's say we filter the table by age. If I type 20, then all rows that are displayed in the table only have 20, or if I type 30, only one row is displayed, 50, no rows found. This is the scenario that we're going to automate in this lesson. Let's jump into it. So going back to the code, and here I just continue the scenario where we left off, and the third example will be looping through the rows. Let me call it like that. So the first step is to what? We need to type something into this age. As usual, inspect, we have a placeholder age that I can take as my locator. So going back, sci.get.placeholder.age, and this will be my locator. So then I need to type some age into this field, let's say 20. And then after that, I want to get sci.getTBody.tr, get all table rows, so I forgot the single quotes like this, TBody.tr, and then I want to loop through each of the table row. And we will use the same method each that we previously used with the list. It's gonna work the same way with the table. So I type each and call it TableRows, and here we go. Now, sci.wrap, wrap my TableRows. I need to find the all columns, TDs. I'm looking for the last column in the list, and this last column should have text, and the text should be 20. So that's almost it, and let's try to run this test. Let's see what's gonna happen. So going back to Cypress and running this test. So the table is opened, and look, the script typed 20 into the right column. The table was filtered, but for some reason, validation failed. And look, we are looking into this not pleasant error, that subject no longer attached to the DOM, and assertion actually failed. But this is weird, right? We see all the values in the table, but why assertion failed? Let's look into CypressRunner and look step by step what happened. So this was a previous test for the John Smith, so I type in 20 over here, right? So you see the 20 is typed. And then when I'm getting tbody and tr, look at what happened. So Cypress getting the entire table, which has a still old value. So this table is not filtered yet, but the value 20 is typed over here. And then we go to the next step, finding the last column. It's also picking the last column with the old value. And in our example, it's a John Smith. So Cypress is kind of running faster than our table was filtered. So that was the problem. And look, we got the last column from there. No, it didn't get the last column. It was trying to get the last column. But right at that moment, the DOM was changed. And that's why we see this error. Again, that subject no longer attached to the DOM. Because this section of the code, Cypress remembered, hey, this is the snapshot that we are working with. But then when we try to get the last column in the row, the DOM was changed. And Cypress, sorry, I lost the DOM. I'm no longer able to operate with this. So how to deal with this situation? If we would have a real API, we could theoretically could wait for the API response, and then based on the response, then continue the script. But this is nothing but the animation. If I just change any value, you see there is a little delay happening between the value changes and so on. So unfortunately, in the situation like this, we need to compensate this visual animation just by a timing delay using CyWait. And this is what I'm gonna do. So let me comment the previous examples for right now. And here, before querying all the rows, I will type CyWait and we'll add a little delay like this. And let's go back now to the script. And now script works successfully. So after typing 20, we waited for half a second. And then that allowed to query table and then validate row one by one. Row number one, number two, number three, and so on. The loop passed successfully. So quick note, using CyWait or hard-coded waits like this is considered not a good practice. But sometimes, there is only way to handle the situation. Always try to avoid it. Try to rely on automatic waiting and automatic Cypress capabilities. But if nothing else is gonna work, CyWait is your last resort. So we fixed this. Now let's add some more scenarios and we'll test a few more values. And for that, I will create an array with a test data, const ages. And let's say that we will test values of 20, 30, 40, and some negative scenario of 200. So we will test that no values are found. And now let's run our scenario through this list. So I call CyWrap, and I wrapping this ages object. And we'll use method each again. So for every cycle, I will have a single value for the age like this. And I'm grabbing all this code, command X and command V, pasting all inside. So now I take this variable and replacing it right here. Instead of typing 20, I will type the variable that will get the value from the array and assertion over here as well. That the last value have to be this one in the every row of the table. Let's run this test. So running the test one more time. And okay, we forgot to clear the value before typing the next one. All right, so where is the type age? Type clear like this. Let's try it one more time. Okay, now it's working successfully. The only last validation is failing. Because last validation is expecting to have 20, but we have text, no data found. And let's validate this scenario as well. That when we provide the value that we know for sure we don't have a users like that, our table should show this message. And for that, we will create a simple condition like this. If age equals to 200, then we expect validation of like table rows should contain text. And the text is, as far as I remember, it's no data found. No data found. Like this, else we will make this validation right here. And yeah, I think this have to be inside of here like this. Okay, so now everything is fixed. So when we get all table rows, if age equals to 200, we make invalidation that it should contains no data found. Otherwise, we validate that the last column of the row should have this age value. All right, so let's try to run it. Running the test. And everything passed successfully, so last validation was successful. All right, so let's quickly summarize what we did in this lesson. When you want to loop through the table rows, you call the trLocator to get the collection of the rows and use method each to loop through the table rows. Then inside of the single row, you can make a validation whatever you need, including conditions if you need to drive your logic differently. Sometimes you may have situations when Cypress not able dynamically wait for the web elements because of animations or something like this. In those rare cases, you can use CyWait, but try to avoid using CyWait and hard-coded wait as much as possible because this is considered not a good practice and use it is only as a last resort when nothing else works. All right, that's it guys, and I'll see you in the next lesson.