RSpec feature specs can't find routes for Rails Engine - ruby-on-rails

I'm developing a Rails Engine using rails v5.1.0 and rspec-rails 3.5.2.
I have a simple feature spec:
require "rails_helper"
module MyEngineName
RSpec.feature "Some Feature", type: :feature do
it "user can navigate to page and blah blah", :js do
visit edit_job_path(1)
# .... other stuff
end
end
end
This raises the error
undefined method `edit_job_path' for #<RSpec::ExampleGroups::SomeFeature:0x007fc098a570e8>
because the route helper edit_job_path can not be found.
Is there something special I need to do in order to allow my feature specs to access my engine routes?
The RSpec documentation mentions that you can specify the engine routes, but that only appears to be for routing specs. When I added it to the feature specs, it fails with undefined method 'routes'
Thanks!
EDIT: Since my routes file was requested, adding it here. It's pretty short -
# config/routes.rb
MyEngineName::Engine.routes.draw do
root to: redirect("/my_engine_name/jobs")
resources :jobs
end
List of all routes from rake
> rake app:routes
....
....
Routes for MyEngineName::Engine:
root GET / redirect(301, /my_engine_name/jobs)
jobs GET /jobs(.:format) my_engine_name/jobs#index
POST /jobs(.:format) my_engine_name/jobs#create
new_job GET /jobs/new(.:format) my_engine_name/jobs#new
edit_job GET /jobs/:id/edit(.:format) my_engine_name/jobs#edit
job GET /jobs/:id(.:format) my_engine_name/jobs#show
PATCH /jobs/:id(.:format) my_engine_name/jobs#update
PUT /jobs/:id(.:format) my_engine_name/jobs#update
DELETE /jobs/:id(.:format) my_engine_name/jobs#destroy

For API request specs, I tried both ways but it doesn't work
routes { MyEngine::Engine.routes }
and
RSpec.configure do |config|
config.before :each, type: :request do
helper.class.include MyEngine::Engine.routes.url_helpers
end
end
If the above solutions doesn't work, try loading helper urls as rspec configs as below:
RSpec.configure do |config|
config.include MyEngine::Engine.routes.url_helpers
end

Something from this should help. Make sure that you have MyEngineName::Engine.routes, not MyEngineName.routes
require "rails_helper"
module MyEngineName
RSpec.feature "Some Feature", type: :feature do
routes { MyEngineName::Engine.routes }
it "user can navigate to page and blah blah", :js do
# ...
or (another solution)
# place this in `spec/rails_helper.rb` file
RSpec.configure do |config|
config.before :each, type: :feature do
helper.class.include MyEngineName::Engine.routes.url_helpers
end
end

Related

Rspec producing a undefined method `route_to' , despite having rspec/rails defined in gemfile/rails helper

