thoughtbot-shoulda 2.10.2 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. data/CONTRIBUTION_GUIDELINES.rdoc +5 -5
  2. data/README.rdoc +72 -89
  3. data/Rakefile +31 -33
  4. data/lib/shoulda.rb +6 -6
  5. data/lib/shoulda/action_controller.rb +8 -0
  6. data/lib/shoulda/action_controller/macros.rb +54 -73
  7. data/lib/shoulda/action_controller/matchers.rb +7 -5
  8. data/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +10 -7
  9. data/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +18 -1
  10. data/lib/shoulda/action_controller/matchers/redirect_to_matcher.rb +62 -0
  11. data/lib/shoulda/action_controller/matchers/render_template_matcher.rb +54 -0
  12. data/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +33 -15
  13. data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +10 -10
  14. data/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +17 -13
  15. data/lib/shoulda/action_controller/matchers/route_matcher.rb +3 -3
  16. data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +13 -2
  17. data/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +1 -1
  18. data/lib/shoulda/action_mailer.rb +3 -0
  19. data/lib/shoulda/action_mailer/assertions.rb +4 -0
  20. data/lib/shoulda/action_mailer/matchers.rb +22 -0
  21. data/lib/shoulda/action_mailer/matchers/have_sent_email.rb +110 -0
  22. data/lib/shoulda/active_record/helpers.rb +8 -3
  23. data/lib/shoulda/active_record/macros.rb +88 -143
  24. data/lib/shoulda/active_record/matchers.rb +0 -1
  25. data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +1 -1
  26. data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +10 -2
  27. data/lib/shoulda/active_record/matchers/association_matcher.rb +8 -8
  28. data/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +1 -1
  29. data/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +2 -2
  30. data/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +11 -11
  31. data/lib/shoulda/active_record/matchers/have_db_index_matcher.rb +8 -8
  32. data/lib/shoulda/active_record/matchers/validate_format_of_matcher.rb +2 -4
  33. data/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +3 -3
  34. data/lib/shoulda/active_record/matchers/validation_matcher.rb +0 -1
  35. data/lib/shoulda/assertions.rb +10 -2
  36. data/lib/shoulda/autoload_macros.rb +20 -20
  37. data/lib/shoulda/context.rb +70 -39
  38. data/lib/shoulda/{rspec.rb → integrations/rspec.rb} +2 -0
  39. data/lib/shoulda/integrations/rspec2.rb +22 -0
  40. data/lib/shoulda/{test_unit.rb → integrations/test_unit.rb} +0 -0
  41. data/lib/shoulda/macros.rb +46 -18
  42. data/lib/shoulda/rails.rb +0 -5
  43. data/lib/shoulda/tasks/yaml_to_shoulda.rake +11 -11
  44. data/lib/shoulda/version.rb +4 -0
  45. data/rails/init.rb +3 -2
  46. data/test/fail_macros.rb +20 -4
  47. data/test/functional/posts_controller_test.rb +7 -7
  48. data/test/functional/users_controller_test.rb +1 -1
  49. data/test/matchers/action_mailer/have_sent_email_test.rb +70 -0
  50. data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +7 -1
  51. data/test/matchers/active_record/allow_value_matcher_test.rb +1 -1
  52. data/test/matchers/active_record/association_matcher_test.rb +16 -16
  53. data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +3 -2
  54. data/test/matchers/active_record/ensure_length_of_matcher_test.rb +1 -1
  55. data/test/matchers/active_record/have_db_column_matcher_test.rb +1 -1
  56. data/test/matchers/active_record/have_db_index_matcher_test.rb +1 -1
  57. data/test/matchers/active_record/have_readonly_attributes_matcher_test.rb +1 -1
  58. data/test/matchers/active_record/validate_acceptance_of_matcher_test.rb +1 -1
  59. data/test/matchers/active_record/validate_format_of_matcher_test.rb +1 -1
  60. data/test/matchers/active_record/validate_numericality_of_matcher_test.rb +1 -1
  61. data/test/matchers/active_record/validate_presence_of_matcher_test.rb +1 -1
  62. data/test/matchers/active_record/validate_uniqueness_of_matcher_test.rb +1 -1
  63. data/test/matchers/controller/assign_to_matcher_test.rb +11 -1
  64. data/test/matchers/controller/filter_param_matcher_test.rb +10 -2
  65. data/test/matchers/controller/redirect_to_matcher_test.rb +37 -0
  66. data/test/matchers/controller/render_template_matcher_test.rb +37 -0
  67. data/test/matchers/controller/render_with_layout_matcher_test.rb +15 -1
  68. data/test/matchers/controller/respond_with_content_type_matcher_test.rb +1 -1
  69. data/test/matchers/controller/respond_with_matcher_test.rb +1 -11
  70. data/test/matchers/controller/route_matcher_test.rb +18 -1
  71. data/test/matchers/controller/set_session_matcher_test.rb +11 -1
  72. data/test/matchers/controller/set_the_flash_matcher.rb +1 -1
  73. data/test/other/autoload_macro_test.rb +1 -1
  74. data/test/other/context_test.rb +210 -27
  75. data/test/other/convert_to_should_syntax_test.rb +1 -1
  76. data/test/other/helpers_test.rb +13 -36
  77. data/test/other/private_helpers_test.rb +2 -2
  78. data/test/other/should_test.rb +13 -13
  79. data/test/{model_builder.rb → rails2_model_builder.rb} +32 -8
  80. data/test/{rails_root → rails2_root}/app/controllers/application_controller.rb +0 -3
  81. data/test/{rails_root → rails2_root}/app/controllers/posts_controller.rb +0 -0
  82. data/test/{rails_root → rails2_root}/app/controllers/users_controller.rb +0 -0
  83. data/test/{rails_root → rails2_root}/app/helpers/application_helper.rb +0 -0
  84. data/test/{rails_root → rails2_root}/app/helpers/posts_helper.rb +0 -0
  85. data/test/{rails_root → rails2_root}/app/helpers/users_helper.rb +0 -0
  86. data/test/{rails_root → rails2_root}/app/models/address.rb +0 -0
  87. data/test/rails2_root/app/models/flea.rb +11 -0
  88. data/test/{rails_root → rails2_root}/app/models/friendship.rb +0 -0
  89. data/test/rails2_root/app/models/notifier.rb +8 -0
  90. data/test/{rails_root → rails2_root}/app/models/pets/cat.rb +0 -0
  91. data/test/{rails_root → rails2_root}/app/models/pets/dog.rb +0 -0
  92. data/test/{rails_root → rails2_root}/app/models/post.rb +1 -1
  93. data/test/{rails_root → rails2_root}/app/models/product.rb +0 -0
  94. data/test/{rails_root → rails2_root}/app/models/profile.rb +0 -0
  95. data/test/{rails_root → rails2_root}/app/models/registration.rb +0 -0
  96. data/test/{rails_root → rails2_root}/app/models/tag.rb +0 -0
  97. data/test/{rails_root → rails2_root}/app/models/tagging.rb +0 -0
  98. data/test/{rails_root → rails2_root}/app/models/treat.rb +0 -0
  99. data/test/{rails_root → rails2_root}/app/models/user.rb +0 -0
  100. data/test/{rails_root → rails2_root}/app/views/layouts/posts.rhtml +0 -0
  101. data/test/{rails_root → rails2_root}/app/views/layouts/users.rhtml +0 -0
  102. data/test/{rails_root → rails2_root}/app/views/layouts/wide.html.erb +0 -0
  103. data/test/rails2_root/app/views/notifier/the_email.html.erb +1 -0
  104. data/test/{rails_root → rails2_root}/app/views/posts/edit.rhtml +0 -0
  105. data/test/{rails_root → rails2_root}/app/views/posts/index.rhtml +0 -0
  106. data/test/{rails_root → rails2_root}/app/views/posts/new.rhtml +0 -0
  107. data/test/{rails_root → rails2_root}/app/views/posts/show.rhtml +0 -0
  108. data/test/{rails_root → rails2_root}/app/views/users/edit.rhtml +0 -0
  109. data/test/{rails_root → rails2_root}/app/views/users/index.rhtml +0 -0
  110. data/test/{rails_root → rails2_root}/app/views/users/new.rhtml +0 -0
  111. data/test/{rails_root → rails2_root}/app/views/users/show.rhtml +0 -0
  112. data/test/{rails_root → rails2_root}/config/boot.rb +0 -0
  113. data/test/{rails_root → rails2_root}/config/database.yml +1 -1
  114. data/test/{rails_root → rails2_root}/config/environment.rb +0 -1
  115. data/test/rails2_root/config/environments/test.rb +23 -0
  116. data/test/{rails_root → rails2_root}/config/initializers/new_rails_defaults.rb +0 -0
  117. data/test/{rails_root → rails2_root}/config/initializers/shoulda.rb +0 -0
  118. data/test/{rails_root → rails2_root}/config/routes.rb +0 -0
  119. data/test/{rails_root → rails2_root}/db/migrate/001_create_users.rb +0 -0
  120. data/test/{rails_root → rails2_root}/db/migrate/002_create_posts.rb +0 -0
  121. data/test/{rails_root → rails2_root}/db/migrate/003_create_taggings.rb +0 -0
  122. data/test/{rails_root → rails2_root}/db/migrate/004_create_tags.rb +0 -0
  123. data/test/{rails_root → rails2_root}/db/migrate/005_create_dogs.rb +0 -0
  124. data/test/{rails_root → rails2_root}/db/migrate/006_create_addresses.rb +0 -0
  125. data/test/{rails_root → rails2_root}/db/migrate/007_create_fleas.rb +0 -0
  126. data/test/{rails_root → rails2_root}/db/migrate/008_create_dogs_fleas.rb +0 -0
  127. data/test/{rails_root → rails2_root}/db/migrate/009_create_products.rb +0 -0
  128. data/test/{rails_root → rails2_root}/db/migrate/010_create_friendships.rb +0 -0
  129. data/test/{rails_root → rails2_root}/db/migrate/011_create_treats.rb +0 -0
  130. data/test/{rails_root → rails2_root}/db/migrate/20090506203502_create_profiles.rb +0 -0
  131. data/test/{rails_root → rails2_root}/db/migrate/20090506203536_create_registrations.rb +0 -0
  132. data/test/{rails_root → rails2_root}/db/migrate/20090513104502_create_cats.rb +0 -0
  133. data/test/{rails_root → rails2_root}/db/schema.rb +0 -0
  134. data/test/{rails_root → rails2_root}/public/404.html +0 -0
  135. data/test/{rails_root → rails2_root}/public/422.html +0 -0
  136. data/test/{rails_root → rails2_root}/public/500.html +0 -0
  137. data/test/{rails_root → rails2_root}/script/console +0 -0
  138. data/test/{rails_root → rails2_root}/script/generate +0 -0
  139. data/test/{rails_root → rails2_root}/test/shoulda_macros/custom_macro.rb +0 -0
  140. data/test/{rails_root → rails2_root}/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +0 -0
  141. data/test/{rails_root → rails2_root}/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +0 -0
  142. data/test/rails2_test_helper.rb +6 -0
  143. data/test/rails3_model_builder.rb +118 -0
  144. data/test/rails3_root/Gemfile +28 -0
  145. data/test/rails3_root/README +244 -0
  146. data/test/rails3_root/Rakefile +10 -0
  147. data/test/rails3_root/app/controllers/application_controller.rb +22 -0
  148. data/test/rails3_root/app/controllers/posts_controller.rb +87 -0
  149. data/test/rails3_root/app/controllers/users_controller.rb +82 -0
  150. data/test/rails3_root/app/helpers/application_helper.rb +2 -0
  151. data/test/rails3_root/app/models/address.rb +7 -0
  152. data/test/rails3_root/app/models/flea.rb +11 -0
  153. data/test/rails3_root/app/models/friendship.rb +4 -0
  154. data/test/rails3_root/app/models/notifier.rb +8 -0
  155. data/test/rails3_root/app/models/pets/cat.rb +7 -0
  156. data/test/rails3_root/app/models/pets/dog.rb +10 -0
  157. data/test/rails3_root/app/models/post.rb +12 -0
  158. data/test/rails3_root/app/models/product.rb +12 -0
  159. data/test/rails3_root/app/models/profile.rb +2 -0
  160. data/test/rails3_root/app/models/registration.rb +2 -0
  161. data/test/rails3_root/app/models/tag.rb +8 -0
  162. data/test/rails3_root/app/models/tagging.rb +4 -0
  163. data/test/rails3_root/app/models/treat.rb +3 -0
  164. data/test/rails3_root/app/models/user.rb +32 -0
  165. data/test/rails3_root/app/views/layouts/application.html.erb +14 -0
  166. data/test/rails3_root/app/views/layouts/posts.rhtml +19 -0
  167. data/test/rails3_root/app/views/layouts/users.rhtml +17 -0
  168. data/test/rails3_root/app/views/layouts/wide.html.erb +1 -0
  169. data/test/rails3_root/app/views/notifier/the_email.html.erb +1 -0
  170. data/test/rails3_root/app/views/posts/edit.rhtml +27 -0
  171. data/test/rails3_root/app/views/posts/index.rhtml +25 -0
  172. data/test/rails3_root/app/views/posts/new.rhtml +24 -0
  173. data/test/rails3_root/app/views/posts/show.rhtml +18 -0
  174. data/test/rails3_root/app/views/users/edit.rhtml +22 -0
  175. data/test/rails3_root/app/views/users/index.rhtml +22 -0
  176. data/test/rails3_root/app/views/users/new.rhtml +21 -0
  177. data/test/rails3_root/app/views/users/show.rhtml +13 -0
  178. data/test/rails3_root/config.ru +4 -0
  179. data/test/rails3_root/config/application.rb +46 -0
  180. data/test/rails3_root/config/boot.rb +6 -0
  181. data/test/rails3_root/config/database.yml +22 -0
  182. data/test/rails3_root/config/environment.rb +5 -0
  183. data/test/rails3_root/config/environments/development.rb +19 -0
  184. data/test/rails3_root/config/environments/production.rb +42 -0
  185. data/test/rails3_root/config/environments/test.rb +32 -0
  186. data/test/rails3_root/config/initializers/backtrace_silencers.rb +7 -0
  187. data/test/rails3_root/config/initializers/inflections.rb +10 -0
  188. data/test/rails3_root/config/initializers/mime_types.rb +5 -0
  189. data/test/rails3_root/config/initializers/secret_token.rb +7 -0
  190. data/test/rails3_root/config/initializers/session_store.rb +8 -0
  191. data/test/rails3_root/config/locales/en.yml +5 -0
  192. data/test/rails3_root/config/routes.rb +4 -0
  193. data/test/rails3_root/db/migrate/001_create_users.rb +19 -0
  194. data/test/rails3_root/db/migrate/002_create_posts.rb +13 -0
  195. data/test/rails3_root/db/migrate/003_create_taggings.rb +12 -0
  196. data/test/rails3_root/db/migrate/004_create_tags.rb +11 -0
  197. data/test/rails3_root/db/migrate/005_create_dogs.rb +12 -0
  198. data/test/rails3_root/db/migrate/006_create_addresses.rb +14 -0
  199. data/test/rails3_root/db/migrate/007_create_fleas.rb +11 -0
  200. data/test/rails3_root/db/migrate/008_create_dogs_fleas.rb +12 -0
  201. data/test/rails3_root/db/migrate/009_create_products.rb +17 -0
  202. data/test/rails3_root/db/migrate/010_create_friendships.rb +14 -0
  203. data/test/rails3_root/db/migrate/011_create_treats.rb +12 -0
  204. data/test/rails3_root/db/migrate/20090506203502_create_profiles.rb +12 -0
  205. data/test/rails3_root/db/migrate/20090506203536_create_registrations.rb +14 -0
  206. data/test/rails3_root/db/migrate/20090513104502_create_cats.rb +12 -0
  207. data/test/rails3_root/db/seeds.rb +7 -0
  208. data/test/rails3_root/public/404.html +26 -0
  209. data/test/rails3_root/public/422.html +26 -0
  210. data/test/rails3_root/public/500.html +26 -0
  211. data/test/{rails_root/config/environments/test.rb → rails3_root/public/favicon.ico} +0 -0
  212. data/test/rails3_root/public/images/rails.png +0 -0
  213. data/test/rails3_root/public/index.html +279 -0
  214. data/test/rails3_root/public/javascripts/application.js +2 -0
  215. data/test/rails3_root/public/javascripts/controls.js +965 -0
  216. data/test/rails3_root/public/javascripts/dragdrop.js +974 -0
  217. data/test/rails3_root/public/javascripts/effects.js +1123 -0
  218. data/test/rails3_root/public/javascripts/prototype.js +4874 -0
  219. data/test/rails3_root/public/javascripts/rails.js +118 -0
  220. data/test/rails3_root/public/robots.txt +5 -0
  221. data/test/rails3_root/script/rails +9 -0
  222. data/test/rails3_root/test/performance/browsing_test.rb +9 -0
  223. data/test/rails3_root/test/test_helper.rb +13 -0
  224. data/test/rails3_test_helper.rb +6 -0
  225. data/test/test_helper.rb +16 -8
  226. data/test/unit/address_test.rb +1 -1
  227. data/test/unit/cat_test.rb +1 -1
  228. data/test/unit/dog_test.rb +1 -1
  229. data/test/unit/flea_test.rb +9 -1
  230. data/test/unit/friendship_test.rb +1 -1
  231. data/test/unit/post_test.rb +1 -5
  232. data/test/unit/product_test.rb +1 -1
  233. data/test/unit/tag_test.rb +1 -5
  234. data/test/unit/tagging_test.rb +1 -1
  235. data/test/unit/user_test.rb +3 -37
  236. metadata +184 -118
  237. data/lib/shoulda/action_view.rb +0 -10
  238. data/lib/shoulda/action_view/macros.rb +0 -61
  239. data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +0 -128
  240. data/test/matchers/active_record/have_named_scope_matcher_test.rb +0 -65
  241. data/test/rails_root/app/models/flea.rb +0 -3
