Insert value in a text field using Ruby - watir/selenium - ruby

I am trying to insert a number in the 'Mine Id' using Ruby - Watir/Selenium
Somehow the field <input> field is not being recognized as a text box and hence I am unable to enter values through the code.
The id 'inputdrs' is used multiple times on the same page.
Any suggestions how to achieve it.
The URL is this
http://www.msha.gov/drs/drshome.htm
The below don't work:
#browser.text_field(:id => /inputdrs/, :index => 2).set("3607277")
browser.text_field(:name, "inputdrs").set("3607277")
Thank you for your help

require 'watir-webdriver'
$browser = Watir::Browser.start "http://www.msha.gov/drs/drshome.htm"
a = 0
b = $browser.text_fields.length
while a < b
$browser.text_fields[a].set a
a += 1
end
This will put the value of a in each text field on this page. I REALLY drew out the loop so you can see whats going on. This isn't as dynamic as you would like it, but if the page has the same amount of text_fields you should be fine.
OR you can do something like..
$browser.text_field(:name => "MineId").select
$browser.send_keys "hello"

Problem
The html of the Mine ID field is:
<input size="8" maxlength="8" name="MineId" onclick="this.value='';" id="inputdrs" align="middle" type="number">
The line:
#browser.text_field(:id => /inputdrs/, :index => 2).set("3607277")
Will fail because it is inputting into the wrong text field. If you get all of the text fields with that id:
browser.text_fields(:id => 'inputdrs').collect(&:name)
#=> ["q", "MineId", "OperSearch", "MineName", "CntctrId", "CntCtrSearch", "Controller"]
You can see it is the second field. However, because Watir is using a 0-based index, you actually get the OperSearch field. This would have worked by using an :index => 1 instead.
The line:
browser.text_field(:name, "inputdrs").set("3607277")
Will fail because the "inputdrs" is the value of the id attribute and not the name attribute.
Solution
Given that the id attribute value is not unique for this page, you should probably not use it for locating. Instead, use something unique, such as the name attribute.
browser.text_field(:name => "MineId").set("3607277")

Related

trying to increment a value of the object by assigning to a variable i . Please advice

Below is my code.I'm trying to input value from the excel sheet to the text boxes in the page. Eg : In text box id is 'allocationRegContrib[17].newFundValue' I want to input a value say 20. Similarly for another text box whose id is 'allocationRegContrib[18].newFundValue', I want to input a value say 40. How to achieve. Similarly the id goes on upto 60. But I do not want to input in all the textboxes. So I'm trying to use like fill_in "allocationRegContrib[i].newFundValue".
#i=17
for j in (workbook.first_row..workbook.last_row)
for k in (workbook.first_column..workbook.last_column)
if(k==1)
fill_in "searchInput", :with => workbook.cell(j,1)
find(:xpath, '//*[#id="sdcaLink"]').click
sleep 3
else
choose("sdcaOption", :option => "YES")
select(workbook.cell(j,k), :from => 'sdcaDuration')
fill_in "allocationRegContrib[i].newFundValue", :with => workbook.cell(j,k)
#i=i+1
find(:xpath, '//*[#id="specialDCAupdate"]').click
But it does not work for me. Error is "unable to locate the capybara element allocationRegContrib[i].newFundValue". Please Advice
You may have two issues:
i and #i aren't the same thing. I think you may want to use i in all the places. i is a local variable (that is, a simple plain old variable). #i is an instance variable of a class, like a "field" or "property" in other languages.
fill_in "allocationRegContrib[i].newFundValue", :with => workbook.cell(j,k)
should probably be:
fill_in "allocationRegContrib[#{i}].newFundValue", :with => workbook.cell(j,k)
#{i} puts in the value of the variable i into the string, then the capybara matcher can find, for example, element allocationRegContrib[17].newFundValue (when i=17)

Watir method (or monkey-patch) to select span (or other) tags with custom ("data-*") attribute values equaling a string value (or matching a regex)

So this is ruby right, and while I do have a solution already, which I'll show below, its not tight. Feels like I'm using ahem "C++ iterators", if you will. Too many lines of code. Not like ruby.
Anyway, I'm wondering if there is classier way to do this:
b = Watir::Browser.new
b.goto "javascriptinjectedtablevalues.com" #not real website url:)
# desired urls in list are immediately located within <span> tags with a "class" of
#"name" plus a custom html attribute attribute of "data-bind" = "name: $data". that's it
# unless I wanted to use child-selectors which I'm not very good at
allrows = b.spans(:class => "name").each_with_index.map do |x, i|
[0, x.attribute_value("data-bind")]
end
real_row_ids = allrows.select{|i, databind| databind == "name: $data" }.map(&:first) #now I have all correct span ids
spans = real_row_ids.map {|id| b.spans(:class => "name")[id] }
Now that's a little messy in my opinion. But it leaves artifacts so I can debug and go back and stuff.
I could use this command to just grab a just the spans
spans = b.spans(:class => "name").map do |span|
[span, span.attribute_value("data-bind")]
end.select {|span, databind| databind == "name: $data"}.map(&:first)
but that still feels messy having no artifacts to show for it to use for later when trying to isolate other html tags nearby the span.
I'm hoping there is something like this pseudo code for watir:
b.spans(:class => "name").with_custom_attributes(:key => "data-bind", :value => "name: $data")
that's what I'd really like to do. superman-patching this custom method onto Watir within a rails initializer would be the optimal solution second to it already existing within Watir!
Watir already supports using data attributes for locators. You simply need to replace the dashes with underscores.
For example:
b.spans(:class => 'name', :data_bind => "name: $data")
Would match elements like:
<span class="name" data-bind="name: $data">
Similarly, you can use a regex when matching the data attribute:
b.spans(:class => 'name', :data_bind => /name/)

