Search code examples
rubyautomated-testswatirpageobjects

Watir page object for complex elements


Having this html:

<div class = "account">
    <div class = "name"></div>
    <div class = "email"></div>
    <div class = "phone"></div>
</div>
<div class = "account">
    <div class = "name"></div>
    <div class = "email"></div>
    <div class = "phone"></div>
</div>
<div class = "account">
    <div class = "name"></div>
    <div class = "email"></div>
    <div class = "phone"></div>
</div>

I want to create a page object that will have list of accounts, but as I am new to Ruby and watir, I have no idea how it will look like.

Here is the Account class:

class Account
  def initialize(browser)
    @browser = browser
  end
  def user
    @browser.div(:class => "name")
  end

  def email
    @browser.div(:class => "email")
  end

  def phone
    @browser.div(:class => "phone")
  end
end

And page object where i need to have a list of accounts

class Page 
  def initialize(browser)
    @browser = browser
  end

#here should be a list of accounts

end 

Solution

  • I assume you're rolling your own page-object framework (as opposed to asking how to do this in a specific framework).

    I would create a class to represent an account. This is the same as what you have, except it assumes you will pass in an element (rather than the browser). This element should represent all of the account content - ie it'd expect a <div class = "account">. Its method would be looking for content relative to this element.

    class Account
      def initialize(element)
        @element = element # expected to be div.account
      end
      def user
        @element.div(:class => "name")
      end
    
      def email
        @element.div(:class => "email")
      end
    
      def phone
        @element.div(:class => "phone")
      end
    end
    

    In the page class, you can create an #accounts method to (1) get all of the account divs and (2) wrap them in your Account class:

    class Page
      def initialize(browser)
        @browser = browser
      end
    
      def accounts
        @browser.divs(class: 'account').map { |d| Account.new(d) }
      end
    end
    

    Your usage of the page would then be:

    page = Page.new(browser)
    
    # Inspecting the collection of accounts
    page.accounts.count
    #=> 3
    
    # Inspecting a specific account (note the 0-based index)
    page.account[1].user.text
    #=> "<second accounts name>"