I have a create.js.erb
template with the following:
<% if @conversation.errors.any? %>
$("#form").html("<%= j render(partial: 'form') %>");
<% else %>
Turbolinks.visit("<%= conversation_url @conversation %>");
<% end %>
I can test the sad path easily using assert_select_jquery
like so:
test 'sad path' do
# code that causes failure ommitted
# test that the error explanation div appears
assert_select_jquery :html, '#form' do
assert_select 'li', "Body can't be blank"
end
end
I'm having trouble testing the happy path:
test "happy path" do
post conversations_url, params: { conversation: attrs }, xhr: true
# Test that Turbolinks takes us to
# the mailbox after successful post
assert_select '.flash', "Message sent successfully."
end
The test fails because the flash div containing the success message only appears after the Turbolinks call. The best I can do so far is test that the response body contains a call to Turblinks.visit()
:
expected_response = "Turbolinks.visit(\"#{conversation_url conversation}\");"
assert_match /#{expected_response}/, response.body.chomp
But this is totally gross. Is there a rails way for telling controller tests to execute any Turblinks directives contained in js.erb files that might be rendered during the request?
execute_javascript_on_page
assert_select :h1, 'xyz'
You need a browser to execute JavaScript so you need a browser test with something like capybara. I'm not sure which Rails version you use but in Rails 5 browser tests are provided by default. See System Testing in Rails Guides. In previous versions, you need to install capybara
yourself.
That being said, I do not think testing for a call to Turbolinks.visit
is that bad. My only concern is that it might be a bit unreadable so I'd define a custom assertion like:
def assert_turbolinks_visit(target_url)
assert_match(%r{Turbolinks.visit("#{target_url}")}, response.body)
end
and then use it like:
assert_turbolinks_visit(conversation_url(conversation))
It might get more problematic if the argument to Turbolinks.visit
isn't a literal. In this case, a browser test may be necessary.