Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: mrchucho/shoulda
...
head fork: mrchucho/shoulda
compare: 979c603362
Checking mergeability… Don't worry, you can still create the pull request.
  • 4 commits
  • 275 files changed
  • 0 commit comments
  • 1 contributor
Showing with 19,319 additions and 227 deletions.
  1. +0 −2  .gitignore
  2. +0 −3  Gemfile
  3. +0 −97 README.md
  4. +162 −0 README.rdoc
  5. +50 −6 Rakefile
  6. +2 −0  cucumber.yml
  7. +48 −20 features/rails_integration.feature
  8. +31 −0 features/step_definitions/common_steps.rb
  9. +83 −0 features/step_definitions/rails2_steps.rb
  10. +60 −0 features/step_definitions/rails3_steps.rb
  11. +0 −77 features/step_definitions/rails_steps.rb
  12. +0 −5 features/support/env.rb
  13. +36 −0 features/support/terminal.rb
  14. +1 −0  init.rb
  15. +7 −2 lib/shoulda.rb
  16. +34 −0 lib/shoulda/action_controller.rb
  17. +208 −0 lib/shoulda/action_controller/macros.rb
  18. +39 −0 lib/shoulda/action_controller/matchers.rb
  19. +112 −0 lib/shoulda/action_controller/matchers/assign_to_matcher.rb
  20. +74 −0 lib/shoulda/action_controller/matchers/filter_param_matcher.rb
  21. +62 −0 lib/shoulda/action_controller/matchers/redirect_to_matcher.rb
  22. +54 −0 lib/shoulda/action_controller/matchers/render_template_matcher.rb
  23. +99 −0 lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb
  24. +74 −0 lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb
  25. +85 −0 lib/shoulda/action_controller/matchers/respond_with_matcher.rb
  26. +93 −0 lib/shoulda/action_controller/matchers/route_matcher.rb
  27. +98 −0 lib/shoulda/action_controller/matchers/set_session_matcher.rb
  28. +100 −0 lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb
  29. +13 −0 lib/shoulda/action_mailer.rb
  30. +40 −0 lib/shoulda/action_mailer/assertions.rb
  31. +22 −0 lib/shoulda/action_mailer/matchers.rb
  32. +110 −0 lib/shoulda/action_mailer/matchers/have_sent_email.rb
  33. +16 −0 lib/shoulda/active_record.rb
  34. +69 −0 lib/shoulda/active_record/assertions.rb
  35. +32 −0 lib/shoulda/active_record/helpers.rb
  36. +436 −0 lib/shoulda/active_record/macros.rb
  37. +42 −0 lib/shoulda/active_record/matchers.rb
  38. +83 −0 lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb
  39. +110 −0 lib/shoulda/active_record/matchers/allow_value_matcher.rb
  40. +226 −0 lib/shoulda/active_record/matchers/association_matcher.rb
  41. +87 −0 lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb
  42. +141 −0 lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb
  43. +169 −0 lib/shoulda/active_record/matchers/have_db_column_matcher.rb
  44. +112 −0 lib/shoulda/active_record/matchers/have_db_index_matcher.rb
  45. +59 −0 lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb
  46. +41 −0 lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb
  47. +65 −0 lib/shoulda/active_record/matchers/validate_format_of_matcher.rb
  48. +39 −0 lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb
  49. +60 −0 lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb
  50. +148 −0 lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb
  51. +56 −0 lib/shoulda/active_record/matchers/validation_matcher.rb
  52. +79 −0 lib/shoulda/assertions.rb
  53. +46 −0 lib/shoulda/autoload_macros.rb
  54. +433 −0 lib/shoulda/context.rb
  55. +8 −0 lib/shoulda/helpers.rb
  56. +13 −0 lib/shoulda/integrations/rspec.rb
  57. +22 −0 lib/shoulda/integrations/rspec2.rb
  58. +22 −0 lib/shoulda/integrations/test_unit.rb
  59. +157 −0 lib/shoulda/macros.rb
  60. +13 −0 lib/shoulda/private_helpers.rb
  61. +14 −0 lib/shoulda/proc_extensions.rb
  62. +8 −0 lib/shoulda/rails.rb
  63. +3 −0  lib/shoulda/tasks.rb
  64. +29 −0 lib/shoulda/tasks/list_tests.rake
  65. +28 −0 lib/shoulda/tasks/yaml_to_shoulda.rake
  66. +1 −1  lib/shoulda/version.rb
  67. +8 −0 rails/init.rb
  68. +6 −14 shoulda.gemspec
  69. +1 −0  tasks/shoulda.rake
  70. +36 −0 test/README
  71. +55 −0 test/fail_macros.rb
  72. +3 −0  test/fixtures/addresses.yml
  73. 0  test/fixtures/friendships.yml
  74. +5 −0 test/fixtures/posts.yml
  75. 0  test/fixtures/products.yml
  76. 0  test/fixtures/taggings.yml
  77. +9 −0 test/fixtures/tags.yml
  78. +6 −0 test/fixtures/users.yml
  79. +121 −0 test/functional/posts_controller_test.rb
  80. +19 −0 test/functional/users_controller_test.rb
  81. +70 −0 test/matchers/action_mailer/have_sent_email_test.rb
  82. +74 −0 test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb
  83. +64 −0 test/matchers/active_record/allow_value_matcher_test.rb
  84. +263 −0 test/matchers/active_record/association_matcher_test.rb
  85. +81 −0 test/matchers/active_record/ensure_inclusion_of_matcher_test.rb
  86. +158 −0 test/matchers/active_record/ensure_length_of_matcher_test.rb
  87. +169 −0 test/matchers/active_record/have_db_column_matcher_test.rb
  88. +91 −0 test/matchers/active_record/have_db_index_matcher_test.rb
  89. +29 −0 test/matchers/active_record/have_readonly_attributes_matcher_test.rb
  90. +44 −0 test/matchers/active_record/validate_acceptance_of_matcher_test.rb
  91. +39 −0 test/matchers/active_record/validate_format_of_matcher_test.rb
  92. +52 −0 test/matchers/active_record/validate_numericality_of_matcher_test.rb
  93. +86 −0 test/matchers/active_record/validate_presence_of_matcher_test.rb
  94. +147 −0 test/matchers/active_record/validate_uniqueness_of_matcher_test.rb
  95. +45 −0 test/matchers/controller/assign_to_matcher_test.rb
  96. +40 −0 test/matchers/controller/filter_param_matcher_test.rb
  97. +37 −0 test/matchers/controller/redirect_to_matcher_test.rb
  98. +37 −0 test/matchers/controller/render_template_matcher_test.rb
  99. +47 −0 test/matchers/controller/render_with_layout_matcher_test.rb
  100. +32 −0 test/matchers/controller/respond_with_content_type_matcher_test.rb
  101. +96 −0 test/matchers/controller/respond_with_matcher_test.rb
  102. +75 −0 test/matchers/controller/route_matcher_test.rb
  103. +48 −0 test/matchers/controller/set_session_matcher_test.rb
  104. +95 −0 test/matchers/controller/set_the_flash_matcher.rb
  105. +18 −0 test/other/autoload_macro_test.rb
  106. +372 −0 test/other/context_test.rb
  107. +63 −0 test/other/convert_to_should_syntax_test.rb
  108. +317 −0 test/other/helpers_test.rb
  109. +32 −0 test/other/private_helpers_test.rb
  110. +271 −0 test/other/should_test.rb
  111. +130 −0 test/rails2_model_builder.rb
  112. +22 −0 test/rails2_root/app/controllers/application_controller.rb
  113. +87 −0 test/rails2_root/app/controllers/posts_controller.rb
  114. +84 −0 test/rails2_root/app/controllers/users_controller.rb
  115. +3 −0  test/rails2_root/app/helpers/application_helper.rb
  116. +2 −0  test/rails2_root/app/helpers/posts_helper.rb
  117. +2 −0  test/rails2_root/app/helpers/users_helper.rb
  118. +7 −0 test/rails2_root/app/models/address.rb
  119. +11 −0 test/rails2_root/app/models/flea.rb
  120. +4 −0 test/rails2_root/app/models/friendship.rb
  121. +8 −0 test/rails2_root/app/models/notifier.rb
  122. +7 −0 test/rails2_root/app/models/pets/cat.rb
  123. +10 −0 test/rails2_root/app/models/pets/dog.rb
  124. +12 −0 test/rails2_root/app/models/post.rb
  125. +12 −0 test/rails2_root/app/models/product.rb
  126. +2 −0  test/rails2_root/app/models/profile.rb
  127. +2 −0  test/rails2_root/app/models/registration.rb
  128. +8 −0 test/rails2_root/app/models/tag.rb
  129. +4 −0 test/rails2_root/app/models/tagging.rb
  130. +3 −0  test/rails2_root/app/models/treat.rb
  131. +32 −0 test/rails2_root/app/models/user.rb
  132. +19 −0 test/rails2_root/app/views/layouts/posts.rhtml
  133. +17 −0 test/rails2_root/app/views/layouts/users.rhtml
  134. +1 −0  test/rails2_root/app/views/layouts/wide.html.erb
  135. +1 −0  test/rails2_root/app/views/notifier/the_email.html.erb
  136. +27 −0 test/rails2_root/app/views/posts/edit.rhtml
  137. +25 −0 test/rails2_root/app/views/posts/index.rhtml
  138. +26 −0 test/rails2_root/app/views/posts/new.rhtml
  139. +18 −0 test/rails2_root/app/views/posts/show.rhtml
  140. +22 −0 test/rails2_root/app/views/users/edit.rhtml
  141. +22 −0 test/rails2_root/app/views/users/index.rhtml
  142. +21 −0 test/rails2_root/app/views/users/new.rhtml
  143. +13 −0 test/rails2_root/app/views/users/show.rhtml
  144. +110 −0 test/rails2_root/config/boot.rb
  145. +4 −0 test/rails2_root/config/database.yml
  146. +17 −0 test/rails2_root/config/environment.rb
  147. +23 −0 test/rails2_root/config/environments/test.rb
  148. +15 −0 test/rails2_root/config/initializers/new_rails_defaults.rb
  149. +8 −0 test/rails2_root/config/initializers/shoulda.rb
  150. +6 −0 test/rails2_root/config/routes.rb
  151. +19 −0 test/rails2_root/db/migrate/001_create_users.rb
  152. +13 −0 test/rails2_root/db/migrate/002_create_posts.rb
  153. +12 −0 test/rails2_root/db/migrate/003_create_taggings.rb
  154. +11 −0 test/rails2_root/db/migrate/004_create_tags.rb
  155. +12 −0 test/rails2_root/db/migrate/005_create_dogs.rb
  156. +14 −0 test/rails2_root/db/migrate/006_create_addresses.rb
  157. +11 −0 test/rails2_root/db/migrate/007_create_fleas.rb
  158. +12 −0 test/rails2_root/db/migrate/008_create_dogs_fleas.rb
  159. +17 −0 test/rails2_root/db/migrate/009_create_products.rb
  160. +14 −0 test/rails2_root/db/migrate/010_create_friendships.rb
  161. +12 −0 test/rails2_root/db/migrate/011_create_treats.rb
  162. +12 −0 test/rails2_root/db/migrate/20090506203502_create_profiles.rb
  163. +14 −0 test/rails2_root/db/migrate/20090506203536_create_registrations.rb
  164. +12 −0 test/rails2_root/db/migrate/20090513104502_create_cats.rb
  165. 0  test/rails2_root/db/schema.rb
  166. 0  test/rails2_root/log/.keep
  167. +40 −0 test/rails2_root/public/.htaccess
  168. +30 −0 test/rails2_root/public/404.html
  169. +30 −0 test/rails2_root/public/422.html
  170. +30 −0 test/rails2_root/public/500.html
  171. +3 −0  test/rails2_root/script/console
  172. +3 −0  test/rails2_root/script/generate
  173. +6 −0 test/rails2_root/test/shoulda_macros/custom_macro.rb
  174. +6 −0 test/rails2_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb
  175. 0  test/rails2_root/vendor/plugins/.keep
  176. +6 −0 test/rails2_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb
  177. +6 −0 test/rails2_test_helper.rb
  178. +118 −0 test/rails3_model_builder.rb
  179. +4 −0 test/rails3_root/.gitignore
  180. +28 −0 test/rails3_root/Gemfile
  181. +244 −0 test/rails3_root/README
  182. +10 −0 test/rails3_root/Rakefile
  183. +22 −0 test/rails3_root/app/controllers/application_controller.rb
  184. +87 −0 test/rails3_root/app/controllers/posts_controller.rb
  185. +82 −0 test/rails3_root/app/controllers/users_controller.rb
  186. +2 −0  test/rails3_root/app/helpers/application_helper.rb
  187. +7 −0 test/rails3_root/app/models/address.rb
  188. +11 −0 test/rails3_root/app/models/flea.rb
  189. +4 −0 test/rails3_root/app/models/friendship.rb
  190. +8 −0 test/rails3_root/app/models/notifier.rb
  191. +7 −0 test/rails3_root/app/models/pets/cat.rb
  192. +10 −0 test/rails3_root/app/models/pets/dog.rb
  193. +12 −0 test/rails3_root/app/models/post.rb
  194. +12 −0 test/rails3_root/app/models/product.rb
  195. +2 −0  test/rails3_root/app/models/profile.rb
  196. +2 −0  test/rails3_root/app/models/registration.rb
  197. +8 −0 test/rails3_root/app/models/tag.rb
  198. +4 −0 test/rails3_root/app/models/tagging.rb
  199. +3 −0  test/rails3_root/app/models/treat.rb
  200. +32 −0 test/rails3_root/app/models/user.rb
  201. +14 −0 test/rails3_root/app/views/layouts/application.html.erb
  202. +19 −0 test/rails3_root/app/views/layouts/posts.rhtml
  203. +17 −0 test/rails3_root/app/views/layouts/users.rhtml
  204. +1 −0  test/rails3_root/app/views/layouts/wide.html.erb
  205. +1 −0  test/rails3_root/app/views/notifier/the_email.html.erb
  206. +27 −0 test/rails3_root/app/views/posts/edit.rhtml
  207. +25 −0 test/rails3_root/app/views/posts/index.rhtml
  208. +24 −0 test/rails3_root/app/views/posts/new.rhtml
  209. +18 −0 test/rails3_root/app/views/posts/show.rhtml
  210. +22 −0 test/rails3_root/app/views/users/edit.rhtml
  211. +22 −0 test/rails3_root/app/views/users/index.rhtml
  212. +21 −0 test/rails3_root/app/views/users/new.rhtml
  213. +13 −0 test/rails3_root/app/views/users/show.rhtml
  214. +4 −0 test/rails3_root/config.ru
  215. +46 −0 test/rails3_root/config/application.rb
  216. +6 −0 test/rails3_root/config/boot.rb
  217. +22 −0 test/rails3_root/config/database.yml
  218. +5 −0 test/rails3_root/config/environment.rb
  219. +19 −0 test/rails3_root/config/environments/development.rb
  220. +42 −0 test/rails3_root/config/environments/production.rb
  221. +32 −0 test/rails3_root/config/environments/test.rb
  222. +7 −0 test/rails3_root/config/initializers/backtrace_silencers.rb
  223. +10 −0 test/rails3_root/config/initializers/inflections.rb
  224. +5 −0 test/rails3_root/config/initializers/mime_types.rb
  225. +7 −0 test/rails3_root/config/initializers/secret_token.rb
  226. +8 −0 test/rails3_root/config/initializers/session_store.rb
  227. +5 −0 test/rails3_root/config/locales/en.yml
  228. +4 −0 test/rails3_root/config/routes.rb
  229. +19 −0 test/rails3_root/db/migrate/001_create_users.rb
  230. +13 −0 test/rails3_root/db/migrate/002_create_posts.rb
  231. +12 −0 test/rails3_root/db/migrate/003_create_taggings.rb
  232. +11 −0 test/rails3_root/db/migrate/004_create_tags.rb
  233. +12 −0 test/rails3_root/db/migrate/005_create_dogs.rb
  234. +14 −0 test/rails3_root/db/migrate/006_create_addresses.rb
  235. +11 −0 test/rails3_root/db/migrate/007_create_fleas.rb
  236. +12 −0 test/rails3_root/db/migrate/008_create_dogs_fleas.rb
  237. +17 −0 test/rails3_root/db/migrate/009_create_products.rb
  238. +14 −0 test/rails3_root/db/migrate/010_create_friendships.rb
  239. +12 −0 test/rails3_root/db/migrate/011_create_treats.rb
  240. +12 −0 test/rails3_root/db/migrate/20090506203502_create_profiles.rb
  241. +14 −0 test/rails3_root/db/migrate/20090506203536_create_registrations.rb
  242. +12 −0 test/rails3_root/db/migrate/20090513104502_create_cats.rb
  243. +7 −0 test/rails3_root/db/seeds.rb
  244. 0  test/rails3_root/lib/tasks/.gitkeep
  245. +26 −0 test/rails3_root/public/404.html
  246. +26 −0 test/rails3_root/public/422.html
  247. +26 −0 test/rails3_root/public/500.html
  248. 0  test/rails3_root/public/favicon.ico
  249. BIN  test/rails3_root/public/images/rails.png
  250. +279 −0 test/rails3_root/public/index.html
  251. +2 −0  test/rails3_root/public/javascripts/application.js
  252. +965 −0 test/rails3_root/public/javascripts/controls.js
  253. +974 −0 test/rails3_root/public/javascripts/dragdrop.js
  254. +1,123 −0 test/rails3_root/public/javascripts/effects.js
  255. +4,874 −0 test/rails3_root/public/javascripts/prototype.js
  256. +118 −0 test/rails3_root/public/javascripts/rails.js
  257. +5 −0 test/rails3_root/public/robots.txt
  258. 0  test/rails3_root/public/stylesheets/.gitkeep
  259. +9 −0 test/rails3_root/script/rails
  260. +9 −0 test/rails3_root/test/performance/browsing_test.rb
  261. +13 −0 test/rails3_root/test/test_helper.rb
  262. 0  test/rails3_root/vendor/plugins/.gitkeep
  263. +6 −0 test/rails3_test_helper.rb
  264. +207 −0 test/rspec_test.rb
  265. +36 −0 test/test_helper.rb
  266. +10 −0 test/unit/address_test.rb
  267. +7 −0 test/unit/cat_test.rb
  268. +9 −0 test/unit/dog_test.rb
  269. +14 −0 test/unit/flea_test.rb
  270. +6 −0 test/unit/friendship_test.rb
  271. +15 −0 test/unit/post_test.rb
  272. +23 −0 test/unit/product_test.rb
  273. +11 −0 test/unit/tag_test.rb
  274. +6 −0 test/unit/tagging_test.rb
  275. +46 −0 test/unit/user_test.rb