@@ -6,30 +6,32 @@ require 'shoulda/action_controller/matchers/respond_with_matcher'
6
6
  require 'shoulda/action_controller/matchers/respond_with_content_type_matcher'
7
7
  require 'shoulda/action_controller/matchers/set_session_matcher'
8
8
  require 'shoulda/action_controller/matchers/route_matcher'
9
+ require 'shoulda/action_controller/matchers/redirect_to_matcher'
10
+ require 'shoulda/action_controller/matchers/render_template_matcher'
9
11
 
10
12
  module Shoulda # :nodoc:
11
13
  module ActionController # :nodoc:
12
14
 
13
15
  # By using the macro helpers you can quickly and easily create concise and
14
16
  # easy to read test suites.
15
- #
17
+ #
16
18
  # This code segment:
17
- #
19
+ #
18
20
  # describe UsersController, "on GET to show with a valid id" do
19
21
  # before(:each) do
20
22
  # get :show, :id => User.first.to_param
21
23
  # end
22
- #
24
+ #
23
25
  # it { should assign_to(:user) }
24
26
  # it { should respond_with(:success) }
25
27
  # it { should render_template(:show) }
26
28
  # it { should not_set_the_flash) }
27
- #
29
+ #
28
30
  # it "should do something else really cool" do
29
31
  # assigns[:user].id.should == 1
