I am starting to write tests for my rails application, and plan to write them prior to building the actual pages, but I am having trouble. I have searched stack overflow and google and have tried several things. The route is specified in my routes.rb file and looks like:
resources :welcome
I have the following written into my test code.
require 'rails_helper'
require 'spec_helper'
RSpec.describe "Welcomes", type: :request do
it "checks the welcome page." do
visit welcome_path
end
end
I get the following Error from guard:
Failures:
1) Welcomes checks the welcome page.
Failure/Error: visit welcome_path
ActionController::UrlGenerationError:
No route matches {:action=>"show", :controller=>"welcome"} missing required keys: [:id]
# ./spec/requests/welcomes_spec.rb:6:in `block (2 levels) in <top (required)>'
Finished in 0.00347 seconds (files took 1.61 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/requests/welcomes_spec.rb:5 # Welcomes checks the welcome page.
Change visit welcome_path to get '/welcome'
The index of a Rails resources route set is at welcomes_path. welcome_path would refer to a specific Welcome and requires an :id parameter.
If the welcome page is just a landing page and not actually a resource, you might just want config/routes.rb to contain:
get 'welcome', to: 'welcome#index`
The first welcome is the path (host.com/welcome), and the to: argument is controller#action.
The Rails routing docs are great. Give them a good read through if this didn't make sense.
Related
Edit 1
I created an issue for rspec-rails and made a repo so people can test it themselves.
Original post
I've build a plugin according to this stackoverflow answer and added a route in my engine as follows:
# /config/routes.rb
Myplugin::Engine.routes.draw do
root to: 'pages#index'
end
My only rspec test is this:
# /spec/controllers/pages_controller_spec.rb
require "spec_helper"
describe Myplugin::PagesController do
describe "GET /admin" do
it "routes to pages#index" do
expect(get: "/admin").to route_to(controller: "pages", action: "index")
end
end
end
And in my dummy app I have this route:
# /spec/dummy/config/routes.rb
Rails.application.routes.draw do
mount Myplugin::Engine => "/admin"
end
I'm getting this error when running rspec in the root of the plugin:
Failures:
1) Myplugin::PagesController GET /admin routes to pages#index
Failure/Error: expect(get: "/admin").to route_to(controller: "pages", action: "index")
No route matches "/admin"
# ./spec/controllers/pages_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
I've tried this stackoverflow answer, but it doesn't change the output.
Any ideas?
I'm using rspec 2.13.0 and rails 3.2.13.
Dummy apps should not be used in you main application, but should be used to test plugins in isolation. For example if your plugin is named Myplugin and you wanted to test the plugin in isolation without any references to your main app, could you create a dummy app at vendors/plugins/my_plugin/spec/dummy and tests at vendors/plugins/admin/specor wherever you have you plugin stored. You use a dummy app because a plugin often can't run alone. Eg devise which is a good example on a plugin, needs a main app with a ApplicationController and a user model (plus some other stuff) to work.
If you only use your plugin in this application or you just want to test that it works correctly with your main app, then just create tests normally in spec and don't create a dummy app. This would work fine, as the plugin is loaded into your main app. You would of course need to have the following in your main route file:
# config/routes.rb
Rails.application.routes.draw do
mount Myplugin::Engine => "/admin"
end
Feel free to ask if you have any questions about this.
I'm building a Rails engine under Rails 3.0.12, but I'm having issues with routes when trying to write specs for my engine's controller.
The context
I've been following an Enginex layout. The engine is named Featuring and is not isolated. It does not declare routes by itself: there is no featuring/config/routes.rb file. Instead, a routes_for_feature method is provided for the main application to define engine-specific routes.
##
# featuring/lib/featuring/rails.rb
#
require 'featuring/rails/routing'
module Featuring
class Engine < ::Rails::Engine
end
end
##
# featuring/lib/featuring/rails/routing.rb
#
module ActionDispatch::Routing
class Mapper
def routes_for_feature(feature_name)
resource_name = feature_name.to_s.pluralize.to_sym
resources resource_name, :controller => "featuring/features", :only => [:index, :show], :feature => feature_name.to_s
end
end
end
Following the Enginex template, I have a Dummy app which define the routes as so:
# featuring/spec/dummy/config/routes.rb
Dummy::Application.routes.draw do
routes_for_feature :feature_model
end
The issue
Everything is working fine when I run the rails server for the Dummy app. I can browse to http://localhost:3000/feature_models and the request is successful.
I would like to spec my Featuring::FeaturesController, but I can't get it to find the routes.
Here is the spec:
# featuring/spec/controllers/features_controller_spec.rb
require 'spec_helper'
describe Featuring::FeaturesController do
context "feature_models" do
it "GET index should be successful" do
puts Rails.application.routes.routes
get :index, { :use_route => "featuring", :feature => "feature_models" }
response.should be_success
end
end
end
And here is the result of running this spec:
rspec spec/controllers/features_controller_spec.rb:7
Featuring::FeaturesController
feature_models
GET /feature_models(.:format) {:action=>"index", :controller=>"featuring/features"}
GET /feature_models/:id(.:format) {:action=>"show", :controller=>"featuring/features"}
GET index should be successful (FAILED - 1)
Failures:
1) Featuring::FeaturesController feature_models GET index should be successful
Failure/Error: get :index, { :use_route => "featuring", :feature => "feature_models" }
ActionController::RoutingError:
No route matches {:feature=>"feature_models", :controller=>"featuring/features"}
# ./spec/controllers/features_controller_spec.rb:8:in `block (3 levels) in <top (required)>'
As you can see, even if the routes are correctly defined, the spec'ed controller seems not to find them.
Something surprises me in the RoutingError: No route matches {:feature=>"feature_models", :controller=>"featuring/features"}. The action => "index" is not displayed.
I had a similar error, and I was also confused by the lack of {:action => "index"} in the route options. However, this turned out not to be the problem. ActionDispatch treats the lack of an :action as equivalent to {:action => "index"}. See:
https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/route_set.rb#L545
You may be missing a request parameter in your spec, as was the case with me. Check the Parameters line in your server log when you load the page in the browser.
The trick is to add routes { } to your spec, like so:
describe Featuring::FeaturesController do
routes { Featuring::Engine.routes }
# ...
end
See also No Route Matches ... Rails Engine
I'm trying to write some rspec integration tests to test that my conditional routes are routing correctly, but I'm getting a bunch of problems.
In routes.rb:
root :to => "error#ie6", :constraints => {:user_agent => /MSIE 6/}
root :to => "protocol_sets#index", :constraints => UserRoleConstraint.new(/doctor/i)
root :to => "refill_requests#create", :constraints => UserRoleConstraint.new(/member/i)
root :to => "refill_requests#create", :constraints => {:subdomain => "demo"}
root :to => "site#index"
In spec/requests/homepage_routing_spec.rb
require 'spec_helper'
describe "User Visits Homepage" do
describe "Routings to homepage" do
it "routes / to site#index when no session information exists" do
visit root_path
end
end
end
I get the following error when I try to run the test.
Failures:
1) User Visits Homepage Routings to homepage routes / to site#index when no session information exists
Failure/Error: visit root_path
NoMethodError:
undefined method `match' for nil:NilClass
# :10:in `synchronize'
# ./spec/requests/homepage_routings_spec.rb:6:in `block (3 levels) in '
Finished in 0.08088 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/requests/homepage_routings_spec.rb:5 # User Visits Homepage Routings to homepage routes / to site#index when no session information exists
From Googling around I'm guessing there may be a problem with how rspec/capybara handle conditional routes.
Is there anyway to test constraints on routes with rspec and capybara?
As this drove me nuts over the last days, I found the solution with the help of a colleague.
When using named route constraints, like UserRoleConstraint in the example, I resorted to actually stubbing the matches? method of the constraint int he specs that needed it, i.e.:
describe 'routing' do
context 'w/o route constraint' do
before do
allow(UserRoleConstraint).to receive(:matches?).and_return { false }
end
# tests without the route constraint
end
context 'w/ route constraint' do
before do
allow(UserRoleConstraint).to receive(:matches?).and_return { true }
end
end
# tests with the route constraint
end
Note that this requires you to have named constraints, which might not apply to your case.
For the protocol constraint you can just specify an entire url with dummy domain. See this answer.
It seems a bunch of my Rspec tests now fail after moving my application to Rspec 2.3 and Rails 3.0.3
An example is here:
it "should not be able to access 'destroy'" do
delete :destroy
response.should redirect_to(signin_path)
flash[:error].should == "You must be signed in to view this page."
end
will give me the error:
1) FriendshipsController when not logged in: should not be able to access 'destroy'
Failure/Error: delete :destroy
No route matches {:controller=>"friendships", :action=>"destroy"}
# ./spec/controllers/friendships_controller_spec.rb:21:in `block (3 levels) in <top (required)>'
In my routes.rb file, I've mapped the resources for this controller...
resources :friendships
Same for
get :edit
get :show
put :update
Only one that seems to work is
post :create
But this I cannot confirm 100%.
Any thoughts? Thanks for your time!
UPDATE:
get :new
also works and my UserSessions controller (Authlogic) doesn't seem to suffer from this problem. Nothing I've done different in my UserSessions controller, model, or test that I can tell.
In the spec, try calling the method by:
delete :destroy, :id => "1"
I generated home and contact page thru:
rails generate Pages home contact
did tests to verify and all was okay, now I wanted to add the page "about". I created the about.html.erb through copying the contact.html.erb and pasting then renaming it to about.html.erb. I then changed the content to "Pages#about" instead of "Pages#contact"
I changed route.rb to:
SampleApp::Application.routes.draw do
get "pages/home"
get "pages/contact"
get "pages/about"
then pages_controller.rb to:
def home
end
def contact
end
def about
end
Finally added this to pages_controller_spec.rb:
describe "GET 'about'" do
it "should be successful" do
get 'about'
response.should be_success
end
end
on my autotest this was the error:
Failures:
1) PagesController GET 'about' should be successful
Failure/Error: get 'about'
No route matches {:controller=>"pages", :action=>"about"}
# ./spec/controllers/pages_controller_spec.rb:22:in `block (3 levels) in <top (required)>'
What did I do wrong?
Should I have generated the about page through:
rails generate Pages about
to generate the about page? instead of copy-paste?
Had the same problem.
In my case the problem was that 'spork' needed a restart
This is because spork doesn't reload your routes. Put this in your spec_helper.rb to force spork to reload routes "each_run" (credit: http://jinpu.wordpress.com/2011/03/13/reload-routes-with-spork-each-run/)
Spork.each_run do
# This code will be run each time you run your specs.
require File.expand_path("../../config/routes", __FILE__)
end
Samesies: restart spork
It was only after I quit in frustration and came back an hour later for another look that it worked.