Chaining Locator

@{cards}    Get WebElements    css=app-card-list app-card
FOR    ${card}    IN    @{cards}
    ${cardName}    Get Text    ${card} >> css=h4.card-title
    Log    ${cardName}
END

I intend to loop through all card elements found by the locator css=app-card-list app-card, and for each card, I want to fetch the text from a child element designated by h4.card-title. I’m using the chaining locator syntax (${card} >> css=h4.card-title) to specify the child element relative to each card.

However, I’m unsure if my usage of chaining locators within this context is correct. Can anyone confirm if this is the right approach or suggest any modifications if needed? Any insights or examples would be greatly appreciated!

Thank you!

RK, overall the logic of that code is valid. But when I ran a similar test it appears we don’t accept a webelement as the initial element in a chain. I recall a conversation about this a while back but forget the details. Sorry to say I am fairly busy at the moment so don’t have time to check now. An alternative for this should be to just move the card title header into the initial Get WeElements call, as in,

@{titles}    Get WebElements    css=app-card-list app-card h4.card-title
FOR    ${title}    IN    @{titles}
    ${cardName}    Get Text    ${title}
    Log    ${cardName}
END

I am look at the element finder and might get a chance to check my understanding of cascade locators and elements later today.

For those following along here was my example test case,

*** Settings ***
Library  SeleniumLibrary

*** Test Cases ***
Use of cascade locators
    Open Browser  https://the-internet.herokuapp.com/tables  Chrome
    @{rows}  Get WebElements  css=.example #table1 tr
    FOR  ${row}  IN  @{rows}
        ${column_text}  Get Text  ${row} >> css=td
        Log  ${column_text}
    END

you could also just get the count of the elements and then iterate over that range.

then in the iteration use the index as part of the selector.

1 Like

It looks like the error you’re encountering is similar to the one in the provided example, which involves an element not being found with Selenium:

Element with locator ‘<selenium.webdriver.remote.webelement.WebElement (session=“e9b2c8bed30e2fef392d719f4b47cb1c”, element=“f.505FD3B32127B932CCF27F33E0A58EF2.d.103B731E8A4584E7BCD9234C84345EA1.e.185”)>’ not found.

To address this issue, it would be beneficial if SeleniumLibrary offered functionality to allow chaining locators that accept a WebElement directly. This would simplify the process of finding elements that are relative to another WebElement, enhancing efficiency and ease of use in locating nested elements.

It seems like the approach suggested does involve repeating the same base locator for each element, with only the index differing. This could make the code a bit redundant as each property within a card requires specifying the card’s locator again.

I am are trying to extract multiple attributes from each card element on a webpage using Selenium, which includes the name, description, price, and image, along with an “add” button. Using chaining locators relative to a specific card element can streamline your code and make it cleaner. Here’s how you can structure your code to achieve this:

@{cards}    Get WebElements    css=app-card-list app-card
FOR    ${card}    IN    @{cards}
    ${cardName}    Get Text    ${card} >> css=h4.card-title
    ${price}       Get Text    ${card} >> div[title='price']
    ${desc}        Get Text    ${card} >> div[title='description']
    Log    ${cardName}
END

This script will loop through each card, extracting the necessary information and logging the name for verification. It effectively uses chaining locators to target elements within each individual card, which enhances readability and maintainability of your code.