30
32
  # end
31
33
  # end
32
- #
34
+ #
33
35
  # Would produce 5 tests for the show action
34
36
  module Matchers
35
37
  end
@@ -30,13 +30,15 @@ module Shoulda # :nodoc:
30
30
  self
31
31
  end
32
32
 
33
- def with(expected_value)
33
+ def with(expected_value = nil, &block)
34
34
  @expected_value = expected_value
35
+ @expectation_block = block
35
36
  self
36
37
  end
37
38
 
38
39
  def matches?(controller)
39
40
  @controller = controller
41
+ @expected_value = @context.instance_eval(&@expectation_block) if @expectation_block
40
42
  assigned_value? && kind_of_expected_class? && equal_to_expected_value?
41
43
  end
42
44
 
@@ -48,6 +50,11 @@ module Shoulda # :nodoc:
48
50
  description
49
51
  end
50
52
 
53
+ def in_context(context)
54
+ @context = context
55
+ self
56
+ end
57
+
51
58
  private
52
59
 
53
60
  def assigned_value?
@@ -56,7 +63,7 @@ module Shoulda # :nodoc:
56
63
  "Expected action to assign a value for @#{@variable}"
57
64
  false
58
65
  else
59
- @negative_failure_message =
66
+ @negative_failure_message =
60
67
  "Didn't expect action to assign a value for @#{@variable}, " <<
