Is it possible to navigate back in browser with watir? - ruby

I'm creating an automated tests that should navigate back a few steps.
Is it possible to do so in Watir??
I'm navigating to a resultlist page and want to go back to the start of my test just by clicking back (windows browser).
Thnx

If you have a Watir::IE object, then #back is a method that does what you are looking for:
http://wtr.rubyforge.org/rdoc/classes/Watir/IE.html#M000245
What error are you seeing?

This is how i tried to do it:
#site.ie.wait_until(1200) { |ie| ie.contains_text(/Sort after/) }
2.times{#site.ie.back
}

Example code that uses Watir's #back call (based on the standard Wikipedia example):
require 'watir'
test_site = 'http://www.google.com/'
ie = Watir::IE.new
ie.goto(test_site)
ie.text_field(:name, "q").set("pickaxe")
ie.button(:name, "btnG").click
if ie.text.include?("Programming Ruby")
puts "Test Passed. Found the test string: 'Programming Ruby'."
else
puts "Test Failed! Could not find: 'Programming Ruby'."
end
ie.back
if ie.url == test_site
puts "Test Passed. Returned to search page."
else
puts "Test Failed! URL is now #{ie.url}."
end
ie.close

You certainly can execute JavaScript using Watir.
#browser.execute_script('window.history.back();')

Related

Unexpected behaviour when using TTY-Prompt

require 'tty-prompt'
def landing_page
prompt = TTY::Prompt.new
choices = ["Create", "Update", "Delete", "Quit"]
answer = prompt.multi_select("Select", choices)
case answer
when choices[0]
puts "works"
else
puts "doesn't work"
sleep(1)
self.landing_page
end
end
landing_page
It's my first time trying to make a terminal app using TTY-Prompt. I'm trying to test the ^above piece of code and expect it to return "works" when the user selects "Create" from the list but it doesn't. Am I missing something?
EDIT: Answer is replace multi_select with select. Thanks to Stefan for clearing that up.

Launch a web url on link click - Ruby Shoes 3

How would I go about launching a web url e.g. https://google.com after clicking a link on Ruby shoes 3?
I used the below code to no effect
flow do
###
para link("some text", click: proc {
visit "https://google.com"
})
###
end
And
flow do
###
para link "some text" do visit "https://google.com" end
###
end
Could someone show me how please?
Try this
flow do
para(link("some text", :click => "https://google.com"))
end
Fixed the link using the method provided on this question
flow do
proc = Proc.new {
system("cmd /c start https://google.com")
}
para link("some text", &proc)
end
Any further suggestions before I close this is welcome.

Can I test that a Sinatra post method successfully saves to a YAML store?

