cheezy / page-object

Gem to implement PageObject pattern in watir-webdriver and selenium-webdriver
MIT License
653 stars 220 forks source link

Add support for multi value in index property #453

Open CognizantCOE opened 6 years ago

CognizantCOE commented 6 years ago

looking for supporting multi value in index property for locators like highlighted in code below. indexed_property(:cart_contents, [ [:span, :title, {:id => 'cart[%s].title[%s]'}], [:text_field, :quantity, {:id => 'cart[%s].quantity'}], [:button, :delete, {:id => 'cart[%s].delete'}] ])

jkotests commented 5 years ago

It wasn't obvious, but we actually already have support for this. We are injecting the "index" into the locator Strings. The "index" can be more complex - eg Array or Hash (see https://stackoverflow.com/a/554877/1200545 for String manipulation examples).

For example, given the page:

<html>
  <body>
    <div>
      <span id="cart[1].title[1]">title 1</span>
      <input type="text" id="cart[1].quantity">
      <button id="cart[1].delete">delete 1</button>
    </div>
    <div>
      <span id="cart[2].title[2]">title 2</span>
      <input type="text" id="cart[2].quantity">
      <button id="cart[2].delete">delete 2</button>
    </div>
  </body>
</html>

You can do:

class MyPage
  include PageObject

  indexed_property(:cart_contents, [
    [:span, :title, {:id => 'cart[%s].title[%s]'}],
    [:text_field, :quantity, {:id => 'cart[%s].quantity'}],
    [:button, :delete, {:id => 'cart[%s].delete'}]
  ])
end

page = MyPage.new(browser)
cart_content = page.cart_contents[[1, 1]]
p cart_content.title
#=> "title 1"
p cart_content.quantity_element.id
#=> "cart[1].quantity"
p cart_content.delete_element.text
#=> "delete 1"

If you need to repeat values, you can avoid duplication by using Hash keys:

class MyPage
  include PageObject

  indexed_property(:cart_contents, [
    [:span, :title, {:id => 'cart[%{idx}].title[%{idx}]'}],
    [:text_field, :quantity, {:id => 'cart[%{idx}].quantity'}],
    [:button, :delete, {:id => 'cart[%{idx}].delete'}]
  ])  
end

page = MyPage.new(browser)
cart_content = page.cart_contents[{idx: 1}]
p cart_content.title
#=> "title 1"
p cart_content.quantity_element.id
#=> "cart[1].quantity"
p cart_content.delete_element.text
#=> "delete 1"

I'll leave this open for a bit. At a minimum, it would help to write an example on the wiki and/or documentation.