cssrobotframework

How to find valid locator for images using Selenium?


I am trying to write a simple code to go to rpachallenge.com, switch to the Movie Search Tab, search for a movie, then download the three resulting movies' title card image, title, and description to a JSON file. So far I'm able to do everything up to and including searching, but I'm unable to find a unique valid locator for the title cards.

When I inspect the page, each of the three resulting movies has code like the following:

<div _ngcontent-c3 class="cardItem">
    <div _ngcontent-3 class="col s4 ">
        <!--bindings={"ng-reflect-ng-if":"/d5NXSklXo0qyIYkgV94XAgMIckC.j"}-->
        <div _ngcontent-c3 class="card col s12"> =
            <div _ngcontent-c3 class="card-image">
                <img _ngcontent-c3 src=​"http:​/​/​image.tmdb.org/​t/​p/​w500//d5NXSklXo0qyIYkgV94XAgMIckC.jpg">​
                    <!--bindings={ "ng-reflect-ng-if": "true" >-->
                ...
            </div>
            <div _ngcontent-c3 class="card-content">
                <span _ngcontent-c3 class="card-title activator">Dune </span> =
                ...
                <p _ngcontent-c3> Paul Atreides, a brilliant and gifted young man born into a great dest...</p>
            </div>
        </div>
    </div>
</div>

where all of the code is the same except (d5NXSklXo0qyIYkgV94XAgMIckC.j), the image source (http:​/​/​image.tmdb.org/​t/​p/​w500//d5NXSklXo0qyIYkgV94XAgMIckC.jpg), movie title (Dune), and shortened movie description (Paul Atreides, a brilliant...).

When I try locating the image using its class="card-image", I get the error

WebDriverException: ... {"code":-32000,"message":"Cannot take screenshot with 0 height."}

After looking into it, I see that I get this error because multiple elements are tagged this way. However, I cannot find a unique locator for the title card image or any of the other elements I am looking for, as all three of the movies that show up look like they have the same code.

I think this should be doable with keywords from the Selenium Library but I am brand new to this and couldn't find what I needed. Here is my code, including some things that I have tried and commented out. As you can see I have no idea what I'm doing... Any help would be much appreciated.

*** Settings ***
Documentation     Searches for given movie on RPA Challenge site 
...               and saves resulting data in JSON.

Library           OperatingSystem
Library           RPA.Browser.Selenium

Suite Teardown    Close All Browsers


*** Variables ***
${RPA_Challenge_URL}     https://rpachallenge.com
${img_URL}     http://image.tmdb.org
${movie}     Dune


*** Keywords ***
Open RPA Challenge Page
    ${use_chrome} =     Get Environment Variable     USE_CHROME     ${EMPTY}
    IF    "${use_chrome}" != ""
        Open Available Browser    ${RPA_Challenge_URL}    browser_selection=Chrome
        ...    download=${True}  # forces Chrome and matching webdriver download
    ELSE
        Open Available Browser    ${RPA_Challenge_URL}  # opens any available browser
    END   

Switch to Movie Search Tab
    Click Link     xpath://a[text()='Movie Search']

Search for Given Movie
    Input Text     name:searchStr     ${movie}
    Press Keys    name:searchStr    ENTER
    Wait Until Page Contains Element     css:div[class='card-image']

# WebDriverException: ... {"code":-32000,"message":"Cannot take screenshot with 0 height."}
Save Movie Card Image
    # Assign ID to Element  //ul[@class='card-image' and ./li[contains(., '_ngcontent-c3')]]    movie_cover
    Capture Element Screenshot     css:div[class='card-image']
    # Capture Element Screenshot     xpath://a[contains(text(), 'image.tmdb.org'.)]
    # Capture Element Screenshot     xpath://a[tag:img]
    # Capture Element Screenshot     css:div[class='card-image' and contains(text(), 'image')]    # invalid

# Element with locator 'css:div[class='card-title-activator']' not found.
Save Movie Title
    Capture Element Screenshot     css:div[class='card-title-activator']

# Return JSON
    # print(driver.find_element_by_xpath("//div[@id='json']").text)
    # Does the above need to go in a .py file?

*** Tasks ***
Return movie information from RPA Challenge site
    TRY
        Open RPA Challenge Page
        Switch to Movie Search Tab
        Search for Given Movie
        # Save Movie Title
        Save Movie Card Image
    EXCEPT
        ${err_ss} =    Set Variable    ${OUTPUT_DIR}${/}error.png
        Capture Page Screenshot     ${err_ss}
        Fail    Checkout the screenshot: ${err_ss}
    END

Solution

  • You can use FOR loop (documentation) to get titles, descriptions etc. I was able to get, for example, all the movie titles as a list with this code:

    Get movie titles
        # on a 'Search for Movies' page
        ${mymovietitles}                                         Create List    # creates an empty list
        ${titleselements}=    SeleniumLibrary.Get WebElements    xpath=//span[@class='card-title activator']    # targets all 3 (Dune) movie titles
        FOR  ${titleelement}  IN  @{titleselements}
            ${title}=    SeleniumLibrary.Get Text    ${titleelement}
            Collections.Append To List               ${mymovietitles}    ${title}
        END
        Log To Console    My movie titles are ${mymovietitles}
    

    OUTPUT: ...My movie titles are ['Dune', 'Dune', 'Dune: Part Two']

    I used SeleniumLibrary (and Collections library for lists) but you can use similar keywords in RPA.Browser.Selenium too. Also, make sure the browser window size is big enough for the header menus to be visible.