I created a very simple Rails 5 demo application that has a bunch of categories (Category
model). There is a _category.html.erb
partial with a link to remove a category:
<%= link_to 'Remove', category_path(category), data: {method: :delete, confirm: 'Are you sure?'} %>
The corresponding destroy
action:
@category.destroy
respond_to do |format|
format.js
format.html {redirect_to root_path, notice: 'Category destroyed!'}
end
Absolutely nothing fancy. Then I write an RSpec feature test that creates a category with FactoryGirl, visits the categories page and clicks the Remove link. After that the Category.count
should equal to 0 (I also added other checks like "expect flash message to contain "Category destroyed!", but that doesn't really matter).
require 'rails_helper'
RSpec.feature 'Category deletion' do
let!(:category) { create(:category) }
scenario 'should be successful' do
visit categories_path
click_link 'Remove'
page.save_and_open_page
expect(Category.count).to eq(0)
end
end
So my problem is that this ACTUALLY WORKS and I don't really understand why. The problem is that the Remove link has the method: :delete
part which is processed by the jquery_ujs library that basically sends a request with the proper HTTP DELETE verb. If JavaScript is disabled on the page and I try to remove the category manually, it doesn't work - a simple GET request is sent.
I use the default RackTest driver with Capybara and it does not support JavaScript. But when I check the page's screenshot generated by the page.save_and_open_page
it really does have the proper flash message.
Therefore the question is - why and how exactly is this working?
So, that's Capybara's doing. They have an option respect_data_method
https://github.com/teamcapybara/capybara/blob/99a0372aeeb0f3cc2b8962e1753371de58b288c7/lib/capybara/rack_test/node.rb#L58 that basically checks for the data-method
attribute and sends the proper HTTP request.
Also, special thanks to Jamis Buck for noticing that.