61
68
  "but it was assigned to #{assigned_value.inspect}"
62
69
  true
@@ -95,11 +102,7 @@ module Shoulda # :nodoc:
95
102
  end
96
103
 
97
104
  def assigned_value
98
- assigns[@variable]
99
- end
100
-
101
- def assigns
102
- @controller.response.template.assigns
105
+ @controller.instance_variable_get("@#{@variable}")
103
106
  end
104
107
 
105
108
  end
@@ -37,7 +37,8 @@ module Shoulda # :nodoc:
37
37
  private
38
38
 
39
39
  def filters_params?
40
- @controller.respond_to?(:filter_parameters)
40
+ @controller.respond_to?(:filter_parameters) ||
41
+ request.respond_to?(:filtered_parameters)
41
42
  end
42
43
 
43
44
  def filters_key?
@@ -45,11 +46,27 @@ module Shoulda # :nodoc:
45
46
  end
46
47
 
47
48
  def filtered_value
49
+ if request.respond_to?(:filtered_parameters)
50
+ filtered_request_value
51
+ else
52
+ filtered_controller_value
53
+ end
54
+ end
55
+
56
+ def filtered_controller_value
48
57
  filtered = @controller.send(:filter_parameters,
49
58
  @key.to_s => @key.to_s)
50
59
  filtered[@key.to_s]
