How can I select the first option inside a dropdown menu by targeting css? - ruby

I'm currently using Cucumber / Selenium / Ruby to create my automation framework and setup my first test. The one I'm working on involves me to fill in a form in order to proceed to the next stage. The form contains a dropdown with multiple values, of which I want to select one (and any one!)
Inspect Element of the Dropdown Menu
<input type="search" class="ember-power-select-trigger-multiple-input" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" id="ember-power-select-trigger-multiple-input-ember3325" aria-controls="ember-power-select-options-ember3325" style="width: 100%;" placeholder="All classes">
I've therefore made use of the class inside my step below:
My Step
#wait.until {#driver.find_element(:css => 'input.ember-power-select-trigger-multiple-input').click}
At the moment, when I run this, it's able to find the correct dropdown option and click it. The options in the list appear, but obviously nothing happens.
What I'd like to know is how I can extend this further so that the dropdown is selected, and that the "first" option is selected? I don't want to specify what it should be, but it just should randomly select the first from the list and use that.
Any thoughts on the easiest way to achieve this?
Research Snippet
I did some research and found the following snippet which I thought I could add to my code, however I'm unsure if it would actually work, or whether I could use this in conjunction with the #wait.until step that I mentioned above?
groupDropdown = #driver.find_element(:css => 'input.ember-power-select-trigger-multiple-input')
option = groupDropdown.find_element(:css, "option:nth-child(1)")
option.click

#wait.until {#driver.find_element(:css => 'input.ember-power-select-trigger-multiple-input').click}
#wait.until {#driver.find_element(:css => '.ember-view > li > .ember-view > li:nth-of-type(1) > .ember-view > li').click}
This worked.

