【问题标题】:Selecting a CSS element with a dynamic id选择具有动态 id 的 CSS 元素
【发布时间】:2014-12-09 23:07:02
【问题描述】:

我正在使用 cucumber 和 SitePrism 编写自动化测试,但我无法在测试之间选择 CSS 元素,因为它的 id 是动态的(随用户 id 而变化)并且名称不是唯一的。该元素是一个用户角色下拉菜单,因此 id 会更改以匹配用户 id。

元素的html是...

<dd>
   <select id="select-role-a02322d1-8add-4234-aeca-02d3fca2a239" name="role_id">
      <option title="System Administrator Role" value ="1">Administrator</option>
      <option title="Secure Content Viewer" value="2">SecureContentView</option>
   </select>
</dd>

当我将页面模型上的元素设置为...时

element :role_dropdown, 'select[name=role_id]'

并执行以下对象/实例...

And(/^select the first value in the Add Role dropdown$/) do
    @page.user.role_dropdown.select("Administrator")
end

我回来了

Capybara::Ambiguous: Ambiguous match, found 2 elements matching css "select[name=role_id]"
from /Users/Alex/.rvm/gems/ruby-2.1.2@railstutorial_rails_4_0/gems/capybara-2.4.3/lib/capybara/node/finders.rb:38:in 
`block in find'

所以要让测试工作,我必须将元素设置为静态 id

element :role_dropdown, '#select-role-8ec3f391-3871-47ff-b605-8f43aa40677d'

但是在没有测试具有该 ID 的用户的所有情况下,该元素都是无用的。

  1. 有没有办法在页面模型上设置元素以具有动态 id?

  2. 在下面的实例中(图 1),如何选择值 1 而不是选项文本?我希望使选择的内容与值有关,而不是文本。这样,如果选项 1 的标题或文本发生更改,选项 1 仍将被选中,并且测试不会失败。

图 1:

And(/^select the first value in the Add Role dropdown$/) do
    @page.user.role_dropdown.select("Administrator")
end
  1. 如果 id 是动态的,我该如何定义 {id}?我可以使用放置在 environment_keys.yaml 中的密钥来定义它吗?

【问题讨论】:

    标签: ruby automation cucumber capybara qa


    【解决方案1】:

    我假设 id 是在外部生成的,测试无法访问(在这种情况下,Anthony 的建议可能不起作用)

    如果是这样,select[name=role_id] 可能是一个好的开始。显然,该选择器在页面上有两个匹配的元素,因此您需要更具体的东西来区分它们。

    要同时找到两者,请打开开发者工具并转到控制台。假设该站点有 jQuery,您可以通过 $('select[name=role_id]') 查找匹配的元素。您可以右键单击它们以在元素面板中显示。树中可能有更高的东西可以用来选择它们。

    有一种可能,一种是可见的,一种是隐藏的。如果是这种情况,那么您可以像这样选择可见的: element :role_dropdown, 'select[name=role_id]', visible: true

    【讨论】:

    • id 是在外部生成的,我知道它显示的唯一位置是在 URL 和带有动态 CSS id 的 HTML 中。我今晚要试试这个以找到另一个匹配的元素,希望visible; true 能做到这一点。感谢您的帮助!
    • 找到冲突的名称...&lt;dd&gt;&lt;select id="current-role-a02322d1-8add-4234-aeca-02d3fca2a239" class="current-role" name="role_id" multiple="multiple"&gt;&lt;/select&gt;&lt;/dd&gt;
    • 如果您确定要获取原始问题中列出的元素,而不是上面粘贴的元素,则可以使用 :not() 伪选择器。 'select[name=role_id]:not(.current-role)' 会忽略错误的,因为只有那个具有 current-role 类。
    • :not() 会派上用场,从来不知道那个。非常感谢老兄!
    【解决方案2】:

    您是在测试中创建角色,对吗?为什么不使用它来隔离您的元素选择:

    @role = Role.create('attributes here')
    element :role_dropdown, "select[name=#{@role.id}]"
    

    【讨论】:

    • 感谢您的回复。我对"select[name=#{@role.id}]" 有点困惑,因为name="role_id" 始终保持不变,无论用户ID 是什么。不是select[id="select-role-#{@role.id}"]吗?为了确保我理解正确,@role = Role.create('attributes here'),你会用a02322d1-8add-4234-aeca-02d3fca2a239 的ID 代替'attributes here' 对吗?难道不是#{@role} 而不是#{@role.id}?我想我对.id 部分有点困惑(对不起,我是新手)。如果你找到时间,你能解释一下吗?谢谢!
    猜你喜欢
    • 2012-11-12
    • 2023-03-09
    • 2016-02-22
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 2014-05-11
    • 2016-05-05
    • 1970-01-01
    相关资源
    最近更新 更多