View
2  .gitignore
@@ -7,5 +7,3 @@ pkg
*.swo
tags
tmp
-.bundle
-Gemfile.lock
View
3  Gemfile
@@ -1,3 +0,0 @@
-source 'http://rubygems.org'
-
-gemspec
View
97 README.md
@@ -1,97 +0,0 @@
-shoulda
-===================================================
-
-The shoulda gem is a meta gem with two dependencies:
-
-* [shoulda-context](https://github.com/thoughtbot/shoulda-context)
-* [shoulda-matchers](https://github.com/thoughtbot/shoulda-matchers)
-
-Official documentation for each gem:
-
-* [shoulda-context](http://rubydoc.info/github/thoughtbot/shoulda-context/master/frames)
-* [shoulda-matchers](http://rubydoc.info/github/thoughtbot/shoulda-matchers/master/frames)
-
-The following describes different use cases and combinations.
-
-rspec with shoulda-matchers
----------------------------
-
-This is what thoughtbot currently does. We write tests like:
-
- describe Post do
- it { should belong_to(:user) }
- it { should validate_presence_of(:title) }
- end
-
-The belong_to and validate_presence_of methods are the matchers.
-All matchers are Rails 3-specific.
-
-Add rspec-rails and shoulda-matchers to the project's Gemfile:
-
- group :test do
- gem 'rspec-rails'
- gem 'shoulda-matchers'
- end
-
-test/unit with shoulda
-----------------------
-
-For the folks who prefer Test::Unit, they'd write tests like:
-
- class UserTest < Test::Unit::TestCase
- should have_many(:posts)
- should_not allow_value("blah").for(:email)
- end
-
-The have_many and allow_value methods are the same kind of matchers
-seen in the RSpec example. They come from the shoulda-matchers gem.
-
-Add shoulda to the project's Gemfile:
-
- group :test do
- gem 'shoulda'
- end
-
-test/unit with shoulda-context
-------------------------------
-
-If you're not testing a Rails project or don't want to use the matchers,
-you can use shoulda-context independently to write tests like:
-
- class CalculatorTest < Test::Unit::TestCase
- context "a calculator" do
- setup do
- @calculator = Calculator.new
- end
-
- should "add two numbers for the sum" do
- assert_equal 4, @calculator.sum(2, 2)
- end
-
- should "multiply two numbers for the product" do
- assert_equal 10, @calculator.product(2, 5)
- end
- end
- end
-
-Add shoulda-context to the project's Gemfile:
-
- group :test do
- gem 'shoulda-context'
- end
-
-Credits
--------
-
-![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
-
-Shoulda is maintained and funded by [thoughtbot, inc](http://thoughtbot.com/community)
-
-Thank you to all [the contributors](https://github.com/thoughtbot/shoulda/contributors)!
-
-The names and logos for thoughtbot are trademarks of thoughtbot, inc.
-
-License
--------
-
-Shoulda is Copyright © 2006-2011 Tammer Saleh, thoughtbot. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
View
162 README.rdoc
@@ -0,0 +1,162 @@
+= NOTICE
+
+*** This is version 2.11.3 of shoulda with the deprecation warnings removed. ***
+
+There are no changes to functionality and, barring any serious bugs, I will not
+update this gem. It is simply way to use the last version of shoulda before
+it switched to rspec style matchers.
+
+= Shoulda - Making tests easy on the fingers and eyes
+
+Shoulda makes it easy to write elegant, understandable, and maintainable tests. Shoulda consists of matchers, test helpers, and assertions. It's fully compatible with your existing tests in Test::Unit or RSpec, and requires no retooling to use.
+
+Matchers:: Test::Unit- and RSpec-compatible one-liners that test common Rails functionality.
+ These tests would otherwise be much longer, more complex, and error-prone.
+Helpers:: #context and #should give you RSpec like test blocks in Test::Unit.
+ In addition, you get nested contexts and a much more readable syntax.
+Assertions:: Many common Rails testing idioms have been distilled into a set of useful assertions.
+
+= Usage
+
+=== ActiveRecord Tests (Shoulda::ActiveRecord::Matchers)
+
+Test your ActiveRecord associations and validations with these powerful matchers:
+
+ class PostTest < Test::Unit::TestCase
+ should belong_to(:user)
+ should have_many(:tags).through(:taggings)
+
+ should validate_uniqueness_of(:title)
+ should validate_presence_of(:body).with_message(/wtf/)
+ should validate_presence_of(:title)
+ should validate_numericality_of(:user_id)
+ end
+
+ class UserTest < Test::Unit::TestCase
+ should have_many(:posts)
+
+ should_not allow_value("blah").for(:email)
+ should_not allow_value("b lah").for(:email)
+ should allow_value("a@b.com").for(:email)
+ should allow_value("asdf@asdf.com").for(:email)
+ should ensure_inclusion_of(:email).in_range(1..100)
+ should ensure_inclusion_of(:age).in_range(1..100)
+ should_not allow_mass_assignment_of(:password)
+ end
+
+Makes TDD so much easier.
+
+=== Controller Tests (Shoulda::Controller::Matchers)
+
+Matchers to test the most common controller patterns...
+
+ class PostsControllerTest < ActionController::TestCase
+ context "on GET to :show for first record" do
+ setup do
+ get :show, :id => 1
+ end
+
+ should assign_to(:user)
+ should respond_with(:success)
+ should render_template(:show)
+ should_not set_the_flash
+
+ should "do something else really cool" do
+ assert_equal 1, assigns(:user).id
+ end
+ end
+ end
+
+=== Context Helpers (Shoulda::Context)
+
+Stop killing your fingers with all of those underscores... Name your tests with plain sentences!
+
+ class UserTest < Test::Unit::TestCase
+ context "A User instance" do
+ setup do
+ @user = User.find(:first)
+ end
+
+ should "return its full name" do
+ assert_equal 'John Doe', @user.full_name
+ end
+
+ context "with a profile" do
+ setup do
+ @user.profile = Profile.find(:first)
+ end
+
+ should "return true when sent #has_profile?" do
+ assert @user.has_profile?
+ end
+ end
+ end
+ end
+
+Produces the following test methods:
+
+ "test: A User instance should return its full name."
+ "test: A User instance with a profile should return true when sent #has_profile?."
+
+So readable!
+
+=== Helpful Assertions (Shoulda::Assertions)
+
+More to come here, but have fun with what's there.
+
+ assert_same_elements([:a, :b, :c], [:c, :a, :b])
+ assert_contains(['a', '1'], /\d/)
+ assert_contains(['a', '1'], 'a')
+
+= Rails Installation (Test::Unit)
+
+Specify the gem dependency in your config/environment.rb file:
+
+ Rails::Initializer.run do |config|
+ config.gem "shoulda", :lib => "shoulda"
+ end
+
+Then:
+
+ $ rake gems:install
+ $ rake gems:unpack
+
+= Rails Installation (RSpec)
+
+If you're using Shoulda with RSpec, we recommend that you add config.gem lines
+for RSpec and Shoulda in your config/environment/test.rb file, but do not ask
+Rails to load the RSpec and Shoulda libraries:
+
+ config.gem 'rspec', :lib => false
+ config.gem 'rspec-rails', :lib => false
+ config.gem 'shoulda', :lib => false
+
+Then require shoulda from your spec/spec_helper.rb file, before Spec::Runner is
+configured:
+
+ # requires for RSpec
+ require 'shoulda'
+ Spec::Runner.configure do |config|
+ # ...
+
+You should not need to require anything besides the top-level shoulda library.
+
+= Rails 3 Installation (RSpec)
+
+With Rails 3 and Bundler, requiring Shoulda is as easy as adding it to your Gemfile:
+
+ group :test do
+ gem "shoulda"
+ gem "rspec-rails", "2.0.0.beta.12"
+ end
+
+Shoulda will automatically include matchers into the appropriate example
+groups.
+
+= Credits
+
+Shoulda is maintained and funded by {thougthbot}[http://thoughtbot.com/community]
+
+= License
+
+Shoulda is Copyright © 2006-2010 Tammer Saleh, Thoughtbot. It is free software, and may be redistributed under the terms specified in the MIT-LICENSE file.
View
56 Rakefile
@@ -1,11 +1,36 @@
require 'rubygems'
-require 'bundler/setup'
require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
require 'rake/gempackagetask'
require 'cucumber/rake/task'
$LOAD_PATH.unshift("lib")
require 'shoulda/version'
+load 'tasks/shoulda.rake'
+
+# Test::Unit::UI::VERBOSE
+test_files_pattern = 'test/{unit,functional,other,matchers}/**/*_test.rb'
+Rake::TestTask.new do |t|
+ t.libs << 'lib' << 'test'
+ t.pattern = test_files_pattern
+ t.verbose = false
+end
+
+Rake::RDocTask.new { |rdoc|
+ rdoc.rdoc_dir = 'doc'
+ rdoc.title = "Shoulda -- Making tests easy on the fingers and eyes"
+ rdoc.options << '--line-numbers'
+ rdoc.template = "#{ENV['template']}.rb" if ENV['template']
+ rdoc.rdoc_files.include('README.rdoc', 'CONTRIBUTION_GUIDELINES.rdoc', 'lib/**/*.rb')
+}
+
+desc "Run code-coverage analysis using rcov"
+task :coverage do
+ rm_rf "coverage"
+ files = Dir[test_files_pattern]
+ system "rcov --rails --sort coverage -Ilib #{files.join(' ')}"
+end
eval("$specification = begin; #{IO.read('shoulda.gemspec')}; end")
Rake::GemPackageTask.new $specification do |pkg|
@@ -16,11 +41,30 @@ end
desc "Clean files generated by rake tasks"
task :clobber => [:clobber_rdoc, :clobber_package]
-Cucumber::Rake::Task.new do |t|
- t.fork = true
- t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
+namespace :cucumber do
+ Cucumber::Rake::Task.new(:rails2, "Run the cucumber features in Rails 2") do |t|
+ t.fork = true
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
+ t.profile = 'rails2'
+ end
+
+ Cucumber::Rake::Task.new(:rails3, "Run the cucumber features in Rails 3") do |t|
+ t.fork = true
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
+ t.profile = 'rails3'
+ end
+end
+
+desc "Run the cucumber features in both Rails 2 and 3"
+task :cucumber => ["cucumber:rails2", "cucumber:rails3"]
+
+desc 'run tests for all supported versions of Rails'
+task :test_all do
+ %w(2.3.8 3.0.0.beta4).each do |version|
+ system("RAILS_VERSION=#{version} rake -s test;")
+ end
end
-desc 'Default: run cucumber features'
-task :default => [:cucumber]
+desc 'Default: run test and cucumber features for support versions'
+task :default => [:test_all, :cucumber]
View
2  cucumber.yml
@@ -0,0 +1,2 @@
+rails2: -r features/support -r features/step_definitions/common_steps.rb -r features/step_definitions/rails2_steps.rb
+rails3: -r features/support -r features/step_definitions/common_steps.rb -r features/step_definitions/rails3_steps.rb
View
68 features/rails_integration.feature
@@ -1,9 +1,9 @@
-@disable-bundler
Feature: integrate with Rails
Background:
When I generate a new rails application
- And I write to "db/migrate/1_create_users.rb" with:
+ And I configure the application to use "shoulda" from this project
+ And I save the following as "db/migrate/1_create_users.rb"
"""
class CreateUsers < ActiveRecord::Migration
def self.up
@@ -13,14 +13,14 @@ Feature: integrate with Rails
end
end
"""
- When I successfully run "rake db:migrate --trace"
- And I write to "app/models/user.rb" with:
+ When I run "rake db:migrate"
+ And I save the following as "app/models/user.rb"
"""
class User < ActiveRecord::Base
validates_presence_of :name
end
"""
- When I write to "app/controllers/examples_controller.rb" with:
+ When I save the following as "app/controllers/examples_controller.rb"
"""
class ExamplesController < ApplicationController
def show
@@ -31,9 +31,36 @@ Feature: integrate with Rails
"""
When I configure a wildcard route
+ Scenario: generate a rails application and use macros in Test::Unit
+ When I save the following as "test/unit/user_test.rb"
+ """
+ require 'test_helper'
+
+ class UserTest < ActiveSupport::TestCase
+ should_validate_presence_of :name
+ end
+ """
+ When I save the following as "test/functional/examples_controller_test.rb"
+ """
+ require 'test_helper'
+
+ class ExamplesControllerTest < ActionController::TestCase
+ def setup
+ get :show
+ end
+
+ should_respond_with :success
+ should_assign_to :example
+ end
+ """
+ When I run "rake test TESTOPTS=-v"
+ Then I should see "1 tests, 1 assertions, 0 failures, 0 errors"
+ And I should see "2 tests, 2 assertions, 0 failures, 0 errors"
+ And I should see "User should require name to be set"
+ And I should see "ExamplesController should assign @example"
+
Scenario: generate a rails application and use matchers in Test::Unit
- When I configure the application to use shoulda
- And I write to "test/unit/user_test.rb" with:
+ When I save the following as "test/unit/user_test.rb"
"""
require 'test_helper'
@@ -41,7 +68,7 @@ Feature: integrate with Rails
should validate_presence_of(:name)
end
"""
- When I write to "test/functional/examples_controller_test.rb" with:
+ When I save the following as "test/functional/examples_controller_test.rb"
"""
require 'test_helper'
@@ -54,17 +81,16 @@ Feature: integrate with Rails
should assign_to(:example)
end
"""
- When I successfully run "rake test TESTOPTS=-v --trace"
- Then the output should contain "1 tests, 1 assertions, 0 failures, 0 errors"
- And the output should contain "2 tests, 2 assertions, 0 failures, 0 errors"
- And the output should contain "User should require name to be set"
- And the output should contain "ExamplesController should assign @example"
+ When I run "rake test TESTOPTS=-v"
+ Then I should see "1 tests, 1 assertions, 0 failures, 0 errors"
+ And I should see "2 tests, 2 assertions, 0 failures, 0 errors"
+ And I should see "User should require name to be set"
+ And I should see "ExamplesController should assign @example"
Scenario: generate a rails application and use matchers in Rspec
When I configure the application to use rspec-rails
- And I configure the application to use shoulda-matchers
And I run the rspec generator
- And I write to "spec/models/user_spec.rb" with:
+ And I save the following as "spec/models/user_spec.rb"
"""
require 'spec_helper'
@@ -72,16 +98,18 @@ Feature: integrate with Rails
it { should validate_presence_of(:name) }
end
"""
- When I write to "spec/controllers/examples_controller_spec.rb" with:
+ When I save the following as "spec/controllers/examples_controller_spec.rb"
"""
require 'spec_helper'
describe ExamplesController, "show" do
before { get :show }
+ # rspec2 doesn't use the controller as the subject
+ subject { controller }
it { should assign_to(:example) }
end
"""
- When I successfully run "rake spec SPEC_OPTS=-fs --trace"
- Then the output should contain "2 examples, 0 failures"
- And the output should contain "should require name to be set"
- And the output should contain "should assign @example"
+ When I run "rake spec SPEC_OPTS=-fs"
+ Then I should see "2 examples, 0 failures"
+ And I should see "should require name to be set"
+ And I should see "should assign @example"
View
31 features/step_definitions/common_steps.rb
@@ -0,0 +1,31 @@
+PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
+TEMP_ROOT = File.join(PROJECT_ROOT, 'tmp').freeze
+APP_NAME = 'testapp'.freeze
+RAILS_ROOT = File.join(TEMP_ROOT, APP_NAME).freeze
+
+Before do
+ FileUtils.rm_rf(TEMP_ROOT)
+ FileUtils.mkdir_p(TEMP_ROOT)
+ @terminal = Terminal.new
+end
+
+After do
+ FileUtils.rm_f(File.join(PROJECT_ROOT, '.specification'))
+end
+
+When /^I save the following as "([^\"]*)"$/ do |path, string|
+ FileUtils.mkdir_p(File.join(RAILS_ROOT, File.dirname(path)))
+ File.open(File.join(RAILS_ROOT, path), 'w') { |file| file.write(string) }
+end
+
+When /^I run "([^\"]*)"$/ do |command|
+ @terminal.cd(RAILS_ROOT)
+ @terminal.run(command)
+end
+
+Then /^I should see "([^\"]*)"$/ do |expected_text|
+ unless @terminal.output.include?(expected_text)
+ raise("Got terminal output:\n#{@terminal.output}\n\nExpected output:\n#{expected_text}")
+ end
+end
+
View
83 features/step_definitions/rails2_steps.rb
@@ -0,0 +1,83 @@
+When /^I generate a new rails application$/ do
+ load_rails = <<-RUBY
+ gem 'rails', '2.3.8'; \
+ load Gem.bin_path('rails', 'rails', '2.3.8')
+ RUBY
+
+ @terminal.cd(TEMP_ROOT)
+ @terminal.run(%{ruby -rubygems -e "#{load_rails.strip!}" #{APP_NAME}})
+end
+
+When /^I configure the application to use "([^\"]+)" from this project$/ do |name|
+ gemspec = File.join(PROJECT_ROOT, "#{name}.gemspec")
+ eval("$specification = begin; #{IO.read(gemspec)}; end")
+ version = $specification.version
+ name = $specification.name
+
+ vendor_gem_root = File.join(RAILS_ROOT, 'vendor', 'gems')
+ vendor_gem_path = File.join(vendor_gem_root, "shoulda-#{version}")
+
+ FileUtils.mkdir_p(vendor_gem_root)
+ FileUtils.ln_s(PROJECT_ROOT, vendor_gem_path)
+ File.open(File.join(vendor_gem_path, ".specification"), "w") do |file|
+ file.write($specification.to_yaml)
+ end
+
+ insert_into_environment("config.gem '#{name}'")
+end
+
+When /^I configure the application to use rspec\-rails$/ do
+ # we have to unpack and copy the generator because Rails won't find the
+ # generators if rspec-rails 2 is installed
+ insert_into_environment("config.gem 'rspec-rails', :lib => false, :version => '1.2.9'")
+ insert_into_environment("config.gem 'rspec', :lib => false, :version => '1.2.9'")
+ steps %{
+ When I run "rake gems:unpack"
+ }
+ rspec_generator = File.join(RAILS_ROOT,
+ 'vendor',
+ 'gems',
+ 'rspec-rails-1.2.9',
+ 'generators')
+ FileUtils.cp_r(rspec_generator, File.join(RAILS_ROOT, 'lib'))
+end
+
+When /^I run the rspec generator$/ do
+ steps %{
+ When I run the "rspec" generator
+ }
+end
+
+When /^I run the "([^"]*)" generator$/ do |name|
+ steps %{
+ When I run "./script/generate #{name}"
+ }
+end
+
+When /^I configure a wildcard route$/ do
+ steps %{
+ When I save the following as "config/routes.rb"
+ """
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action/:id'
+ end
+ """
+ }
+end
+
+module InsertionHelpers
+ def insert_into(path, find, replace)
+ contents = IO.read(path)
+ contents.sub!(find, replace)
+ File.open(path, "w") { |file| file.write(contents) }
+ end
+
+ def insert_into_environment(contents)
+ environment_file = File.join(RAILS_ROOT, 'config', 'environment.rb')
+ initializer = "Rails::Initializer.run do |config|"
+ replace = "#{initializer}\n #{contents}"
+ insert_into(environment_file, initializer, replace)
+ end
+end
+
+World(InsertionHelpers)
View
60 features/step_definitions/rails3_steps.rb
@@ -0,0 +1,60 @@
+When /^I generate a new rails application$/ do
+ @terminal.cd(TEMP_ROOT)
+ @terminal.run("rails _3.0.0.beta4_ new #{APP_NAME}")
+ steps %{
+ When I save the following as "Gemfile"
+ """
+ source "http://rubygems.org"
+ gem 'rails', '3.0.0.beta4'
+ gem 'sqlite3-ruby', :require => 'sqlite3'
+ """
+ }
+end
+
+When /^I configure the application to use "([^\"]+)" from this project$/ do |name|
+ append_to_gemfile "gem '#{name}', :path => '../../'"
+ steps %{And I run "bundle lock"}
+end
+
+When /^I run the "([^"]*)" generator$/ do |name|
+ steps %{
+ When I run "./script/rails generate #{name}"
+ }
+end
+
+When /^I run the rspec generator$/ do
+ steps %{
+ When I run the "rspec:install" generator
+ }
+end
+
+When /^I configure the application to use rspec\-rails$/ do
+ append_to_gemfile "gem 'rspec-rails', '>= 2.0.0.beta.12'"
+ steps %{And I run "bundle lock"}
+end
+
+When /^I configure a wildcard route$/ do
+ steps %{
+ When I save the following as "config/routes.rb"
+ """
+ Rails.application.routes.draw do |map|
+ match ':controller(/:action(/:id(.:format)))'
+ end
+ """
+ }
+end
+
+module AppendHelpers
+ def append_to(path, contents)
+ File.open(path, "a") do |file|
+ file.puts
+ file.puts contents
+ end
+ end
+
+ def append_to_gemfile(contents)
+ append_to(File.join(RAILS_ROOT, 'Gemfile'), contents)
+ end
+end
+
+World(AppendHelpers)
View
77 features/step_definitions/rails_steps.rb
@@ -1,77 +0,0 @@
-PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
-APP_NAME = 'testapp'.freeze
-
-When /^I generate a new rails application$/ do
- steps %{
- When I run "rails _3.0.3_ new #{APP_NAME}"
- And I cd to "#{APP_NAME}"
- And I write to "Gemfile" with:
- """
- source "http://rubygems.org"
- gem 'rails', '3.0.3'
- gem 'sqlite3-ruby', :require => 'sqlite3'
- """
- And I successfully run "bundle install --local"
- }
-end
-
-When /^I configure the application to use "([^\"]+)" from this project$/ do |name|
- append_to_gemfile "gem '#{name}', :path => '#{PROJECT_ROOT}'"
- steps %{And I run "bundle install --local"}
-end
-
-When /^I run the rspec generator$/ do
- steps %{
- When I successfully run "rails generate rspec:install"
- }
-end
-
-When /^I configure the application to use rspec\-rails$/ do
- append_to_gemfile "gem 'rspec-rails'"
- steps %{And I run "bundle install --local"}
-end
-
-When /^I configure the application to use shoulda-context$/ do
- append_to_gemfile "gem 'shoulda-context', :git => 'git@github.com:thoughtbot/shoulda-context.git'"
- steps %{And I run "bundle install --local"}
-end
-
-When /^I configure the application to use shoulda$/ do
- append_to_gemfile "gem 'shoulda-matchers', :git => 'git@github.com:thoughtbot/shoulda-matchers.git', :require => false"
- append_to_gemfile "gem 'shoulda-context', :git => 'git@github.com:thoughtbot/shoulda-context.git', :require => false"
- append_to_gemfile "gem 'shoulda', :path => '../../..'"
- steps %{And I run "bundle install --local"}
-end
-
-When /^I configure the application to use shoulda-matchers$/ do
- append_to_gemfile "gem 'shoulda-matchers', :git => 'git@github.com:thoughtbot/shoulda-matchers.git'"
- steps %{And I run "bundle install --local"}
-end
-
-When /^I configure a wildcard route$/ do
- steps %{
- When I write to "config/routes.rb" with:
- """
- Rails.application.routes.draw do
- match ':controller(/:action(/:id(.:format)))'
- end
- """
- }
-end
-
-module AppendHelpers
- def append_to(path, contents)
- in_current_dir do
- File.open(path, "a") do |file|
- file.puts
- file.puts contents
- end
- end
- end
-
- def append_to_gemfile(contents)
- append_to('Gemfile', contents)
- end
-end
-
-World(AppendHelpers)
View
5 features/support/env.rb
@@ -1,5 +0,0 @@
-require 'aruba/cucumber'
-
-Before do
- @aruba_timeout_seconds = 15
-end
View
36 features/support/terminal.rb
@@ -0,0 +1,36 @@
+require 'fileutils'
+
+class Terminal
+ attr_reader :output, :status
+
+ def initialize
+ @cwd = FileUtils.pwd
+ @output = ""
+ @status = 0
+ @logger = Logger.new(File.join(TEMP_ROOT, 'terminal.log'))
+ end
+
+ def cd(directory)
+ @cwd = directory
+ end
+
+ def run(command)
+ output << "#{command}\n"
+ FileUtils.cd(@cwd) do
+ logger.debug(command)
+ result = `#{command} 2>&1`
+ logger.debug(result)
+ output << result
+ end
+ @status = $?
+ end
+
+ def echo(string)
+ logger.debug(string)
+ end
+
+ private
+
+ attr_reader :logger
+end
+
View
1  init.rb
@@ -0,0 +1 @@
+require File.join(File.dirname(__FILE__), 'rails', 'init')
View
9 lib/shoulda.rb
@@ -1,4 +1,9 @@
require 'shoulda/version'
-require 'shoulda-matchers'
-require 'shoulda-context'
+if defined?(RSpec)
+ require 'shoulda/integrations/rspec2'
+elsif defined?(Spec)
+ require 'shoulda/integrations/rspec'
+else
+ require 'shoulda/integrations/test_unit'
+end
View
34 lib/shoulda/action_controller.rb
@@ -0,0 +1,34 @@
+require 'shoulda'
+require 'shoulda/action_controller/matchers'
+require 'shoulda/action_controller/macros'
+
+module Test # :nodoc: all
+ module Unit
+ class TestCase
+ include Shoulda::ActionController::Matchers
+ extend Shoulda::ActionController::Macros
+ end
+ end
+end
+
+require 'shoulda/active_record/assertions'
+require 'shoulda/action_mailer/assertions'
+
+module ActionController #:nodoc: all
+ module Integration
+ class Session
+ include Shoulda::Assertions
+ include Shoulda::Helpers
+ include Shoulda::ActiveRecord::Assertions
+ include Shoulda::ActionMailer::Assertions
+ end
+ end
+end
+
+if defined?(ActionController::TestCase)
+ class ActionController::TestCase
+ def subject
+ @controller
+ end
+ end
+end
View
208 lib/shoulda/action_controller/macros.rb
@@ -0,0 +1,208 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ # = Macro test helpers for your controllers
+ #
+ # By using the macro helpers you can quickly and easily create concise and easy to read test suites.
+ #
+ # This code segment:
+ # context "on GET to :show for first record" do
+ # setup do
+ # get :show, :id => 1
+ # end
+ #
+ # should_assign_to :user
+ # should_respond_with :success
+ # should_render_template :show
+ # should_not_set_the_flash
+ #
+ # should "do something else really cool" do
+ # assert_equal 1, assigns(:user).id
+ # end
+ # end
+ #
+ # Would produce 5 tests for the +show+ action
+ module Macros
+ include Matchers
+
+ # Deprecated: use ActionController::Matchers#set_the_flash instead.
+ #
+ # Macro that creates a test asserting that the flash contains the given
+ # value. Expects a +String+ or +Regexp+.
+ #
+ # Example:
+ #
+ # should_set_the_flash_to "Thank you for placing this order."
+ # should_set_the_flash_to /created/i
+ def should_set_the_flash_to(val)
+ should set_the_flash.to(val)
+ end
+
+ # Deprecated: use ActionController::Matchers#set_the_flash instead.
+ #
+ # Macro that creates a test asserting that the flash is empty.
+ def should_not_set_the_flash
+ should_not set_the_flash
+ end
+
+ # Deprecated: use ActionController::Matchers#filter_param instead.
+ #
+ # Macro that creates a test asserting that filter_parameter_logging
+ # is set for the specified keys
+ #
+ # Example:
+ #
+ # should_filter_params :password, :ssn
+ def should_filter_params(*keys)
+ keys.each do |key|
+ should filter_param(key)
+ end
+ end
+
+ # Deprecated: use ActionController::Matchers#assign_to instead.
+ #
+ # Macro that creates a test asserting that the controller assigned to
+ # each of the named instance variable(s).
+ #
+ # Options:
+ # * <tt>:class</tt> - The expected class of the instance variable being checked.
+ #
+ # If a block is passed, the assigned variable is expected to be equal to
+ # the return value of that block.
+ #
+ # Example:
+ #
+ # should_assign_to :user, :posts
+ # should_assign_to :user, :class => User
+ # should_assign_to(:user) { @user }
+ def should_assign_to(*names, &block)
+ klass = get_options!(names, :class)
+ names.each do |name|
+ matcher = assign_to(name).with_kind_of(klass)
+ matcher = matcher.with(&block) if block
+ should matcher
+ end
+ end
+
+ # Deprecated: use ActionController::Matchers#assign_to instead.
+ #
+ # Macro that creates a test asserting that the controller did not assign to
+ # any of the named instance variable(s).
+ #
+ # Example:
+ #
+ # should_not_assign_to :user, :posts
+ def should_not_assign_to(*names)
+ names.each do |name|
+ should_not assign_to(name)
+ end
+ end
+
+ # Deprecated: use ActionController::Matchers#respond_with instead.
+ #
+ # Macro that creates a test asserting that the controller responded with a 'response' status code.
+ # Example:
+ #
+ # should_respond_with :success
+ def should_respond_with(response)
+ should respond_with(response)
+ end
+
+ # Deprecated: use ActionController::Matchers#respond_with_content_type instead.
+ #
+ # Macro that creates a test asserting that the response content type was 'content_type'.
+ # Example:
+ #
+ # should_respond_with_content_type 'application/rss+xml'
+ # should_respond_with_content_type :rss
+ # should_respond_with_content_type /rss/
+ def should_respond_with_content_type(content_type)
+ should respond_with_content_type(content_type)
+ end
+
+ # Deprecated: use ActionController::Matchers#set_session instead.
+ #
+ # Macro that creates a test asserting that a value returned from the
+ # session is correct. Expects the session key as a parameter, and a block
+ # that returns the expected value.
+ #
+ # Example:
+ #
+ # should_set_session(:user_id) { @user.id }
+ # should_set_session(:message) { "Free stuff" }
+ def should_set_session(key, &block)
+ matcher = set_session(key)
+ matcher = matcher.to(&block) if block
+ should matcher
+ end
+
+ # Deprecated: use ActionController::Matchers#render_template instead.
+ #
+ # Macro that creates a test asserting that the controller rendered the given template.
+ # Example:
+ #
+ # should_render_template :new
+ def should_render_template(template)
+ should render_template(template)
+ end
+
+ # Deprecated: use ActionController::Matchers#render_with_layout instead.
+ #
+ # Macro that creates a test asserting that the controller rendered with the given layout.
+ # Example:
+ #
+ # should_render_with_layout 'special'
+ def should_render_with_layout(expected_layout = 'application')
+ should render_with_layout(expected_layout)
+ end
+
+ # Deprecated: use ActionController::Matchers#render_with_layout instead.
+ #
+ # Macro that creates a test asserting that the controller rendered without a layout.
+ # Same as @should_render_with_layout false@
+ def should_render_without_layout
+ should_not render_with_layout
+ end
+
+ # Deprecated: use ActionController::Matchers#redirect_to instead.
+ #
+ # Macro that creates a test asserting that the controller returned a
+ # redirect to the given path. The passed description will be used when
+ # generating a test name. Expects a block that returns the expected path
+ # for the redirect.
+ #
+ # Example:
+ #
+ # should_redirect_to("the user's profile") { user_url(@user) }
+ def should_redirect_to(description, &block)
+ should redirect_to(description, &block)
+ end
+
+ # Deprecated: use ActionController::Matchers#route instead.
+ #
+ # Macro that creates a routing test. It tries to use the given HTTP
+ # +method+ on the given +path+, and asserts that it routes to the
+ # given +options+.
+ #
+ # If you don't specify a :controller, it will try to guess the controller
+ # based on the current test.
+ #
+ # +to_param+ is called on the +options+ given.
+ #
+ # Examples:
+ #
+ # should_route :get, "/posts", :controller => :posts, :action => :index
+ # should_route :get, "/posts/new", :action => :new
+ # should_route :post, "/posts", :action => :create
+ # should_route :get, "/posts/1", :action => :show, :id => 1
+ # should_route :edit, "/posts/1", :action => :show, :id => 1
+ # should_route :put, "/posts/1", :action => :update, :id => 1
+ # should_route :delete, "/posts/1", :action => :destroy, :id => 1
+ # should_route :get, "/users/1/posts/1",
+ # :action => :show, :id => 1, :user_id => 1
+ #
+ def should_route(method, path, options)
+ should route(method, path).to(options)
+ end
+ end
+ end
+end
View
39 lib/shoulda/action_controller/matchers.rb
@@ -0,0 +1,39 @@
+require 'shoulda/action_controller/matchers/assign_to_matcher'
+require 'shoulda/action_controller/matchers/filter_param_matcher'
+require 'shoulda/action_controller/matchers/set_the_flash_matcher'
+require 'shoulda/action_controller/matchers/render_with_layout_matcher'
+require 'shoulda/action_controller/matchers/respond_with_matcher'
+require 'shoulda/action_controller/matchers/respond_with_content_type_matcher'
+require 'shoulda/action_controller/matchers/set_session_matcher'
+require 'shoulda/action_controller/matchers/route_matcher'
+require 'shoulda/action_controller/matchers/redirect_to_matcher'
+require 'shoulda/action_controller/matchers/render_template_matcher'
+
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+
+ # By using the macro helpers you can quickly and easily create concise and
+ # easy to read test suites.
+ #
+ # This code segment:
+ #
+ # describe UsersController, "on GET to show with a valid id" do
+ # before(:each) do
+ # get :show, :id => User.first.to_param
+ # end
+ #
+ # it { should assign_to(:user) }
+ # it { should respond_with(:success) }
+ # it { should render_template(:show) }
+ # it { should not_set_the_flash) }
+ #
+ # it "should do something else really cool" do
+ # assigns[:user].id.should == 1
+ # end
+ # end
+ #
+ # Would produce 5 tests for the show action
+ module Matchers
+ end
+ end
+end
View
112 lib/shoulda/action_controller/matchers/assign_to_matcher.rb
@@ -0,0 +1,112 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ module Matchers
+
+ # Ensures that the controller assigned to the named instance variable.
+ #
+ # Options:
+ # * <tt>with_kind_of</tt> - The expected class of the instance variable
+ # being checked.
+ # * <tt>with</tt> - The value that should be assigned.
+ #
+ # Example:
+ #
+ # it { should assign_to(:user) }
+ # it { should_not assign_to(:user) }
+ # it { should assign_to(:user).with_kind_of(User) }
+ # it { should assign_to(:user).with(@user) }
+ def assign_to(variable)
+ AssignToMatcher.new(variable)
+ end
+
+ class AssignToMatcher # :nodoc:
+
+ def initialize(variable)
+ @variable = variable.to_s
+ end
+
+ def with_kind_of(expected_class)
+ @expected_class = expected_class
+ self
+ end
+
+ def with(expected_value = nil, &block)
+ @expected_value = expected_value
+ @expectation_block = block
+ self
+ end
+
+ def matches?(controller)
+ @controller = controller
+ @expected_value = @context.instance_eval(&@expectation_block) if @expectation_block
+ assigned_value? && kind_of_expected_class? && equal_to_expected_value?
+ end
+
+ attr_reader :failure_message, :negative_failure_message
+
+ def description
+ description = "assign @#{@variable}"
+ description << " with a kind of #{@expected_class}" if @expected_class
+ description
+ end
+
+ def in_context(context)
+ @context = context
+ self
+ end
+
+ private
+
+ def assigned_value?
+ if assigned_value.nil?
+ @failure_message =
+ "Expected action to assign a value for @#{@variable}"
+ false
+ else
+ @negative_failure_message =
+ "Didn't expect action to assign a value for @#{@variable}, " <<
+ "but it was assigned to #{assigned_value.inspect}"
+ true
+ end
+ end
+
+ def kind_of_expected_class?
+ return true unless @expected_class
+ if assigned_value.kind_of?(@expected_class)
+ @negative_failure_message =
+ "Didn't expect action to assign a kind of #{@expected_class} " <<
+ "for #{@variable}, but got one anyway"
+ true
+ else
+ @failure_message =
+ "Expected action to assign a kind of #{@expected_class} " <<
+ "for #{@variable}, but got #{@variable.inspect} " <<
+ "(#{@variable.class.name})"
+ false
+ end
+ end
+
+ def equal_to_expected_value?
+ return true unless @expected_value
+ if @expected_value == assigned_value
+ @negative_failure_message =
+ "Didn't expect action to assign #{@expected_value.inspect} " <<
+ "for #{@variable}, but got it anyway"
+ true
+ else
+ @failure_message =
+ "Expected action to assign #{@expected_value.inspect} " <<
+ "for #{@variable}, but got #{assigned_value.inspect}"
+ false
+ end
+ end
+
+ def assigned_value
+ @controller.instance_variable_get("@#{@variable}")
+ end
+
+ end
+
+ end
+ end
+end
View
74 lib/shoulda/action_controller/matchers/filter_param_matcher.rb
@@ -0,0 +1,74 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ module Matchers
+
+ # Ensures that filter_parameter_logging is set for the specified key.
+ #
+ # Example:
+ #
+ # it { should filter_param(:password) }
+ def filter_param(key)
+ FilterParamMatcher.new(key)
+ end
+
+ class FilterParamMatcher # :nodoc:
+
+ def initialize(key)
+ @key = key.to_s
+ end
+
+ def matches?(controller)
+ @controller = controller
+ filters_params? && filters_key?
+ end
+
+ def failure_message
+ "Expected #{@key} to be filtered"
+ end
+
+ def negative_failure_message
+ "Did not expect #{@key} to be filtered"
+ end
+
+ def description
+ "filter #{@key}"
+ end
+
+ private
+
+ def filters_params?
+ @controller.respond_to?(:filter_parameters) ||
+ request.respond_to?(:filtered_parameters)
+ end
+
+ def filters_key?
+ filtered_value == '[FILTERED]'
+ end
+
+ def filtered_value
+ if request.respond_to?(:filtered_parameters)
+ filtered_request_value
+ else
+ filtered_controller_value
+ end
+ end
+
+ def filtered_controller_value
+ filtered = @controller.send(:filter_parameters,
+ @key.to_s => @key.to_s)
+ filtered[@key.to_s]
+ end
+
+ def filtered_request_value
+ request.env['action_dispatch.request.parameters'] = { @key.to_s => 'value' }
+ request.filtered_parameters[@key.to_s]
+ end
+
+ def request
+ @request ||= ::ActionController::TestRequest.new
+ end
+ end
+
+ end
+ end
+end
View
62 lib/shoulda/action_controller/matchers/redirect_to_matcher.rb
@@ -0,0 +1,62 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ module Matchers
+
+ # Ensures a controller redirected to the given url.
+ #
+ # Example:
+ #
+ # it { should redirect_to('http://somewhere.com') }
+ # it { should redirect_to(users_path) }
+ def redirect_to(url_or_description, &block)
+ RedirectToMatcher.new(url_or_description, self, &block)
+ end
+
+ class RedirectToMatcher # :nodoc:
+
+ def initialize(url_or_description, context, &block)
+ if block
+ @url_block = block
+ @location = @url_or_description
+ else
+ @url = url_or_description
+ @location = @url
+ end
+ @context = context
+ end
+
+ def in_context(context)
+ @context = context
+ self
+ end
+
+ def matches?(controller)
+ @controller = controller
+ redirects_to_url?
+ end
+
+ attr_reader :failure_message, :negative_failure_message
+
+ def description
+ "redirect to #{@location}"
+ end
+
+ private
+
+ def redirects_to_url?
+ @url = @context.instance_eval(&@url_block) if @url_block
+ begin
+ @context.send(:assert_redirected_to, @url)
+ @negative_failure_message = "Didn't expect to redirect to #{@url}"
+ true
+ rescue Test::Unit::AssertionFailedError => error
+ @failure_message = error.message
+ false
+ end
+ end
+
+ end
+
+ end
+ end
+end
View
54 lib/shoulda/action_controller/matchers/render_template_matcher.rb
@@ -0,0 +1,54 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ module Matchers
+
+ # Ensures a controller rendered the given template.
+ #
+ # Example:
+ #
+ # it { should render_template(:show) }
+ def render_template(template)
+ RenderTemplateMatcher.new(template, self)
+ end
+
+ class RenderTemplateMatcher # :nodoc:
+
+ def initialize(template, context)
+ @template = template.to_s
+ @context = context
+ end
+
+ def matches?(controller)
+ @controller = controller
+ renders_template?
+ end
+
+ attr_reader :failure_message, :negative_failure_message
+
+ def description
+ "render template #{@template}"
+ end
+
+ def in_context(context)
+ @context = context
+ self
+ end
+
+ private
+
+ def renders_template?
+ begin
+ @context.send(:assert_template, @template)
+ @negative_failure_message = "Didn't expect to render #{@template}"
+ true
+ rescue Test::Unit::AssertionFailedError => error
+ @failure_message = error.message
+ false
+ end
+ end
+
+ end
+
+ end
+ end
+end
View
99 lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb
@@ -0,0 +1,99 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ module Matchers
+
+ # Ensures that the controller rendered with the given layout.
+ #
+ # Example:
+ #
+ # it { should render_with_layout }
+ # it { should render_with_layout(:special) }
+ # it { should_not render_with_layout }
+ def render_with_layout(expected_layout = nil)
+ RenderWithLayout.new(expected_layout)
+ end
+
+ class RenderWithLayout # :nodoc:
+
+ def initialize(expected_layout)
+ @expected_layout = expected_layout.to_s unless expected_layout.nil?
+ end
+
+ # Used to provide access to layouts recorded by
+ # ActionController::TemplateAssertions in Rails 3
+ def in_context(context)
+ @context = context
+ self
+ end
+
+ def matches?(controller)
+ @controller = controller
+ rendered_with_layout? && rendered_with_expected_layout?
+ end
+
+ def failure_message
+ "Expected #{expectation}, but #{result}"
+ end
+
+ def negative_failure_message
+ "Did not expect #{expectation}, but #{result}"
+ end
+
+ def description
+ description = "render with "
+ if @expected_layout.nil?
+ description << "a layout"
+ else
+ description << "the #{@expected_layout.inspect} layout"
+ end
+ description
+ end
+
+ private
+
+ def rendered_with_layout?
+ !rendered_layouts.empty?
+ end
+
+ def rendered_with_expected_layout?
+ return true if @expected_layout.nil?
+ rendered_layouts.include?(@expected_layout)
+ end
+
+ def rendered_layouts
+ if recorded_layouts
+ recorded_layouts.keys.compact.map { |layout| layout.sub(%r{^layouts/}, '') }
+ else
+ layout = @controller.response.layout
+ if layout.nil?
+ []
+ else
+ [layout.split('/').last]
+ end
+ end
+ end
+
+ def recorded_layouts
+ if @context
+ @context.instance_variable_get('@layouts')
+ end
+ end
+
+ def expectation
+ "to #{description}"
+ end
+
+ def result
+ if rendered_with_layout?
+ "rendered with " <<
+ rendered_layouts.map { |layout| layout.inspect }.join(", ")
+ else
+ "rendered without a layout"
+ end
+ end
+
+ end
+
+ end
+ end
+end
View
74 lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb
@@ -0,0 +1,74 @@
+module Shoulda # :nodoc:
+ module ActionController # :nodoc:
+ module Matchers
+
+ # Ensures a controller responded with expected 'response' content type.
+ #
+ # You can pass an explicit content type such as 'application/rss+xml'
+ # or its symbolic equivalent :rss
+ # or a regular expression such as /rss/
+ #
+ # Example: