How to handle dynamic elements with cucumber and capybara - ruby

(Click for image) I am working on an project to write a scenario to test login feature. For some reason capybara is not accessing dynamic elements.
Steps to Reproduce:
1) visit Redfin.com(for example)
2) click on Sign in button
3) a dynamic popup dialog appears
4) click on "continue with email" and try and enter details and clicking on submit.
I am not able to find any of the elements with find(#) and inturn not able to click on submit or enter details.
Also I believe the webapp is build with React.
Please do let me know how to handle this.
<div class="emailSignInButtonWrapper" style="position: relative;">
<button class="button Button tertiary emailSignInButton v3" type="button" tabindex="0" data-rf-test-name="submitButton">
<span>
<span class="signInText">Continue with Email</span>
</span>
</button>

None of the elements you are talking about have ids so a CSS find using #<id> (find('#my_button').click) isn't going to work. However to click that button you should just be able to do
click_button('Continue with Email') # case of the text matters
or
click_button(class: 'emailSignInButton')
This all assumes you are using a driver with Capybara that supports JS - https://github.com/teamcapybara/capybara#drivers
Here's code that shows it works if using a JS capable driver
require 'capybara/dsl'
require 'selenium-webdriver'
session = Capybara::Session.new(:selenium_chrome)
session.visit "https://www.redfin.com"
session.click_link('Sign In', href: nil)
session.click_button('Continue with Email')

Here's what worked for me on the redfin site:
scenario "bring up signup form on redfin" do
visit 'https://www.redfin.com'
find('a', :text => 'Sign In').click
click_button('Continue with Email')
end

Related

not able to click radio button element by xpath in selenium using python

Below is my HTML
<div id="slectrole" class="collapse in" role="tabpanel" aria-labelledby="selectrole">
<div class="panel-body">
<div class="dropdown">
<input class="search-control jsSayt jsRolesFreeText" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Eg: Delivery, BPO, Driver'" placeholder="Eg: Delivery, BPO, Driver" value="" aria-expanded="false" aria-haspopup="true" data-toggle="dropdown" type="text">
<ul class="jsSaytList jsRolesFilter">
<li id="jsFilter_subRole_1" class="checkbox-inline jsFilterSubRole jsRoleValue_1" data-value="Accountant">
<input id="Accountant" class="radio-custom jsFilterRadio jsRole" value="Accountant" name="Role" data-roleid="1" type="radio">
<label class="radio-custom-label" for="Accountant">Accountant</label>
Below is the code I am using to click the radio button:
wait.until(EC.visibility_of_element_located((By.XPATH, "//div[#id='slectrole']/descendant::li[#data-value='Accountant']/label[#for='Accountant']")))
driver.find_element_by_xpath("//div[#id='slectrole']/descendant::li[#data-value='Accountant']/label[#for='Accountant']").click()
The code runs ok but it does not select the radio button.
OK, so I can understand your frustration, I tried your code and wasn't able to .click() (select) the element when located via xpath. See bellow print-screen:
As you can see, it was only clicking the radio-button when issuing a .click() via a CSS-located element.
Question No.1: Are you bound to the xpath locator strategy in one way or another?
If NOT, then just use a regulat CSS selector: 'input[id="Accountant"]'.
Else, you have to figure out what is wrong with the website you are testing, or switch to another WebElement locator strategy. (e.g.: ID, Class, CSS, LinkText, etc.)
If you would opt to go with the CSS locator-strategy, then your code would look like this:
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "label[for='Accountant']")))
driver.find_element_by_css("input[id='Accountant']").click()
Alternatively, you can try to click on the <label> tag attached to the radio-button, which in my console works the same way:
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "label[for='Accountant']")))
driver.find_element_by_css("label[for='Accountant']").click()
Explanation: In a real-life scenario, you can select the radio-button both via the actual radio-button, or via its label. That's why your solution worked.
Question No.2: Why are you using such a long xpath selector?
In order to have a optimal selector, you should ALWAYS go with the shortest, combination of tags/attributes that will UNIQUELY identify your target element. Else you will be susceptible to website changes, flaky test cases, etc.
You can perform the click on the drop down and then wait for the radio button to appear, before clicking it. Hence, try following:
driver.find_element_by_xpath("//div[#id='slectrole']/div/div[#class='dropdown']/input[1]")).click()
wait = WebDriverWait(driver, 10)
wait.until(EC.visibility_of_element_located((By.XPATH, '//div[#id='slectrole']/descendant::li[#data-value='Accountant']/input[1]')))
driver.find_element_by_xpath("//div[#id='slectrole']/descendant::li[#data-value='Accountant']/input[1]").click()
Let me know, if above code works for you.

How do I click this button using Ruby Capybara?