51
60
  end
52
61
 
62
+ def filtered_request_value
63
+ request.env['action_dispatch.request.parameters'] = { @key.to_s => 'value' }
64
+ request.filtered_parameters[@key.to_s]
65
+ end
66
+
67
+ def request
68
+ @request ||= ::ActionController::TestRequest.new
69
+ end
53
70
  end
54
71
 
55
72
  end
@@ -0,0 +1,62 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionController # :nodoc:
3
+ module Matchers
4
+
5
+ # Ensures a controller redirected to the given url.
6
+ #
7
+ # Example:
8
+ #
9
+ # it { should redirect_to('http://somewhere.com') }
10
+ # it { should redirect_to(users_path) }
11
+ def redirect_to(url_or_description, &block)
12
+ RedirectToMatcher.new(url_or_description, self, &block)
13
+ end
14
+
15
+ class RedirectToMatcher # :nodoc:
16
+
17
+ def initialize(url_or_description, context, &block)
18
+ if block
19
+ @url_block = block
20
+ @location = @url_or_description
21
+ else
22
+ @url = url_or_description
23
+ @location = @url
24
+ end
25
+ @context = context
26
+ end
27
+
28
+ def in_context(context)
29
+ @context = context
30
+ self
31
+ end
32
+
33
+ def matches?(controller)
34
+ @controller = controller
35
+ redirects_to_url?
36
+ end
37
+
38
+ attr_reader :failure_message, :negative_failure_message
39
+
40
+ def description
41
+ "redirect to #{@location}"
42
+ end
43
+
44
+ private
45
+
46
+ def redirects_to_url?
47
+ @url = @context.instance_eval(&@url_block) if @url_block
48
+ begin
49
+ @context.send(:assert_redirected_to, @url)
50
+ @negative_failure_message = "Didn't expect to redirect to #{@url}"
51
+ true
52
+ rescue Test::Unit::AssertionFailedError => error
53
+ @failure_message = error.message
54
+ false
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,54 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionController # :nodoc:
3
+ module Matchers
4
+
5
+ # Ensures a controller rendered the given template.
6
+ #
7
+ # Example:
8
+ #
9
+ # it { should render_template(:show) }
10
+ def render_template(template)
11
+ RenderTemplateMatcher.new(template, self)
12
+ end
13
+
14
+ class RenderTemplateMatcher # :nodoc:
15
+
16
+ def initialize(template, context)
17
+ @template = template.to_s
18
+ @context = context
19
+ end
20
+
21
+ def matches?(controller)
22
+ @controller = controller
23
+ renders_template?
24
+ end
25
+
26
+ attr_reader :failure_message, :negative_failure_message
27
+
28
+ def description
29
+ "render template #{@template}"
30
+ end
31
+
32
+ def in_context(context)
33
+ @context = context
34
+ self
35
+ end
36
+
37
+ private
38
+
39
+ def renders_template?
40
+ begin
41
+ @context.send(:assert_template, @template)
42
+ @negative_failure_message = "Didn't expect to render #{@template}"
43
+ true
44
+ rescue Test::Unit::AssertionFailedError => error
45
+ @failure_message = error.message
46
+ false
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -9,14 +9,21 @@ module Shoulda # :nodoc:
9
9
  # it { should render_with_layout }
