我有多组select_list和具有相同属性的复选框。虽然我可以使用index => 0
,index => 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
答案 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。虽然您可以要求对项目进行更改。