使用capybara在表中查找特定行

时间:2016-09-13 21:46:19

标签: html ruby-on-rails ruby capybara

我有一个用户表,其中列出了用户的ID,姓名,电子邮件和用户名。我试图做的是验证该表中的特定条目。

基本上我想要做的是找到ID = 22的行,然后验证Download and install NodeJS. From a Command-line window, run the command: npm install -g cordova. name = John Smithemail = john@smith.com。该功能设置如下所示。我不明白的是一些事情......

  1. 如何获取具有特定文本的行,I.E。那个为user.id = 22.
  2. 一旦我拥有该行,我如何使用它获取每个元素。
  3. 我以为我可以做一种for循环,但无法弄清楚如何设置username = jsmith条件。 (下面是伪代码)

    has_selector?

    表格代码

    page.all('tr').each do |tr|
      next unless tr.has_selector?('td.id = 22') #psuedocode
    
      expect(tr.get('td.name').to eq("John Smith")
      #other expects here...
    end 
    

4 个答案:

答案 0 :(得分:5)

一个很好的干净方法是为每个tr元素添加一个“data-user-id”属性,然后用tr = find('tr[data-user-id="22"]')找到你想要的行,但如果这不是一个选项,有很多种方法去做这个。

之一
td = page.find(:css, 'td.id', text: /^22$/) # find the id td with text of exactly 22
tr = td.find(:xpath, './parent::tr') # get the parent tr of the td
expect(tr).to have_css('td.name', text: 'John Smith')

或仅使用像

这样的xpath查找行
tr = page.find(:xpath, ".//tr[./td[@class='id'][text()='22']]")
expect(tr).to have_css('td.name', text: 'John Smith')

应该做你想做的事。如果你想坚持使用循环方法(不推荐,因为它会很慢 - 以及你的循环结构的方式,它可能无法验证任何东西)它将是

page.all('tr').each do |tr|
  next unless tr.has_css?('td.id', text: /^22$/)
  expect(tr).to have_css('td.name', text: "John Smith")
  #other expects here...
end 

答案 1 :(得分:0)

为什么不这样做?:

def f(w):
    best = ''
    for i in range(len(w)):
        idx = -i-1
        c = w[idx]
        if c >= best:
            best = c
        else:
            l = sorted(w[idx:])
            for j, ch in enumerate(l):
                if ch > c:
                    return w[:idx] + ch + ''.join(l[:j] + l[j+1:])
    return 'no answer'

n = input()
for i in range(n):
    print f(raw_input())

答案 2 :(得分:0)

这不是一个技术性答案,因为它是一种替代方法,可以避免编写可能脆弱且过于复杂的测试。

通常,我只是通过查找一些聪明的文本来验证页面上是否出现了某些对象。也许它在一个表中,或者它可能在一个响应式网格中...如果我让我的测试关注UI实现,它可能会在UI中发生变化时中断。

我的"技巧"是使用一些非常不寻常的文本进行测试。而约翰史密斯"应该工作,你可以使用" John Zebra"并且你绝对不会意外地在页面上显示该文本。

但是当我确实需要关心表中出现的数据时,我会为每一行使用dom_id。在这个超级管理员组织列表的示例中,经销商组织名称显示在两行中 - 第一行是经销商org的行,并且他在转销组织的转销列中表示:

表格视图代码段...

%table.orgs-list.stripe
  %thead
    %tr
      %th Created
      %th Name
      %th Reseller
      ...
  %tbody
    - organizations.each do |org|
      %tr{id: dom_id(org)}
        %td= org.created_at....
        %td= link_to org.name, org
        %td= org.reseller.try(:name)
        ...

黄瓜测试代码片段:

Then(/^I should see "([^"]*)" showing "([^"]*)" as the reseller$/) do |org_name, reseller_name|
  org = Organization.where( name: org_name).first
  reseller = Organization.where( name: reseller_name).first
  dom_id = "organization_#{org._id}"
  within("tr##{dom_id}") do
    expect(page).to have_text(reseller.name)
  end
end

答案 3 :(得分:-1)

def row_containing_cell_with_text(text, exact = false)
  find('td,th', text: text, exact: exact).ancestor('tr')
end