10
10
  # it { should render_with_layout(:special) }
11
11
  # it { should_not render_with_layout }
12
- def render_with_layout(layout = nil)
13
- RenderWithLayout.new(layout)
12
+ def render_with_layout(expected_layout = nil)
13
+ RenderWithLayout.new(expected_layout)
14
14
  end
15
15
 
16
16
  class RenderWithLayout # :nodoc:
17
17
 
18
- def initialize(layout)
19
- @layout = layout.to_s unless layout.nil?
18
+ def initialize(expected_layout)
19
+ @expected_layout = expected_layout.to_s unless expected_layout.nil?
20
+ end
21
+
22
+ # Used to provide access to layouts recorded by
23
+ # ActionController::TemplateAssertions in Rails 3
24
+ def in_context(context)
25
+ @context = context
26
+ self
20
27
  end
21
28
 
22
29
  def matches?(controller)
@@ -34,10 +41,10 @@ module Shoulda # :nodoc:
34
41
 
35
42
  def description
36
43
  description = "render with "
37
- if @layout.nil?
44
+ if @expected_layout.nil?
38
45
  description << "a layout"
39
46
  else
40
- description << "the #{@layout.inspect} layout"
47
+ description << "the #{@expected_layout.inspect} layout"
41
48
  end
42
49
  description