Until
The “until” method within Selenium requires a “truthy” response to continue with the rest of the code.
What you could do is this:
power_select = #driver.find_element(:css => 'input.ember-power-select-trigger-multiple-input')
#wait.until {power_select.displayed?}
power_select.click
This will wait for the element to be displayed on the page, which returns a boolean, and then follow through with a click
Select
Following on from that, the methods for Selects are hidden within the library quite well, but after searching around for a bit:
To Select by text:
Selenium::WebDriver::Support::Select.new(#driver.find_element(:css => <insert_css_of_select_here>)).select_by(:text, <insert_option_text_here>)
To Select by index:
Selenium::Webdriver::Support::Select.new(#driver.find_element(:css => <insert_css_of_select_here>)).select_by(:index, <insert_index_value_here>)
Selecting by index is what you most likely want to do here, setting the index value to 0 to select the first option.

This will let you select required option of ember-power-select with Capybara:
find('.ember-power-select-trigger').click # Open trigger
find_all('ul.ember-power-select-options > li')[1].click # Select 2nd option
Tested with latest ember-power-select.
You might find the click be quite slow if your Capybara.default_max_wait_time is high, so to speed things further you can do this:
find('.ember-power-select-trigger').click # Open trigger
Capybara.using_wait_time(0.1) do
find_all('ul.ember-power-select-options > li')[1].click # Select 2nd option
end

Related

Click an exact match in cypress from drop down

Firstly ,I was doing cy.contains(option) with it was clicking the exact value eg -I want to click One but One One is also there so cy.contains not working.
I tried Regex but it is not working
I am trying to click the exact match from drop down writing test step as ;
cy.contains(new RegExp(option, "g"))
but not giving me correct output. I am getting error : Timed out retrying after 4000ms: Expected to find content: 'option' but never did.
Since you are using a dropdown, you can and should use the .select() command which will choose the option by exact match:
cy.get('select')
.select('One')
.should('have.value', 'One')
When the dropdown is like this, the above will choose the 2nd option.
<select>
<option>One One</option>
<option>One</option>
</select>
for the regex to work, you need to use the ^ and $ characters to indicate beginning and end of string
// works on <span>One</span> but not on <span> One </span> or <span>One One</span>
cy.get(`span`).contains(/^One$/)
// so you might want to also include white space
cy.get(`span`).contains(/^\s?One\s?$/)
You can click using the dropdown option if you now by default what is the option
cy.get(DROPDOWN IDENTIFIER).eq(NUMBER OF THE DROPDOWN MATCH).click();
What do you want is the .click() function to click on the match.
This will not work if you dropdown menu is a .

Loop through drop down with dynamic html table

I'm hard stuck with this one so any advice welcome!
Ive been trying to create a flow that goes to this website https://dlv.tnl-uk-uni-guide.gcpp.io/ and scrapes the data from each table in the Subject Areas drop down list. My knowledge of HTML is sketchy at best but from what I understand it's a dynamic html table that just refreshes with new data rather than going to a new url. I can extract the subject list as a variable and in my head i think i just need to add this to a UI selector action but despite numerous attempts i've got absolutely nowhere. Anyone got any ideas as to how i could fix this or work around?
Because it is not a conventional drop-down using the "Set drop-down list value on web page" doesn't work all that well.
You can use a bit of javascript and variables for this.
Hit F12 to show developer tools, you will see there is a list of hidden items with the class class="gug-select-items gug-select-hide" you will use this in the javascript.
Then add a 'Press button on web page' function and add the 'drop-down' element, which is a <div>
Then edit the element selector and change it to text editor.
then change the selector to make use of the nth-child(0) selector but use a variable for the index.
so it looks something like #gug-overall-ranking-select > div.gug-select-items > div:nth-child(%ddIdx%)
Use the "Run JavaScript function on web page" function to get the number of options available to the drop-down. (child elements)
The returned result is text, so convert it to a number that can be used in the loop.
function ExecuteScript() { /*your code here, return something (optionally); */
var firstDDlist = document.querySelector("#gug-overall-ranking-select > div.gug-select-items.gug-select-hide");
return firstDDlist.children.length;
}
In the loop each element will be pressed and cause the table to reload.
The table data extraction can then also be done in the loop, but that this code only shows the looping through the options.
The full flow 'code' (copy this and paste it in power automate).
WebAutomation.LaunchEdge.LaunchEdge Url: $'''https://dlv.tnl-uk-uni-guide.gcpp.io/?taxonomyId=36&/#gug-university-table''' WindowState: WebAutomation.BrowserWindowState.Normal ClearCache: False ClearCookies: False WaitForPageToLoadTimeout: 60 Timeout: 60 BrowserInstance=> Browser
WebAutomation.ExecuteJavascript BrowserInstance: Browser Javascript: $'''function ExecuteScript() { /*your code here, return something (optionally); */
var firstDDlist = document.querySelector(\"#gug-overall-ranking-select > div.gug-select-items.gug-select-hide\");
return firstDDlist.children.length;
}''' Result=> numberOfItems
Text.ToNumber Text: numberOfItems Number=> itemCount
LOOP ddIdx FROM 1 TO itemCount STEP 1
WebAutomation.PressButton.PressButton BrowserInstance: Browser Control: appmask['Web Page \'h ... sity-table\'']['Div \'gug-select-selected\''] WaitForPageToLoadTimeout: 60
END
It should end up looking like this:
Flow running:
With using Power Automate Desktop (PAD), the goal is to be a low-code solution. Of course knowing HTML is a bonus and will help you on tricky webpages or problems, but not knowing much is alright usually. I'm not really comfortable going to that web page you shared but you could try the below option.
PAD has a built in function in the action pane:
'Browser automation' > 'Web data extraction' > 'Extract data from web page'
Try using that and when asked to add UI Element select the table/dropdown list to see what information you get back. If that doesn't work you might need to try out JavaScript or another method.

Second drop down list does not get filled with Cypress

I ran into a problem. Can anyone help me ?
So, I have two drop down lists and the second is dependent on the option I choose on the first.
Say, for example: The first drop down list has the options 'numbers' and 'letters', while the second drop down list is empty by default. However, when I choose the option 'letters' on the first drop down list, the second is filled with the options 'A', 'B' and 'C'. Manually, it is working fine, but when I select the first drop down list with Cypress, the second doesnt get filled. It remains empty, so I cant choose anything on it.
HTML:
<select id="list" class="selectpicker form-control" onchange=""><option value="0">select your preferences</option><option value="2">numbers</option><option value="3">letters</option></select>
CYPRESS:
cy.get('#list').select('letters')
it does select the option letters, I can see the option letters selected on the first drop down list, but nothing happens on the second.
The solution from what it seems is to force the click because, from what I could gather, cypress chooses the option but IT DOESNT CLICK THE OPTION! Is this a bug?
So, this is the giant that was necessery, in the end to make it work:
//choose the option on the first drop down
cy.get('#list').select('letters')
cy.get('#list').contains('letters').then(option => {
cy.wrap(option).contains('letters');
option[0].click();
cy.get('#list').contains('letters');
});
//choose the option on the second drop down
cy.get('#list2').select('A')
cy.get('#list2').contains('A').then(option => {
cy.wrap(option).contains('A');
option[0].click();
cy.get('#list2').contains('A');
});
//click on the button to save the options selected
cy.get('.saveButton').click()
when, normally, it should be only:
cy.get('#list').select('letters')
cy.get('#list2').select('A')
cy.get('.saveButton').click()
Do you guys think this is a bug ?
I think you should "force" the refreshing data from the "non-updated" dropdown.
Try to "click()" it.
Something like this:
cy.get('#list')
.contains('letters')
.then(option => { // Confirm have correct option
cy.wrap(option).contains('letters');
option[0].click(); // After click, mdc-select should hold the text of the
// selected option: cy.get('#list').contains('letters');
});
Maybe this link can help you: select dropdownlist item using cypress
alternatively you can select by value cypress docs
cy.get('#list').select('3')

Unable to read checkbox value in cucumber

I am new to automation (Cucumber), and has very less idea of coding. I am looking for the script through which I can click on checkbox or radiobutton. Below is the HTML code I am looking at:
<"input class="facetoption" type="checkbox" value="facets.price_range%5B%5D=Rs.+2000+and+Below" autocomplete="off">
And below is the step definition which I tried
Step definition:
Then(/^Select the first Price Range Option$/) do
#browser.checkbox(:value => 'facets.price_range5B%5D=Rs.+2000+and+Below').click
end
The value in your locator doesn't match the value in the <input> tag. Compare the strings, and you'll see they are different.
your HTML: "facets.price_range%5B%5D=Rs.+2000+and+Below"
your code: "facets.price_range5B%5D=Rs.+2000+and+Below"
Update your step definition to the following, and it should work:
Then(/^Select the first Price Range Option$/) do
#browser.checkbox(:value =>'facets.price_range%5B%5D=Rs.+2000+and+Below').click
end
I don't know why you try to find checkbox by value. Better option is to find checkbox by id or class:
find('input#id').click()
If you still like to find checkbox by value please use:
find(:xpath, "input[#value='John']").click()
Use a regex so you can focus on the imporant parts, and ignore the unimporant parts
#browser.checkbox(:value => /2000\+and\+Below/).click

Ruby/Selenium: How to click on a specific item that appears multiple times on a page

Here's the item in question - specifically that little caret:
http://screencast.com/t/NMPOM9Ok58q
As you can see there are multiples of those within the same page, they all have the same class etc.
I've tried several different routes and I've not been able to successfully click on that item.
I always want to click on the last of them present on that page (the number of them are dynamic so sometimes it's the 2nd one and sometimes it's the 6th - so referring to it with a specific number doesn't work)
Thanks for the help (my tests are written in ruby, using selenium and testunit)
Here are some things I've tried and a few variations of these as well (none of which actually produce a click on that item)
#driver.find_element(:class, "dropdown-toggle")[-1].click
#driver.find_element(:css, "(//*[contains,'a.dropdown-toggle')]").click
element_present?(:css, "div.dropdown.open > a.dropdown-toggle").click
#driver.find_element(:css, "div.dropdown.open > a.dropdown-toggle").click
#driver.find_elements(:css, "caret")[-1].click
#driver.find_element(:css, "caret:last-of-type").click
#driver.find_element(:css, "div.dropdown.open > a.dropdown-toggle:last-child").click
#driver.find_element(:class, "span1").find_element(:tag_name, "a").click
^ This one actually is the only one that clicks anything - but it only clicks the first carat.
Ultimately what I'm doing with this test is adding a filter, closing the filter window, re-opening the filter window, deleting the previous filter, adding a new one and closing the window.
how about using the CSS last child selector?
#driver.find_element(:css, "div.dropdown.open > a.dropdown-toggle:last-child").click
If <div class="span1"> is unique, you can try someth like:
#driver.find_element(:class, "span1").find_element(:tag_name, "a").click
ok, so, if you need to click all links, or just someth of it, then:
#links = #driver.find_element(:class, "span1").find_elements(:tag_name, "a")
#links[0].click - for first link
#links[1].click - for second link
etc.

Resources