I'm working on an application that will be primarily served as an API (other than a few minor views, such as session/registration, which will be "standard"). I like the approach that was finalized in Railscast #350: Versioning an API, and so followed it. My routes look like:
namespace :api, :defaults => {:format => 'json'} do
scope :module => :v1, :constraints => ApiConstraints.new(:version => 1, :default => false) do
resources :posts, :only => [:create, :show, :destroy, :index]
end
scope :module => :v2, :constraints => ApiConstraints.new(:version => 2, :default => true) do
resources :posts, :only => [:create, :show, :destroy, :index]
end
end
In each route, my Constraint is a new ApiConstraints object, which is located in my ./lib
folder. The class looks like this:
class ApiConstraints
def initialize(options)
@version = options[:version]
@default = options[:default]
end
def matches?(req)
@default || req.headers['Accept'].include?("application/vnd.MYAPP.v#{@version}")
end
end
Now, when testing manually, everything works as expected. In my API, I may have between 5 and 10 controllers per version, and don't want to test that the API constraints works for each individual controller, as that makes no sense. I'm looking for one spec file that tests my API constraints, but I'm unsure of where to put that spec.
I've tried adding a spec/routing/api_spec.rb
file to test things, but it's not working properly, as it complains that some things aren't provided, like so:
it "should route an unversioned request to the latest version" do
expect(:get => "/api/posts", :format => "json").to route_to(:controller => "api/v1/posts")
end
The above throws an error even though the controller matches properly. It fails with the following error:
The recognized options <{"format"=>"json", "action"=>"index", "controller"=>"api/v1/posts"}>
did not match <{"controller"=>"api/v1/posts"}>,
difference: <{"format"=>"json", "action"=>"index"}>.
Notice that the controller was properly determined, but since I don't want to test for the format and action in this test, it errors out. I would like there to be 3 "API specs":
- It should route an unversioned request to the latest version
- It should default to the JSON format if none is specified
- It should return a specified API version when requested
Does anyone have experience with writing specs for these kinds of routes? I don't want to add specs for every controller inside the API, as they're not responsible for this functionality.