Command to use instead of sleep() in Calabash - ruby

I am using calabash automation with Ruby for my project in iOS.
scenario/Ruby:
Given(/^I click Login$/) do
homePage = page(HomePage)
homePage.loginButton()
sleep(3)
end
When(/^I enter valid credentials$/) do
loginPage = page(LoginPage)
loginPage.enterEmailaddress()
loginPage.enterPassword()
loginPage.done()
sleep(3)
loginPage.loginButton()
sleep(5)
end
As you can see I am using sleep() many times
Is there any other command that can be used instead of sleep()

You might be looking for the await method:
The await method just returns the page object after waiting for the
page to be loaded
As always, read the docs.
https://github.com/calabash/x-platform-example#step-2---step-definitions

Related

Continue execution in Cucumber in case of any errors

I'm building an automation suite using Ruby/Selenium-WebDriver/Cucumber. What I want to achieve is to resume the cucumber scenario in case of any unexpected errors.
For e.g. Unexpected pop-ups
I might get a modal dialog at any point in the application. I want my code to close the pop-ups whenever the exception occurs and resume the execution.
The point of doing this is, the automation suite will run for multiple days on multiple systems. There won't be any kind of monitoring except logs and output reports. I don't want these unwanted exception to hamper the execution.
Given that the alerts can be opened at any time, the best option may be to use an AbstractEventListener. This allows you to perform actions before (or after) Selenium interacts with the browser. This means that you could call your alert closing code right before each interaction.
The sample event listener would be defined like:
class AlertListener < Selenium::WebDriver::Support::AbstractEventListener
def close_alerts(driver)
# Assuming you want to handle the dialogs using Watir code instead of Selenium,
# convert the Selenium::WebDriver to a Watir::Browser
browser = Watir::Browser.new(driver)
# Run whatever code you have for handling the dialog instances
browser.alert.ok if browser.alert.exists?
end
def before_change_value_of(element, driver)
close_alerts(driver)
end
def before_click(element, driver)
close_alerts(driver)
end
def before_close(driver)
close_alerts(driver)
end
def before_execute_script(script, driver)
close_alerts(driver)
end
def before_find(by, what, driver)
close_alerts(driver)
end
def before_navigate_back(driver)
close_alerts(driver)
end
def before_navigate_forward(driver)
close_alerts(driver)
end
def before_navigate_to(url, driver)
close_alerts(driver)
end
def before_quit(driver)
close_alerts(driver)
end
end
Note that you would replace the close_alerts method with whatever code you have already written for handling the alerts. The event listener is Selenium, which means you need to either write Selenium code or convert the element/driver to Watir (which is what is done in the example).
Once you have the listener created, you need to pass it to the browser during initialization:
listener = AlertListener.new
browser = Watir::Browser.new :chrome, :listener => listener
You could get your goal by accepting any alert that pops up on the screen.
You can do this in following steps:
Given(/^I should see the error message and accept it$/) do
def alert_accept
end
end
So whenever there is a popup it will accept it and continue forward.
You can find this step as well here:
https://github.com/ModusCreateOrg/cucumber-watir/blob/appium/features/step_definitions/appium_steps.rb

Why do I need to add sleep for rspec to pass with selenium 2.48.0?

Recently we upgraded our selenium web driver from 2.47.1 to 2.48.0.
With this upgrade I need to add sleep for a few seconds in rspec to pass. Spec was working properly without sleep with the older version.
sleep(inspection_time=5) // why do I need this?
my_form_page.save_button.click
// some assertion here
Edit
I tried using implicit wait instead of sleep.But it's not working. Is there any specific reason behind it?
Capybara.current_session.driver.browser.manage.timeouts.implicit_wait = 50
Generally speaking, rspec selenium tests are known to be "flakey". Sometimes rspec tries to search for an element before it appears on page due to many reasons (ie: element appears upon ajax response).
Here's a tip that may help you solve this, if you will wrap your capybara finders inside of a within block, your tests will wait until it finds that within selector FIRST before trying to run the code inside of it.
This more-often-than-not will help solve a test running too fast on a page that takes a while to load and your button or selector or whatever isn't actually on the page yet (which is why it fails).
So take a look at these 2 examples and try the within method...
# spec/features/home_page_spec.rb
require "spec_helper"
describe "the home page", type: :feature do
context "form" do
# THIS MIGHT FAIL!!!!
it "submits the form", js: true, driver: :selenium do
visit "/"
find("#submit_button").click
end
# THIS PROBABLY WILL PASS!!!
it "submits the form", js: true, driver: :selenium do
visit "/"
within "form" do
find("#submit_button").click
end
end
end
end

I'm using the Selenium Webdriver gem to try to click on the facebook chat bar, sometimes it work and sometimes it doesn't

