pythonselectorseleniumbase

Using SeleniumBase to wait for an image to become visible


I have a table header element:

<th><input type="image" src="../../..//images/icons/cell_state_header_icon.png" onclick="javascript:__doPostBack('ctl00$left_pane$gvSelectedFeatures','Sort$Status')" style="border-width:0px;"></th>

and I am trying to "WAIT" for this element to display using the code below

sb.wait_for_element_present("//*[/html/body/form/div[3]/div/div[3]/div/div[5]/div[2]/div/div[2]/table/tbody/tr[1]/th[1]/input=cell_state_header_icon.png]", timeout=None)

however this does not seem to wait. Do I have the selector formatted correctly?


Solution

  • You didn't show real URL so I can't test if there is no other problems.

    Your xpath seems incorrect and I think Selenium could even raise error for this (but I'm not sure). If you have it in try/except then for test you should run it without try/except

    It should be compared with src, not with input= - something like this

    input[contains(@src, "cell_state_header_icon.png")]
    

    Next you could make it shorter and skip all these div and other elements because structure can be different and often tbody doesn't exist even if DevTools shows it in HTML.

    So to get input I would start with

    '//input[contains(@src, "cell_state_header_icon.png")]'
    

    and to get th which has this input

    '//th[input[contains(@src, "cell_state_header_icon.png")]]'
    

    and to get first matching I would test one of this

    '//th[1][input[contains(@src, "cell_state_header_icon.png")]]'
    '//th[input[contains(@src, "cell_state_header_icon.png")]][1]'
    

    eventually with ( )

    '(//th[1])[input[contains(@src, "cell_state_header_icon.png")]]'
    '(//th[input[contains(@src, "cell_state_header_icon.png")]])[1]'
    

    And if it would find wrong element then I would add more details in xpath.


    For test first I would check '//input' to see if it can find any input.


    Full code used for tests:

    from seleniumbase import SB
    
    # ---
    
    import seleniumbase
    print('SeleniumBase:', seleniumbase.__version__)
    
    # ---
    
    html = """
    <table>
    <tr>
    <th><input type="image" src="../../..//images/icons/cell_state_header_icon.png" onclick="javascript:__doPostBack('ctl00$left_pane$gvSelectedFeatures','Sort$Status')" style="border-width:0px;">Header 1</th>
    <th><input type="image" src="../../..//images/icons/cell_state_header_icon.png" onclick="javascript:__doPostBack('ctl00$left_pane$gvSelectedFeatures','Sort$Status')" style="border-width:0px;">Header 2</th>
    <th><input type="image" src="../../..//images/icons/cell_state_header_icon.png" onclick="javascript:__doPostBack('ctl00$left_pane$gvSelectedFeatures','Sort$Status')" style="border-width:0px;">Header 3</th>
    </tr>
    <table>
    """
    
    #with SB(browser='firefox') as sb:
    with SB(uc=True) as sb:
        #sb.open("data:text/html;charset=utf-8," + html)
        sb.load_html_string(html)
    
        # works
        #item = sb.wait_for_element_present('//th[1][input[contains(@src, "icon.png")]]')
    
        # doesn't work - probably it uses XPath 1.0 which doesn't have `ends-with()` (but it has `starts-with()`)
        #item = sb.wait_for_element_present('//th[1][input[ends-with(@src, "icon.png")]]')
    
        # works instead of `ends-with()`
        item = sb.wait_for_element_present('//th[1][input[substring(@src, string-length(@src) - string-length("icon.png") + 1) = "icon.png"]]')
    
        print('text:', item.text)