Clicking a button with Ruby Mechanize - ruby

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)

Related

How to handle dynamic elements with cucumber and capybara

(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

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

change input hidden controls in ruby mechanize

When I click on a button:
<input type="button" onclick="document.lista_de_precios.opcion.value='por_categoria';showCat()" value="Por Categoría" class="btn btn-mini">
A input type:hidden value is changed to the button name: "por_categoria"
How do I change
<input type="hidden" value="" name="opcion">
to
<input type="hidden" value="por_categoria" name="opcion">
in Ruby Mechanize gem, I already tried using python examples in ruby with no success..
page.form.new_control('hidden','opcion',{'value': 'por_categoria'}
Update:
I investigated a little bit more and:
QUOTE from webpage
Sometimes mechanize won't pick up certain hidden form controls. Since mechanize doesn't pick up these controls, you will need to create them manually in order to get the form submission to work.
I think I will leave this post as is, because I don't know how to create form controls in this ruby code and mechanize.
You can ignore the advice on that page, it's talking about Python mechanize which is a different library (and not a very good one apparently!)
Here's how to do it with ruby mechanize:
form = page.forms[0] # or some other number
form['opcion'] = 'por_categoria'

A way around Element cannot be scrolled into view - Watir-webdriver with Ruby

So, we have the following code in our page:
<div class="toggle-wrapper">
<input id="HasRegistration_true" class="registration_required toggle" type="radio" value="True" name="HasRegistration" data-val-required="The HasRegistration field is required." data-val="true">
<label for="HasRegistration_true" class="">On</label>
<input id="HasRegistration_false" class="registration_required toggle" type="radio" value="False" name="HasRegistration" checked="checked">
<label class="checked" for="HasRegistration_false">Off</label>
</div>
These are 2 radio buttons. 'On' and 'Off'. 'Off' is the default value.
Using Watir-webdriver and Ruby, we want to select the 'On' radio button. We do so like this:
browser.radio(:id => "HasRegistration_true").set
But in doing so, we get the following error:
`WebElement.clickElement': Element cannot be scrolled into view:[object HTMLInputElement] (Selenium::WebDriver::Error::MoveTargetOutOfBoundsError)
We know Selenium 2 scrolls the page to the element, so trying to scroll down is useless.
We are always using the latest releases of watir-webdriver and ruby.
We can't change the HTML of the page since we're QA engineers.
Here are two solutions that have worked for me:
There is a Ruby gem called watir-scroll that can work.
Then
require 'watir-scroll'
browser.scroll.to browser.radio(:id, "HasRegistration_true")
If you don't want to add a gem, my co-worker suggested something that somewhat surprisingly (to me) had the same effect as the above code:
browser.radio(:id, "HasRegistration_true").focus
browser.radio(:id, "HasRegistration_true").set
In my code, ".focus" scrolled straight to the element that was previously not visible. It may work for you as well.
First of all try locating the element using XPATH:
browser.element(:xpath, "//input[#id='HasRegistration_true']").click
or
alternatively if it is a hidden element you are trying to locate then you are better off using CSS. Download firebug add-on for firefox and copy the CSS path of your element.
It should be something like:
browser.element(:css => "the CSS path you have copied from Firebug").click
One of the 2 should do it for you!!
Best of luck!
You could manipulate the html on the fly by executing some javascript to make the radio element settable. To execute javascript on a page, do something like:
#browser.execute_script("your javascript here")
I used something like the following javascript to strip the class out of a label tag which moved it out of the way of the input tag I was attempting to act on for a Chrome specific problem I had.
execute_script("$(\"label.classname\").removeClass(\"classname inline\")")
If the element is contained within a form and a div (Wrap) class I found that I had to do the following to click the 'No' radio button on the "https://quote.comparethemarket.com/Motor/Motor/AboutYourVehicle.aspx?" page:
div_list = #browser.form(:action => "AboutYourVehicle.aspx?ton_t=CTMMO&prdcls=PC&rqstyp=newmotorquote&AFFCLIE=CM01").div(:class => "inputWrap").divs(:class => "custom-radio")
And then:
div_list[1].click
Hope this solves your issue too :-)
I'm not using watir but I have the same error as you "...could not be scrolled into view ...". I tried to use watir just to solve it and didn't work for me. Then, I use an ActionBuilder (move_to with click) and the error disappeared.
My line to avoid the error is:
#driver.action.move_to(*webelement*).click.perform
I hope it will be useful for you

Firefox 3.5.2 Refresh(F5) causes Highlighted Form value to get copied to next field

I am having a strange issue in Firefox 3.5.2 with F5 refresh.
Basically, when I focus on an input field and hit f5 the contents of that input field gets copied to the next form field after the F5 refresh.
But, if you inspect the HTML source code, the values are correctly loaded.
I am not having this issue in IE8 or Safari 4.0.3.
The problem does not occur if I do a hard refresh or run window.location.refresh(true).
After F5 Refresh: http://i805.photobucket.com/albums/yy339/abepark/after.jpg
Here's an overview of what's going on.
I believe the thing you should look into is the autocomplete attribute,
you should set it to off on the input box. However be careful since this will trigger two effects.
When you refresh the page it won't remember the old values
The default dropdown of the already used values on that input box will also be disabled.
If you want to keep the second behavior you should set the autocomplete attribute back to on with JS.
Browsers can remember form field contents over a refresh. This can really throw your scripting off if it is relying on the initial value of a field matching what's in the HTML. You could try to prevent it by calling form.reset() at the start.
Different browsers have different strategies for detecting when a form or a field is the same as in the previous page. If you have clashing names, or names that change on reload, it is very possible to end up confusing them. Would have to see some code to work it out for sure.
In the backend, I am using ASP.NET MVC 1.0 with the Spark View engine. When I examine the source code after an F5 refresh in Firefox 3.5.2, the page renders correctly; however, if you look at the page visually the adjacent form field field gets populated with the value from the previous field.
I included enough code so you can just get an idea of what I'm trying to do.
Again, the rendering is fine and the final view/HTML code is fine. It's what I see on the screen that is incorrect. I am using hidden vars; but the issue occurred before using it as well.
Note in the code below, I have 2 distinct ID fields: "date_{projectTask.ProjectTaskId}" and "finishDate_{projectTask.ProjectTaskId}, which gets renders to something like "date_1" and "finishDate_2".
<table>
<for each="ProjectTask projectTask in projectTasksByProjectPhase">
<input type="hidden" value="${projectTask.ProjectTaskId}" />
<tr>
<td class="date">
<div class="box">
<div class="datefield">
<input type="text" id="date_${projectTask.ProjectTaskId}" value="${startDate}" /><button type="button" id="show_${projectTask.ProjectTaskId}" title="Show Calendar"><img src="~/Content/yui/assets/calbtn.gif" width="18" height="18" alt="Calendar" ></button>
</div>
</div>
</td>
<td>
<div class="box">
<div class="datefield">
<input type="text" id="finishDate_${projectTask.ProjectTaskId}" value="${finishDate}" /><button type="button" id="finishShow_${projectTask.ProjectTaskId}" title="Show Calendar"><img src="~/Content/yui/assets/calbtn.gif" width="18" height="18" alt="Calendar" ></button>
</div>
</div>
</td>
</tr>
</for>
</table>
FYI: ${} are used to output variables in the Spark View engine.
I am also using the YUI 2.7 Connection to make Ajax calls to update the datebase for "change" and "enter/tab key press" events. I am able to verify that the AJAX calls are made correctly and the form field values are still valid.
The problem occurs when I just do a F5 refresh; for some reason, the "finishDate_1" gets populated with the value from "date_1".
This problem occurs just by clicking on "date_1" and hitting F5; so, the adjacent field just gets populated even if there are no AJAX calls.
Here's the Javascript code I call towards the end of the body"
YAHOO.util.Event.onDOMReady(
function() {
var idList = YAHOO.util.Dom.getElementsBy(function (el) { return (el.type == 'hidden'); }, 'input');
len = idList.length;
var startDatePickers = new Array();
var finishDatePickers = new Array();
for (var i = 0; i < len; i++) {
var id = idList[i].value
startDatePickers[i] = new DatePicker("date_" + id, "show_" + id, "cal_" + id);
startDatePickers[i].valueChanged.subscribe(updateDate, 'S');
finishDatePickers[i] = new DatePicker("finishDate_" + id, "finishShow_" + id, "finishCal_" + id);
finishDatePickers[i].valueChanged.subscribe(updateDate, 'F');
}
}
}
The form field gets copied over before any Javascript code is processed because I call the Javascript code towards the end of the body after all HTML is rendered. So, I'm guessing it's a refresh issue in Firefox? What do you guys think?
As you can see above, I created my own calender date picker objects which allows you to either enter the date in the text manually or by clicking on a button to view the calendar and select a date. Once you enter or select the date, an AJAX call will be made to update the datebase in the back end.
Thanks everybody for the quick responses.
#Anonymous: whoever you are, you are awesome!
#bobince: thanks for the feedback as well.
I added a dummy form tag with the attribute autocomplete="off" and that solved the problem!
I was scratching my head because I didn't get this issue in Safari 4.0.3 or Internet Explorer 8.
<form action="" autcomplete="off">
<!-- my code -->
</form>
The values were loading correctly in the back end (ASP.NET MVC 1.0/Spark View engine) and the HTML source code reflected this, but the input field values were not getting populated correctly. I was using the YUI Connection Manager and Javascript to support edit-in-place and the date pickers.
I tried changing the XHR call to a GET call instead of POST and the same issue was happening.
Anyway, the problem was that the Firefox was not setting the correct values for the input fields for F5 refreshes.
Again, thanks so much! You guys rock!
All element id's must be unique, if two elements have same id's then that could be reason why Firefox inserts same values to elments that didn't orginally have those values entered.
I had a similar problem related to my question at Input control shows incorrect value, even 'though inspect element shows the right value is there
The problem occurred for me in Firefox, but not Chrome, for some but not all controls on the form, and when I pressed F5, but not ctrl-F5.
The "dummy form" seems to have resolved it for me.

Resources