【问题标题】:How to search for a Page Object element inside another element in ruby如何在 ruby​​ 中的另一个元素内搜索页面对象元素
【发布时间】:2014-03-12 11:04:24
【问题描述】:

我有一个包含 3 个 div 的地址(主地址、辅助地址、添加地址)的表单。 每个 div 包含以下元素 (text_field):姓名、地址、电话。 根据场景,我想编辑特定 div 的文本字段。

所以我有这种情况:

Given I am at the form for editing addresses
When the div "main address" is visible
Then fill the "name" element for the "main address" div
And erase the "address" for the "main address" div

及以下步骤定义:

Then(/^fill the "([^"]+)" element for the "([^"]+)" div$/) do |element, div|
   on_page(AddressPage).fill_element element div
end

现在我不确定的部分是地址页

class AddressPage
  include PageObject
  include DataMagic
  div(:main_address, :id => 'main_address')
  div(:secondary_address, :id => 'secondary_address')
  div(:add_address, :id => 'add_address')

  def fill_element(element, div)
    current_div = self.send("#{div}_element")
    # now the part I don't know how to do:
    current_element = div.search_within(current_div, element)
    fill_with_correct_data current_element
  end

  def search_within(div, element)
    # How to do this?
  end
end

我怎样才能做到这一点,这样我就不必为所有 div 定义所有元素(div 的数量是动态的)? 我需要知道的是是否有一种方法可以搜索一个元素以使其位于另一个元素中。

谢谢:)


编辑 html 将如下所示:

<div id='main_address'>
    <input id='name'>
    </input>
    <input id='address'>
    </input>
    <input id='phone'>
    </input>
</div>
<div id='secondary_address'>
    <input id='name'>
    </input>
    <input id='address'>
    </input>
    <input id='phone'>
    </input>
</div>
<div id='add_address'>
    <input id='name'>
    </input>
    <input id='address'>
    </input>
    <input id='phone'>
    </input>
</div>

第二次编辑重点是还要声明:

select_list(:name, :id => 'name')
select_list(:address, :id => 'address')
select_list(:phone, :id => 'phone')

#Is this possible?
current_name_element = main_address.name
#?
#Also, at the end the point is to call the Datamagic populate_page_with method
populate_page_with data_for 'new_user'

“default.yml”如下所示:

new_user:
  name: ~first_name
  address: ~address
  phone: ~phone

我可以在哪里选择要填充的 div。这可能吗?

【问题讨论】:

  • 澄清一下,这是Cheezy's page object gem吗?可以分享一下html的相关部分吗?
  • 贾斯汀,是的,Cheezy Page Object gem。我将对其进行编辑并添加 html。

标签: ruby cucumber element page-object-gem


【解决方案1】:

您可以使用element locators 在元素中查找元素。这些方法使用与访问器方法中相同类型的定位器。

例如,对于给定的current_div,您可以获得其相关的文本字段:

current_element = current_div.text_field_element(:id => 'name')
current_element = current_div.text_field_element(:id => 'address')
current_element = current_div.text_field_element(:id => 'phone')

注意:您可能需要更改这些定位器。可能这些 id 并不完全正确,因为 id 在页面上应该是唯一的。

将以上内容应用于您的页面对象,您可以将fill_element 方法定义为:

def fill_element(element, div)
  current_div = self.send("#{div}_element")   
  current_element = current_div.text_field_element(:id => element)

  # I assume this is a method you have already
  fill_with_correct_data current_element
end

调用方法就像:

page.fill_element('name', 'main_address')
page.fill_element('address', 'secondary_address')
page.fill_element('phone', 'add_address')

更新 - 创建范围定位器:

这似乎有点混乱,但考虑到页面对象 gem 的当前实现,这是我能想到的最好的方法。我认为有一些对 gem 的积压功能请求可以使这个更清晰。

你可以做的是:

class AddressPage
    include PageObject

    class ScopedLocator
        def initialize(name, page_object)
            @name = name
            @page = page_object
        end

        def populate_with(data)
            scoped_data = Hash[data.map {|k, v| ["#{@name}_#{k}", v] }]
            @page.populate_page_with scoped_data
        end

        def method_missing(m, *args)  
            @page.send("#{@name}_#{m}", *args)
        end
    end

    ['main_address', 'secondary_address', 'add_address'].each do |name|
        define_method(name) { ScopedLocator.new(name, self) }
        text_field("#{name}_name"){ div_element(:id => name).text_field_element(:id => 'name') }
        text_field("#{name}_address"){ div_element(:id => name).text_field_element(:id => 'address') }
        text_field("#{name}_phone"){ div_element(:id => name).text_field_element(:id => 'phone') }
    end  
end

这做了两件事:

  1. 它将为每个地址创建正常的访问器。例如,它会创建一个 :main_address_name、:main_address_address 和 :main_address_phone(对于其他地址类型也是如此)。
  2. 它创建一个方法,例如main_address,将操作委托给普通访问器。这是为了给出main_address.populate_with 语法。

使用此页面对象,您可以对给定的地址部分执行 populate_with:

page.main_address.populate_with data_for 'new_user'
page.secondary_address.populate_with data_for 'new_user'
page.add_address.populate_with data_for 'new_user'

以及能够更新地址的各个字段。例如:

page.main_address.name = 'user'

【讨论】:

  • 嗯,理想情况下不会有重复的 id,但在这个网页中有。我不知道嵌套元素方法。好的,我要试试这个!谢谢:)
  • 我刚刚编辑了这个问题。你能看看吗? :)
  • 如果是第二次编辑,populate_page_with 怎么知道要更新哪个地址(即主要、次要、添加)?它是要填充所有地址还是仅填充特定地址?如果是后者,main_address.populate_with data_for 'new_user' 可以吗?
  • 贾斯汀,是的,当场。这正是我想要它做的:)
  • 我添加了一个可能的解决方案来获取main_address.populate_with
猜你喜欢
  • 1970-01-01
  • 2012-02-15
  • 2022-01-24
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
  • 1970-01-01
相关资源
最近更新 更多