43
50
  end
@@ -45,20 +52,30 @@ module Shoulda # :nodoc:
45
52
  private
46
53
 
47
54
  def rendered_with_layout?
48
- !layout.blank?
55
+ !rendered_layouts.empty?
49
56
  end
50
57
 
51
58
  def rendered_with_expected_layout?
52
- return true if @layout.nil?
53
- layout == @layout
59
+ return true if @expected_layout.nil?
60
+ rendered_layouts.include?(@expected_layout)
54
61
  end
55
62
 
56
- def layout
57
- layout = @controller.response.layout
58
- if layout.nil?
59
- nil
63
+ def rendered_layouts
64
+ if recorded_layouts
65
+ recorded_layouts.keys.compact.map { |layout| layout.sub(%r{^layouts/}, '') }
60
66
  else
61
- layout.split('/').last
67
+ layout = @controller.response.layout
68
+ if layout.nil?
69
+ []
70
+ else
71
+ [layout.split('/').last]
72
+ end
73
+ end
74
+ end
75
+
76
+ def recorded_layouts
77
+ if @context
78
+ @context.instance_variable_get('@layouts')
62
79
  end
63
80
  end
64
81
 
@@ -68,7 +85,8 @@ module Shoulda # :nodoc:
68
85
 
69
86
  def result