I'm trying to click a button, but I'm getting the following error:
Unable to find link or button "My Tasks" (Capybara::ElementNotFound)
This is what I get when I inspect it on Chrome:
<a class="btn btn-lg btn-success" href="/tasks" role="button">My Tasks</a>
And this is my code (my steps.rb):
# go to my tasks page
def visitTasksPage
page.has_content?('Signed in succesfully') do
clicK_link 'My Tasks'
end
self
end
I'm new to Ruby Capybara, can anyone help me please?
The problem might be that it's really a link that you're trying to click (an Some Text tag) not a button (a <button type="button">Some text</button> tag). To not have this problem, I recommend that you use the following method:
click_on('My Tasks') # clicks on either links or buttons
Or it could be that the link or button does not appear on the page before Capybara times out. Capybara by default waits 2 seconds before it times out, but you can extend it with
Capybara.default_max_wait_time = 9
Another thing you can do to debug this problem is add a call to binding.pry right before clicking the link/button and check if the button is actually there with the text you expect it to have:
page.has_content?('Signed in succesfully') do
binding.pry # at this point you can test if the link is really there with page.has_content?('My Tasks')
click_link 'My Tasks'
end
Note you would need to install pry by adding it to you Gemfile or with gem install pry.

Watir-Webdriver - Unable to locate a button with id, name, text, value

I am very new to web automation and watir-webdriver. i am trying a script to launch a web and submit the login form. I was able to identify the username and password text fields with the 'id' tag. but the login button doesn't have any of the id, name, text and value keys. i have tried looking all the sources, they all have atleast any one key to search the button. but as i am not seeing that in my web application, could someone help me how to search the button and click it.
Here's a portion of the HTML from the page where the button is identified
<jl-button-bar class="margin-bottom centered ng-scope">
<button class="primary full jl-button ng-scope" type="submit" tabindex="0">
<ng-transclude>
<span class="ng-scope">Login</span>
</ng-transclude>
</button>
</jl-button-bar>
It is hard to tell what is unique about the button without seeing the entire page. However, assuming there is only one login button, you can probably do:
browser.button(text: 'Login').click
If the application supports multiple languages, you might not want to use the text. If there is only the login form, you can probably do:
browser.button(type: 'submit').click

Having trouble hovering and clicking button using Capybara and Xpath

I'm trying to click a button using Capybara. I've tried all combinations I can think of but no luck. Trying to click on the 'delete' link. The delete link only shows up when you hover over the row in the table.
This is the HTML:
<tbody>
<tr class="even" id="informal_6">
<td class="columnOrganizationNameColumnValue" id="informal_7">
<div>
<a id="showLink_0" title="Organization Details" class="viewLink">
Institution / Automation
</a>
</div>
<div class="gridMenuDescription">
</div>
<div class="gridMenu">
<a id="gridMenuDirectLink_1" title="Edit Organization" class="gridMenuItem">
edit
</a>
<a id="gridMenuDirectLink_2" class="gridMenuItem delete">
delete
</a>
</div>
</td>
</tbody>
I'd like to note, that the "gridMenu" div, when you hover over it using Firebug it turns to:
<div class="gridMenu hover gridMenuShow">
Some things I've tried, but no luck:
find(:xpath, '//*[(#id = "gridMenuDirectLink_2")]').click
find("#informal_6").find("#informal_7").find(".gridMenu.hover.gridMenuShow").find(".gridMenuItem.delete").click
Suggestions?
After a crazy amount of attempts trying different things I was able to get it to work with this code:
find('#informal_6').hover.find('.gridMenu').hover.find('.gridMenuItem.delete').click
Try the below code to hover over the row.
page.driver.browser.mouse.move_to(page.driver.browser.find_element(:id=>"locator"))
I have a calendar interface where AJAX edit & delete links appear only when you hover over each calendar entry. It's nice and compact, but I had trouble getting Capybara to click on those dynamically displayed elements, and using .hover on the parent element didn't seem to make a difference. So I tried a brute-force approach that is working nicely so far:
# Use Jquery to force display a hidden element. Useful for getting at links
# that are dynamically displayed.
# Call it like: js_show(".entry.scheduled[data-id=\"#{#da3.id}\"] .actions")
def js_show(selector)
page.execute_script(" $('#{selector}').show(); ")
end
def js_hide(selector)
page.execute_script(" $('#{selector}').hide(); ")
end
Now, when I need to click on an element that's only displayed on hover etc., I can call js_show(".whatever.container.selector") to force the links to display, then page.find(...).click works.

Clicking a button with Ruby Mechanize

I have a particularly difficult form that I am trying to click the search button and can't seem to do it. Here is the code for the form from the page source:
<input type="image" name="" src="http://images.example.com/WOKRS53B4/images/search.gif" align="absmiddle" border="0" onclick="return check_form_inputs('UA_GeneralSearch_input_form','search');" title="Search" alt="Search" class="">
I am trying to do the standard mechanize click action:
login_page = agent.click(homepage.link_with(:text => "Search"))
Is this because the button uses javascript? If so, any suggestions?
I struggled with this too, especially since my form had multiple buttons.
There are multiple ways to submit a form (with many using a 'form_with' block), but this helped me:
# get the form
form = agent.page.form_with(:name => "my-form")
# get the button you want from the form
button = form.button_with(:value => "Search")
# submit the form using that button
agent.submit(form, button)
See more info here
Also, make sure you upgrade to the latest mechanize. I was using mechanize 1.x, which was giving me "undefined method" errors for the code above.
It is not a link, it is a button. What you need to do is look for the form (for example, with form_with) and then look for the ImageButton and submit it.
button = form.button_with(value: 'Search')
form.click_button(button)

Resources