User314159
User314159

Reputation: 8065

Testing a general controller action using rspec

Here's how my routes look like:

 /article/:id/:action     {:root=>"article", :controller=>"article/article", :title=>"Article"}

Here's how my controller looks like:

# app/controllers/article/article_controller.rb
class ArticleController < ApplicationController
  def save_tags
    # code here
  end
end

I want to test the save_tags action so I write my spec like this:

describe ArticleController do       
   context 'saving tags' do
     post :save_tags, tag_id => 123, article_id => 1234
     # tests here
   end
end

But when I run this spec, I get the error

ActionController::RoutingError ...
No route matches {:controller=>"article/article", :action=>"save_tags"}

I think the issue is the save_tags action is a general controller action, ie. there's no /article/:id/save_tags in routes. What's the best way to test this controller action?

Upvotes: 4

Views: 274

Answers (2)

CDub
CDub

Reputation: 13354

You're spot on. The issue is that you're looking for a route which doesn't have :id in it, but you don't have one. You'll need to pass a parameter to the post :save_tags of :id, and given the above question, I believe it is what you are calling article_id.

Therefore, try changing your test to:

describe ArticleController do       
   context 'saving tags' do
     post :save_tags, tag_id => 123, id => 1234
     # tests here
   end
end

Update

Rails might be getting confused because you're using :action in your route and I believe action is either a reserved word or a word that Rails treats as special. Maybe try changing your routes to:

/article/:id/:method_name {:root=>"article", :controller=>"article/article", :title=>"Article"}

And your test to:

describe ArticleController do       
  context 'saving tags' do
    post :save_tags, { :tag_id => 123, :article_id => 1234, :method_name => "save_tags" }
    # tests here
  end
end

Upvotes: 3

house9
house9

Reputation: 20624

You need a route to map to your controller actions

post '/article/:id/save_tags' 

should work, or consider using resources helper to build your routes

# creates the routes new, create, edit, update, show, destroy, index
resources :articles

# you can exclude any you do not want
resources :articles, except: [:destroy]

# add additional routes that require an article in the member block
resources :articles do 
  member do 
    post 'save_tags'
  end
end

# add additional routes that do NOT require an article in the collection block
resources :articles do 
  collection do 
    post 'publish_all'
  end
end

Upvotes: 0

Related Questions