Skip to content

krupani/web-object

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

web-object

Create page-object style test framework using original webdriver flavor. Now what does original webdriver flavor is, it simply means, no additional wrappers, no additional syntax. Hence just create page-objects and start using basic webdriver commands on it.

Moral of the story, elements created using web-object gem will be objects of WebElement class and one can perform all webdriver commands on it like send_keys, click, displayed? .. and so on...

WebObject gem is completely compatible with Appium and can also be used for ruby-appium frameworks, to sound a little more mobile-like, WebObject class has an alias called AppObject to be used instead PageObjects in case of Mobile frameworks..

Table of Contents

Installation 👀

There are multiple ways in which you can install and use web-object gem. You must have Ruby installed before you can install this gem.

Just use following command from you Terminal.

gem install web-object 

You can include it in your Gemfile and run bundle install

gem 'web-object' 

then run following

bundle install   

Syntax 👀

To use web-object, you need to extend your page class with web-object

1. Finding Element

Syntax
element :name_of_element, {:locator_strategy => "locator value"}
or
find :name_of_element, {:locator_strategy => "locator value"}, error=false

Eg:

element :login_email, {:id => "email"}   
element :login_password, {:css => "#pwd"}   
element :login_button, {:xpath => "//button[@id='signin']"}   

or

find :login_email, {:id => "email"}   
find :login_password, {:css => "#pwd"}   
find :login_button, {:xpath => "//button[@id='signin']"}

Returns an object of WebElement.
Raise an exception by default if element is not found.
Will return Boolean false if error=false parameter is explicitly passed and element is not found.

Eg of error handling as mentioned above:

1) element :login_button, {:id => 'signIn'}
2) element :profile_link, {:css => '.user_profile'}, error=false
   
# Example 1 will raise element not found exception if element not found on the page   
# Example 2 will just return a Boolean false if element not found on the page   

2. Finding Multiple Element

Syntax
elements :name_of_element, {:locator_strategy => "locator value"}
or
all :name_of_element, {:locator_strategy => "locator value"}, error=true
or
element_list :name_of_element, {:locator_strategy => "locator value"}

Eg:

elements :product_prices, {:id => "prices"}   
elements :active_users, {:css => ".users>#active"}, error=true    

or

element_list :product_prices, {:id => "prices"}   
element_list :active_users, {:css => ".users>#active"}   

or

all :product_prices, {:id => "prices"}   
all :active_users, {:css => ".users>#active"}   

Returns an array of WebElement objects.
Return an empty array in element is not found by default.
Will raise an error if error=true parameter explicitly passed and element is not found.

Eg of error handling as mentioned above:

1) elements :names, {:id => 'names'}, error=true
2) elements :header_tabs, {:css => '.menu-item'}
   
# Example 1 will raise element not found exception if element not found on the page   
# Example 2 will just return an empty array if element not found on the page   

3. Syntax Summary :

  • error parameter is completely optional and web-object will continue to work as before.
  • Default behaviour will now match the same as webdriver.
  • Finding single element will raise an exception by default if element not found on the page.
  • Finding multiple elements will return a blank array by default if element not found on the page.
  • error parameter is used only to reverse the natural default behaviour.
  • Finding single element will return Boolean false if error paramter is sent as false and element not found on the page.
  • Finding multiple elements will raise exception if error paramter is sent as true and element not found on the page.

Usage 👀

Now as we saw how to create page objects, lets see how to put it to practical use.

Web Usage

class LoginPage < WebObject
  element :login_email, {:id => "email"}   
  element :login_password, {:css => "#pwd"}   
  element :login_button, {:xpath => "//button[@id='signin']"}   
  elements :active_users, {:css => ".users>#active"} 
  
  def login_to_portal(email,pwd)  
    login_email.send_keys(email)  
    login_pwd.send_keys(pwd)  
    login_button.click  
  end  
    
  def get_active_user_count   
    active_users.size
  end
end  

App or Mobile Usage

class LoginScreen < AppObject
  element :username_field, {accessibility_id: "username"}
  element :password_field, {predicate: 'name=="password"'}
  element :login_button, {class_chain: "**/XCUIElementTypeButton[`value=='Log In'`]"}
end

WebConditions 👀

Always envied the fancy ExpectedConditions class which Java and Python has where they smoothly pass a condition within the WebDriver explicit wait object... And when it comes to Ruby, you need to go through a painfully lenghty procudere of creating your own method or fallback to other framweworks like Capybara or Watir loosing the original WebDriver flavor.

Well, not to worry as web-object gem to the rescue.

web-object gem is now equipped with an extensive list of WebConditions (we do not want to be called people who copied the name from Java so we call it WebConditions). It can be used for both waiting for a particular condition inside the wait.until object and also in rspec assertions.

How to use it then: here is how:

wait = Selenium::WebDriver::Wait.new(:timeout => 30)
wait.until{alert_present?}

or

wait = Selenium::WebDriver::Wait.new(:timeout => 30)    # Create wait object
wait.until{element_is_visible(element)}                 # Pass a condition with web element parameter 
wait.until{element_is_invisible(:id => 'some_button')}  # or just pass a condition with a locator hash

Full list of WebConditions and documentation on how to use can be found here.

Aliases 👀

There is an option to use PageObject class instead of WebObject.
Eg: class LoginPage < PageObject

There is an option to use AppObject class instead of WebObject to sound more mobile-like for appium frameworks.
Eg: class DashboardScreen < AppObject

Also for elements as mentioned above
for element there is an option to use find (for capybara flavor loving people)
for elements there is an option to use element_list or all

Contributing 👀

Ideas and suggestions are always always most welcome. Please fork this gem code and feel free to add any updates, suggestions etc and create a pull request.

Issues 👀

If you face any problem related to syntax, usability, documentation then please raise an issues...