QUESTION: What have I done wrong that the route_to method remains undefined?
I'm very new to this but I'm trying to develop some route tests via the rspec gem.
My issue is that I am obtaining the error:
undefined method `route_to' for #<RSpec::ExampleGroups::RouteToHomepage
I have already looked through the API for this query, and I've already done the following:
Install gem 'rspec-rails'
In rails_helper.rb
require 'rspec/rails'
In my routing_spec.rb (where I am writing the routes)
require 'rails_helper'
describe "route to homepage" do
it "routes /home to index" do
expect(:get => "/homes").to route_to(
action: "index"
)
end
end
What exactly do I need to change or add, so the "route_to" method is defined? I've already read around and apparently it's defined in the "rspec-rails" gem, which I have, and already included.
From the documentation:
Routing specs are marked by :type => :routing or if you have set
config.infer_spec_type_from_file_location! by placing them in spec/routing.
You didn't say where the routing_spec.rb is located, but if it's inside the folder spec/routing/ then you could choose to enable the above config option.
Otherwise, or in general, you must do this:
require 'rails_helper'
describe "route to homepage", type: :routing do
it "routes /home to index" do
expect(:get => "/homes").to route_to(
action: "index"
)
end
end
Doing this will include the necessary RSpec helper that defines route_to, among other methods.

RSpec controller testing http://test.host/login error on index spec test

I am creating controller tests for my application. I am just trying to test the index action for my maps_controller.
I created this test for the index to see if it renders.
require 'rails_helper'
RSpec.describe MapsController, type: :controller do
describe 'GET #index' do
it 'shows a list of all maps' do
get :index
expect(response).to redirect_to maps_path
end
end
end
However when I run this spec test I get this error message.
Failure/Error: expect(response).to redirect_to maps_path
Expected response to be a redirect to http://test.host/maps but was a redirect to http://test.host/login.
Expected "http://test.host/maps" to be === "http://test.host/login".
I can understand this because it does require a user to get to this path. However, I am unsure why this is trying to go to http://test.host/maps instead of localhost:3000/maps. I was unable to find anything in RSpec docs about setting the test url. How can I set this to go to localhost:3000 instead of test.host?
You can set it globally in your spec_helper.rb file:
Since your spec is set to type: :controller, you would do it this way:
RSpec.configure do |config|
# other config options
config.before(:each) do
#request.host = "localhost:3000"
end
end
However, as of RSpec 3.5 the preferred method of testing controllers is with a :request spec. So if possible, change your spec to type: :request and then you would do it this way:
RSpec.configure do |config|
# other config options
config.before(:each) do
host! "localhost:3000"
end
end
its work for me
RSpec.configure do |config|
config.before(type: :request) do
host! "localhost:3000"
end
end
set default hosts in environment configuration:
config/environments/test.rb
config.action_mailer.default_url_options = { host: 'http://localhost' }
config.action_controller.default_url_options = { host: 'http://localhost' }
also, you probably want set default host for request, then you can override default value in rails_helper.rb like:
module ActionDispatch
class TestRequest
def host
'localhost'
end
end
end
That should be enought.

Where should I put authenticated routes tests using Devise + RSpec?

I'm pretty new to Rails.
We are using Devise to handle user authentication and RSpec for testing the application (Rails 4).
I have an Admin devise model which has access to some authenticated routes. Here's an excerpt from routes.rb:
devise_for :admins
authenticate :admin do
get 'admin', to: 'admin#index'
end
It (obviously) works flawlessly: if I visit /admin, I get redirected to /admins/sign_in and, once I sign in (or if I already am in session) I have direct access to /admin.
Now, as I understand, routes should be tested inside spec/routes/<controller_name>_routes_spec.rb. I like the idea of testing routes (and that the right controller handle each route with the right action etc.) on their own.
We're facing the issue of testing routes when the said routes are authenticated. Including
config.include Devise::TestHelpers[, type: :controller]
inside spec/spec_helper.rb still doesn't make the sign_in (or sign_[out|up]) methods available inside routes specs.
What are we supposed to do? How should we test authenticated routes?
It just feels wrong to me that non authenticated routes are tested as spec/routes, while authenticated routes should be tested inside integration tests, manually filling sign-in forms with Capybara-like stuff.
(note: I read this, but it didn't help at all)
You can include the devise helper in your routes controller by removing the conditional in your spec_helper config. Mine looks like this:
...
RSpec.configure do |config|
config.include Devise::TestHelpers
...
end
def sign_in_user( user=nil )
#user = FactoryGirl.build(:user)
#user.skip_confirmation!
#user.save!
sign_in #user
end
Or if you want to insure that you're not abusing devise in weird place you can include it in just the controller and routing tests.
RSpec.configure do |config|
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :routing
...
end
This is all assuming you're typing your spec files. One of my routing files looks like this:
require "spec_helper"
RSpec.describe WidgetsController, :type => :controller do
describe "routing" do
before(:each) do
sign_in_user
end
it "routes to #index" do
expect(:get => "/widgets").to route_to("widgets#index")
end
it "routes to #new" do
expect(:get => "/widgets/new").to route_to("widgets#new")
end
it "routes to #show" do
expect(:get => "/widgets/1").to route_to("widgets#show", :id => "1")
end
it "routes to #edit" do
expect(:get => "/widgets/1/edit").to route_to("widgets#edit", :id => "1")
end
it "routes to #create" do
expect(:post => "/widgets").to route_to("widgets#create")
end
it "routes to #update" do
expect(:put => "/widgets/1").to route_to("widgets#update", :id => "1")
end
it "routes to #destroy" do
expect(:delete => "/widgets/1").to route_to("widgets#destroy", :id => "1")
end
end
end

Multiple Rails engine rspec controller test not work

I have multiple Rails engines in my Rails 4 beta1 application. I'm installed rspec-rails gem to every engines. And I created my engine following command:
rails plugin new store_frontend --dummy-path=spec/dummy -d postgresql --skip-test-unit --mountable
In my engine's dummy application I configured database and routes. Here is example routes.rb file:
Rails.application.routes.draw do
mount StoreFrontend::Engine => "/store"
end
When I run rspec inside first engine I get following errors:
1) StoreAdmin::DashboardController GET 'index' returns http success
Failure/Error: get 'index'
ActionController::UrlGenerationError:
No route matches {:action=>"index", :controller=>"store_admin/dashboard"}
# ./spec/controllers/store_admin/dashboard_controller_spec.rb:8:in `block (3 levels) in <module:StoreAdmin>'
And here is my controller test /It's generated from Rails/:
require 'spec_helper'
module StoreFrontend
describe HomeController do
describe "GET 'index'" do
it "returns http success" do
get 'index'
response.should be_success
end
end
end
end
It seems like controller test is not working. I have model tests and it's working fine. Any idea?
UPDATE 1:
My application structure:
bin/
config/
db/
lib/
log/
public/
tmp/
engine1/
engine2/
engine3/
The solution is very simple. Add use_route to your controller test. Here is the example.
module StoreFrontend
describe HomeController do
describe "GET 'index'" do
it "returns http success" do
get 'index', use_route: 'store_frontend' # in my case
response.should be_success
end
end
end
end
The configuration and spec you show are for StoreFrontend but the error is for StoreAdmin::DashboardController. So it seems like you are just confused about which engine you are testing and/or which engine is failing.
Of course the simple solution is to create the missing route {:action=>"index", :controller=>"store_admin/dashboard"}
In order to get the routing correct when testing Rails engine controllers with Rspec, I typically add the following code to my spec_helper.rb:
RSpec.configure do |config|
config.before(:each, :type => :controller) { #routes = YourEngineName::Engine.routes }
config.before(:each, :type => :routing) { #routes = YourEngineName::Engine.routes }
end

RSpec Rails Login Filter

I recently switched started using rspec-rails(2.6.1) with my Rails(3.0.8) app. I'm used to Test::Unit, and I can't seem to get a filter working for my test methods. I like to keep things as DRY as possible, so I'd like to set up a filter that I can call on any test method that will login as an Authlogic user before the test method is called. I tried accomplishing this by using an RSpec filter in spec_helper.rb:
config.before(:each, :login_as_admin => true) do
post "/user_sessions/create", :user_session => {:username => "admin", :password => "admin"}
end
Then I use it in the corresponding test method(in this case spec/controllers/admin_controller_spec.rb):
require 'spec_helper'
describe AdminController do
describe "GET index" do
it("gives a 200 response when visited as an admin", :login_as_admin => true) do
get :index
response.code.should eq("200")
end
end
end
However, I get this error when I run rspec spec:
Failures:
1) AdminController GET index gives a 200 response when visited as an admin
Failure/Error: Unable to find matching line from backtrace
RuntimeError:
#routes is nil: make sure you set it in your test's setup method.
Blech. Can I only send one HTTP request per test? I also tried stubbing out my authenticate_admin method(inside the config.before block), without any luck.
Unfortunately, there is no way at the moment to do what you're trying to do in a globally defined before hook. The reason is that before hooks are executed in the order in which they get registered, and those declared in RSpec.configure are registered before the one that rspec-rails registers internally to set up the controller, request, response, etc.
Also, this has been reported to https://github.com/rspec/rspec-rails/issues/391.
You should use shulda's macrons. To use shoulda modify your spec_helper.rb
RSpec.configure do |config|
config.include Clearance::Shoulda::Helpers
end
And then can setup filter in controller spec like
require 'spec_helper'
describe AdminController do
fixture :users
before(:each) do
sign_in_as users(:your_user)
end
describe "GET index" do
it("gives a 200 response when visited as an admin", :login_as_admin => true) do
get :index
response.code.should eq("200")
end
end
end

Resources