From d3105066af0183ec81aa890de555f3fa287645de Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Wed, 9 Feb 2011 08:43:03 -0500 Subject: [PATCH 1/2] Build route_to matcher shortcuts This is based on the conversation at http://groups.google.com/group/rspec/browse_thread/thread/52a0935544557693/9d437ba9566527b0?lnk=gst&q=fiorini#9d437ba9566527b0. It enables a couple shortcuts for specifying routes that makes it a little more in line with Rails 3. --- .../routing_specs/route_to_matcher.feature | 20 ++++++++++++++ lib/rspec/rails/matchers/routing_matchers.rb | 26 ++++++++++++++++--- spec/rspec/rails/matchers/route_to_spec.rb | 5 ++++ 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/features/routing_specs/route_to_matcher.feature b/features/routing_specs/route_to_matcher.feature index 35cf5302fb..f804cc36a3 100644 --- a/features/routing_specs/route_to_matcher.feature +++ b/features/routing_specs/route_to_matcher.feature @@ -5,6 +5,10 @@ Feature: route_to matcher { :get => "/" }.should route_to(:controller => "welcome") + or + + get("/").should route_to("welcome#index") + Scenario: passing route spec Given a file named "spec/routing/widgets_routing_spec.rb" with: """ @@ -21,6 +25,22 @@ Feature: route_to matcher When I run "rspec spec/routing/widgets_routing_spec.rb" Then the examples should all pass + Scenario: passing route spec + Given a file named "spec/routing/widgets_routing_spec.rb" with: + """ + require "spec_helper" + + describe "routes for Widgets" do + it "routes /widgets to the widgets controller" do + get("/widgets"). + should route_to("widgets#index") + end + end + """ + + When I run "rspec spec/routing/widgets_routing_spec.rb" + Then the examples should all pass + Scenario: route spec for a route that doesn't exist (fails) Given a file named "spec/routing/widgets_routing_spec.rb" with: """ diff --git a/lib/rspec/rails/matchers/routing_matchers.rb b/lib/rspec/rails/matchers/routing_matchers.rb index 43c40914a5..f20318eb30 100644 --- a/lib/rspec/rails/matchers/routing_matchers.rb +++ b/lib/rspec/rails/matchers/routing_matchers.rb @@ -2,17 +2,36 @@ module RSpec::Rails::Matchers module RoutingMatchers extend RSpec::Matchers::DSL - matcher :route_to do |route_options| - match_unless_raises ActiveSupport::TestCase::Assertion do |path| + %w(get post put delete options head).each do |method| + define_method method do |path| + { method.to_sym => path } + end + end + + matcher :route_to do |*route_options| + match_unless_raises Test::Unit::AssertionFailedError do |path| assertion_path = { :method => path.keys.first, :path => path.values.first } - assert_recognizes(route_options, assertion_path) + + path, options = *route_options + + if path.is_a?(String) + parts = path.split("#") + options ||= {} + options.merge!({ :controller => parts.first, :action => parts.last }) + else + options = path + end + + assert_recognizes(options, assertion_path) end failure_message_for_should do rescued_exception.message end + end + matcher :be_routable do match_unless_raises ActionController::RoutingError do |path| @routing_options = routes.recognize_path( @@ -24,5 +43,6 @@ module RoutingMatchers "expected #{path.inspect} not to be routable, but it routes to #{@routing_options.inspect}" end end + end end diff --git a/spec/rspec/rails/matchers/route_to_spec.rb b/spec/rspec/rails/matchers/route_to_spec.rb index e95242564d..ed98b5aa9d 100644 --- a/spec/rspec/rails/matchers/route_to_spec.rb +++ b/spec/rspec/rails/matchers/route_to_spec.rb @@ -8,6 +8,11 @@ {:get => "path"}.should route_to("these" => "options") end + it "uses shortcut syntax" do + self.should_receive(:assert_recognizes).with({ :controller => "controller", :action => "action", :extra => "options"}, { :method=> :get, :path=>"path" }) + get("path").should route_to("controller#action", :extra => "options") + end + context "with should" do context "when assert_recognizes passes" do it "passes" do From 0730aaa4867d8f780da8d64c280aa5dd9aabe846 Mon Sep 17 00:00:00 2001 From: Joe Fiorini Date: Fri, 18 Feb 2011 14:25:52 -0500 Subject: [PATCH 2/2] Split route helpers into own module ControllerExampleGroup also includes RouteMatchers, and since Rails already implements get, post, put, etc for controller tests the helpers clash. --- lib/rspec/rails/example/routing_example_group.rb | 1 + lib/rspec/rails/matchers/routing_matchers.rb | 16 ++++++++++------ spec/rspec/rails/matchers/route_to_spec.rb | 16 +++++++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/rspec/rails/example/routing_example_group.rb b/lib/rspec/rails/example/routing_example_group.rb index 52ee055a0f..e248385979 100644 --- a/lib/rspec/rails/example/routing_example_group.rb +++ b/lib/rspec/rails/example/routing_example_group.rb @@ -6,6 +6,7 @@ module RoutingExampleGroup include RSpec::Rails::RailsExampleGroup include ActionDispatch::Assertions::RoutingAssertions include RSpec::Rails::Matchers::RoutingMatchers + include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers module InstanceMethods attr_reader :routes diff --git a/lib/rspec/rails/matchers/routing_matchers.rb b/lib/rspec/rails/matchers/routing_matchers.rb index f20318eb30..82f348572c 100644 --- a/lib/rspec/rails/matchers/routing_matchers.rb +++ b/lib/rspec/rails/matchers/routing_matchers.rb @@ -2,12 +2,6 @@ module RSpec::Rails::Matchers module RoutingMatchers extend RSpec::Matchers::DSL - %w(get post put delete options head).each do |method| - define_method method do |path| - { method.to_sym => path } - end - end - matcher :route_to do |*route_options| match_unless_raises Test::Unit::AssertionFailedError do |path| assertion_path = { :method => path.keys.first, :path => path.values.first } @@ -44,5 +38,15 @@ module RoutingMatchers end end + module RouteHelpers + + %w(get post put delete options head).each do |method| + define_method method do |path| + { method.to_sym => path } + end + end + + end + end end diff --git a/spec/rspec/rails/matchers/route_to_spec.rb b/spec/rspec/rails/matchers/route_to_spec.rb index ed98b5aa9d..3f45402ea8 100644 --- a/spec/rspec/rails/matchers/route_to_spec.rb +++ b/spec/rspec/rails/matchers/route_to_spec.rb @@ -2,15 +2,25 @@ describe "route_to" do include RSpec::Rails::Matchers::RoutingMatchers + include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers it "delegates to assert_recognizes" do self.should_receive(:assert_recognizes).with({ "these" => "options" }, { :method=> :get, :path=>"path" }) {:get => "path"}.should route_to("these" => "options") end - it "uses shortcut syntax" do - self.should_receive(:assert_recognizes).with({ :controller => "controller", :action => "action", :extra => "options"}, { :method=> :get, :path=>"path" }) - get("path").should route_to("controller#action", :extra => "options") + context "with shortcut syntax" do + + it "routes with extra options" do + self.should_receive(:assert_recognizes).with({ :controller => "controller", :action => "action", :extra => "options"}, { :method=> :get, :path=>"path" }) + get("path").should route_to("controller#action", :extra => "options") + end + + it "routes without extra options" do + self.should_receive(:assert_recognizes).with({ :controller => "controller", :action => "action"}, { :method=> :get, :path=>"path" }) + get("path").should route_to("controller#action") + end + end context "with should" do