Selenium with Ruby - cannot access HTML elements that I want - ruby

I am following SauceLab's Ruby and Selenium guidebook - it's a free book to help teach Selenium in combination with Rspec. In the first real example of the book, the author leads us to write a test script that goes to this link:
http://the-internet.herokuapp.com/login
Our script then will insert the appropriate uname and pwd (listed in text on the page... it's tomsmith and SuperSecretPassword!), and then submit the form.
All of the above works - then it goes a little further and looks to introduce an assert to ensure that we got to the correct page (the page that results from successful login). This assert, even when I do as per the example in the book, does not work. It can't find the element, and says so as here:
Failure/Error: expect(#driver.find_element(css: '.flash.success').displayed?)
Selenium::WebDriver::Error::NoSuchElementError:
Unable to locate element: .flash.success
# ./ruby_spec.rb:20:in `block (2 levels) in <top (required)>'
I was hoping I could get some help from SO in helping me formulate a working assert to ensure I'm on the login page after successful login via test script. Here is my code so far
require 'selenium-webdriver'
describe 'Login' do
before(:each) do
#driver = Selenium::WebDriver.for :firefox
end
after(:each) do
#driver.quit
end
it 'test_to_succeed' do
#driver.get 'http://the-internet.herokuapp.com/login'
#driver.find_element(id: 'username').send_keys('tomsmith')
#driver.find_element(id: 'password').send_keys('SuperSecretPassword!')
#driver.find_element(id: 'login').submit
expect(#driver.find_element(css: '.flash.success').displayed?) #line that fails every run
end
end
Minus a little revised rspec syntax, this is exactly as what is listed in the book. The book has for the failing line as below, with some deprecated syntax:
#driver.find_element(css: '.flash.success').displayed?.should be_true
But this also fails with the exact same error above. To further suss out it being my expect(), I have tested the expect() syntax for other elements to test that it is working/not the source of the problem. The source of the problem, instead, is that my script is not resolving the css element as the book indicates it would be able to. It can't find '.flash.success', in loose terms.
So I went to page source of the successful login page and found some other things I could assert against. This came as attractive since it is unique to the success page:
<div data-alert id='flash' class='flash success'>
You logged into a secure area!
×
</div>
But alas, I found the exact same failures when trying this in my code:
expect(#driver.find_element(class: 'flash success').displayed?) #line that fails every run
or even
expect(#driver.find_element(id: 'flash').displayed?) #line that fails every run
Essentially, I'm a little mystified how I am supposed to get a unique element off of the successful login page to assert correctly. All the efforts above (including the one in the sample text that I'm learning from) would seem reasonable to work, to me... but it is not so. Rather than simply switching texts to one with working examples, I thought it would be more instructive for me to work out and try to discover why the examples above do not work.

Related

verify text in selenium ruby

I have an issue with verifying text in selenium webdriver and Ruby.
Aim: Verify that the sentence 'Registration Form' is valid on the website.
I have the below code:
if /registration Form/.match(driver.page_source)
puts "Test Passed".green
else
puts "Test Failed".red
end
This code will output "Test Failed" even though the text is present. I have noticed if I only search for one word E.G. 'Registration' the test will pass, but my code needs to check for more than one word.
Additional question:
In addition, this may be a rather simple question to answer, but even when my test fails with "Test Failed" in Cucumber, my result is actually passed. Does anyone know how I could get the actual Cucumber test to fail via an extra line of code?
Thank you for the help.

My Cucumber script doesn't seem to be picking up my Ruby script

I am very new to Cucumber and Ruby, so please forgive me if what I'm missing seems simple. I'm able to run my Cucumber script, and it gives me the following result:
Feature: guru99 Demopage Login
In order to Login in Demopage we have to enter login details
Scenario: Register On Guru99 Demopage without email # test.feature:5
Given I am on the Guru homepage # test.feature:7
When enter blank details for Register # test.feature:9
Then error email shown # test.feature:11
1 scenario (1 undefined)
3 steps (3 undefined)
0m0.040s
You can implement step definitions for undefined steps with these snippets:
Given(/^I am on the Guru homepage$/) do
pending # Write code here that turns the phrase above into concrete actions
end
When(/^enter blank details for Register$/) do
pending # Write code here that turns the phrase above into concrete actions
end
Then(/^error email shown$/) do
pending # Write code here that turns the phrase above into concrete actions
end
This is expected. However, when I add my .rb file which contains:
require 'watir-webdriver'
require 'colorize'
browser = Watir::Browser.new
Given(/^I am on the Guru homepage$/) do
pending # Write code here that turns the phrase above into concrete actions
end
When(/^enter blank details for Register$/) do
pending # Write code here that turns the phrase above into concrete actions
end
Then(/^error email shown$/) do
pending # Write code here that turns the phrase above into concrete actions
end
Running the Cucumber script returns the exact same result as it did before. I have everything in a folder called "features" and the .rb file is in a subfolder of that called step_definitions. What am I doing wrong? I can't seem to find an answer online, so any help at all will be greatly appreciated!
Since your feature files and step definitions are in features folder, try to run cucumber with --require features option.

#driver.find_element(:id=>"body").text.include?(textcheck) not verifying the text only the id

I am using Selenium-WebDriver for Ruby and I am trying to verify that text is present on a page. I have done many searches and tried many things and the best answer I have found is to use something like
def check_page(textcheck)
if verify {#driver.find_element(:id=>"body").text.include?(textcheck)}
yield it_to "fail"
else
yield it_to "pass"
end
end
The expected outcome if the value of textcheck is present in the body would be pass and if the value of textcheck is not present in the body it would be fail. What is actually happening is if :id=>"body" is present then it is pass and if it is not present then it is fail regardless of .text.include?(textcheck)
If anyone could point me in the right direction for how to verify text is present on a page using Selenium-WebDriver in Ruby it would be greatly appreciated. I have found workarounds for certain cases where I can do
verify {#driver.find_element(:tag_name, 'h1').text!=(textcheck)}
but the element I am trying to verify I can't get to so easily. I looked into css locators and was very confused on how to simplify the tag so I could use it. Any help would be greatly appreciated. Thank you very much. If you require any more information from me please let me know and I will provide it as soon as possible.
I am using Ruby 1.93 with Selenium-WebDriver 2.25 testing in Firefox 14.0.1
I do it this way
#wait = Selenium::WebDriver::Wait.new(:timeout => 30)
begin
#wait.until { #driver.find_element(:tag_name => "body").text.include?("your text")}
rescue
puts "Failure! text is not present on the page"
#Or do one of the options below
#raise
#assert_match "true","false", "The text is not present"
end
UPDATE
Answer to your question in the comments section.
There are two kind of "waits", implicit wait and explicit wait. You can read more about it here. The reason your code failed was because you were searching by "id"=>"body" and not by "tag_name"=>"body". Usually all text is encompassed within the "body" HTML tags in your DOM.

StaleElementReferenceError with Selenium with content already loaded

I'm using Capybara with Ruby 1.9.3 using the selenium driver in order to get information off a website. After clicking through a couple of pages I visit the page I want and I put:
all(:css, 'td').each { |td| a_info << td }
a_info.each {|t| puts t.text }
The error I then get after about 10 seconds of waiting:
[remote server] resource://fxdriver/modules/web_element_cache.js:5628:in `unknown': Element not found in the cache - perhaps the page has changed since it was looked up (Selenium::WebDriver::Error::StaleElementReferenceError)
Followed a lot more remote server errors. I've given the page 10-30 seconds of sleep time and it's still not loading and when I do print page.html, I see a javascript script and then all the td's that I'm trying to get info from. I know that the error means an element being found is not the current one but it seems like all the elements have been loaded already so I'm not sure why they wouldn't exist anymore. I've scoured the internet for hours looking for this and would love any kind of help from possible solutions to try and the next steps for trying to figure it out. I can provide any extra information needed, just let me know.
It happens when you make a scope and into that you change the page, for example, but keeps making assertions inside it, like the following:
within 'selector' do
expect(page).to have_link 'Link'
visit 'page'
expect(page).to have_link 'I do not know this whitin, I am stale.'
find('I do not know this within, I am stale.').click
end
Just reopen you scope again over to keep working on the old one.
within 'selector' do
expect(page).to have_link 'Link'
end
visit 'page'
within 'selector' do
expect(page).to have_link 'Now i am fresh'
find('#now-i-am-fresh').click
end
This is my least favorite error. I'm gonna refer you to this exact question on stack overflow asked about a year before Random "Element is no longer attached to the DOM" StaleElementReferenceException
In presented code you are printing text on console, but maybe in your real code you are clicking on these links inside each loop which is wrong.
Solution
Try first to extract href attributes and then go through them in loop.
Code:
a_href = a_node.collect {|a| a[:href] }
a_href.each { |a| visit(a) }
I'm not sure if it fits to your situation, give more info in comments.

How to handle security alert in Firefox with Selenium

I'm using selenium-webdriver with ruby to write automated tests.
Chrome and the chromedriver binary work really well, but I have an issue with Firefox that is related to the configuration of the browser and that's making my tests fail, whereas they pass with Chrome.
When executing the tests in Firefox, sometimes I get an alert with this message:
Although this page is encrypted, the information you have entered is
to be sent over an unencrypted connection and could easily be read by
a third party
And it breaks the execution. Is there a way of disabling this warning in recent Firefox versions (10+) or handling this behavior with Selenium?
In the process of finding a solution for this, I think I might have found a bug in Capybara (v1.1.2).
I managed to get around this problem using the following approach, instead of using the click from capybara (which would not allow me to capture an exception), I started using the click method from selenium-webdriver.
It seems that when Firefox triggers this alertbox, a string with the message
Although this page is encrypted, the information you have entered is
to be sent over an unencrypted connection and could easily be read by
a third party
is returned as a result of object.native.click, otherwise the string
ok
is returned.
# Define the click method in ruby and call it when you're executing a 'click'
# Public: Click the object.
#
# object - Capybara::Node::Element object to click.
def click object
return_string = object.native.click
check_firefox_alertbox if return_string == "ok"
end
def check_firefox_alertbox
if #current_browser == :firefox
#session.driver.browser.switch_to.alert.accept
end
rescue Exception => e
puts e
end
Here is what you can do. Type about:config in the firefox. You would be presented a number of options (once you pass through a warning message).
You have to look for security.warn_leaving_secure; and security.warn_leaving_insecure. Make both of them false. And you would be good to go.
Please note: This would work only on the FF instance you have made modification to, so you will need to use firefox profile to launch this instance.
Hope this helps.
Actually this meant to be a comment but I need to go above 50 in order to be able to comment..I suppose by 'breaking' the execution you mean that of the Ruby Script right? What happens to Firefox? Needs a click to proceed? If that is the case you can improvise by capturing the Ruby error after inserting the sensitive code (where it breaks) between a BEGIN and a RESCUE clause..Something like this..
BEGIN
.
.
Code that is giving you a headache
.
.
RESCUE
.
Capture the exception and give Ruby a chance to continue the script normally.
.
.
END
Alternatively if you don't fancy the above solution you can go to Firefox and then type in the address box about:config. Filter by 'security.warn' and set to false all the boolean variables you see there. Good riddance, fingers crossed ;)

Resources