Rspec: 用js提交表单时模型没有更新
Rspec: model not updated when submitting form with js
我有一个纸模型。其中有两个状态:draft 和 approved.
我在 edit_paper_path 上有一个表格,它使用 remote: true.
创建一个 put
我的控制器:
def update
paper = Paper.find(params[:id])
puts paper.status # => :draft
paper.approved!
puts paper.status # => :approved
end
我的测试是:
it 'changes status to Approved', js: true do
expect {
click_button 'Approve'
}.to change { paper.status }
end
但是测试失败了,我注意到在模型控制器中所做的更改丢失了,所以状态一直是:草稿。
附加:
这是我的 database_cleaner 配置:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.append_after(:each) do
DatabaseCleaner.clean
end
end
有什么想法吗?
您的测试失败,因为当您的测试在内存中的模型上运行时控制器更新了数据库中的记录。
您需要做的是将内存中的表示与数据库同步:
it 'changes status to Approved' do
expect(paper.approved?).to be_falsy # sanity check
click_button 'Approve'
# trick to get capybara to wait for request to finish
# note that there actually needs to be a flash message
expect(page).to have_css(".flash")
paper.reload
expect(paper.approved?).to be_truthy
end
根据 Anthony E 的反馈进行编辑以处理竞争条件。
Capybara AJAX 请求 运行 异步,因此 paper.status
在数据库中更新值之前正在评估。
事实上,Capybara 与数据库分离,因此您应该尝试使用典型的 has_content
/[=12= 查询 DOM 本身来测试您的 ajax 更新] Capybara提供的查询方式
您可以通过使用 sleep
等待事务完成来解决此问题,但这是一个有点棘手的解决方案,并且不能保证通过,具体取决于数据库提交所需的时间发生。
另一种选择是使用 jQuery.active
查询脚本等到 AJAX 调用完成。这里有一篇很好的文章解释了这种方法:https://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara.
我有一个纸模型。其中有两个状态:draft 和 approved.
我在 edit_paper_path 上有一个表格,它使用 remote: true.
创建一个 put我的控制器:
def update
paper = Paper.find(params[:id])
puts paper.status # => :draft
paper.approved!
puts paper.status # => :approved
end
我的测试是:
it 'changes status to Approved', js: true do
expect {
click_button 'Approve'
}.to change { paper.status }
end
但是测试失败了,我注意到在模型控制器中所做的更改丢失了,所以状态一直是:草稿。
附加:
这是我的 database_cleaner 配置:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, js: true) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.append_after(:each) do
DatabaseCleaner.clean
end
end
有什么想法吗?
您的测试失败,因为当您的测试在内存中的模型上运行时控制器更新了数据库中的记录。
您需要做的是将内存中的表示与数据库同步:
it 'changes status to Approved' do
expect(paper.approved?).to be_falsy # sanity check
click_button 'Approve'
# trick to get capybara to wait for request to finish
# note that there actually needs to be a flash message
expect(page).to have_css(".flash")
paper.reload
expect(paper.approved?).to be_truthy
end
根据 Anthony E 的反馈进行编辑以处理竞争条件。
Capybara AJAX 请求 运行 异步,因此 paper.status
在数据库中更新值之前正在评估。
事实上,Capybara 与数据库分离,因此您应该尝试使用典型的 has_content
/[=12= 查询 DOM 本身来测试您的 ajax 更新] Capybara提供的查询方式
您可以通过使用 sleep
等待事务完成来解决此问题,但这是一个有点棘手的解决方案,并且不能保证通过,具体取决于数据库提交所需的时间发生。
另一种选择是使用 jQuery.active
查询脚本等到 AJAX 调用完成。这里有一篇很好的文章解释了这种方法:https://robots.thoughtbot.com/automatically-wait-for-ajax-with-capybara.