【问题标题】:Rails app testing with RSpec and Capybara. I get Error Capybara::ElementNotFound使用 RSpec 和 Capybara 进行 Rails 应用程序测试。我收到错误 Capybara::ElementNotFound
【发布时间】:2019-11-17 10:44:55
【问题描述】:

_customers_table.html.erb

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Phone number</th>
      <th>Description</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
    <% @customers.each do |customer| %>
      <tr>
        <td><%= customer.name %></td>
        <td><%= customer.phone_number %></td>
        <td><%= customer.description %></td>
        <td><%= link_to customer.status.humanize, toggle_status_customer_path(customer), class: "move-to-black" %></td>
        <td><%= link_to 'Show', customer %></td>
        <td><%= link_to 'Edit', edit_customer_path(customer) %></td>
        <td><%= link_to 'Destroy', customer, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
  </tbody>
</table>


creating_customer_spec.rb

require 'rails_helper'

describe "creating new customer", type: :feature do
  let(:customer) { customer = FactoryBot.create(:customer) }

  it 'should create new customer' do
    visit '/customers/new'
    fill_in 'Name', with: customer.name
    fill_in 'Phone number', with: customer.phone_number
    click_button 'Create Customer'
    expect(page).to have_content "#{customer.name}"
  end

  it 'should change customer status' do
    visit '/'
    click_on customer.status.humanize
    expect(customer).to have_status "move_to_white_list"
  end
end


第一个示例“应创建新客户”通过,但第二个示例“应更改客户状态”出现错误

Capybara::ElementNotFound:
       Unable to find link or button "Move to black list"

元素存在,您可以在图像上看到它。 如果有人可以提供帮助,我将不胜感激。enter image description here

我更改了第二个示例,现在它可以工作了。这是我的错误,我没有 解释清楚,“黑名单”表在不同的视图上, 当状态改变时,它会移动到另一个页面,所以实际上它不是 可以在那里找到它。

    require 'rails_helper'

describe "creating new customer", type: :feature do
  let!(:customer) { customer = FactoryBot.create(:customer) }

  it 'should create new customer' do
    visit '/customers/new'
    fill_in 'Name', with: customer.name
    fill_in 'Phone number', with: customer.phone_number
    click_button 'Create Customer'
    expect(page).to have_content "#{customer.name}"
  end

  it 'should change customer status' do
    visit '/customers'
    click_on customer.status.humanize
    expect(page).to have_content "Customer #{customer.name} moved to black list"

    visit '/black_list'
    expect(customer.reload.status).to eq "move_to_white_list"
  end
end

【问题讨论】:

  • 您是否在测试中尝试过click_link 而不是click_on
  • 我在那里看不到您的“创建客户”元素
  • @Clepsyd click_onclick_link_or_button 的别名,因此仅使用 click_link 不会有任何区别。

标签: ruby-on-rails ruby testing capybara


【解决方案1】:

这里有很多问题。首先,您将在创建客户实例之前进入页面,这意味着它不会显示在页面上。这是因为 let 懒惰地评估 - 请参阅 https://relishapp.com/rspec/rspec-core/v/3-8/docs/helper-methods/let-and-let - 并且只会在客户第一次在测试中被调用时创建客户。

visit '/' # <= no customer instance exists here
click_on customer.status.humanize # <= customer instance actually created here

您可以通过使用非延迟评估版本let! 来解决此问题,该版本将始终创建一个客户实例,或者在调用visit 之前调用customer

其次,您的测试正在修改数据库中的客户实例,但永远不会重新加载您在内存中的实例(因此永远不会看到新状态)

expect(customer.reload).to have_status "move_to_white_list"

第三,如果您使用支持异步行为的驱动程序(机架测试以外的任何驱动程序),则无法保证操作方法(click_on 等)引起的任何副作用将在该方法之前完成调用返回。这意味着您的期望很可能会在客户实例状态发生变化之前被调用。为了解决这个问题,have_status 匹配器需要被编写为具有重试行为(就像所有 Capybara 提供的匹配器一样)并且在匹配器中也具有重新加载行为。这就是为什么在系统/功能测试中验证数据库更改通常不是一个好主意,而是坚持在 UI 中验证更改的主要原因。

【讨论】:

  • 我找到了一个解决方案,它在问题更改中。非常感谢您的详细解释和您的时间。
  • @MichaMichael 不客气 - 如果对您有帮助,请不要忘记接受答案(复选标记),以便您的问题被标记为已回答
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多