8

I've created a Rails Engine in the normal fashion, installed RSpec, and generated a scaffold for a model, but I can't get any routing specs to pass.

Here's one example:

describe Licensing::LicensesController do
  it 'routes to #index' do
    get('/licensing/licenses').should route_to('licensing/licenses#index')
  end
end

I'm running the examples in the dummy app like this:

$ cd spec/dummy
$ rake spec
/Users/brandan/.rvm/rubies/ruby-1.9.3-p194/bin/ruby -S rspec ../routing/licensing/licenses_routing_spec.rb
F

Failures:

  1) Licensing::LicensesController routes to #index
     Failure/Error: get('/licensing/licenses').should route_to('licensing/licenses#index')
       No route matches "/licensing/licenses"
     # /Users/brandan/repos/licensing/spec/routing/licensing/licenses_routing_spec.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.04345 seconds
1 example, 1 failure

The engine is mounted correctly in the dummy app:

# spec/dummy/config/routes.rb
Rails.application.routes.draw do
  mount Licensing::Engine => "/licensing"
end

And I can go into the dummy app and fire up the console and get that route just fine:

1.9.3p194 :001 > app.get('/licensing/licenses')
  Licensing::License Load (0.3ms)  SELECT "licensing_licenses".* FROM "licensing_licenses" 
200
1.9.3p194 :002 > app.response.body
"<!DOCTYPE html>..."

There's some discrepancy between the dummy app and RSpec, and I can't figure out what it is. I've found several articles that claim to solve this problem, but none of them have helped, and several of them are specific to Rails 3.1:

Has anybody solved this problem in Rails 3.2/RSpec 2.10?

Brandan
  • 14,735
  • 3
  • 56
  • 71
  • I'm assuming you're testing against a dummy app that integrates your engine. Are you sure that the engine is mounted in dummy app's routes? If yes, are you sure your spec is of `:type => :routing`? – Tanzeeb Khalili Aug 02 '12 at 03:36
  • @TanzeebKhalili I'm certain that the routes are correct because they work in the console and in the browser. I'm running the specs from within the dummy app. The files are under `spec/routing`, and explicitly specifying `:type => :routing` doesn't cause the examples to pass either. Any more ideas? :-/ – Brandan Aug 02 '12 at 15:39
  • 1
    How about the following changes: 1) Different described object: `describe "the routes" do ...` and 2) Different syntax: `{ :get => '/licensing/licenses' }.should be_routable` – Tanzeeb Khalili Aug 03 '12 at 07:17
  • 1
    @TanzeebKhalili Sorry, neither of those helped either. I found [a discussion on GitHub](https://github.com/rspec/rspec-rails/pull/539) that seems to indicate this is a problem with Rails and not RSpec, but there's still no solution. – Brandan Aug 03 '12 at 13:04
  • [Example Rspec Routes](https://cbabhusal.wordpress.com/2015/12/15/rails-rspec-examples-of-routing-specs/#more-1623) – Shiva Dec 15 '15 at 03:32

2 Answers2

10

Update (2013-10-31)

RSpec 2.14 now fully supports engine routes:

module MyEngine
  describe ExampleController do
    routes { MyEngine::Engine.routes }
  end
end

Add it to all routing specs:

# spec/spec_helper.rb
config.include Module.new {
  def self.included(base)
    base.routes { Reportr::Engine.routes }
  end 
}, type: :routing

The best solution I've been able to find so far is explicitly setting the route set that will be used during the tests:

RSpec.configure do |config|
  config.before(:each, type: :controller) { @routes = Licensing::Engine.routes }
  config.before(:each, type: :routing)    { @routes = Licensing::Engine.routes }
end

Then I had to rewrite my routing examples to omit the namespace:

it 'routes to #index' do
  get('/licenses').should route_to('licensing/licenses#index')
end

This seems like a bit of a hack, but it does make sense. I'm not testing whether Rails is able to mount an engine at a particular path. I'm only testing that my engine has correctly set up its own routes. Still, I'd rather not have to overwrite an instance variable to make it happen.

Here are another couple of good threads on this topic:

Community
  • 1
  • 1
Brandan
  • 14,735
  • 3
  • 56
  • 71
  • yes, and there is routes { Licensing::Engine.routes } to replace it: you can add this to a spec, but I just have to find a solution to add this to __all__ controller-specs of an engine... – mugwump Nov 15 '13 at 10:07
  • @mugwump I added an example showing how to include the routes for all routing specs at once in `spec_helper.rb`. – Brandan Nov 16 '13 at 04:28
  • @Brandan thank you! works&helps to dry out my specs! – mugwump Nov 16 '13 at 09:00
7

I think you need to explicitly inform RSpec that you are using a namespaced Rails route. EG,

# :use_route => ENGINE_NAMESPACE
:use_route => 'licensing'

Additionally, why not simplify the writting of RSpec controller tests like this,

describe Licensing::LicensesController do
  it 'GET index' do
    get :index, use_route: 'licensing'
  end
end

Here's a link for RSpec controllers I did, https://github.com/westonplatter/questionnaire_engine/tree/engine/spec/controllers

westonplatter
  • 1,475
  • 2
  • 19
  • 30
  • Thanks for your answer, but my question is specifically about routing tests — i.e., I want to explicitly test that `/licensing/licenses` routes to the correct controller and action, not just that I can `get :index` on a given controller. I think I may have found a solution, although it's not pretty. – Brandan Aug 11 '12 at 14:56