How to upload a file with watir and Internet Explorer? - ruby

Over the last couple of days i have been put in charge of Automating certain aspects of my companies CMS systems. (We are using Drupal)
One of the issue i am having with my ruby script is getting IE to select a local file from my machine and adding it to my submit form.
Now i have been reading up about this and found a few simular posts, but the different with the form we are using is that the browse button is made out of flash and there is no input field for the file path. The options i have is to either type in the "File Name" and clicks the "Open" button or the second option is to double click a file.
So they way i have got round this so far is to tab down to the "browser button and then press the "Enter" key to open the browse menu. But i now need the ability to select a file name.
This is my Ruby File.
require 'watir'
include Watir
ie = Watir::IE.new
ie.goto ("file:///C:/Ruby193/bin/ruby-capybara/features/step_definitions/form.html")
ie.text_field(:id, "edit-submitted-ugc-video-title").set("Title")
ie.text_field(:id, "edit-submitted-ugc-video-firstname").set("First Name")
ie.text_field(:id, "edit-submitted-ugc-video-lastname").set("Last Name")
ie.text_field(:id, "edit-submitted-ugc-video-phonenumber").set("01234567891")
ie.text_field(:id, "edit-submitted-ugc-video-location").set("London")
ie.text_field(:id, "edit-submitted-ugc-video-email").set("test#test.com")
ie.text_field(:id, "edit-submitted-ugc-video-email2").set("test#test.com")
ie.send_keys('{TAB}')
ie.send_keys('{ENTER}')
uploadfile = "V:\GIR-FP-WSD-QA\Test Media Files\Video1.mp4"
assert_equal uploadfile, ie.file_field(:name,"Video1.mp4").value
ie.button(:name, 'upload').click
#
Edited:
require 'watir'
require 'win32ole'
include Watir
ie = Watir::IE.new
ie.goto ("file:///C:/Ruby193/bin/ruby-capybara/features/step_definitions/form.html")
ie.text_field(:id, "edit-submitted-ugc-video-title").set("Title")
ie.text_field(:id, "edit-submitted-ugc-video-firstname").set("First Name")
ie.text_field(:id, "edit-submitted-ugc-video-lastname").set("Last Name")
ie.text_field(:id, "edit-submitted-ugc-video-phonenumber").set("01234567891")
ie.text_field(:id, "edit-submitted-ugc-video-location").set("London")
ie.text_field(:id, "edit-submitted-ugc-video-email").set("test#test.com")
ie.text_field(:id, "edit-submitted-ugc-video-email2").set("test#test.com")
ie.send_keys('{TAB}')
ie.send_keys('{ENTER}')
class FileField < InputElement
# set the file location in the Choose file dialog in a new process
# will raise a Watir Exception if AutoIt is not correctly installed
def set(setPath)
assert_exists
require 'watir/windowhelper'
WindowHelper.check_autoit_installed
begin
thrd = Thread.new do
system("rubyw -e \"require 'win32ole'; #autoit=WIN32OLE.new('AutoItX3.Control');
waitresult=#autoit.WinWait 'Bird annoys Cat.mp4', '', 15; sleep 1; if waitresult == 1\" -e
\"#autoit.ControlSetText 'Bird annoys Cat.mp4', '', 'Edit1', '#{setPath}';
#autoit.ControlSend 'Bird annoys Cat.mp4', '', 'Button2', '{ENTER}';\" -e \"end\"")
end
thrd.join(1)
rescue
raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
end
click
$end
ie.button(:name, 'upload').click

I'm afraid in this situation you have to use windows automation.
It may be either winapi or some sort of automation framework, for example autoit:
class FileField < InputElement
# set the file location in the Choose file dialog in a new process
# will raise a Watir Exception if AutoIt is not correctly installed
def set(setPath)
assert_exists
require 'watir/windowhelper'
WindowHelper.check_autoit_installed
begin
thrd = Thread.new do
system("rubyw -e \"require 'win32ole'; #autoit=WIN32OLE.new('AutoItX3.Control');
waitresult=#autoit.WinWait 'Choose file', '', 15; sleep 1; if waitresult == 1\" -e
\"#autoit.ControlSetText 'Choose file', '', 'Edit1', '#{setPath}';
#autoit.ControlSend 'Choose file', '', 'Button2', '{ENTER}';\" -e \"end\"")
end
thrd.join(1)
rescue
raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
end
click
end
end

Automating stuff done in flash is sometimes a pretty big pain due to how proprietary it is. You may want to look into using an image based automation method for this section of the test. See this blog posting for more info

Is the file selection dialog native Windows File Open Dialog or is that also proprietary flash solution?
If it is native dialog (e.g. same as in everywhere else) then you can use my library RAutomation or autoit as suggested above.
If that's the case, then you could take some hints how to do that from Watir's code.
Also, does that flash upload have some JavaScript API? If that's the case then you could use #execute_script to do all the things you need - e.g. set the file programmatically and move on. I'm doing something similar with flash video player.

Related

'Headless' browser still opening up FireFox in script, which in turn does not work in cron job. Why?

I wrote this bit of code to be called in a script that runs on a cron job, knowing it has to be a headless browser to be ran in a cron job, i found Headless. It sounds like a wonderful gem to do exactly what i want it do to, the only problem is it still opens up FireFox when I run the code.
I thought the whole point of headless was to not have to access the display and run in the background, like :phantomjs. Am I missing something or did I mistake what the headless gem is supposed to accomplish? (P.S. at bottom about when i tried to use :phantomjs)
#encoding: utf-8
require 'watir-webdriver'
require 'headless'
#log into admin dashboard
headless = Headless.new
browser = Watir::Browser.start 'http://app.mycompany.com/admin'
browser.link(:xpath =>'/html/body/div/div/div/div/a').when_present.click
browser.text_field(:id => 'Email').when_present.set 'me#mycompany.com'
browser.button(:id => 'next').click
browser.text_field(:id => 'Passwd').when_present.set 'password'
browser.button(:id => 'signIn').click
browser.goto 'https://app.mycompany.com/admin/dashboard'
#browser is at dashboard to grab yesterday's numbers
code that grabs data
#closes browser after grabbing data
browser.close
headless.destroy
#send timestamp
current_time = Time.now
puts "Screen grabbed at " + current_time.inspect + "\n\n"
#puts all data into array then outputs array split on each metric's title
dailyreportdata = [my glorious array of data]
dailyreportdata.each_slice(2) { |x|
puts x.join
}
My script runs to completion, but the data doesnt appear so I am guessing that it fails over when it tries to load the browser, thus loading no data to grab and send to my file.
My script look like this:
#!/bin/sh
_now=$(date +"%m_%d_%Y")
ruby dailyreportscraper.rb > ~/dailyscrape_$_now.txt
if I run it outside of the cron job, it works just fine.
P.S. - I tried phantomjs but every time it got to the "Enter Email" field, it would time out on waiting for the element to appear - it is a google login so maybe there is something to do with that, I even tried using the xpath as well.
Thanks for the help!
Call headless.start after you do headless = Headless.new.
And make sure you are running Xvfb.

Ruby Cucumber PDF reader

I'm running tests to render and check a PDF. I've got it working but the PDF's are date stamped in the filename. I'm looking for a way to always have today's generated file to be opened. I've tried the Date.today approach but had no joy as PDF reader doesn't see it as a correct filename. Here is my code so you can see what I'm trying to do:
today = Date.today
Given /^I open the saved PDF and confirm the VRM is "(.*?)"$/ do |vrm|
filename = 'C:\Users\user\Downloads\vehicle_summary_VRM_#{today}.pdf'
PDF::Reader.open(filename) do |reader|
reader.pages.each do |page|
expect(reader.page(1)).to have_content vrm
puts page.text
end
end
end
I get the following exception: input must be an IO-like object or a filename (ArgumentError)
Any ideas?
Thanks
Change single quotes in:
filename = 'C:\Users\user\Downloads\vehicle_summary_VRM_#{today}.pdf'
to double quotes:
filename = "C:\Users\user\Downloads\vehicle_summary_VRM_#{today}.pdf"

Open URLs from CSV

I am using Ruby 2.1.0p0 on Mac OS.
I'm parsing a CSV file and grabbing all the URLs, then using Nokogiri and OpenURI to scrape them which is where I'm getting stuck.
When I try to use an each loop to run through the URLs array, I get this error:
initialize': No such file or directory # rb_sysopen - URL (Errno::ENOENT)
When I manually create an array, and then run through it I get no error. I've tried to_s, URI::encode, and everything I could think of and find on Stack Overflow.
I can copy and paste the URL from the CSV or from the terminal after using puts on the array and it opens in my browser no problem. I try to open it with Nokogiri it's not happening.
Here's my code:
require 'rubygems'
require 'nokogiri'
require 'open-uri'
require 'uri'
require 'csv'
events = Array.new
CSV.foreach('productfeed.csv') do |row|
events.push URI::encode(row[0]).to_s
end
events.each do |event|
page = Nokogiri::HTML(open("#{event}"))
#eventually, going to find info on the page, and scrape it, but not there yet.
#something to show I didn't get an error
puts "open = success"
end
Please help! I am completely out of ideas.
It looks like you're processing the header row, where on of those values is literally "URL". That's not a valid URI so open-uri won't touch it.
There's a headers option for the CSV module that will make use of the headers automatically. Try turning that on and referring to row["URL"]
I tried doing the same thing and found it to work better using a text file.
Here is what I did.
#!/usr/bin/python
#import webbrowser module and time module
import webbrowser
import time
#open text file as "dataFile" and verify there is data in said file
dataFile = open('/home/user/Desktop/urls.txt','r')
if dataFile > 1:
print("Data file opened successfully")
else:
print("!!!!NO DATA IN FILE!!!!")
exit()
#read file line by line, remove any spaces/newlines, and open link in chromium-browser
for lines in dataFile:
url = str(lines.strip())
print("Opening " + url)
webbrowser.get('chromium-browser').open_new_tab(url)
#close file and exit
print("Closing Data File")
dataFile.close()
#wait two seconds before printing "Data file closed".
#this is purely for visual effect.
time.sleep(2)
print("Data file closed")
#after opener has run, user is prompted to press enter key to exit.
raw_input("\n\nURL Opener has run. Press the enter key to exit.")
exit()
Hope this helps!

Cucumber no output screen

I'm pretty new to cucumber automated testing. When I first started, a co-worker had set up everything for me on my computer, and (now that he's gone) I've run into a problem that I can't seem to figure out.
I'm using cucumber to test a web application. In the past when I run the script, an internet explorer pops up, and I can see each line of the script being executed.
I recently had to reinstall cucumber, ruby, watir, etc., and that internet explorer screen no longer pops up.
I installed Ruby 1.9.3, cucumber (gem install cucumber), watir (gem install watir). Am I missing something? Is it an extra plug in? The script still runs. However, instead of taking say 1 min + to run a 320 step script, it now takes 1.5 seconds. There are no error messages. When run from the command window, it literally looked like it just scrolled through the script instead of going through each step.
What is the pop up screen called anyways? A scenario screen? Output screen?
It was really difficult for me to look it up on google because I had no idea how to refer to that screen.
Any help is appreciated. and I realize I might not have described the problem well enough. Just leave a comment, and I can try to clarify it more.
Feature:
'To go to a webpage'
Scenario:
# ----------
# GO TO PAGE
# ----------
Given that I have gone to the Login page at "url"
#
# ----------
# LOG IN
# ----------
When I add "username" to the Username
When I add "password" to the Password
And click the Login button
Then "Welcome" should be mentioned on the page
script definitions:
require "rubygems"
require "watir"
puts "Browser is running..."
END {
puts "Closing browser..."
}
BEGIN {
puts "Starting browser..."
}
Given /^that I have gone to the Login page at "(.*)"$/ do |item|
#browser = Watir::IE.start(item)
lnk_found = 0
#browser.links.each do |lnk|
if lnk.id.to_s.matches("overridelink")
lnk_found += 1
end
end
if lnk_found > 0
#browser.link(:id, "overridelink").click
end
# puts "Watir Version: #{Watir::IE::VERSION}"
#browser.maximize
end
#
#
#
When /^I add "(.*)" to the Username$/ do |item|
#browser.text_field(:name, "loginName").set(item)
end
#
#
When /^I add "(.*)" to the Password$/ do |item|
#browser.text_field(:name, "passwd").set(item)
end
#
#
#
Then /^"(.*)" should be mentioned on the page$/ do |item|
if #browser.text.include?(item)
# puts "TEST PASSED. FOUND >#{item}<"
else
puts "*** TEST FAILED ***. >#{item}< was not found."
end
end
Directory Structure
Cucumber
Testing
lib
login.rb
login.feature
I don't know what exactly fixed it but after taking suggestions and advices from different people I basically uninstalled and reinstalled watir several times.
I also updated the code, took out "require 'rubygems'" and replaced Watir::IE.start with Watir::Browser.start.
It seems like the problem was the existing scripts I worked with was based off of older versions of watir/cucumber/ruby, so when I had to reinstall everything, the scripts were no longer compatible with newer versions of everything.

How to upload a file with watir and IE?

I am writing a watir script to test an upload form.
But the script does not automatically choose the file that is to be uploaded from my harddrive.
Instead IE stops with the file chooser dialog open. As soon as I manually select the to be uploaded file in the dialog and click ok, watir continues as desired. I wonder why it stops.
This is my watir script:
require 'test/unit'
require 'watir'
# runs on win3k, IE 6.0.3790; ruby 1.8.6, watir
class EpcHomePage < Test::Unit::TestCase
def test_upload
ie = #browser
htmlfile = "C:\\testing\\upload.html"
uploadfile = "C:\\testing\\upload.html"
ie.goto(htmlfile)
ie.file_field(:name,"file1").set(uploadfile)
assert_equal uploadfile, ie.file_field(:name,"file1").value
ie.button(:name, 'upload').click
end
def setup
#browser = Watir::IE.new
end
def teardown
#browser.close
end
end
I got the code from this page: http://wiki.openqa.org/display/WTR/File+Uploads
This is the form:
<html><body>
<form name="form1" enctype="multipart/form-data" method="post" action="upload.html">
<input type="file" name="file1">
<input type="submit" name="upload" value="ok">
</form>
</body></html>
I have found this manual http://svn.openqa.org/svn/watir/trunk/watir/unittests/filefield_test.rb also. I am using IE 6 and also IE 7for the testing.
Edit: I have uploaded my simple example here (3 files that live in c:\testing\ on my machines, just start the cmd file):
http://dl.dropbox.com/u/1508092/testing.rar
It fails on 3 different machines (all windows 2003, 2x IE 6 and 1 x IE 7). I have also changed the sleep time in the script c:\ruby\lib\ruby\gems\1.8\gems\watir-1.6.5\lib\watir\input_elements.rb from 1 second to 5 seconds, like suggested by Željko Filipin in his answer:
def set(path_to_file)
assert_exists
require 'watir/windowhelper'
WindowHelper.check_autoit_installed
begin
Thread.new do
sleep 5 # it takes some time for popup to appear
system %{ruby -e '
...
This is where it stops (please note that I did manually navigate to the directory in the file dialog once. From that point on IE always shows the open dialog with this directory, but that does not mean that the script selected the directory. I think it means that IE always shows the last directory where it left):
this is where it stops http://dl.dropbox.com/u/1508092/upload-dialog.JPG
Edit:
I found that that the ole32 code looks for the english title:
POPUP_TITLES = ['Choose file', 'Choose File to Upload']
I installed IE 7 english version now. Still no success. But I think it has something to do with the localization, because input_elements.rb searches the window titles. I wonder why it still fails now. This is the code from input_elements.rb:
class FileField < InputElement
INPUT_TYPES = ["file"]
POPUP_TITLES = ['Choose file', 'Choose File to Upload']
# set the file location in the Choose file dialog in a new process
# will raise a Watir Exception if AutoIt is not correctly installed
def set(path_to_file)
assert_exists
require 'watir/windowhelper'
WindowHelper.check_autoit_installed
begin
Thread.new do
sleep 2 # it takes some time for popup to appear
system %{ruby -e '
require "win32ole"
#autoit = WIN32OLE.new("AutoItX3.Control")
time = Time.now
while (Time.now - time) < 15 # the loop will wait up to 15 seconds for popup to appear
#{POPUP_TITLES.inspect}.each do |popup_title|
next unless #autoit.WinWait(popup_title, "", 1) == 1
#autoit.ControlSetText(popup_title, "", "Edit1", #{path_to_file.inspect})
#autoit.ControlSend(popup_title, "", "Button2", "{ENTER}")
exit
end # each
end # while
'}
end.join(1)
rescue
raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
end
click
end
end
The text "Choose file" now appears in the title of my new IE. Anything else that should be localized or changed here? I updated the screenshot to the english version.
I knew about that problem, and completely forgot! Go to input_elements.rb file in your gems directory, and add the title of the file upload window in your language to POPUP_TITLES (line 443).
Example:
before
POPUP_TITLES = ['Choose file', 'Choose File to Upload']
after
POPUP_TITLES = ['Choose file', 'Choose File to Upload', 'File upload in my language']
I installed windows xp in english now, and it works! (The error occured on a localised windows server 2003)
I guess it was the localisation issue. I will just run watir on the english computer from now on.
I had the same problem today (March1,2012) and landed here via Google.
Thanks Željko for pointing me in the right direction, however the solution of changing the [POPUP_TITLES] didn't work. In fact, this array seems not to exist anymore in the current version of the gem (watir-2.0.4), or maybe I just misread.
I solved the problem in watir-2.0.4/lib/watir/dialogs/file_field.rb:
Here, the various window and button titles are defined as regular expressions. Change the regexps in the following methods
open_button()
cancel_button()
file_upload_window()
to match your localized window names. After reloading the gem, it worked flawlessly.
I would suggest that you take a look at FileField#set in input_elements.rb (in your Ruby gems directory), and change sleep 1 to sleep 2 (or some higher number). I have noticed that on slower machines it takes more than a second for file upload pop up to appear.
#modal = #browser.driver.switch_to.alert #Switch to open windows modal
key_to_send = "C:\\Users\\singhku\\Calabash_doc.pdf" #Path and name of file
#modal.send_keys(key_to_send)
require 'win32ole'
wsh = WIN32OLE.new('Wscript.Shell')
wsh.AppActivate('Choose File to Upload') #Name of the modal that is open
wsh.SendKeys('{ENTER}')

Resources