Search code examples
ruby-on-railsrubyrspecrspec-rails

How to identify the route being called in a RSpec controller spec


I have an RSpec controller spec and I'm trying to understand how to find what exact route is being called in my example.

In services_controller_spec.rb:

describe 'create comment' do
  let!(:service) { FactoryGirl.create(:service) }

  describe 'with valid comment' do
    it 'creates a new comment' do
      expect {
        post :add_comment, id: service.id
      }.to change(service.service_comments, :count).by(1)

      expect(response).to redirect_to(service_path(service))
    end
  end
end

Is there a way to pp or puts the route that is being sent via the post?

I am asking because I want to post to the route /services/:id/add_comment and want to verify where exactly the route is going.

My routes.rb for this route:

resources :services do
  member do
     post 'add_comment'
  end
end

Solution

  • You can print the name of the route used in an rspec-rails controller spec with something like this:

    routes.formatter.send(
      :match_route,
      nil,
      controller: ServicesController.controller_path,
      action: 'add_comment', # what you passed to the get method, but a string, not a symbol
      id: service.id         # the other options that you passed to the get method
    ) { |route| puts route.name }
    

    rspec-rails uses the route only internally. The above is how rspec-rails (actually ActionController::TestCase, which rspec-rails uses) looks up and uses the route, but with a block that just prints the route.

    There are a lot of method calls between the post call in a spec and the above, so if you want to understand how rspec-rails gets to the above I suggest putting a breakpoint in ActionDispatch::Journey::Formatter.match_routes before running your example.

    Note that an rspec-rails controller spec doesn't use the route to decide what action method to call or what controller class to call it on; it already knows them from the controller class you pass to describe and the action you pass to the action method (get, post, etc.). However, it does look up the route and use it to format the request environment. Among other uses, it puts the path in request.env['PATH_INFO'].

    I investigated this in Rails 4.1, since that's what the project I have handy uses. It might or might not be accurate for other versions of Rails.