daOnlyBG
daOnlyBG

Reputation: 601

Unable to select dropdown menu with Selenium in Python

I am unable to select a particular element in this webpage for automation in Selenium (python).

These two fields, taken from the webpage, are what I'm looking for:

enter image description here

When I right-clicked and clicked on "inspect element," I found the following html markup (well, a subset of it):

<label>Client ID:</label>
<db-client-combobox default-value="vm.clientId" on-select="vm.onClientSelected(clientId)" class="ng-isolate-scope">
    <db-combobox placeholder="Select a client" list="clientNames" default-value="defaultValue" on-select="onClientSelected(value)" mode="longlist" class="ng-isolate-scope">
        <div class="input-group combobox dropdown">
            <input type="text" class="form-control ng-pristine ng-valid ng-touched" placeholder="Select a client" data-toggle="dropdown" ng-model="itemSelected" ng-change="onInputKeyUp()" ng-focus="onInputFocus()" aria-expanded="false">
            <span class="input-group-addon dropdown-toggle btn" id="combobox-list" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span class="caret"></span>
            </span>
            <ul class="dropdown-menu" aria-labelledby="combobox-list">
                <!-- ngIf: mode == 'longlist' -->
                <div class="sf-viewport sf-viewport-biglist real ng-scope" ng-if="mode == 'longlist'" style="overflow: auto; max-height: 300px;">
                    <div style="margin: 0px; padding: 0px; border: 0px; box-sizing: border-box; height: 67912px;">
                    </div>
                </div>
                <!-- end ngIf: mode == 'longlist' -->
                <!-- ngIf: mode == 'shortlist' -->
            </ul>
        </div>
    </db-combobox>
</db-client-combobox>
</div> &nbsp;
<div class="form-group">
    <label>Agent ID:</label>
    <input type="text" class="form-control js-call-type ng-pristine ng-valid ng-touched" ng-model="vm.agentId">
</div>

The "Client ID" field is both a drop-down and a text field (it's up to the user to choose whether said user wants to type the Client ID or select it from a drop down menu). The Agent ID is simply a text field to enter numbers.

I can't seem to select either in Selenium. To select the Client ID, for example, I've tried the following Python commands (separately):

client_id_field = browser.find_elements_by_css_selector('select')
client_id_field = browser.find_element_by_css_selector("input.form-control ng-pristine ng-valid ng-touched")
client_id_field = browser.find_element_by_css_selector("input.form-control.ng-pristine.ng-valid.ng-touched")
client_id_field = browser.select_by_xpath('/html/body/div[1]/div/div[1]/div/div/div[1]/db-client-combobox/db-combobox/div/input')
client_id_field = browser.select_by_class_name('form-control ng-pristine ng-valid ng-touched')

Sadly, nothing seems to work, and I'm not sure why. The only other possibility I see is selecting the labels, i.e. <label>Client ID:</label> and then telling the interpreter to go to the next element and select that- though I'm not sure what the correct syntax would be.

Can anyone help?

UPDATE: after following alecxe's suggestion to try inserting

client_id_box = browser.find_element_by_xpath("//label[. = 'Client ID:']/following-sibling::db-client-combobox")

I got the following error in the command line prompt:

selenium.common.exceptions.NoSuchElementException: Message: {"errorMessage":"Una
ble to find element with xpath '//label[. = 'Client ID:']/following-sibling::db-
client-combobox'","request":{"headers":{"Accept":"application/json","Accept-Enco
ding":"identity","Connection":"close","Content-Length":"147","Content-Type":"app
lication/json;charset=UTF-8","Host":"127.0.0.1:53214","User-Agent":"Python-urlli
b/2.7"},"httpVersion":"1.1","method":"POST","post":"{\"using\": \"xpath\", \"ses
sionId\": \"d67f3550-e736-11e6-a1df-2f9c010cd01f\", \"value\": \"//label[. = 'Cl
ient ID:']/following-sibling::db-client-combobox\"}","url":"/element","urlParsed
":{"anchor":"","query":"","file":"element","directory":"/","path":"/element","re
lative":"/element","port":"","host":"","password":"","user":"","userInfo":"","au
thority":"","protocol":"","source":"/element","queryKey":{},"chunks":["element"]
},"urlOriginal":"/session/d67f3550-e736-11e6-a1df-2f9c010cd01f/element"}}
Screenshot: available via screen

Something that strikes me oddly (sorry if this sounds so naive) is that the command line says unable to find element with xpath... and then after listing the xpath I asked for, it also lists lots of other jargon that I didn't mean to ask for. Am I not making the most out of the interpreter's debugging response?

Upvotes: 2

Views: 1075

Answers (1)

alecxe
alecxe

Reputation: 474161

The only other possibility I see is selecting the labels, i.e. Client ID: and then telling the interpreter to go to the next element and select that- though I'm not sure what the correct syntax would be.

This can be achieved with a following-sibling axis:

client_id_box = browser.find_element_by_xpath("//label[. = 'Client ID:']/following-sibling::db-client-combobox")

Then, once you have the client id box element, you can locate the inner input:

client_id_input = client_id_box.find_element_by_tag_name("input")
client_id_input.click()  # TODO: you might not need it, please check
client_id_input.send_keys("Test")

For the dropdown, you first probably need to open it up and then select the desired option:

client_id_box.find_element_by_id("combobox-list").click()  # open the dropdown
# TODO: select option

Note that, to make things more reliable and to avoid timing errors, you may need to start using Explicit Waits.

Upvotes: 1

Related Questions