I'm using the Selenium Webdriver gem to try to click on the facebook chat bar, sometimes it work and sometimes it doesn't. When it does not work it returns the Selenium Element not visible error, but it clearly is visible. I'm not sure what's wrong with my code.
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :chrome # instantiates a google chrome session
driver.navigate.to 'https://www.facebook.com/' # takes you to facebook.com
emailBar = driver.find_element(:id,"email") #finds email input bar
passwordBar = driver.find_element(:id,"pass") #find password input bar
loginButton = driver.find_element(:id,"u_0_n") #finds login button
emailBar.send_keys "austinspreadsheet#gmail.com" # puts in the email
passwordBar.send_keys "YOURPASSWORD" # puts in the password
loginButton.click # clicks the login button
#THIS IS THE CODE BLOCK THAT DOES NOT WORK
links = driver.find_elements(:class,"fbNubButton") # finds the chat bar
#driver.manage.timeouts.page_load = 10
links[0].click # opens the chat bar
links[1].click # NOTE that sometime it clicks and sometimes it doesn't but if you click both chat box classes it usually works, so the error is ok
I have tried not clicking both chat links and it works less when I do that.
I am using Selenium with Python. In case like yours the issue is related to waiting until all the elements in the page are full loaded.
The basic behavior of Selenium offers you Explicit and Implicit Waits. So basicly you can force the system to wait a default number of second or wait until an element is loaded.
From Selenium documentation (http://docs.seleniumhq.org/docs/04_webdriver_advanced.jsp)
Explicit wait
An explicit waits is code you define to wait for a certain condition to occur before proceeding further in the code. The worst case of this is Thread.sleep(), which sets the condition to an exact time period to wait. There are some convenience methods provided that help you write code that will wait only as long as required. WebDriverWait in combination with ExpectedCondition is one way this can be accomplished.
require 'rubygems' # not required for ruby 1.9 or if you installed without gem
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
driver.get "http://somedomain/url_that_delays_loading"
wait = Selenium::WebDriver::Wait.new(:timeout => 10) # seconds
begin
element = wait.until { driver.find_element(:id => "some-dynamic-element") }
ensure
driver.quit
end
Implicit wait
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
require 'rubygems' # not required for ruby 1.9 or if you installed without gem
require 'selenium-webdriver'
driver = Selenium::WebDriver.for :firefox
driver.manage.timeouts.implicit_wait = 10 # seconds
driver.get "http://somedomain/url_that_delays_loading"
element = driver.find_element(:id => "some-dynamic-element")
The answer that aberna gives you on this thread has a lot of great information but it isn't going to solve your issue. If you use the Explicit wait method that aberna suggests, you also probably need to make sure the element is visible. Using .findElements on its own doesn't guarantee clickability/visibility . You could try to use expectedconditions .visibilityOfElementLocated which will also check for visibility as well as presence.
Or, alternatively, you can check for presence of the element on the DOM using .findElement but then use the expectedconditions.visibilityOf to check for the visibility part of it.
I am using sleep(5) before run main logic
I was facing the same issue. Solution that worked for me was to maximise my browser window. This solved many of failing specs.
Capybara.current_session.driver.browser.manage.window.maximize

Disable puts output in RSpec

I got a ProgressBar with some logs, and it is being displayed on each iteration. When I run RSpec, I'd like that only the results to get displayed (only . or f, and not the output that my app may display).
Between, I'm not using rails, so I don't have environments.
I got this:
And I want this:
My code is deadly simple:
progress_bar = ProgressBar.create(:total => nil)
progress_bar.increment
progress_bar.log "New Page added on depth #{depth}! #{url}"
any_instance is deprecated since RSpec 3.
Also the ProgressBar inner classes seem to have changed. This did it for me :
before(:each) do
allow_any_instance_of(ProgressBar::Output).to receive(:stream).and_return(double().as_null_object)
end
Just stub logging in tests:
ProgressBar.any_instance.stub(:log)
if there are more than 1 test for this action, put it in before(:each):
before(:each) do
ProgressBar.any_instance.stub(:log)
end
If you use progressbar gem, it will create ProgressBar::Base instance, so you should use:
ProgressBar::Base.any_instance.stub(:log)

How to handle Watir::Exception::UnknownObjectException:

I'm using watir to automate the deleting of elements using a while loop, but when the scripts reaches the end it errors out since the element that the while loop is dependent on is no longer visible. Is there anyway to have Watir carry on with the test?
Here is an example of my code:
class Delete_element
def org_roster_remove
parameters = Tt_parameters.new
driver = Login.new.log_in(parameters.username3, parameters.password3)
while driver.a(:data_class, 'home.group.edit_group_btn').visible? == true
driver.p(:data_class, 'home.conv.messagePreview').hover
sleep(1)
driver.div(:class, 'delete').click
sleep(1)
driver.a(:data_class, 'home.conv.deleteFromRoster_btn').click
sleep(1)
end
driver.quit
end
end
This is the error:
Watir::Exception::UnknownObjectException: unable to locate element, using {:data_class=>"home.group.edit_group_btn", :tag_name=>"a"}
I would use .present? instead of .visible?
Also consider using .wait_until_visible instead of sleeping. See Watir-webdriver Waiting.
Additionally, investigate a page object framework such as Cheezy's page-object gem

Resources