Created
June 17, 2009 22:50
-
-
Save rjharmon/131569 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | |
# NOTE: Existing routing specs will continue passing 100%, so nobody has to change | |
# anything they have already written for rspec 1.2 compat. | |
# The current routing spec scaffold can be shortened to remove the route recognition specs. | |
# ahem. After originally posting, I realized that I hadn't tested .should get() the way I thought I had. | |
# those aren't working. So, we can punt on that part, or maybe figure out a way to get it. | |
describe SitesController do | |
it "maps #index" do | |
route_for(:controller => "sites", :action => "index").should == "/sites" | |
end | |
it "maps #new" do | |
# same as .should == | |
route_for(:controller => "sites", :action => "new").should get("/sites/new") | |
end | |
it "maps #show" do | |
route_for(:controller => "sites", :action => "show", :id => "1").should get("/sites/1") | |
end | |
it "maps #edit" do | |
route_for(:controller => "sites", :action => "edit", :id => "1").should get("/sites/1/edit") | |
end | |
it "maps #create" do | |
route_for(:controller => "sites", :action => "create").should post("/sites") | |
end | |
it "maps #update" do | |
route_for(:controller => "sites", :action => "update", :id => "1").should put("/sites/1") | |
end | |
it "maps #destroy" do | |
route_for(:controller => "sites", :action => "destroy", :id => "1").should delete("/sites/1") | |
end | |
end | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') | |
# a more detailed example where we make some actions available through /designs, and others only through /site/42/designs: | |
describe DesignsController do | |
describe "route generation" do | |
it "does not map #index at all" do | |
# be_routable() is a simple test - does it croak or not? | |
route_for( {:controller => "designs", :action => "index" } ).should_not be_routable | |
route_for( {:controller => "designs", :action => "index", :site_id => "42" } ).should_not be_routable | |
end | |
it "maps #new, but only when nested with the site" do | |
# backward-compatible assertion, still tests normal success case: | |
route_for(:controller => "designs", :action => "new", :site_id => "42" ).should == "/sites/42/designs/new" | |
route_for(:controller => "designs", :action => "new").should_not be_routable | |
end | |
it "does not map #show" do | |
route_for(:controller => "designs", :action => "show", :id => "1").should_not be_routable | |
route_for(:controller => "designs", :action => "show", :id => "1", :site_id => "42" ).should_not be_routable | |
end | |
it "maps #edit when not nested" do | |
# be_<method>() has a different failure condition. It is recommended to use it only for negative cases. | |
# So, when this passes, it's fine. | |
route_for(:controller => "designs", :action => "edit", :id => "1" ).should be_get("/designs/1/edit") | |
# ... but when it fails, it's less than informative. .should == is more | |
# informative, because it doesn't catch any of the possible exceptions. | |
route_for(:controller => "designs", :action => "edit", :id => "1" ).should == "/designs/1/edit" | |
# .should_not be_get() is useful for verifying negative cases. | |
# Because it catches the exceptions and returns false, we don't have to | |
# jump through any hoops to check those cases in our spec: | |
route_for(:controller => "designs", :action => "edit", :site_id => "42", :id => "1" ).should_not be_get("/sites/42/designs/1/edit") | |
end | |
it "maps #create, but only when nested with the site" do | |
route_for(:controller => "designs", :action => "create").should_not be_routable | |
route_for(:controller => "designs", :action => "create", :site_id => "42" ).should be_post("/sites/42/designs") | |
# backward-compatible assertion, still tests normal success case: | |
route_for(:controller => "designs", :action => "create", :site_id => "42" ).should == {:path => "/sites/42/designs", :method => :post } | |
end | |
it "maps #update" do | |
route_for(:controller => "designs", :action => "update", :id => "1").should be_put("/designs/1") | |
end | |
it "maps #destroy" do | |
route_for(:controller => "designs", :action => "destroy", :id => "1").should be_delete("/designs/1") | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class RouteFor | |
include ::Spec::Rails::Example::RoutingHelpers::ParamsFromQueryString | |
TEST_ROUTABILITY="<test routabilty only>" | |
def initialize(example, options) | |
@example, @options = example, options | |
end | |
def routable? | |
begin | |
self == TEST_ROUTABILITY | |
rescue ActionController::RoutingError | |
return false | |
rescue ActionController::MethodNotAllowed | |
return false | |
rescue Exception => e | |
if e.to_s =~ /generated path.*did not match/ | |
# that's not a routing error, just a path-matching issue - so it must have worked fine | |
return true | |
end | |
raise # re-raise the exception | |
end | |
return true | |
end | |
def ==(expected) | |
if Hash === expected | |
path, querystring = expected[:path].split('?') | |
path_string = path | |
path = expected.merge(:path => path) | |
else | |
path, querystring = expected.split('?') | |
path_string = path | |
end | |
params = querystring.blank? ? {} : @example.params_from_querystring(querystring) | |
if path_string == TEST_ROUTABILITY | |
# debugger | |
end | |
@example.assert_generates(path_string, @options, params) | |
unless path_string == TEST_ROUTABILITY | |
@example.assert_recognizes(@options, path, params) | |
end | |
true | |
end | |
def check_with_method(expected) | |
begin | |
result = ! self.==(expected) | |
rescue ActionController::MethodNotAllowed | |
return false | |
rescue Exception => e | |
e.to_s =~ /found extras/ and return false | |
raise e | |
end | |
return true | |
end | |
# these allow the .should_not be_get() expectations. | |
# they try not to raise the usual exceptions. | |
def get?(expected) | |
check_with_method({:path => expected, :method => :get}) | |
end | |
def post?(expected) | |
check_with_method({:path => expected, :method => :post}) | |
end | |
def put?(expected) | |
check_with_method({:path => expected, :method => :put}) | |
end | |
def delete?(expected) | |
check_with_method({:path => expected, :method => :delete}) | |
end | |
# these allow an alternate form of ==, shortening the required syntax | |
# but allowing exceptions to be displayed as desired for positive cases. | |
# usage: route_for(...).should get("/path") | |
def get(expected) | |
self == {:path => expected, :method => :get} | |
end | |
def post(expected) | |
self == {:path => expected, :method => :post} | |
end | |
def put(expected) | |
self == {:path => expected, :method => :put} | |
end | |
def delete(expected) | |
self == {:path => expected, :method => :delete} | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ahem. After originally posting, I realized that I hadn't tested .should get() the way I thought I had. | |
# those aren't working. So, we can punt on that part, or maybe figure out a way to get it. | |
# that 'ahem' might obsolete the following. | |
I'm not 100% perfectly satisfied with the discrepancy between .should post() and .should_not be_post(). | |
They do each read intuitively, which I like. .should be_post() does also read okay, and it operates | |
fine for success cases. I'm not loving its uninformative failure case, but if the scaffold demonstrates | |
with .should post(), it's probably fine. | |
The part that leaves me unsettled is, route_for().should_not post(). If you specify this, all the | |
expected failures will be uncaught, resulting in exceptions when should_not post() *should* technically | |
pass. If the post() part is true, a reasonable message will appear griping that it should_not have | |
passed. | |
Maybe we can have get() and friends be implemented as wrap_equals(), which catches the exceptions and | |
adds a suggestion that if they were hoping to should_not() the test, they should use be_foo() instead | |
of foo(). UPDATE: I have tested a version of this exception-wrapping, using be_posty() method instead | |
of a post() method, and it works very well. Failures do show a very reasonable suggestion to do a more | |
useful thing for a should_not test. | |
An optional match_negative() method on custom matchers would allow us to do some nice things here. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment