如何在indexed_property的运行时期间将值传递给索引?

时间:2014-11-17 18:25:00

标签: page-object-gem

我有多组select_list和具有相同属性的复选框。虽然我可以使用index => 0index => 1等区分它们,但有没有办法使用indexed_property来实现这一点?

当我尝试时:

indexed_property(:my_index_prop, 
  [[:select_list, :my_select, {:name => 'my_select',:index => '%d'}],
  [:checkbox,     :my_check,  {:name => 'my_check',:index => '%d'}]]
)

导致错误'预期fixnum got string“0”'。

如果无法使用indexed_property,是否有办法在运行时传递索引并识别元素?例如:

for cnt in 0 .. 6
  # identify element using index
end

1 个答案:

答案 0 :(得分:1)

问题是,当Watir-WebDriver要求:index值为数字时,Page-Object将:index值作为String发送。

解决方案1 ​​ - 使用元素集合

鉴于您只使用indexed属性来指定:index locator,您可以改为定义元素集合。

假设您的网页类似于:

<html>
  <body>
    <select name="my_select" id="0"></select>
    <input name="my_check" id="a" type="checkbox">

    <select name="my_select" id="1"></select>
    <input name="my_check" id="b" type="checkbox">

    <select name="my_select" id="2"></select>
    <input name="my_check" id="c" type="checkbox"> 
  </body>
</html>

您可以将页面对象定义为:

class MyPage
  include PageObject

  select_lists(:my_index_prop_select_list, :name => 'my_select')
  checkboxes(:my_index_prop_checkbox, :name => 'my_check')
end

两个元素集合是数组,这意味着您可以使用[]方法指定索引:

page = MyPage.new(browser)
p page.my_index_prop_select_list_elements[1].attribute('id')
#=> "1"
p page.my_index_prop_checkbox_elements[1].attribute('id')
#=> "b"

此解决方案的问题在于您无法获得不同存取方法的好处。

解决方案2 - 使用XPath

另一种选择是使用:xpath定位器和indexed_property:

class MyPage
  include PageObject

  indexed_property(:my_index_prop, [
    [:select_list, :my_select, {:xpath => '//select[@name="my_select"][%s + 1]'}],
    [:checkbox, :my_check, {:xpath => '//input[@type="checkbox"][@name="my_check"][%s + 1]'}] 
  ])  
end

这样做的好处是可以获得创建的常用访问方法:

page = MyPage.new(browser)
p page.my_index_prop[1].my_select_element.attribute('id')
#=> "1"
p page.my_index_prop[1].my_check_element.attribute('id')
#=> "b"    
page.my_index_prop[1].check_my_check
p page.my_index_prop[1].my_check_checked?
#=> true 

这里的缺点是你必须编写XPath,这很简单。

解决方案3 - 修改页面对象

最后,您可以修改Page-Object gem以将:index转换为数字,然后再将其传递给Watir。这可以通过添加monkey-patch来完成:

class PageObject::IndexedProperties::RowOfElements
  def initialize (browser, index, identifier_list)
    initialize_browser(browser)

    identifier_list.each do |identifier|
      type = identifier[0]
      name = identifier[1]
      how_and_what = identifier[2].clone # Cannot modify the original...
      how_and_what.each do |key, value|
        if key == :index
          how_and_what[key] = (value % index).to_i
        else
          how_and_what[key] = value % index
        end
      end
      self.class.send type, name, how_and_what unless self.class.instance_methods.include? name
    end
  end
end

这将允许页面对象按预期定义:

class MyPage
  include PageObject

  indexed_property(:my_index_prop, [
    [:select_list, :my_select, {:name => 'my_select', :index => '%d'}],
    [:checkbox, :my_check, {:name => 'my_check', :index => '%d'}]
  ])
end

与以前的解决方案使用的相同:

page = MyPage.new(browser)
p page.my_index_prop[1].my_select_element.attribute('id')
#=> "1"
p page.my_index_prop[1].my_check_element.attribute('id')
#=> "b"    
page.my_index_prop[1].check_my_check
p page.my_index_prop[1].my_check_checked?
#=> true 

缺点当然是你必须修补Page-Object gem。虽然您可以要求对项目进行更改。