70
87
  if rendered_with_layout?
71
- "rendered with the #{layout.inspect} layout"
88
+ "rendered with " <<
89
+ rendered_layouts.map { |layout| layout.inspect }.join(", ")
72
90
  else
73
91
  "rendered without a layout"
74
92
  end
@@ -34,7 +34,7 @@ module Shoulda # :nodoc:
34
34
  def description
35
35
  "respond with content type of #{@content_type}"
36
36
  end
37
-
37
+
38
38
  def matches?(controller)
39
39
  @controller = controller
40
40
  if @content_type.is_a?(Regexp)
@@ -43,32 +43,32 @@ module Shoulda # :nodoc:
43
43
  response_content_type == @content_type
44
44
  end
45
45
  end
46
-
46
+
47
47
  def failure_message
48
48
  "Expected #{expectation}"
49
49
  end
50
-
50
+
51
51
  def negative_failure_message
52
52
  "Did not expect #{expectation}"
53
53
  end
54
-
54
+
55
55
  protected
56
-
56
+
57
57
  def response_content_type
58
- @controller.response.content_type
58
+ @controller.response.content_type.to_s
59
59
  end
60
-
60
+
61
61
  def lookup_by_extension(extension)
62
62
  Mime::Type.lookup_by_extension(extension.to_s).to_s
63
63
  end
64
-
64
+
65
65
  def expectation
66
66
  "content type to be #{@content_type}, " <<
67
67
  "but was #{response_content_type}"
68
68
  end
69
-
69
+
70
70
  end
71
-
71
+
72
72
  end
73
73
  end
74
74
  end
@@ -24,16 +24,16 @@ module Shoulda # :nodoc:
24
24
  def initialize(status)
25
25
  @status = symbol_to_status_code(status)
26
26
  end
27
-
27
+
28
28
  def matches?(controller)
29
29
  @controller = controller
30
30
  correct_status_code? || correct_status_code_range?
31
31
  end
32
-
32
+
33
33
  def failure_message
34
34
  "Expected #{expectation}"
35
35
  end
36
-
36
+
37
37
  def negative_failure_message
38
38
  "Did not expect #{expectation}"
39
39
  end
@@ -41,41 +41,45 @@ module Shoulda # :nodoc:
41
41
  def description
42
42
  "respond with #{@status}"
43
43
  end
44
-
44
+
45
45
  protected
46
-
46
+
47
47
  def correct_status_code?
48
48
  response_code == @status
49
49
  end
50
-
50
+
51
51
  def correct_status_code_range?
52
52
  @status.is_a?(Range) &&
53
53
  @status.include?(response_code)
54
54
  end
55
-
55
+
56
56
  def response_code
57
57
  @controller.response.response_code
58
58
  end
59
-
59
+
60
60
  def symbol_to_status_code(potential_symbol)
61
61
  case potential_symbol
62
62
  when :success then 200
63
63
  when :redirect then 300..399
64
64
  when :missing then 404
65
65
  when :error then 500..599
66
- when Symbol
67
- ::ActionController::StatusCodes::SYMBOL_TO_STATUS_CODE[potential_symbol]
66
+ when Symbol
67
+ if defined?(::Rack::Utils::SYMBOL_TO_STATUS_CODE)
68
+ ::Rack::Utils::SYMBOL_TO_STATUS_CODE[potential_symbol]
69
+ else
70
+ ::ActionController::Base::SYMBOL_TO_STATUS_CODE[potential_symbol]
71
+ end
68
72
  else
69
73
  potential_symbol
70
74
  end
71
75
  end
72
-
76
+
73
77
  def expectation
74
78
  "response to be a #{@status}, but was #{response_code}"
75
79
  end
76
-
80
+
77
81
  end
78
-
82
+
79
83
  end
80
84
  end
81
85
  end