【问题标题】:Finding a specific row in a table using capybara使用 capybara 在表中查找特定行
【发布时间】:2017-01-21 14:43:01
【问题描述】:

我有一个列出用户 ID、姓名、电子邮件和用户名的用户表。我正在尝试做的是验证该表中是否有特定条目。

所以基本上我想做的是找到 ID = 22 的行,然后验证 name = John Smithemail = john@smith.comusername = jsmith。能够设置如下所示。我不明白的是几件事......

  1. 如何获得包含特定文本的行,即即 user.id = 22。
  2. 拥有该行后,如何使用它获取每个元素。

我以为我可以做一种 for 循环,但不知道如何设置 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 

表格代码

<table class="table table-striped table-condensed">
  <thead>
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Email</th>
      <th>Username</th>
    </tr>
  </thead>
  <tbody>
    <% @users.each do |user| %>
      <tr>
        <td class="id"><%= user.id %></td>
        <td class="name"><%= link_to user.name, user %></td>
        <td class="email"><%= user.base_name %></td>
        <td class="username"><%= user.username %></td>
      </tr>
    <% end %>
  </tbody>
</table>

【问题讨论】:

    标签: html ruby-on-rails ruby capybara


    【解决方案1】:
    def row_containing_cell_with_text(text, exact = false)
      find('td,th', text: text, exact: exact).ancestor('tr')
    end
    

    【讨论】:

      【解决方案2】:

      这与其说是一个技术性的答案,不如说是一种替代方法,可以避免编写易碎且过于复杂的测试。

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

      我的“诀窍”是使用一些非常不寻常的文本进行测试。虽然“John Smith”应该可以工作,但您可以使用“John Zebra”,您绝对不会不小心在页面上出现该文本。

      但是当我确实需要关心表格中出现的数据时,我会为每一行使用 dom_id。在此超级管理员的组织列表示例中,经销商组织名称出现在两行中 - 第一行是经销商组织所在的行,然后是推荐组织的经销商列:

      表格视图代码sn-p...

      %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)
              ...
      

      还有黄瓜测试代码sn -p:

      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】:

        一个不错的干净方法是为每个 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 
        

        【讨论】:

          【解决方案4】:

          为什么不这样做呢?:

          feature "index users" do
            let!(:user) { create(:user, name: "John Smith") }
          
            it "shows users" do
              visit users_path
              within ".name_#{user.id}" do
                expect(page).to have_content("John Smith")
              end
            end
          end
          

          【讨论】:

          • 这行不通,因为没有“name_#{user.id}”类的元素
          • 我知道,但你可以像 td class="name_&lt;%= user.id %&gt;" 那样把它放在那里,或者如果只有一个用户实例,你也可以不使用 inside。
          • 将用户ID添加到类只会使样式更加复杂,如果添加到html它应该是行的数据属性。
          • 为什么会变得复杂?你可以叫它&lt;td class="name name_&lt;%= user.id %&gt;"&gt;
          • 太棒了 - 然后您还必须向 id、电子邮件和用户名 tds 添加另一个类。您将添加大量只使用过一次的类名(代码味道不好)。您正试图滥用类来确切了解为什么将数据属性添加到 html
          猜你喜欢
          • 2020-06-15
          • 2012-12-20
          • 2012-10-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-04-23
          • 1970-01-01
          相关资源
          最近更新 更多