Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you test route constraints using RSpec

Given a couple of cities in the DB:

City.first.attributes => {:id => 1, :name => 'nyc'}
City.last.attributes =>  {:id => 2, :name => 'boston'}

And a route like:

match '/:city/*dest' => 'cities#do_something', :constraints => {:city => /#{City.all.map{|c| c.name}.join('|'}/}

(so the constraints should evaluate to: /nyc|boston/)

And a spec:

it "recognizes and generates a route for city specific paths" do
  { :put => '/bad-city/some/path' }.should route_to({:controller => "cities", :action => "do_something", :dest => 'some/path', :city => 'bad-city'})
end

I would expect a failure. But it passes.

Likewise:

it "doesn't route bad city names" do
  { :put => '/some-bad-city/some/path' }.should_not be_routable
end

Here I expect it to pass, but it fails.

It seems the constraint is being ignored in the specs, since the matching cities have the same behavior as the bad ones.

Is this a known issue, or am I missing something that I need to do?

like image 455
Matt Van Horn Avatar asked Oct 04 '10 14:10

Matt Van Horn


People also ask

How should you test routes in Rails?

Routes should be done as part of integration tests. Integration tests are where you test the important work flows of your application - more specifically whether a URL is defined or not seems to be an important workflow.

What is RSpec testing?

RSpec is a unit test framework for the Ruby programming language. RSpec is different than traditional xUnit frameworks like JUnit because RSpec is a Behavior driven development tool. What this means is that, tests written in RSpec focus on the "behavior" of an application being tested.

Is RSpec BDD or TDD?

RSpec is a testing tool for Ruby, created for behavior-driven development (BDD). It is the most frequently used testing library for Ruby in production applications. Even though it has a very rich and powerful DSL (domain-specific language), at its core it is a simple tool which you can start using rather quickly.

What is a fixture RSpec?

Fixtures allow you to define a large set of sample data ahead of time and store them as YAML files inside your spec directory, inside another directory called fixtures. When you're test sweep first starts up RSpec will use those fixture files to prepopulate your database tables.


1 Answers

This approach works: In routes.rb

match '/:city/*destination' => 'cities#myaction', :constraints => {:city => /#{City.all.map{|c|c.slug}.join('|')}/}

In the spec:

describe "routing" do
  before(:each) do
    @mock_city = mock_model(City, :id => 42, :slug => 'some-city')
    City.stub!(:find_by_slug => @mock_city, :all => [@mock_city])
    MyApp::Application.reload_routes!
  end

  it "recognizes and generates a route for city specific paths" do
    { :get => '/some-city/some/path' }.should route_to({:controller => "cities", :action => "myaction", :destination => 'some/path', :city => 'some-city'})
  end

  it "rejects city paths for cities that don't exist in the DB" do
    { :get => '/some-bad-city/some/path' }.should_not be_routable
  end
end

Lastly, I added an observer to reload routes whenever the cities table changes.

like image 148
Matt Van Horn Avatar answered Oct 16 '22 02:10

Matt Van Horn