Capybara - Fill in form element within form using arguments

Im trying to fill in a field via its name. Because there are two fields with the same name in 2 different forms I can't just use fill_in on its own as there is an ambiguous match.
Im trying to do something like below, but obviously the within doesnt look by name, so it cannot find the form.
When(/^I type "(.*?)" into the "(.*?)" textbox in the "(.*?)" form$/) do |textboxValue, textboxName, textboxForm|
within(:name, textboxForm) do
fill_in textboxName, :with => textboxValue
end
end
texboxForm - Name of the form the element is within
textboxName - Name of the textbox
textboxValue - The value I want to fill the textbox with
Any ideas?
Thanks
Its a bit horrible, but this worked.
find("form[name='" + textboxForm + "']").fill_in textboxName, :with => textboxValue

How to submit formstack form using ruby?

I have a form similiar to THIS and want to be submit data to it from a CSV file using ruby. Here is what I have been trying to do:
require 'uri'
require 'net/http'
params = {
'field15157482-first' => 'bip',
'field15157482-last' => 'bop',
'field15157485' => 'bip#bob.com',
'field15157487' => 'option1'
'fsSubmitButton1196962' => 'Submit'
}
x = Net::HTTP.post_form(URI.parse('http://www.formstack.com/forms/?1196833-GxMTxR20GK'), params)
I keep getting A valid form ID was not supplied. I have a hunch I am using the wrong URL but I don't know what to replace it with.
I would use the the API but I don't have access to the token hence my stone age approach. Any suggestions would be much appreciated.
The form uses hidden variables and cookies to attempt to maintain a "unique session". Fortunately, Mechanize makes handling 'sneaky' forms quite easy.
require "mechanize"
form_uri = "http://www.formstack.com/forms/?1196962-617Z6Foyif"
#agent = Mechanize.new
page = #agent.get form_uri
form = page.forms[0]
form.fields_with(:class => /fsField/).each do |field|
field.value = case field.name
when /first/ then "First Name"
when /last/ then "Last Name"
else "email#address.com"
end
end
page = form.submit form.buttons.first
puts
puts "=== Response Header"
puts
puts page.header
puts
puts "=== Response Body"
puts
puts page.body
Looking at the source on http://www.formstack.com/forms/?1196833-GxMTxR20GK and the example in your link, it appears that formstack forms post to index.php, and require a form id to be passed in to identify which form is being submitted.. Looking at the forms in both examples, you'll see a field similar to this:
<input type="hidden" name="form" value="1196833" />
Try adding the following to your params hash:
'form' => '1196883' # or other appropriate form value
You may also need to include the other hidden fields for a valid submit.

How do I get an array of check boxes in haml?

I have an array of strings, called #theModels, in a routine implemented as part of a Sinatra server. These models are options for the user to select, and are obtained by the back end (the idea being, as new models are added, then the front end code should not change).
I'm using haml to render html.
How can I enumerate each element in the list of #theModels such that each element is a checkbox? And how can I obtain which checkboxes the user has selected?
I see that just putting
= #theModels
will give me the list of strings contained in #theModels, but without spacing or the like, and certainly not in checkboxes. I've found this question that appears to be similar, but my haml-fu isn't good enough to convert that into what I need.
UPDATE:
These are options associated with a file upload, such that now the code looks like:
%form{:action=>"/Upload",:method=>"post",:enctype=>"multipart/form-data"}
- #theModelHash.each do |key,value|
%br
%input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
=key
%input{:type=>"file",:name=>"file"}
%input{:type=>"submit",:value=>"Upload"}
Problem is, that puts a file upload button on each option, instead of at the end. I only want one submit button in the end; should I have two forms that both report their results when the 'Upload' button is pressed?
UPDATE2:
After a moment's thought, the above can be modified to:
Thanks!
%form{:action=>"/Upload",:method=>"post",:enctype=>"multipart/form-data"}
- #theModelHash.each do |key,value|
%br
%input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
=key
%form{:action=>"/Upload",:method=>"post",:enctype=>"multipart/form-data"}
%input{:type=>"file",:name=>"file"}
%input{:type=>"submit",:value=>"Upload"}
And that appears to do what I want.
I think you should send the content as an hash instead.
This will give you the opportunity to set initial values in the form.
The hash #params will give you the result.
E.g. {"oranges"=>"1"}
#app.haml
%form{:method => 'post', :action => "/"}
- #models.each do |key,value|
%br
%input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
=key
%input{:type => :submit, :value => "Save"}
#app.rb
require 'sinatra'
require 'haml'
get '/' do
#models = {"oranges" => true, "bananas" => false}
haml :app
end
post '/' do
#params.inspect
end
The link you provided linked to a rails solution where you have a function returning the proper html.
You can define this function yourself:
Input: key, value
Output: %input{:type=>"checkbox", :name=>"#{key}", :value=>1, :checked=>value}
def check_box(key, value)
...
end
and call it in haml with
=check_box(key,value)

Resources