I can't find a basic explanation anywhere about how I can test, with Rack::Test, that a Ruby/Sinatra post method successfully saves data to a YAML store/file. (This explains testing get, which I can do(!), but not post; other mentions of testing post methods with rack/test seem irrelevant.) For self-study, I'm building a "to do" app in Ruby/Sinatra and I'm trying to use TDD everything and unit test like a good little boy. A requirement I have is: When a user posts a new task, it is saved in the YML store.
I was thinking of testing this either by seeing if a "Task saved" was shown in the response to the user (which of course isn't directly testing the thing itself...but is something I'd also like to test):
assert last_response.body.include?("Task saved")
or by somehow testing that a test task's description is now in the YML file. I guess I could open up the YML file and look, and then delete it from the YML file, but I'm pretty sure that's not what I'm supposed to do.
I've confirmed post does correctly save to a YML file:
get('/') do |*user_message|
# prepare erb messages
#user_message = session[:message] if session[:message]
#overlong_description = session[:overlong_description] if
session[:overlong_description]
session[:message] = nil # clear message after being used
session[:overlong_description] = nil # ditto
#tasks = store.all
erb :index #, user_message => {:user_message => params[:user_message]}
end
post('/newtask') do
#task = Task.new(store, params)
# decide whether to save & prepare user messages
if #task.complete == true # task is complete!
#task.message << " " + "Task saved!"
session[:message] = #task.message # use session[:message] for user messages
#task.message = ""
store.save(#task)
else
#task.message << " " + "Not saved." # task incomplete
session[:message] = #task.message # use session[:message] for user messages
session[:overlong_description] = #task.overlong_description if
#task.overlong_description
#task.message = ""
#task.overlong_description = nil
end
redirect '/'
end
As you can see, it ends in a redirect...one response I want to test is actually on the slash route, not on the /newtask route.
So of course the test doesn't work:
def test_post_newtask
post('/newtask', params = {"description"=>"Test task 123"})
# Test that "saved" message for user is in returned page
assert last_response.body.include?("Task saved") # boooo
end
Github source here
If you can give me advice on a book (chapter, website, blog, etc.) that goes over this in a way accessible to a relative beginner, I'd be most grateful.
Be gentle...I'm very new to testing (and programming).
Nobody answered my question and, since I have figured out what the answer is, I thought I would share it here.
First of all, I gather that it shouldn't be necessary to check if the data is actually saved to the YAML store; the main thing is to see if the web page returns the correct result (we assume the database is groovy if so).
The test method I wrote above was correct; it was simply missing the single line follow_redirect!. Apparently I didn't realize that I needed to instruct rake/test to follow the redirect.
Part of the problem was that I simply hadn't found the right documentation. This page does give the correct syntax, but doesn't give much detail. This page helped a lot, and this bit covers redirects.
Here's the updated test method:
def test_post_newtask
post "/newtask", params = {"description" => "Write about quick brown foxes",
"categories" => "writing823"}
follow_redirect!
assert last_response.body.include?("Task saved")
assert last_response.body.include?("Write about quick brown foxes")
end
(With thanks to the Columbus Ruby Brigade.)

How to put asserts in Selenium webdriver Ruby script?

I wish to check value on UI with the provided value in script. And on comparing these two, it should display message "test passed" in console.
I have written following code: -
browser.find_element(:xpath,"//*[#id="total"]/tbody/tr/td[4]/span").value.should == "$466,634,599.67"
But it does not display anything on console. What could be required next?
Thanks!
Abhishek
Assertions, eg the .should==, are typically used within a test framework such as RSpec, MiniTest, Cucumber, etc. These test frameworks are designed to have reporting of the assertion's pass or fail result.
Given that you are not using a test framework, you will need to manually handle the output of results.
The most straightforward way would be to drop the assertion part and use an if statement:
element_value = browser.find_element(:xpath,"//*[#id="total"]/tbody/tr/td[4]/span").text
if element_value == "$466,634,599.67"
puts 'Test passed'
else
puts 'Test failed'
end
Note that the puts statements are used to output results to the console (unless you have changed the default output location).
Alternatively, if you do want to use the assertion, you could do:
element_value = browser.find_element(:xpath,"//*[#id="total"]/tbody/tr/td[4]/span").text
element_value.should == "$466,634,599.67"
puts 'Test passed'
In this approach, the assertion will raise an exception if the test fails. The assertion would stop the execution of the code and would therefore not output the 'Test passed' message (as expected). If the test passes, the 'Test passed' message would get outputted.
I use capybara gem for this purpose. It can check almost all front-end possibilities.
Code should look something like this:
describe "User pages" do
subject { page }
describe "index" do
before(:each) do
sign_in user
visit users_path
end
it { expect(page).to have_selector('li', text: user.name) }
end

Element not found in the cache - perhaps the page has changed since it was looked up in Selenium Ruby web driver?

I am trying to write a crawler that crawls all links from loaded page and logs all request and response headers along with response body in some file say XML or txt. I am opening all links from first loaded page in new browser window so I wont get this error:
Element not found in the cache - perhaps the page has changed since it was looked up
I want to know what could be the alternate way to make requests and receive response from all links and then locate input elements and submit buttons form all opened windows.
I am able to do above to some extent except when opened window has common site searh box like one on this http://www.testfire.net in the upper right corner.
What I want to do is I want to omit such common boxes so that I can fill other inputs with values using i.send_keys "value" method of webdriver and dont get this error
ERROR: Element not found in the cache - perhaps the page has changed since it was looked up.
What is the way to detect and distinguish input tags from each opened window so that value does not get filled repeatably in common input tags that appear on most pages of website.
My code is following:
require 'rubygems'
require 'selenium-webdriver'
require 'timeout'
class Clicker
def open_new_window(url)
#driver = Selenium::WebDriver.for :firefox
#url = #driver.get " http://test.acunetix.com "
#link = Array.new(#driver.find_elements(:tag_name, "a"))
#windows = Array.new(#driver.window_handles())
#link.each do |a|
a = #driver.execute_script("var d=document,a=d.createElement('a');a.target='_blank';a.href=arguments[0];a.innerHTML='.';d.body.appendChild(a);return a", a)
a.click
end
i = #driver.window_handles
i[0..i.length].each do |handle|
#driver.switch_to().window(handle)
puts #driver.current_url()
inputs = Array.new(#driver.find_elements(:tag_name, 'input'))
forms = Array.new(#driver.find_elements(:tag_name, 'form'))
inputs.each do |i|
begin
i.send_keys "value"
puts i.class
i.submit
rescue Timeout::Error => exc
puts "ERROR: #{exc.message}"
rescue Errno::ETIMEDOUT => exc
puts "ERROR: #{exc.message}"
rescue Exception => exc
puts "ERROR: #{exc.message}"
end
end
forms.each do |j|
begin
j.send_keys "value"
j.submit
rescue Timeout::Error => exc
puts "ERROR: #{exc.message}"
rescue Errno::ETIMEDOUT => exc
puts "ERROR: #{exc.message}"
rescue Exception => exc
puts "ERROR: #{exc.message}"
end
end
end
#Switch back to the original window
#driver.switch_to().window(i[0])
end
end
ol = Clicker.new
url = ""
ol.open_new_window(url)
Guide me how can I get all requeat and response headers with response body using Selenium Webdriver or using http.set_debug_output of ruby's net/http ?
Selenium is not one of the best options to use to attempt to build a "web-crawler". It can be too flakey at times, especially when it comes across unexpected scenarios. Selenium WebDriver is a great tool for automating and testing expectancies and user interactions.
Instead, good old fashioned curl would probably be a better option for web-crawling. Also, I am pretty sure there are some ruby gems that might help you web-crawl, just Google search it!
But To answer the actual question if you were to use Selenium WebDriver:
I'd work out a filtering algorithm where you can add the HTML of an element that you interact with to an variable array. Then, when you go on to the next window/tab/link, it would check against the variable array and skip the element if it finds a matching HTML value.
Unfortunately, SWD does not support getting request headers and responses with its API. The common work-around is to use a third party proxy to intercept the requests.
============
Now I'd like to address a few issues with your code.
I'd suggest before iterating over the links, add a #default_current_window = #driver.window_handle. This will allow you to always return back to the correct window at the end of your script when you call #driver.switch_to.window(#default_current_window).
In your #links iterator, instead of iterating over all the possible windows that could be displayed, use #driver.switch_to.window(#driver.window_handles.last). This will switch to the most recently displayed new window (and it only needs to happen once per link click!).
You can DRY up your inputs and form code by doing something like this:
inputs = []
inputs << #driver.find_elements(:tag_name => "input")
inputs << #driver.find_elements(:tag_name => "form")
inputs.flatten
inputs.each do |i|
begin
i.send_keys "value"
i.submit
rescue e
puts "ERROR: #{e.message}"
end
end
Please note how I just added all of the elements you wanted SWD to find into a single array variable that you iterate over. Then, when something bad happens, a single rescue is needed (I assume you don't want to automatically quit from there, which is why you just want to print the message to the screen).
Learning to DRY up your code and use external gems will help you achieve a lot of what you are trying to do, and at a faster pace.

Resources