I am trying to select values one by one in a dropdown and having difficulty.
selenium-webdriver (4.0.3)
watir (7.0.0)
ChromeDriver 94.0.4606.81
The dropdown is md-select which on click displays a hidden div with 2 choices.
<md-select ng-if="vm.datas.length" ng-model="vm.activeData" ng-change="vm.refreshDash()" id="active-data-select" aria-label="data selector" class="ng-pristine ng-valid md-default-theme ng-empty ng-touched" tabindex="0" aria-disabled="false" role="button" aria-haspopup="listbox" aria-invalid="false" aria-labelledby="active-data-select select_value_label_8" style="" aria-owns="select_listbox_10">
<md-select-value class="md-select-value" id="select_value_label_8"><span><div class="md-text">My test data 1</div></span><span class="md-select-icon" aria-hidden="true"></span></md-select-value>
</md-select>
<div class="md-select-menu-container md-default-theme md-active md-clickable" aria-hidden="false" role="presentation" id="select_container_9" style="display: block; left: 507px; top: 8px; min-width: 336.891px; font-size: 20px;">
<md-select-menu role="presentation" class="_md md-default-theme" style="transform-origin: 152.445px 32px 0px;">
<md-content role="listbox" tabindex="-1" aria-multiselectable="false" class="_md md-default-theme" id="select_listbox_10" aria-activedescendant="select_option_14">
<!---->
<md-option ng-repeat="data in ::vm.datas | orderBy:'name' track by $index" ng-value="data" value="[object Object]" ng-class="{'selected': data.name == vm.activeData.name }" tabindex="0" class="md-default-theme selected md-focused" role="option" id="select_option_14" selected="selected" aria-selected="true"><div class="md-text">My test data 1</div></md-option>
<!---->
<md-option ng-repeat="data in ::vm.datas | orderBy:'name' track by $index" ng-value="data" value="[object Object]" ng-class="{'selected': data.name == vm.activeData.name }" tabindex="0" class="md-default-theme" role="option" id="select_option_15"><div class="md-text">My test data 2</div></md-option>
<!---->
</md-content>
</md-select-menu>
</div>
When I am trying to do the below to display the hidden div to select next value:
browser.element(id: 'active-data-select').click
I get the following error:
element located, but timed out after 30 seconds, waiting for #<Watir::HTMLElement: located: true; {:id=>"active-data-select"}> to be present
I have tried many different things, but not able to find a solution yet. Any ideas?
Thank you,
-Andrey
If you are certain that clicking select element will solve your problem
browser.element(id: 'active-data-select').fire_event :click
will perform click even if element is obscured or not even on screen
You can also try
browser.element(id: 'active-data-select').send_keys :enter
or
browser.element(id: 'active-data-select').send_keys [:down, :down, :enter]
In your html it seems like div select_container_9 is holding the select with options elements, so try
browser.div(id: "select_container_9").select_list.options.first.select
It seems like it's id is autogenerated so different locator should be used in case it works
But you should probably debug how many selects there are on page with
browser.selects.count then you can flash each select to pinpoint the one you are after with browser.selects[x].flash then count how many options are available in that select with browser.selects[1].options.count and then you can proceed with selecting the option you want with browser.selects[1].options[1].select and then improve locators
Related
Hi I am new in exploring cypress.
I notice that, there is no select options in my html code. How can I select the option in the dropdown box?
Let's take a look of my html
<div class="row asset_config">
<div class="loader-container">
<div class="loader-content">
<div class="required form-group"><label for="cc_7sgwxb2v9" class="">allocation</label>
<div class="Select css-b62m3t-container"><span id="react-select-3-live-region" class="css-1f43avz-a11yText-A11yText"></span><span aria-live="polite" aria-atomic="false" aria-relevant="additions text" class="css-1f43avz-a11yText-A11yText"></span>
<div class="Select__control css-1s2u09g-control">
<div class="Select__value-container css-319lph-ValueContainer">
<div class="Select__placeholder css-14el2xx-placeholder" id="react-select-3-placeholder">Select allocation</div>
<div class="Select__input-container css-6j8wv5-Input" data-value=""><input class="Select__input" autocapitalize="none" autocomplete="off" autocorrect="off" id="cc_7sgwxb2v9" spellcheck="false" tabindex="0" type="text" aria-autocomplete="list" aria-expanded="false" aria-haspopup="true" role="combobox" value="" style="color: inherit; background: 0px center; opacity: 1; width: 100%; grid-area: 1 / 2 / auto / auto; font: inherit; min-width: 2px; border: 0px; margin: 0px; outline: 0px; padding: 0px;"></div>
</div>
<div class="Select__indicators css-1hb7zxy-IndicatorsContainer">
<div class="Select__indicator Select__dropdown-indicator css-tlfecz-indicatorContainer" aria-hidden="true"><span class="connect-icon connect-icon-caret-down"></span></div>
</div>
</div><input name="allocationType" type="hidden" value="">
</div>
</div>
</div>
</div>
</div>
In fact, I also notice that, cypress studio suggest me code to click the dropdown box:
cy.get(':nth-child(2) > form > .allocation_session > .asset_config > .loader-container > .loader-content > .required > .Select > .Select__control > .Select__value-container > .Select__input-container').click()
I found that not only unreadable is this approach, but also not reliable, because sometimes suggested codes that click on other dropdown doesnt work, if I didnt run the example code above or other suggested code.
Is there any reason behind why suggested code is coupled with other suggested code?
Is there a better way to select the element I want to get?
edit:
picture included
The react-select has the same user-actions as an ordinary HTML select, but you cannot use cy.select() command on it.
The general pattern is
open the dropdown menu by clicking on the "main" control
find the option you want to select within the menu listbox that is injected into the DOM after the above click action
click that option
verify the text of the option is now showing in the placeholder
// open the dropdown menu
cy.contains('label', 'allocation')
.next('.Select')
.click()
// find the option
cy.contains('Balanced Plus')
.click()
// verify option is selected
cy.contains('label', 'allocation')
.next('.Select')
.find('.Select__placeholder')
.should('contain', 'Balanced Plus')
<div class="accrd-row">
<h3 class="ui-helper-reset ui-accordion-header ui-corner-top ui-accordion-header-collapsed ui-corner-all ui-state-default ui-accordion-icons" role="tab" id="ui-id-1" aria-controls="ui-id-2" aria-selected="false" aria-expanded="false" tabindex="0"><span class="ui-accordion-header-icon ui-icon ui-icon-triangle-1-e"></span><span class="icon icon-ki-act-panda"></span>Outdoor Activities</h3>
<div class="accrd-detail ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-2" aria-labelledby="ui-id-1" role="tabpanel" aria-hidden="true" style="display: none;">Need to grab this text here</div>
</div>
I am trying to grab the text:
Need to grab this text here
Based on that the span above has the word "panda" in it. I know it is something like:
//span/#class[contains(.,'panda')]/following-sibling::a/div
But I cannot seem to get this to pick up the text.
You need to go back to the parent of span since the div you are looking for is a sibling of h3 not span.
There is probably a nicer way to do it but this is working for me to get the div element you need:
//h3//span[contains(#class, 'panda')]/parent::h3/following-sibling::div
I want to check the checkbox based on the value in the text input labeled 'Field' I have tried the following:
<tr>
<td>check</td>
<td>/label[text()="Field"]/../input[#value="6 1012 49817"]/preceding-sibling::label[text()="Private"]/../input</td>
<td></td>
</tr>
Here is the HTML:
<div class="wdg colShwHdeCls" id="divFormFieldPrivate-0" style="width: 82px;">
<input id="FormFieldPrivate-0" name="FormFieldPrivate-0" title="" style="" class="wdg colShwHdeCls" type="checkbox">
<label for="FormFieldPrivate-0">Private</label>
</div>
<div class="csLineBreak"> </div>
<div class="acI fldWd100 wdg colShwHdeOpn" id="divFormFieldId-0"><label for="FormFieldId-0">Field<a class="aut" title="Show selection list"></a>
<a style="display: inline-block; opacity: 0.0118143;" href="field/view?FieldId=" title="View this Field" class="acOptVw acLb acI"></a>
<a style="display: inline-block; opacity: 0.0118143;" href="field/edit?FieldId=" class="acEd acLb acI" title="Edit this Field"></a>
<a style="display: inline-block; opacity: 0.0118143;" href="field/add?FieldId=" class="acAd lightbox acI" title="Add a new Field"></a>
</label>
<br>
<span style="display:none;" id="FormFieldId-0-Old">6 1012 49817</span>
<input id="FormFieldId-0" name="FormFieldId-0" value="11955" type="hidden">
<input autocomplete="off" id="FormFieldId-0-Dsp" title="type three or more characters to see selection list" class="wdg csAutCpl csAutCplFld ui-autocomplete-input" value="6 1012 49817" type="text">
<span class="ui-helper-hidden-accessible" aria-live="polite" role="status"></span>
</div>
Suggestions are welcome thanks ;-)
This is one possible way. First part of the XPath supposed to find the div element containing label with certain text ("Field" in this case) and input with certain value attribute :
//div[label[normalize-space(text())="Field"] and input[#value="6 1012 49817"]]
From the above div, find preceding sibling div containing label with text equals "Private", then get the input child element of that div :
/preceding-sibling::div[label[text()="Private"]]/input
So the entire XPath will look about like this :
//div[label[normalize-space(text())="Field"] and input[#value="6 1012 49817"]]/preceding-sibling::div[label[text()="Private"]]/input
xpathtester.com demo
My html Code i have a button
<input class="search hidden" id="search_button" type="submit" value="Search" style="display: block;"></input>
when i clicked in Button many items is generated like this :
<div id="search_results" class="" style="display: block; left: 522.083px; top: 459.617px; width: 398px;">
<img alt="Load-circle" class="load-circle" src=".../123">
<div id="app_341446764" class="search-result"><img src=".../DictationIcon.png">abc</div>
<div id="app_561941526" class="search-result"><img src=".../Icon.png">def</div>
</div>
i have many div with class search-result i don't know how to click one of them(class="search-result") anyone suggest me a solution.
Ideally you would add a unique id as #juan-manuel-rodulfo-salcedo suggested. However, if you can't do that then you could find all the divs with class=search-result. Below is an example of how to click the second div on the page:
page.all('.search-result')[1].click
For more examples of how to select multiple elements, see this SO answer.
I'd like to be able to click (to see available options/list of accounts, seem to be hidden to start with) and then set a dijit widget "select_list" to a certain value.
I can find the object using
##ie.element(:css, "#accountSwitcherSelect.dijitDownArrowButton").flash
#works
but cannot use click or set with it:
##ie.element(:css, "#accountSwitcherSelect.dijitDownArrowButton").click
#no errors, but doesn't do anything
##ie.element(:css, "#accountSwitcherSelect.dijitSelectLabel").set("Account2")
#NoMethodError: undefined method `set' for <Watir::HTMLElement:0x4d6af60>
##ie.element(:css, "#accountSwitcherSelect.dijitSelectLabel").send_keys("Account3")
#NoMethodError: undefined method `send_keys' for <Watir::HTMLElement:0x4d6af60>
In the past the site was implemented using plain html and had a select_list, so
##ie.select_list(:name, "link").set(/Account1/i)
worked just fine.
Here's the current html behind the site:
<table id="accountSwitcherSelect" class="dijit dijitReset dijitInline dijitLeft dijitDownArrowButton dijitSelectFixedWidth dijitValidationTextBoxFixedWidth dijitSelect dijitValidationTextBox" lang="en-US" cellspacing="0" cellpadding="0" aria-haspopup="true" role="listbox" data-dojo-attach-point="_buttonNode,tableNode,focusNode" style="-moz-user-select: none; width: 207px;" tabindex="0" widgetid="accountSwitcherSelect" aria-expanded="false" aria-invalid="false">
<tbody role="presentation">
<tr role="presentation">
<td class="dijitReset dijitStretch dijitButtonContents" role="presentation">
<div class="dijitReset dijitInputField dijitButtonText" role="presentation" data-dojo-attach-point="containerNode,_popupStateNode" popupactive="true">
<span class="dijitReset dijitInline dijitSelectLabel dijitValidationTextBoxLabel " role="option">Account1</span>
</div>
<div class="dijitReset dijitValidationContainer">
</td>
<td class="dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer" role="presentation" data-dojo-attach-point="titleNode">
<input class="dijitReset dijitInputField dijitArrowButtonInner" type="text" role="presentation" readonly="readonly" tabindex="-1" value="? ">
</td>
Assuming that the the "select list" is similar to those on the digit.form.Select documentation page, you need to:
Click the dropdown arrow (an input element)
Click the cell that has the text you want (a td element)
In your case, it would look like:
##ie.input(:class => 'dijitArrowButtonInner').click
##ie.td(:class => 'dijitMenuItemLabel', :text => /Account1/i).click
Here is a working example (though it relies on the dijit css files still being available online).
require 'watir-webdriver'
browser = Watir::Browser.new
browser.goto "data:text/html,#{DATA.read}"
browser.input(:class => 'dijitArrowButtonInner').click
browser.td(:class => 'dijitMenuItemLabel', :text => 'Arizona').click
sleep(10) # Just so that you can see the dropdown has changed
browser.close
__END__
<html>
<head>
<link rel="stylesheet" href="https://dojotoolkit.org/reference-guide/1.9/_static/js/dijit/themes/claro/claro.css">
<script>dojoConfig = {async: true, parseOnLoad: true}</script>
<script src="https://dojotoolkit.org/reference-guide/1.9/_static/js/dojo/dojo.js"></script>
<script>require(["dojo/parser", "dijit/form/Select"]);</script>
</head>
<body class="claro">
<div name="select3" value="AL" data-dojo-type="dijit/form/Select">
<span value="AL"><b>Alabama</b></span>
<span value="AZ"><i>Arizona</i></span>
</div>
</body>
</html>
Watir-Classic
The above solution works for watir-webdriver, but not watir-classic. Clicking the dropdown (actually a table) is not triggering sufficient events to open the dropdown. As a work around, it seems you can use send_keys to trigger the right events.
Assuming that browser is opened to a page with the above html, the following will work:
browser.table(:id => 'dijit_form_Select_0').send_keys :enter
browser.td(:class => 'dijitMenuItemLabel', :text => 'Arizona').click
Note that the table in this code is the selected option (when the dropdown is closed).