├── .document ├── .gitignore ├── Contribute.rdoc ├── Gemfile ├── History.rdoc ├── License.txt ├── Manifest.txt ├── README.rdoc ├── Rakefile ├── TODO.txt ├── Upgrade.rdoc ├── generators ├── integration_spec │ ├── integration_spec_generator.rb │ └── templates │ │ └── integration_spec.rb ├── rspec │ ├── CHANGES │ ├── rspec_generator.rb │ └── templates │ │ ├── previous_failures.txt │ │ ├── rcov.opts │ │ ├── rspec.rake │ │ ├── script │ │ ├── autospec │ │ └── spec │ │ ├── spec.opts │ │ └── spec_helper.rb ├── rspec_controller │ ├── USAGE │ ├── rspec_controller_generator.rb │ └── templates │ │ ├── controller_spec.rb │ │ ├── helper_spec.rb │ │ └── view_spec.rb ├── rspec_default_values.rb ├── rspec_model │ ├── USAGE │ ├── rspec_model_generator.rb │ └── templates │ │ └── model_spec.rb └── rspec_scaffold │ ├── rspec_scaffold_generator.rb │ └── templates │ ├── controller_spec.rb │ ├── edit_erb_spec.rb │ ├── helper_spec.rb │ ├── index_erb_spec.rb │ ├── new_erb_spec.rb │ ├── routing_spec.rb │ └── show_erb_spec.rb ├── init.rb ├── lib ├── autotest │ ├── discover.rb │ └── rails_rspec.rb └── spec │ ├── rails.rb │ └── rails │ ├── example.rb │ ├── example │ ├── assigns_hash_proxy.rb │ ├── controller_example_group.rb │ ├── cookies_proxy.rb │ ├── functional_example_group.rb │ ├── helper_example_group.rb │ ├── integration_example_group.rb │ ├── model_example_group.rb │ ├── render_observer.rb │ ├── routing_example_group.rb │ ├── routing_helpers.rb │ └── view_example_group.rb │ ├── extensions.rb │ ├── extensions │ ├── action_controller │ │ ├── rescue.rb │ │ ├── test_case.rb │ │ └── test_response.rb │ ├── action_view │ │ └── base.rb │ ├── active_record │ │ └── base.rb │ ├── active_support │ │ └── test_case.rb │ └── spec │ │ ├── matchers │ │ └── have.rb │ │ └── runner │ │ └── configuration.rb │ ├── interop │ └── testcase.rb │ ├── matchers.rb │ ├── matchers │ ├── ar_be_valid.rb │ ├── assert_select.rb │ ├── change.rb │ ├── have_text.rb │ ├── include_text.rb │ ├── redirect_to.rb │ ├── render_template.rb │ └── route_to.rb │ ├── mocks.rb │ └── version.rb ├── rspec-rails.gemspec └── spec ├── autotest └── mappings_spec.rb ├── rails_suite.rb ├── resources ├── controllers │ ├── action_view_base_spec_controller.rb │ ├── application.rb │ ├── controller_spec_controller.rb │ ├── example.txt │ ├── redirect_spec_controller.rb │ ├── render_spec_controller.rb │ └── rjs_spec_controller.rb ├── helpers │ ├── addition_helper.rb │ ├── explicit_helper.rb │ ├── more_explicit_helper.rb │ ├── plugin_application_helper.rb │ └── view_spec_helper.rb ├── models │ ├── animal.rb │ ├── person.rb │ └── thing.rb └── views │ ├── controller_spec │ ├── _partial.html.erb │ ├── action_setting_flash_after_session_reset.html.erb │ ├── action_setting_flash_before_session_reset.html.erb │ ├── action_setting_the_assigns_hash.html.erb │ ├── action_with_errors_in_template.html.erb │ ├── action_with_template.html.erb │ └── non_existent_action_with_existent_template.html.erb │ ├── layouts │ ├── application.html.erb │ └── simple.html.erb │ ├── objects │ └── _object.html.erb │ ├── render_spec │ ├── _a_partial.html.erb │ ├── action_with_alternate_layout.html.erb │ ├── some_action.html.erb │ └── some_action.js.rjs │ ├── rjs_spec │ ├── _replacement_partial.html.erb │ ├── hide_div.js.rjs │ ├── hide_page_element.js.rjs │ ├── insert_html.js.rjs │ ├── replace.js.rjs │ ├── replace_html.js.rjs │ ├── replace_html_with_partial.js.rjs │ ├── visual_effect.js.rjs │ └── visual_toggle_effect.js.rjs │ ├── tag_spec │ ├── no_tags.html.erb │ ├── single_div_with_no_attributes.html.erb │ └── single_div_with_one_attribute.html.erb │ └── view_spec │ ├── _partial.html.erb │ ├── _partial_used_twice.html.erb │ ├── _partial_with_local_variable.html.erb │ ├── _partial_with_sub_partial.html.erb │ ├── _spacer.html.erb │ ├── accessor.html.erb │ ├── block_helper.html.erb │ ├── entry_form.html.erb │ ├── explicit_helper.html.erb │ ├── foo │ └── show.html.erb │ ├── implicit_helper.html.erb │ ├── multiple_helpers.html.erb │ ├── path_params.html.erb │ ├── should_not_receive.html.erb │ ├── template_with_partial.html.erb │ ├── template_with_partial_using_collection.html.erb │ ├── template_with_partial_with_array.html.erb │ └── view_helpers.html.erb ├── spec └── rails │ ├── example │ ├── assigns_hash_proxy_spec.rb │ ├── configuration_spec.rb │ ├── controller_example_group_spec.rb │ ├── controller_isolation_spec.rb │ ├── cookies_proxy_spec.rb │ ├── error_handling_spec.rb │ ├── example_group_factory_spec.rb │ ├── helper_example_group_spec.rb │ ├── model_example_group_spec.rb │ ├── routing_example_group_spec.rb │ ├── shared_routing_example_group_examples.rb │ ├── test_unit_assertion_accessibility_spec.rb │ └── view_example_group_spec.rb │ ├── extensions │ ├── action_view_base_spec.rb │ └── active_record_spec.rb │ ├── interop │ └── testcase_spec.rb │ ├── matchers │ ├── ar_be_valid_spec.rb │ ├── assert_select_spec.rb │ ├── errors_on_spec.rb │ ├── have_text_spec.rb │ ├── include_text_spec.rb │ ├── redirect_to_spec.rb │ ├── render_template_spec.rb │ └── should_change_spec.rb │ ├── mocks │ ├── ar_classes.rb │ ├── mock_model_spec.rb │ └── stub_model_spec.rb │ ├── sample_modified_fixture.rb │ ├── sample_spec.rb │ └── spec_spec.rb └── spec_helper.rb /.document: -------------------------------------------------------------------------------- 1 | lib/**/*.rb 2 | History.rdoc 3 | License.txt 4 | README.rdoc 5 | Upgrade.rdoc 6 | features/**/*.feature 7 | 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tmtags 2 | .DS_Store 3 | .emacs-project 4 | *~ 5 | pkg 6 | doc 7 | email.txt 8 | *.swp 9 | -------------------------------------------------------------------------------- /Contribute.rdoc: -------------------------------------------------------------------------------- 1 | == Contribute 2 | 3 | If you're interested in contributing to rspec-rails, please see 4 | http://wiki.github.com/dchelimsky/rspec-dev for information. 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in rspec-rails.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /License.txt: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | ==================================================================== 4 | ==== RSpec, RSpec-Rails 5 | Copyright (c) 2005-2009 The RSpec Development Team 6 | ==================================================================== 7 | ==== ARTS 8 | Copyright (c) 2006 Kevin Clark, Jake Howerton 9 | ==================================================================== 10 | ==== ZenTest 11 | Copyright (c) 2001-2006 Ryan Davis, Eric Hodel, Zen Spider Software 12 | ==================================================================== 13 | ==== AssertSelect 14 | Copyright (c) 2006 Assaf Arkin 15 | ==================================================================== 16 | 17 | Permission is hereby granted, free of charge, to any person obtaining a copy of 18 | this software and associated documentation files (the "Software"), to deal in 19 | the Software without restriction, including without limitation the rights to 20 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 21 | of the Software, and to permit persons to whom the Software is furnished to do 22 | so, subject to the following conditions: 23 | 24 | The above copyright notice and this permission notice shall be included in all 25 | copies or substantial portions of the Software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 30 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 31 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 32 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 | SOFTWARE. 34 | -------------------------------------------------------------------------------- /Manifest.txt: -------------------------------------------------------------------------------- 1 | .document 2 | Contribute.rdoc 3 | History.rdoc 4 | License.txt 5 | Manifest.txt 6 | README.rdoc 7 | Rakefile 8 | TODO.txt 9 | Upgrade.rdoc 10 | generators/integration_spec/integration_spec_generator.rb 11 | generators/integration_spec/templates/integration_spec.rb 12 | generators/rspec/CHANGES 13 | generators/rspec/rspec_generator.rb 14 | generators/rspec/templates/previous_failures.txt 15 | generators/rspec/templates/rcov.opts 16 | generators/rspec/templates/rspec.rake 17 | generators/rspec/templates/script/autospec 18 | generators/rspec/templates/script/spec 19 | generators/rspec/templates/spec.opts 20 | generators/rspec/templates/spec_helper.rb 21 | generators/rspec_controller/USAGE 22 | generators/rspec_controller/rspec_controller_generator.rb 23 | generators/rspec_controller/templates/controller_spec.rb 24 | generators/rspec_controller/templates/helper_spec.rb 25 | generators/rspec_controller/templates/view_spec.rb 26 | generators/rspec_default_values.rb 27 | generators/rspec_model/USAGE 28 | generators/rspec_model/rspec_model_generator.rb 29 | generators/rspec_model/templates/model_spec.rb 30 | generators/rspec_scaffold/rspec_scaffold_generator.rb 31 | generators/rspec_scaffold/templates/controller_spec.rb 32 | generators/rspec_scaffold/templates/edit_erb_spec.rb 33 | generators/rspec_scaffold/templates/helper_spec.rb 34 | generators/rspec_scaffold/templates/index_erb_spec.rb 35 | generators/rspec_scaffold/templates/new_erb_spec.rb 36 | generators/rspec_scaffold/templates/routing_spec.rb 37 | generators/rspec_scaffold/templates/show_erb_spec.rb 38 | init.rb 39 | lib/autotest/discover.rb 40 | lib/autotest/rails_rspec.rb 41 | lib/spec/rails.rb 42 | lib/spec/rails/example.rb 43 | lib/spec/rails/example/assigns_hash_proxy.rb 44 | lib/spec/rails/example/controller_example_group.rb 45 | lib/spec/rails/example/cookies_proxy.rb 46 | lib/spec/rails/example/functional_example_group.rb 47 | lib/spec/rails/example/helper_example_group.rb 48 | lib/spec/rails/example/integration_example_group.rb 49 | lib/spec/rails/example/model_example_group.rb 50 | lib/spec/rails/example/render_observer.rb 51 | lib/spec/rails/example/routing_example_group.rb 52 | lib/spec/rails/example/routing_helpers.rb 53 | lib/spec/rails/example/view_example_group.rb 54 | lib/spec/rails/extensions.rb 55 | lib/spec/rails/extensions/action_controller/rescue.rb 56 | lib/spec/rails/extensions/action_controller/test_case.rb 57 | lib/spec/rails/extensions/action_controller/test_response.rb 58 | lib/spec/rails/extensions/action_view/base.rb 59 | lib/spec/rails/extensions/active_record/base.rb 60 | lib/spec/rails/extensions/active_support/test_case.rb 61 | lib/spec/rails/extensions/spec/matchers/have.rb 62 | lib/spec/rails/extensions/spec/runner/configuration.rb 63 | lib/spec/rails/interop/testcase.rb 64 | lib/spec/rails/matchers.rb 65 | lib/spec/rails/matchers/ar_be_valid.rb 66 | lib/spec/rails/matchers/assert_select.rb 67 | lib/spec/rails/matchers/change.rb 68 | lib/spec/rails/matchers/have_text.rb 69 | lib/spec/rails/matchers/include_text.rb 70 | lib/spec/rails/matchers/redirect_to.rb 71 | lib/spec/rails/matchers/render_template.rb 72 | lib/spec/rails/matchers/route_to.rb 73 | lib/spec/rails/mocks.rb 74 | lib/spec/rails/version.rb 75 | spec/autotest/mappings_spec.rb 76 | spec/rails_suite.rb 77 | spec/resources/controllers/action_view_base_spec_controller.rb 78 | spec/resources/controllers/application.rb 79 | spec/resources/controllers/controller_spec_controller.rb 80 | spec/resources/controllers/example.txt 81 | spec/resources/controllers/redirect_spec_controller.rb 82 | spec/resources/controllers/render_spec_controller.rb 83 | spec/resources/controllers/rjs_spec_controller.rb 84 | spec/resources/helpers/addition_helper.rb 85 | spec/resources/helpers/explicit_helper.rb 86 | spec/resources/helpers/more_explicit_helper.rb 87 | spec/resources/helpers/plugin_application_helper.rb 88 | spec/resources/helpers/view_spec_helper.rb 89 | spec/resources/models/animal.rb 90 | spec/resources/models/person.rb 91 | spec/resources/models/thing.rb 92 | spec/resources/views/controller_spec/_partial.html.erb 93 | spec/resources/views/controller_spec/action_setting_flash_after_session_reset.html.erb 94 | spec/resources/views/controller_spec/action_setting_flash_before_session_reset.html.erb 95 | spec/resources/views/controller_spec/action_setting_the_assigns_hash.html.erb 96 | spec/resources/views/controller_spec/action_with_errors_in_template.html.erb 97 | spec/resources/views/controller_spec/action_with_template.html.erb 98 | spec/resources/views/layouts/application.html.erb 99 | spec/resources/views/layouts/simple.html.erb 100 | spec/resources/views/objects/_object.html.erb 101 | spec/resources/views/render_spec/_a_partial.html.erb 102 | spec/resources/views/render_spec/action_with_alternate_layout.html.erb 103 | spec/resources/views/render_spec/some_action.html.erb 104 | spec/resources/views/render_spec/some_action.js.rjs 105 | spec/resources/views/rjs_spec/_replacement_partial.html.erb 106 | spec/resources/views/rjs_spec/hide_div.js.rjs 107 | spec/resources/views/rjs_spec/hide_page_element.js.rjs 108 | spec/resources/views/rjs_spec/insert_html.js.rjs 109 | spec/resources/views/rjs_spec/replace.js.rjs 110 | spec/resources/views/rjs_spec/replace_html.js.rjs 111 | spec/resources/views/rjs_spec/replace_html_with_partial.js.rjs 112 | spec/resources/views/rjs_spec/visual_effect.js.rjs 113 | spec/resources/views/rjs_spec/visual_toggle_effect.js.rjs 114 | spec/resources/views/tag_spec/no_tags.html.erb 115 | spec/resources/views/tag_spec/single_div_with_no_attributes.html.erb 116 | spec/resources/views/tag_spec/single_div_with_one_attribute.html.erb 117 | spec/resources/views/view_spec/_partial.html.erb 118 | spec/resources/views/view_spec/_partial_used_twice.html.erb 119 | spec/resources/views/view_spec/_partial_with_local_variable.html.erb 120 | spec/resources/views/view_spec/_partial_with_sub_partial.html.erb 121 | spec/resources/views/view_spec/_spacer.html.erb 122 | spec/resources/views/view_spec/accessor.html.erb 123 | spec/resources/views/view_spec/block_helper.html.erb 124 | spec/resources/views/view_spec/entry_form.html.erb 125 | spec/resources/views/view_spec/explicit_helper.html.erb 126 | spec/resources/views/view_spec/foo/show.html.erb 127 | spec/resources/views/view_spec/implicit_helper.html.erb 128 | spec/resources/views/view_spec/multiple_helpers.html.erb 129 | spec/resources/views/view_spec/path_params.html.erb 130 | spec/resources/views/view_spec/should_not_receive.html.erb 131 | spec/resources/views/view_spec/template_with_partial.html.erb 132 | spec/resources/views/view_spec/template_with_partial_using_collection.html.erb 133 | spec/resources/views/view_spec/template_with_partial_with_array.html.erb 134 | spec/resources/views/view_spec/view_helpers.html.erb 135 | spec/spec/rails/example/assigns_hash_proxy_spec.rb 136 | spec/spec/rails/example/configuration_spec.rb 137 | spec/spec/rails/example/controller_example_group_spec.rb 138 | spec/spec/rails/example/controller_isolation_spec.rb 139 | spec/spec/rails/example/cookies_proxy_spec.rb 140 | spec/spec/rails/example/error_handling_spec.rb 141 | spec/spec/rails/example/example_group_factory_spec.rb 142 | spec/spec/rails/example/helper_example_group_spec.rb 143 | spec/spec/rails/example/model_example_group_spec.rb 144 | spec/spec/rails/example/routing_example_group_spec.rb 145 | spec/spec/rails/example/shared_routing_example_group_examples.rb 146 | spec/spec/rails/example/test_unit_assertion_accessibility_spec.rb 147 | spec/spec/rails/example/view_example_group_spec.rb 148 | spec/spec/rails/extensions/action_view_base_spec.rb 149 | spec/spec/rails/extensions/active_record_spec.rb 150 | spec/spec/rails/interop/testcase_spec.rb 151 | spec/spec/rails/matchers/ar_be_valid_spec.rb 152 | spec/spec/rails/matchers/assert_select_spec.rb 153 | spec/spec/rails/matchers/errors_on_spec.rb 154 | spec/spec/rails/matchers/have_text_spec.rb 155 | spec/spec/rails/matchers/include_text_spec.rb 156 | spec/spec/rails/matchers/redirect_to_spec.rb 157 | spec/spec/rails/matchers/render_template_spec.rb 158 | spec/spec/rails/matchers/should_change_spec.rb 159 | spec/spec/rails/mocks/ar_classes.rb 160 | spec/spec/rails/mocks/mock_model_spec.rb 161 | spec/spec/rails/mocks/stub_model_spec.rb 162 | spec/spec/rails/sample_modified_fixture.rb 163 | spec/spec/rails/sample_spec.rb 164 | spec/spec/rails/spec_spec.rb 165 | spec/spec_helper.rb 166 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = Spec::Rails 2 | 3 | * http://rspec.info 4 | * http://rubyforge.org/projects/rspec 5 | * http://github.com/dchelimsky/rspec-rails 6 | * http://wiki.github.com/dchelimsky/rspec/rails 7 | * mailto:rspec-devel@rubyforge.org 8 | 9 | == DESCRIPTION: 10 | 11 | Behaviour Driven Development for Ruby on Rails. 12 | 13 | rspec-rails is an RSpec extension that allows you to drive the development of 14 | Ruby on Rails applications with RSpec. 15 | 16 | This is the repository for rspec-rails-1.x. If you're looking 17 | for rspec-rails-2 for rails-3, see http://github.com/rspec/rspec-rails. 18 | 19 | == FEATURES: 20 | 21 | * Use RSpec to independently specify Rails Models, Views, Controllers and Helpers 22 | * Integrated fixture loading 23 | * Special generators for Resources, Models, Views and Controllers that generate RSpec code examples. 24 | 25 | == VISION: 26 | 27 | For people for whom TDD is a brand new concept, the testing support built into 28 | Ruby on Rails is a huge leap forward. The fact that it is built right in is 29 | fantastic, and Ruby on Rails apps are generally much easier to maintain than 30 | they might have been without such support. 31 | 32 | For those of us coming from a history with TDD, and now BDD, the existing 33 | support presents some problems related to dependencies across examples. To 34 | that end, RSpec on Rails supports 4 types of examples. We’ve also built in 35 | first class mocking and stubbing support in order to break dependencies across 36 | these different concerns. 37 | 38 | == MORE INFORMATION: 39 | 40 | See Spec::Rails::Example for information about the different kinds of example 41 | groups you can use to spec the different Rails components 42 | 43 | See Spec::Rails::Matchers for information about Rails-specific 44 | expectations you can set on responses and models, etc. 45 | 46 | == INSTALL 47 | 48 | * Visit http://wiki.github.com/dchelimsky/rspec/rails for installation instructions. 49 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"..","rspec","lib"))) 5 | $:.unshift(File.expand_path(File.join(File.dirname(__FILE__),"lib"))) 6 | 7 | require 'spec/rails/version' 8 | require 'spec/rake/spectask' 9 | 10 | Spec::Rake::SpecTask.new 11 | 12 | task :default => [:features] 13 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | * wiki 2 | * need a matrix of which rspec-rails versions support which rails versions 3 | * CI 4 | * need a robust CI setup that runs 5 | * Multiple rubies 6 | * MRI: 1.8.6 7 | * MRI: 1.8.7 8 | * MRI: 1.9.1 9 | * JRuby 10 | * IronRuby??? (perhaps using mono) 11 | * Multiple rails-es 12 | * 2.0.5 13 | * 2.1.2 14 | * 2.2.2 15 | * 2.3.4 16 | * 3.0 (once available) 17 | * With and without ActiveRecord 18 | -------------------------------------------------------------------------------- /Upgrade.rdoc: -------------------------------------------------------------------------------- 1 | = Upgrade to 1.2.8 - 1.3.2 2 | 3 | == What's new 4 | 5 | === route_to and be_routable matchers 6 | 7 | Stop using route_for and params_from today! These new matchers from Randy 8 | Harmon are more expressive and more reliable. Here's how you use them: 9 | 10 | { :put => "/projects/37" }.should route_to(:controller => 'projects', :action => 'update', :id => '37') 11 | 12 | { :get => "/nonexisting_route" }.should_not be_routable 13 | 14 | == What's changed 15 | 16 | === spec_server has been removed 17 | 18 | spec_server was deprecated in 1.2.7 and has now been removed. Admittedly, this 19 | was a short deprecation cycle, but spec server never quite worked right in all 20 | situations and spork is a great solution that you can use today! This is all 21 | you need to do: 22 | 23 | [sudo] gem install spork 24 | cd path/to/project 25 | spork --bootsrap 26 | 27 | Now open up spec/spec_helper.rb and follow the directions at the top. You'll 28 | be up and running in no time. 29 | 30 | For more info: 31 | 32 | * http://github.com/timcharper/spork 33 | * http://groups.google.com/group/sporkgem 34 | 35 | = Upgrade to 1.2.7 36 | 37 | == What's changed 38 | 39 | === spec_server is deprecated 40 | 41 | spec_server is deprecated in favor of Tim Harper's new spork library 42 | (http://github.com/timcharper/spork). Get it. Use it. Love it. 43 | 44 | gem install spork 45 | 46 | = Upgrade to 1.2.0-1.2.6 47 | 48 | == What's changed 49 | 50 | === Supported Rails Versions 51 | 52 | This release supports the following versions of rails: 53 | 54 | * 2.0.5 55 | * 2.1.2 56 | * 2.2.2 57 | * 2.3.2 58 | 59 | === update generated files 60 | 61 | Be sure to run "script/generate rspec" and allow the following files to be overwritten: 62 | 63 | * lib/tasks/rspec.rake 64 | * script/spec 65 | * script/spec_server 66 | 67 | === controller.use_rails_error_handling! is deprecated 68 | 69 | Use rescue_action_in_public! instead. It comes directly from rails and does 70 | exactly the same thing 71 | 72 | === route_for 73 | 74 | After a change to edge rails broke our monkey-patched route_for method, I 75 | decided to just delegate to rails' assert_generates method. For most cases, 76 | this will not present a problem, but for some it might. You'll know if you 77 | upgrade and see any newly failing, route-related examples. Here are the things 78 | that you might need to change. 79 | 80 | ==== Make sure IDs are strings 81 | 82 | If you had :id => 1 before, you need to change that to :id => "1" 83 | 84 | #old 85 | route_for(:controller => 'things', :action => 'show', :id => 1).should == "/things/1" 86 | 87 | #new 88 | route_for(:controller => 'things', :action => 'show', :id => "1").should == "/things/1" 89 | 90 | ==== Convert paths for non-get methods to hashes 91 | 92 | If you had an example with a route that requires post, put, or delete, you'll 93 | need to declare that explicitly. 94 | 95 | #old 96 | route_for(:controller => 'things', :action => 'create').should == "/things" 97 | 98 | #new 99 | route_for(:controller => 'things', :action => 'create').should == {:path => "/things", :method => :post} 100 | 101 | === Controller/template isolation 102 | 103 | Even though controller specs do not render views by default (use 104 | integrate_views to get them to render views), the way this works has 105 | changed in this version. 106 | 107 | It used to be that the view template need not even exist, but due to changes 108 | in rails it became much more difficult to manage that for all the different 109 | versions of rails that rspec-rails supports. So now the template must exist, 110 | but it still won't be rendered unless you declare integrate_views. 111 | 112 | == What's new 113 | 114 | === render no longer requires a path 115 | 116 | The render() method in view specs will infer the path from the 117 | first argument passed to describe(). 118 | 119 | describe "players/show" do 120 | it "does something" do 121 | render 122 | response.should have_tag("....") 123 | end 124 | end 125 | 126 | === routing specs live in spec/routing 127 | 128 | script/generate rspec_scaffold now generates its routing spec in 129 | spec/routing/. 130 | 131 | === bypass_rescue 132 | 133 | Added a new bypass_rescue() declaration for controller specs. Use this 134 | when you want to specify that an error is raised by an action, even if that 135 | error is later captured by a rescue_from() declaration. 136 | 137 | describe AccountController do 138 | describe "GET @account" do 139 | context "requested by anonymous user" do 140 | it "denies access" do 141 | bypass_rescue 142 | lambda do 143 | get :show, :id => "37" 144 | end.should raise_error(AccessDenied) 145 | end 146 | end 147 | end 148 | end 149 | -------------------------------------------------------------------------------- /generators/integration_spec/integration_spec_generator.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../rspec_default_values' 2 | 3 | class IntegrationSpecGenerator < ModelGenerator 4 | def manifest 5 | record do |m| 6 | m.class_collisions class_path, class_name 7 | m.template 'integration_spec.rb', File.join('spec/integration', class_path, "#{class_name.tableize}_spec.rb") 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /generators/integration_spec/templates/integration_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "<%= class_name.pluralize %>" do 4 | end 5 | -------------------------------------------------------------------------------- /generators/rspec/CHANGES: -------------------------------------------------------------------------------- 1 | Please refer to the CHANGES file for RSpec's core -------------------------------------------------------------------------------- /generators/rspec/rspec_generator.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | 3 | # This generator bootstraps a Rails project for use with RSpec 4 | class RspecGenerator < Rails::Generator::Base 5 | DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'], 6 | Config::CONFIG['ruby_install_name']) 7 | 8 | def initialize(runtime_args, runtime_options = {}) 9 | if test ?f, 'spec/spec_helper.rb' 10 | 11 | puts <<-HELPFUL_INSTRUCTIONS 12 | 13 | It looks like you are upgrading rspec-rails in this application. Please let 14 | this script overwrite everything it wants to with the following exceptions, 15 | *if* you have customized any of these files: 16 | 17 | * spec/spec.opts 18 | * spec/rcov.opts 19 | * spec/spec_helper.rb 20 | 21 | If you have customized spec/spec_helper.rb, please set aside a copy of that 22 | file so that it can be updated and you can manually restore your changes. 23 | 24 | HELPFUL_INSTRUCTIONS 25 | end 26 | Dir.mkdir('lib/tasks') unless File.directory?('lib/tasks') 27 | 28 | if Rails::VERSION::STRING >= '2.1' 29 | test_env = 'config/environments/test.rb' 30 | contents = File.read(test_env) 31 | unless contents =~ /config\.gem\s+(\"|\')rspec/m 32 | puts "Configuring rspec and rspec-rails gems in #{test_env} ..." 33 | puts 34 | require File.expand_path('../../../lib/spec/rails/version.rb', __FILE__) 35 | rspec_config = <<-EOF 36 | config.gem 'rspec-rails', :version => '>= #{Spec::Rails::VERSION::STRING}', :lib => false unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails')) 37 | EOF 38 | File.open(test_env, "wb") do |f| 39 | f.puts contents 40 | f.puts 41 | f.puts rspec_config 42 | end 43 | end 44 | end 45 | 46 | super 47 | end 48 | 49 | def manifest 50 | record do |m| 51 | script_options = { :chmod => 0755, :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang] } 52 | 53 | m.directory 'lib/tasks' 54 | m.file 'rspec.rake', 'lib/tasks/rspec.rake' 55 | 56 | m.file 'script/autospec', 'script/autospec', script_options 57 | m.file 'script/spec', 'script/spec', script_options 58 | 59 | m.directory 'spec' 60 | m.file 'rcov.opts', 'spec/rcov.opts' 61 | m.file 'spec.opts', 'spec/spec.opts' 62 | m.template 'spec_helper.rb', 'spec/spec_helper.rb' 63 | end 64 | end 65 | 66 | protected 67 | 68 | def banner 69 | "Usage: #{$0} rspec" 70 | end 71 | 72 | end 73 | -------------------------------------------------------------------------------- /generators/rspec/templates/previous_failures.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/generators/rspec/templates/previous_failures.txt -------------------------------------------------------------------------------- /generators/rspec/templates/rcov.opts: -------------------------------------------------------------------------------- 1 | --exclude "spec/*,gems/*" 2 | --rails -------------------------------------------------------------------------------- /generators/rspec/templates/rspec.rake: -------------------------------------------------------------------------------- 1 | gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 2 | rspec_gem_dir = nil 3 | Dir["#{RAILS_ROOT}/vendor/gems/*"].each do |subdir| 4 | rspec_gem_dir = subdir if subdir.gsub("#{RAILS_ROOT}/vendor/gems/","") =~ /^(\w+-)?rspec-(\d+)/ && File.exist?("#{subdir}/lib/spec/rake/spectask.rb") 5 | end 6 | rspec_plugin_dir = File.expand_path(File.dirname(__FILE__) + '/../../vendor/plugins/rspec') 7 | 8 | if rspec_gem_dir && (test ?d, rspec_plugin_dir) 9 | raise "\n#{'*'*50}\nYou have rspec installed in both vendor/gems and vendor/plugins\nPlease pick one and dispose of the other.\n#{'*'*50}\n\n" 10 | end 11 | 12 | if rspec_gem_dir 13 | $LOAD_PATH.unshift("#{rspec_gem_dir}/lib") 14 | elsif File.exist?(rspec_plugin_dir) 15 | $LOAD_PATH.unshift("#{rspec_plugin_dir}/lib") 16 | end 17 | 18 | # Don't load rspec if running "rake gems:*" 19 | unless ARGV.any? {|a| a =~ /^gems/} 20 | 21 | begin 22 | require 'spec/rake/spectask' 23 | rescue MissingSourceFile 24 | module Spec 25 | module Rake 26 | class SpecTask 27 | include ::Rake::DSL if defined?(::Rake::DSL) 28 | 29 | def initialize(name) 30 | task name do 31 | # if rspec-rails is a configured gem, this will output helpful material and exit ... 32 | require File.expand_path(File.join(File.dirname(__FILE__),"..","..","config","environment")) 33 | 34 | # ... otherwise, do this: 35 | raise <<-MSG 36 | 37 | #{"*" * 80} 38 | * You are trying to run an rspec rake task defined in 39 | * #{__FILE__}, 40 | * but rspec can not be found in vendor/gems, vendor/plugins or system gems. 41 | #{"*" * 80} 42 | MSG 43 | end 44 | end 45 | end 46 | end 47 | end 48 | end 49 | 50 | Rake.application.instance_variable_get('@tasks').delete('default') 51 | 52 | spec_prereq = File.exist?(File.join(RAILS_ROOT, 'config', 'database.yml')) ? "db:test:prepare" : :noop 53 | task :noop do 54 | end 55 | 56 | task :default => :spec 57 | task :stats => "spec:statsetup" 58 | 59 | desc "Run all specs in spec directory (excluding plugin specs)" 60 | Spec::Rake::SpecTask.new(:spec => spec_prereq) do |t| 61 | t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] 62 | t.spec_files = FileList['spec/**/*_spec.rb'] 63 | end 64 | 65 | namespace :spec do 66 | desc "Run all specs in spec directory with RCov (excluding plugin specs)" 67 | Spec::Rake::SpecTask.new(:rcov) do |t| 68 | t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] 69 | t.spec_files = FileList['spec/**/*_spec.rb'] 70 | t.rcov = true 71 | t.rcov_opts = lambda do 72 | IO.readlines("#{RAILS_ROOT}/spec/rcov.opts").map {|l| l.chomp.split " "}.flatten 73 | end 74 | end 75 | 76 | desc "Print Specdoc for all specs (excluding plugin specs)" 77 | Spec::Rake::SpecTask.new(:doc) do |t| 78 | t.spec_opts = ["--format", "specdoc", "--dry-run"] 79 | t.spec_files = FileList['spec/**/*_spec.rb'] 80 | end 81 | 82 | desc "Print Specdoc for all plugin examples" 83 | Spec::Rake::SpecTask.new(:plugin_doc) do |t| 84 | t.spec_opts = ["--format", "specdoc", "--dry-run"] 85 | t.spec_files = FileList['vendor/plugins/**/spec/**/*_spec.rb'].exclude('vendor/plugins/rspec/*') 86 | end 87 | 88 | [:models, :controllers, :views, :helpers, :lib, :integration].each do |sub| 89 | desc "Run the code examples in spec/#{sub}" 90 | Spec::Rake::SpecTask.new(sub => spec_prereq) do |t| 91 | t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] 92 | t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"] 93 | end 94 | end 95 | 96 | desc "Run the code examples in vendor/plugins (except RSpec's own)" 97 | Spec::Rake::SpecTask.new(:plugins => spec_prereq) do |t| 98 | t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] 99 | t.spec_files = FileList['vendor/plugins/**/spec/**/*_spec.rb'].exclude('vendor/plugins/rspec/*').exclude("vendor/plugins/rspec-rails/*") 100 | end 101 | 102 | namespace :plugins do 103 | desc "Runs the examples for rspec_on_rails" 104 | Spec::Rake::SpecTask.new(:rspec_on_rails) do |t| 105 | t.spec_opts = ['--options', "\"#{RAILS_ROOT}/spec/spec.opts\""] 106 | t.spec_files = FileList['vendor/plugins/rspec-rails/spec/**/*_spec.rb'] 107 | end 108 | end 109 | 110 | # Setup specs for stats 111 | task :statsetup do 112 | require 'code_statistics' 113 | ::STATS_DIRECTORIES << %w(Model\ specs spec/models) if File.exist?('spec/models') 114 | ::STATS_DIRECTORIES << %w(View\ specs spec/views) if File.exist?('spec/views') 115 | ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers) if File.exist?('spec/controllers') 116 | ::STATS_DIRECTORIES << %w(Helper\ specs spec/helpers) if File.exist?('spec/helpers') 117 | ::STATS_DIRECTORIES << %w(Library\ specs spec/lib) if File.exist?('spec/lib') 118 | ::STATS_DIRECTORIES << %w(Routing\ specs spec/routing) if File.exist?('spec/routing') 119 | ::STATS_DIRECTORIES << %w(Integration\ specs spec/integration) if File.exist?('spec/integration') 120 | ::CodeStatistics::TEST_TYPES << "Model specs" if File.exist?('spec/models') 121 | ::CodeStatistics::TEST_TYPES << "View specs" if File.exist?('spec/views') 122 | ::CodeStatistics::TEST_TYPES << "Controller specs" if File.exist?('spec/controllers') 123 | ::CodeStatistics::TEST_TYPES << "Helper specs" if File.exist?('spec/helpers') 124 | ::CodeStatistics::TEST_TYPES << "Library specs" if File.exist?('spec/lib') 125 | ::CodeStatistics::TEST_TYPES << "Routing specs" if File.exist?('spec/routing') 126 | ::CodeStatistics::TEST_TYPES << "Integration specs" if File.exist?('spec/integration') 127 | end 128 | 129 | namespace :db do 130 | namespace :fixtures do 131 | desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z." 132 | task :load => :environment do 133 | ActiveRecord::Base.establish_connection(Rails.env) 134 | base_dir = File.join(Rails.root, 'spec', 'fixtures') 135 | fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir 136 | 137 | require 'active_record/fixtures' 138 | (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file| 139 | Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*')) 140 | end 141 | end 142 | end 143 | end 144 | end 145 | 146 | end 147 | -------------------------------------------------------------------------------- /generators/rspec/templates/script/autospec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 3 | ENV['RSPEC'] = 'true' # allows autotest to discover rspec 4 | ENV['AUTOTEST'] = 'true' # allows autotest to run w/ color on linux 5 | system((RUBY_PLATFORM =~ /mswin|mingw/ ? 'autotest.bat' : 'autotest'), *ARGV) || 6 | $stderr.puts("Unable to find autotest. Please install ZenTest or fix your PATH") 7 | -------------------------------------------------------------------------------- /generators/rspec/templates/script/spec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | if ARGV.any? {|arg| %w[--drb -X --generate-options -G --help -h --version -v].include?(arg)} 3 | require 'rubygems' unless ENV['NO_RUBYGEMS'] 4 | else 5 | gem 'test-unit', '1.2.3' if RUBY_VERSION.to_f >= 1.9 6 | ENV["RAILS_ENV"] ||= 'test' 7 | require File.expand_path(File.dirname(__FILE__) + "/../config/environment") unless defined?(RAILS_ROOT) 8 | end 9 | require 'spec/autorun' 10 | exit ::Spec::Runner::CommandLine.run 11 | -------------------------------------------------------------------------------- /generators/rspec/templates/spec.opts: -------------------------------------------------------------------------------- 1 | --colour 2 | --format progress 3 | --loadby mtime 4 | --reverse 5 | -------------------------------------------------------------------------------- /generators/rspec/templates/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # This file is copied to ~/spec when you run 'ruby script/generate rspec' 2 | # from the project root directory. 3 | ENV["RAILS_ENV"] ||= 'test' 4 | require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment')) 5 | require 'spec/autorun' 6 | require 'spec/rails' 7 | 8 | # Uncomment the next line to use webrat's matchers 9 | #require 'webrat/integrations/rspec-rails' 10 | 11 | # Requires supporting files with custom matchers and macros, etc, 12 | # in ./support/ and its subdirectories. 13 | Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f} 14 | 15 | Spec::Runner.configure do |config| 16 | # If you're not using ActiveRecord you should remove these 17 | # lines, delete config/database.yml and disable :active_record 18 | # in your config/boot.rb 19 | config.use_transactional_fixtures = true 20 | config.use_instantiated_fixtures = false 21 | config.fixture_path = RAILS_ROOT + '/spec/fixtures/' 22 | 23 | # == Fixtures 24 | # 25 | # You can declare fixtures for each example_group like this: 26 | # describe "...." do 27 | # fixtures :table_a, :table_b 28 | # 29 | # Alternatively, if you prefer to declare them only once, you can 30 | # do so right here. Just uncomment the next line and replace the fixture 31 | # names with your fixtures. 32 | # 33 | # config.global_fixtures = :table_a, :table_b 34 | # 35 | # If you declare global fixtures, be aware that they will be declared 36 | # for all of your examples, even those that don't use them. 37 | # 38 | # You can also declare which fixtures to use (for example fixtures for test/fixtures): 39 | # 40 | # config.fixture_path = RAILS_ROOT + '/spec/fixtures/' 41 | # 42 | # == Mock Framework 43 | # 44 | # RSpec uses its own mocking framework by default. If you prefer to 45 | # use mocha, flexmock or RR, uncomment the appropriate line: 46 | # 47 | # config.mock_with :mocha 48 | # config.mock_with :flexmock 49 | # config.mock_with :rr 50 | # 51 | # == Notes 52 | # 53 | # For more information take a look at Spec::Runner::Configuration and Spec::Runner 54 | end 55 | -------------------------------------------------------------------------------- /generators/rspec_controller/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | The rspec_controller generator creates stub specs and files for a new 3 | controller and its views. 4 | 5 | The generator takes a controller name and a list of views as arguments. 6 | The controller name may be given in CamelCase or under_score and should 7 | not be suffixed with 'Controller'. To create a controller within a 8 | module, specify the controller name as 'module/controller'. 9 | 10 | The generator creates stubs for a controller (and spec), a view (and spec) 11 | for each view in the argument list, plus a helper. 12 | 13 | Example: 14 | ./script/generate rspec_controller dog bark fetch 15 | ... 16 | create spec/controllers/dog_controller_spec.rb 17 | create app/controllers/dog_controller.rb 18 | create app/helpers/dog_helper.rb 19 | create spec/views/dog/bark_view_spec.rb 20 | create app/views/dog/bark.rhtml 21 | create spec/views/dog/fetch_view_spec.rb 22 | create app/views/dog/fetch.rhtml 23 | 24 | Modules Example: 25 | ./script/generate rspec_controller 'pets/dog' bark fetch 26 | ... 27 | create spec/controllers/pets/dog_controller_spec.rb 28 | create app/controllers/pets/dog_controller.rb 29 | create app/helpers/pets/dog_helper.rb 30 | create spec/views/pets/dog/bark_view_spec.rb 31 | create app/views/pets/dog/bark.rhtml 32 | create spec/views/pets/dog/fetch_view_spec.rb 33 | create app/views/pets/dog/fetch.rhtml 34 | -------------------------------------------------------------------------------- /generators/rspec_controller/rspec_controller_generator.rb: -------------------------------------------------------------------------------- 1 | require 'rails_generator/generators/components/controller/controller_generator' 2 | 3 | class RspecControllerGenerator < ControllerGenerator 4 | 5 | def manifest 6 | record do |m| 7 | # Check for class naming collisions. 8 | m.class_collisions class_path, "#{class_name}Controller", "#{class_name}Helper" 9 | 10 | # Controller, helper, views, and spec directories. 11 | m.directory File.join('app/controllers', class_path) 12 | m.directory File.join('app/helpers', class_path) 13 | m.directory File.join('app/views', class_path, file_name) 14 | m.directory File.join('spec/controllers', class_path) 15 | m.directory File.join('spec/helpers', class_path) 16 | m.directory File.join('spec/views', class_path, file_name) 17 | 18 | @default_file_extension = "html.erb" 19 | 20 | # Controller spec, class, and helper. 21 | m.template 'controller_spec.rb', 22 | File.join('spec/controllers', class_path, "#{file_name}_controller_spec.rb") 23 | 24 | m.template 'helper_spec.rb', 25 | File.join('spec/helpers', class_path, "#{file_name}_helper_spec.rb") 26 | 27 | m.template 'controller:controller.rb', 28 | File.join('app/controllers', class_path, "#{file_name}_controller.rb") 29 | 30 | m.template 'controller:helper.rb', 31 | File.join('app/helpers', class_path, "#{file_name}_helper.rb") 32 | 33 | 34 | 35 | # Spec and view template for each action. 36 | actions.each do |action| 37 | m.template 'view_spec.rb', 38 | File.join('spec/views', class_path, file_name, "#{action}.#{@default_file_extension}_spec.rb"), 39 | :assigns => { :action => action, :model => file_name } 40 | path = File.join('app/views', class_path, file_name, "#{action}.#{@default_file_extension}") 41 | m.template "controller:view.#{@default_file_extension}", 42 | path, 43 | :assigns => { :action => action, :path => path } 44 | end 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /generators/rspec_controller/templates/controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe <%= class_name %>Controller do 4 | 5 | <% if actions.empty? -%> 6 | #Delete this example and add some real ones 7 | <% else -%> 8 | #Delete these examples and add some real ones 9 | <% end -%> 10 | it "should use <%= class_name %>Controller" do 11 | controller.should be_an_instance_of(<%= class_name %>Controller) 12 | end 13 | 14 | <% unless actions.empty? -%> 15 | <% for action in actions -%> 16 | 17 | describe "GET '<%= action %>'" do 18 | it "should be successful" do 19 | get '<%= action %>' 20 | response.should be_success 21 | end 22 | end 23 | <% end -%> 24 | <% end -%> 25 | end 26 | -------------------------------------------------------------------------------- /generators/rspec_controller/templates/helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe <%= class_name %>Helper do 4 | 5 | #Delete this example and add some real ones or delete this file 6 | it "should be included in the object returned by #helper" do 7 | included_modules = (class << helper; self; end).send :included_modules 8 | included_modules.should include(<%= class_name %>Helper) 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /generators/rspec_controller/templates/view_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "/<%= class_name.underscore %>/<%= action %>" do 4 | before(:each) do 5 | render '<%= class_name.underscore %>/<%= action %>' 6 | end 7 | 8 | #Delete this example and add some real ones or delete this file 9 | it "should tell you where to find the file" do 10 | response.should have_tag('p', %r[Find me in app/views/<%= class_name.underscore %>/<%= action %>]) 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /generators/rspec_default_values.rb: -------------------------------------------------------------------------------- 1 | module Rails 2 | module Generator 3 | class GeneratedAttribute 4 | def default_value 5 | @default_value ||= case type 6 | when :int, :integer then "1" 7 | when :float then "1.5" 8 | when :decimal then "9.99" 9 | when :datetime, :timestamp, :time then "Time.now" 10 | when :date then "Date.today" 11 | when :string, :text then "\"value for #{@name}\"" 12 | when :boolean then "false" 13 | when :belongs_to, :references then "1" 14 | else 15 | "" 16 | end 17 | end 18 | 19 | def name_or_reference 20 | if ::Rails::VERSION::STRING >= '2.2' 21 | reference? ? :"#{name}_id" : name 22 | else 23 | name 24 | end 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /generators/rspec_model/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | The rspec_model generator creates stubs for a new model. 3 | 4 | The generator takes a model name as its argument. The model name may be 5 | given in CamelCase or under_score and should not be suffixed with 'Model'. 6 | 7 | The generator creates a model class in app/models, an RSpec spec in 8 | spec/models, database fixtures in spec/fixtures/plural_name.yml, and a migration 9 | in db/migrate. 10 | 11 | Example: 12 | ./script/generate rspec_model Account 13 | 14 | This will create an Account model: 15 | Model: app/models/account.rb 16 | Spec: spec/models/account_spec.rb 17 | Fixtures: spec/fixtures/accounts.yml 18 | Migration: db/migrate/XXX_add_accounts.rb 19 | -------------------------------------------------------------------------------- /generators/rspec_model/rspec_model_generator.rb: -------------------------------------------------------------------------------- 1 | require 'rails_generator/generators/components/model/model_generator' 2 | require File.dirname(__FILE__) + '/../rspec_default_values' 3 | 4 | class RspecModelGenerator < ModelGenerator 5 | 6 | def manifest 7 | 8 | record do |m| 9 | # Check for class naming collisions. 10 | m.class_collisions class_path, class_name 11 | 12 | # Model, spec, and fixture directories. 13 | m.directory File.join('app/models', class_path) 14 | m.directory File.join('spec/models', class_path) 15 | unless options[:skip_fixture] 16 | m.directory File.join('spec/fixtures', class_path) 17 | end 18 | 19 | # Model class, spec and fixtures. 20 | m.template 'model:model.rb', File.join('app/models', class_path, "#{file_name}.rb") 21 | m.template 'model_spec.rb', File.join('spec/models', class_path, "#{file_name}_spec.rb") 22 | unless options[:skip_fixture] 23 | m.template 'model:fixtures.yml', File.join('spec/fixtures', "#{table_name}.yml") 24 | end 25 | 26 | unless options[:skip_migration] 27 | m.migration_template 'model:migration.rb', 'db/migrate', :assigns => { 28 | :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}" 29 | }, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}" 30 | end 31 | 32 | end 33 | end 34 | 35 | end 36 | -------------------------------------------------------------------------------- /generators/rspec_model/templates/model_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe <%= class_name %> do 4 | before(:each) do 5 | @valid_attributes = { 6 | <%= attributes.map{|a| ":#{a.name_or_reference} => #{a.default_value}" }.join(",\n ") %> 7 | } 8 | end 9 | 10 | it "should create a new instance given valid attributes" do 11 | <%= class_name %>.create!(@valid_attributes) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/rspec_scaffold_generator.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../rspec_default_values' 2 | 3 | class RspecScaffoldGenerator < Rails::Generator::NamedBase 4 | default_options :skip_migration => false 5 | 6 | attr_reader :controller_name, 7 | :controller_class_path, 8 | :controller_file_path, 9 | :controller_class_nesting, 10 | :controller_class_nesting_depth, 11 | :controller_class_name, 12 | :controller_singular_name, 13 | :controller_plural_name, 14 | :resource_edit_path, 15 | :default_file_extension 16 | alias_method :controller_file_name, :controller_singular_name 17 | alias_method :controller_table_name, :controller_plural_name 18 | 19 | def initialize(runtime_args, runtime_options = {}) 20 | super 21 | 22 | @controller_name = @name.pluralize 23 | 24 | base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name) 25 | @controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name) 26 | 27 | if @controller_class_nesting.empty? 28 | @controller_class_name = @controller_class_name_without_nesting 29 | else 30 | @controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}" 31 | end 32 | 33 | @default_file_extension = "html.erb" 34 | end 35 | 36 | def manifest 37 | record do |m| 38 | 39 | # Check for class naming collisions. 40 | m.class_collisions(controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}Helper") 41 | m.class_collisions(class_path, "#{class_name}") 42 | 43 | # Controller, helper, views, and spec directories. 44 | m.directory(File.join('app/models', class_path)) 45 | m.directory(File.join('app/controllers', controller_class_path)) 46 | m.directory(File.join('app/helpers', controller_class_path)) 47 | m.directory(File.join('app/views', controller_class_path, controller_file_name)) 48 | m.directory(File.join('app/views/layouts', controller_class_path)) 49 | m.directory(File.join('public/stylesheets', class_path)) 50 | 51 | m.directory(File.join('spec/controllers', controller_class_path)) 52 | m.directory(File.join('spec/routing', controller_class_path)) 53 | m.directory(File.join('spec/models', class_path)) 54 | m.directory(File.join('spec/helpers', class_path)) 55 | m.directory File.join('spec/fixtures', class_path) 56 | m.directory File.join('spec/views', controller_class_path, controller_file_name) 57 | m.directory File.join('spec/integration', class_path) 58 | 59 | # Layout and stylesheet. 60 | m.template("scaffold:layout.html.erb", File.join('app/views/layouts', controller_class_path, "#{controller_file_name}.html.erb")) 61 | m.template("scaffold:style.css", 'public/stylesheets/scaffold.css') 62 | 63 | # Controller spec, class, and helper. 64 | m.template 'rspec_scaffold:routing_spec.rb', 65 | File.join('spec/routing', controller_class_path, "#{controller_file_name}_routing_spec.rb") 66 | 67 | m.template 'rspec_scaffold:controller_spec.rb', 68 | File.join('spec/controllers', controller_class_path, "#{controller_file_name}_controller_spec.rb") 69 | 70 | m.template "scaffold:controller.rb", 71 | File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb") 72 | 73 | m.template 'rspec_scaffold:helper_spec.rb', 74 | File.join('spec/helpers', class_path, "#{controller_file_name}_helper_spec.rb") 75 | 76 | m.template "scaffold:helper.rb", 77 | File.join('app/helpers', controller_class_path, "#{controller_file_name}_helper.rb") 78 | 79 | for action in scaffold_views 80 | m.template( 81 | "scaffold:view_#{action}.#{@default_file_extension}", 82 | File.join('app/views', controller_class_path, controller_file_name, "#{action}.#{default_file_extension}") 83 | ) 84 | end 85 | 86 | # Model class, unit test, and fixtures. 87 | m.template 'model:model.rb', File.join('app/models', class_path, "#{file_name}.rb") 88 | m.template 'model:fixtures.yml', File.join('spec/fixtures', class_path, "#{table_name}.yml") 89 | m.template 'rspec_model:model_spec.rb', File.join('spec/models', class_path, "#{file_name}_spec.rb") 90 | 91 | # View specs 92 | m.template "rspec_scaffold:edit_erb_spec.rb", 93 | File.join('spec/views', controller_class_path, controller_file_name, "edit.#{default_file_extension}_spec.rb") 94 | m.template "rspec_scaffold:index_erb_spec.rb", 95 | File.join('spec/views', controller_class_path, controller_file_name, "index.#{default_file_extension}_spec.rb") 96 | m.template "rspec_scaffold:new_erb_spec.rb", 97 | File.join('spec/views', controller_class_path, controller_file_name, "new.#{default_file_extension}_spec.rb") 98 | m.template "rspec_scaffold:show_erb_spec.rb", 99 | File.join('spec/views', controller_class_path, controller_file_name, "show.#{default_file_extension}_spec.rb") 100 | 101 | # Integration 102 | m.template 'integration_spec:integration_spec.rb', File.join('spec/integration', class_path, "#{table_name}_spec.rb") 103 | 104 | unless options[:skip_migration] 105 | m.migration_template( 106 | 'model:migration.rb', 'db/migrate', 107 | :assigns => { 108 | :migration_name => "Create#{class_name.pluralize.gsub(/::/, '')}", 109 | :attributes => attributes 110 | }, 111 | :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}" 112 | ) 113 | end 114 | 115 | m.route_resources controller_file_name 116 | 117 | end 118 | end 119 | 120 | protected 121 | # Override with your own usage banner. 122 | def banner 123 | "Usage: #{$0} rspec_scaffold ModelName [field:type field:type]" 124 | end 125 | 126 | def add_options!(opt) 127 | opt.separator '' 128 | opt.separator 'Options:' 129 | opt.on("--skip-migration", 130 | "Don't generate a migration file for this model") { |v| options[:skip_migration] = v } 131 | end 132 | 133 | def scaffold_views 134 | %w[ index show new edit ] 135 | end 136 | 137 | def model_name 138 | class_name.demodulize 139 | end 140 | end 141 | 142 | module Rails 143 | module Generator 144 | class GeneratedAttribute 145 | def input_type 146 | @input_type ||= case type 147 | when :text then "textarea" 148 | else 149 | "input" 150 | end 151 | end 152 | end 153 | end 154 | end 155 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/controller_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe <%= controller_class_name %>Controller do 4 | 5 | def mock_<%= file_name %>(stubs={}) 6 | @mock_<%= file_name %> ||= mock_model(<%= class_name %>, stubs) 7 | end 8 | 9 | describe "GET index" do 10 | it "assigns all <%= table_name.pluralize %> as @<%= table_name.pluralize %>" do 11 | <%= class_name %>.stub(:find).with(:all).and_return([mock_<%= file_name %>]) 12 | get :index 13 | assigns[:<%= table_name %>].should == [mock_<%= file_name %>] 14 | end 15 | end 16 | 17 | describe "GET show" do 18 | it "assigns the requested <%= file_name %> as @<%= file_name %>" do 19 | <%= class_name %>.stub(:find).with("37").and_return(mock_<%= file_name %>) 20 | get :show, :id => "37" 21 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 22 | end 23 | end 24 | 25 | describe "GET new" do 26 | it "assigns a new <%= file_name %> as @<%= file_name %>" do 27 | <%= class_name %>.stub(:new).and_return(mock_<%= file_name %>) 28 | get :new 29 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 30 | end 31 | end 32 | 33 | describe "GET edit" do 34 | it "assigns the requested <%= file_name %> as @<%= file_name %>" do 35 | <%= class_name %>.stub(:find).with("37").and_return(mock_<%= file_name %>) 36 | get :edit, :id => "37" 37 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 38 | end 39 | end 40 | 41 | describe "POST create" do 42 | 43 | describe "with valid params" do 44 | it "assigns a newly created <%= file_name %> as @<%= file_name %>" do 45 | <%= class_name %>.stub(:new).with({'these' => 'params'}).and_return(mock_<%= file_name %>(:save => true)) 46 | post :create, :<%= file_name %> => {:these => 'params'} 47 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 48 | end 49 | 50 | it "redirects to the created <%= file_name %>" do 51 | <%= class_name %>.stub(:new).and_return(mock_<%= file_name %>(:save => true)) 52 | post :create, :<%= file_name %> => {} 53 | response.should redirect_to(<%= table_name.singularize %>_url(mock_<%= file_name %>)) 54 | end 55 | end 56 | 57 | describe "with invalid params" do 58 | it "assigns a newly created but unsaved <%= file_name %> as @<%= file_name %>" do 59 | <%= class_name %>.stub(:new).with({'these' => 'params'}).and_return(mock_<%= file_name %>(:save => false)) 60 | post :create, :<%= file_name %> => {:these => 'params'} 61 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 62 | end 63 | 64 | it "re-renders the 'new' template" do 65 | <%= class_name %>.stub(:new).and_return(mock_<%= file_name %>(:save => false)) 66 | post :create, :<%= file_name %> => {} 67 | response.should render_template('new') 68 | end 69 | end 70 | 71 | end 72 | 73 | describe "PUT update" do 74 | 75 | describe "with valid params" do 76 | it "updates the requested <%= file_name %>" do 77 | <%= class_name %>.should_receive(:find).with("37").and_return(mock_<%= file_name %>) 78 | mock_<%= file_name %>.should_receive(:update_attributes).with({'these' => 'params'}) 79 | put :update, :id => "37", :<%= file_name %> => {:these => 'params'} 80 | end 81 | 82 | it "assigns the requested <%= file_name %> as @<%= file_name %>" do 83 | <%= class_name %>.stub(:find).and_return(mock_<%= file_name %>(:update_attributes => true)) 84 | put :update, :id => "1" 85 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 86 | end 87 | 88 | it "redirects to the <%= file_name %>" do 89 | <%= class_name %>.stub(:find).and_return(mock_<%= file_name %>(:update_attributes => true)) 90 | put :update, :id => "1" 91 | response.should redirect_to(<%= table_name.singularize %>_url(mock_<%= file_name %>)) 92 | end 93 | end 94 | 95 | describe "with invalid params" do 96 | it "updates the requested <%= file_name %>" do 97 | <%= class_name %>.should_receive(:find).with("37").and_return(mock_<%= file_name %>) 98 | mock_<%= file_name %>.should_receive(:update_attributes).with({'these' => 'params'}) 99 | put :update, :id => "37", :<%= file_name %> => {:these => 'params'} 100 | end 101 | 102 | it "assigns the <%= file_name %> as @<%= file_name %>" do 103 | <%= class_name %>.stub(:find).and_return(mock_<%= file_name %>(:update_attributes => false)) 104 | put :update, :id => "1" 105 | assigns[:<%= file_name %>].should equal(mock_<%= file_name %>) 106 | end 107 | 108 | it "re-renders the 'edit' template" do 109 | <%= class_name %>.stub(:find).and_return(mock_<%= file_name %>(:update_attributes => false)) 110 | put :update, :id => "1" 111 | response.should render_template('edit') 112 | end 113 | end 114 | 115 | end 116 | 117 | describe "DELETE destroy" do 118 | it "destroys the requested <%= file_name %>" do 119 | <%= class_name %>.should_receive(:find).with("37").and_return(mock_<%= file_name %>) 120 | mock_<%= file_name %>.should_receive(:destroy) 121 | delete :destroy, :id => "37" 122 | end 123 | 124 | it "redirects to the <%= table_name %> list" do 125 | <%= class_name %>.stub(:find).and_return(mock_<%= file_name %>(:destroy => true)) 126 | delete :destroy, :id => "1" 127 | response.should redirect_to(<%= table_name %>_url) 128 | end 129 | end 130 | 131 | end 132 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/edit_erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | <% output_attributes = attributes.reject{|attribute| [:datetime, :timestamp, :time, :date].index(attribute.type) } -%> 4 | describe "/<%= table_name %>/edit.<%= default_file_extension %>" do 5 | include <%= controller_class_name %>Helper 6 | 7 | before(:each) do 8 | assigns[:<%= file_name %>] = @<%= file_name %> = stub_model(<%= class_name %>, 9 | :new_record? => false<%= output_attributes.empty? ? '' : ',' %> 10 | <% output_attributes.each_with_index do |attribute, attribute_index| -%> 11 | :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == output_attributes.length - 1 ? '' : ','%> 12 | <% end -%> 13 | ) 14 | end 15 | 16 | it "renders the edit <%= file_name %> form" do 17 | render 18 | 19 | response.should have_tag("form[action=#{<%= file_name %>_path(@<%= file_name %>)}][method=post]") do 20 | <% for attribute in output_attributes -%> 21 | with_tag('<%= attribute.input_type -%>#<%= file_name %>_<%= attribute.name %>[name=?]', "<%= file_name %>[<%= attribute.name %>]") 22 | <% end -%> 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/helper_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe <%= controller_class_name %>Helper do 4 | 5 | #Delete this example and add some real ones or delete this file 6 | it "is included in the helper object" do 7 | included_modules = (class << helper; self; end).send :included_modules 8 | included_modules.should include(<%= controller_class_name %>Helper) 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/index_erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | <% output_attributes = attributes.reject{|attribute| [:datetime, :timestamp, :time, :date].index(attribute.type) } -%> 4 | describe "/<%= table_name %>/index.<%= default_file_extension %>" do 5 | include <%= controller_class_name %>Helper 6 | 7 | before(:each) do 8 | assigns[:<%= table_name %>] = [ 9 | <% [1,2].each_with_index do |id, model_index| -%> 10 | stub_model(<%= class_name %><%= output_attributes.empty? ? (model_index == 1 ? ')' : '),') : ',' %> 11 | <% output_attributes.each_with_index do |attribute, attribute_index| -%> 12 | :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == output_attributes.length - 1 ? '' : ','%> 13 | <% end -%> 14 | <% if !output_attributes.empty? -%> 15 | <%= model_index == 1 ? ')' : '),' %> 16 | <% end -%> 17 | <% end -%> 18 | ] 19 | end 20 | 21 | it "renders a list of <%= table_name %>" do 22 | render 23 | <% for attribute in output_attributes -%> 24 | response.should have_tag("tr>td", <%= attribute.default_value %>.to_s, 2) 25 | <% end -%> 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/new_erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | <% output_attributes = attributes.reject{|attribute| [:datetime, :timestamp, :time, :date].index(attribute.type) } -%> 4 | describe "/<%= table_name %>/new.<%= default_file_extension %>" do 5 | include <%= controller_class_name %>Helper 6 | 7 | before(:each) do 8 | assigns[:<%= file_name %>] = stub_model(<%= class_name %>, 9 | :new_record? => true<%= output_attributes.empty? ? '' : ',' %> 10 | <% output_attributes.each_with_index do |attribute, attribute_index| -%> 11 | :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == output_attributes.length - 1 ? '' : ','%> 12 | <% end -%> 13 | ) 14 | end 15 | 16 | it "renders new <%= file_name %> form" do 17 | render 18 | 19 | response.should have_tag("form[action=?][method=post]", <%= table_name %>_path) do 20 | <% for attribute in output_attributes -%> 21 | with_tag("<%= attribute.input_type -%>#<%= file_name %>_<%= attribute.name %>[name=?]", "<%= file_name %>[<%= attribute.name %>]") 22 | <% end -%> 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/routing_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe <%= controller_class_name %>Controller do 4 | describe "routing" do 5 | it "recognizes and generates #index" do 6 | { :get => "/<%= table_name %>" }.should route_to(:controller => "<%= table_name %>", :action => "index") 7 | end 8 | 9 | it "recognizes and generates #new" do 10 | { :get => "/<%= table_name %>/new" }.should route_to(:controller => "<%= table_name %>", :action => "new") 11 | end 12 | 13 | it "recognizes and generates #show" do 14 | { :get => "/<%= table_name %>/1" }.should route_to(:controller => "<%= table_name %>", :action => "show", :id => "1") 15 | end 16 | 17 | it "recognizes and generates #edit" do 18 | { :get => "/<%= table_name %>/1/edit" }.should route_to(:controller => "<%= table_name %>", :action => "edit", :id => "1") 19 | end 20 | 21 | it "recognizes and generates #create" do 22 | { :post => "/<%= table_name %>" }.should route_to(:controller => "<%= table_name %>", :action => "create") 23 | end 24 | 25 | it "recognizes and generates #update" do 26 | { :put => "/<%= table_name %>/1" }.should route_to(:controller => "<%= table_name %>", :action => "update", :id => "1") 27 | end 28 | 29 | it "recognizes and generates #destroy" do 30 | { :delete => "/<%= table_name %>/1" }.should route_to(:controller => "<%= table_name %>", :action => "destroy", :id => "1") 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /generators/rspec_scaffold/templates/show_erb_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | <% output_attributes = attributes.reject{|attribute| [:datetime, :timestamp, :time, :date].index(attribute.type) } -%> 4 | describe "/<%= table_name %>/show.<%= default_file_extension %>" do 5 | include <%= controller_class_name %>Helper 6 | before(:each) do 7 | assigns[:<%= file_name %>] = @<%= file_name %> = stub_model(<%= class_name %><%= output_attributes.empty? ? ')' : ',' %> 8 | <% output_attributes.each_with_index do |attribute, attribute_index| -%> 9 | :<%= attribute.name %> => <%= attribute.default_value %><%= attribute_index == output_attributes.length - 1 ? '' : ','%> 10 | <% end -%> 11 | <% if !output_attributes.empty? -%> 12 | ) 13 | <% end -%> 14 | end 15 | 16 | it "renders attributes in

" do 17 | render 18 | <% for attribute in output_attributes -%> 19 | response.should have_text(/<%= Regexp.escape(attribute.default_value).gsub(/^"|"$/, '')%>/) 20 | <% end -%> 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | # Placeholder to satisfy Rails. 2 | # 3 | # Do NOT add any require statements to this file. Doing 4 | # so will cause Rails to load this plugin all of the time. 5 | # 6 | # Running 'ruby script/generate rspec' will 7 | # generate spec/spec_helper.rb, which includes the necessary 8 | # require statements and configuration. This file should 9 | # be required by all of your spec files. -------------------------------------------------------------------------------- /lib/autotest/discover.rb: -------------------------------------------------------------------------------- 1 | Autotest.add_discovery do 2 | style = [] 3 | style << "rails" if File.exist? 'config/environment.rb' 4 | style 5 | end -------------------------------------------------------------------------------- /lib/autotest/rails_rspec.rb: -------------------------------------------------------------------------------- 1 | # (c) Copyright 2006 Nick Sieger 2 | # 3 | # Permission is hereby granted, free of charge, to any person 4 | # obtaining a copy of this software and associated documentation files 5 | # (the "Software"), to deal in the Software without restriction, 6 | # including without limitation the rights to use, copy, modify, merge, 7 | # publish, distribute, sublicense, and/or sell copies of the Software, 8 | # and to permit persons to whom the Software is furnished to do so, 9 | # subject to the following conditions: 10 | # 11 | # The above copyright notice and this permission notice shall be 12 | # included in all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 18 | # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 19 | # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | $:.push(*Dir["vendor/rails/*/lib"]) 24 | 25 | require 'active_support' 26 | require 'autotest/rspec' 27 | 28 | Autotest.add_hook :initialize do |at| 29 | %w{config/ coverage/ db/ doc/ log/ public/ script/ tmp/ vendor/rails vendor/plugins previous_failures.txt}.each do |exception| 30 | at.add_exception(exception) 31 | end 32 | 33 | at.clear_mappings 34 | 35 | at.add_mapping(%r%^(test|spec)/fixtures/(.*).yml$%) { |_, m| 36 | ["spec/models/#{m[2].singularize}_spec.rb"] + at.files_matching(%r%^spec\/views\/#{m[2]}/.*_spec\.rb$%) 37 | } 38 | at.add_mapping(%r%^spec/(models|controllers|routing|views|helpers|lib)/.*rb$%) { |filename, _| 39 | filename 40 | } 41 | at.add_mapping(%r%^app/models/(.*)\.rb$%) { |_, m| 42 | ["spec/models/#{m[1]}_spec.rb"] 43 | } 44 | at.add_mapping(%r%^app/views/(.*)$%) { |_, m| 45 | at.files_matching %r%^spec/views/#{m[1]}_spec.rb$% 46 | } 47 | at.add_mapping(%r%^app/controllers/(.*)\.rb$%) { |_, m| 48 | if m[1] == "application" 49 | at.files_matching %r%^spec/controllers/.*_spec\.rb$% 50 | else 51 | ["spec/controllers/#{m[1]}_spec.rb"] 52 | end 53 | } 54 | at.add_mapping(%r%^app/helpers/(.*)_helper\.rb$%) { |_, m| 55 | if m[1] == "application" then 56 | at.files_matching(%r%^spec/(views|helpers)/.*_spec\.rb$%) 57 | else 58 | ["spec/helpers/#{m[1]}_helper_spec.rb"] + at.files_matching(%r%^spec\/views\/#{m[1]}/.*_spec\.rb$%) 59 | end 60 | } 61 | at.add_mapping(%r%^config/routes\.rb$%) { 62 | at.files_matching %r%^spec/(controllers|routing|views|helpers)/.*_spec\.rb$% 63 | } 64 | at.add_mapping(%r%^config/database\.yml$%) { |_, m| 65 | at.files_matching %r%^spec/models/.*_spec\.rb$% 66 | } 67 | at.add_mapping(%r%^(spec/(spec_helper|shared/.*)|config/(boot|environment(s/test)?))\.rb$%) { 68 | at.files_matching %r%^spec/(models|controllers|routing|views|helpers)/.*_spec\.rb$% 69 | } 70 | at.add_mapping(%r%^lib/(.*)\.rb$%) { |_, m| 71 | ["spec/lib/#{m[1]}_spec.rb"] 72 | } 73 | end 74 | 75 | class Autotest::RailsRspec < Autotest::Rspec 76 | end 77 | -------------------------------------------------------------------------------- /lib/spec/rails.rb: -------------------------------------------------------------------------------- 1 | begin 2 | require_dependency 'application_controller' 3 | rescue MissingSourceFile 4 | require_dependency 'application' 5 | end 6 | require 'rack/utils' 7 | 8 | require 'action_controller/test_process' 9 | require 'action_controller/integration' 10 | require 'active_support/test_case' 11 | require 'active_record/fixtures' if defined?(ActiveRecord::Base) 12 | 13 | require 'spec/test/unit' 14 | 15 | require 'spec/rails/matchers' 16 | require 'spec/rails/mocks' 17 | require 'spec/rails/example' 18 | require 'spec/rails/extensions' 19 | require 'spec/rails/interop/testcase' 20 | 21 | Spec::Example::ExampleGroupFactory.default(ActiveSupport::TestCase) 22 | 23 | if ActionView::Base.respond_to?(:cache_template_extensions) 24 | ActionView::Base.cache_template_extensions = false 25 | end 26 | 27 | -------------------------------------------------------------------------------- /lib/spec/rails/example.rb: -------------------------------------------------------------------------------- 1 | dir = File.dirname(__FILE__) 2 | 3 | require 'spec/rails/example/routing_helpers' 4 | require 'spec/rails/example/assigns_hash_proxy' 5 | require "spec/rails/example/render_observer" 6 | require "spec/rails/example/model_example_group" 7 | require "spec/rails/example/functional_example_group" 8 | require "spec/rails/example/controller_example_group" 9 | require "spec/rails/example/helper_example_group" 10 | require "spec/rails/example/view_example_group" 11 | require "spec/rails/example/routing_example_group" 12 | require "spec/rails/example/integration_example_group" 13 | require "spec/rails/example/cookies_proxy" 14 | 15 | module Spec 16 | module Rails 17 | # Spec::Rails::Example extends Spec::Example (RSpec's core Example module) to provide 18 | # Rails-specific contexts for describing Rails Models, Views, Controllers and Helpers. 19 | # 20 | # == Model Examples 21 | # 22 | # These are the equivalent of unit tests in Rails' built in testing. Ironically (for the traditional TDD'er) these are the only specs that we feel should actually interact with the database. 23 | # 24 | # See Spec::Rails::Example::ModelExampleGroup 25 | # 26 | # == Controller Examples 27 | # 28 | # These align somewhat with functional tests in rails, except that they do not actually render views (though you can force rendering of views if you prefer). Instead of setting expectations about what goes on a page, you set expectations about what templates get rendered. 29 | # 30 | # See Spec::Rails::Example::ControllerExampleGroup 31 | # 32 | # == View Examples 33 | # 34 | # This is the other half of Rails functional testing. View specs allow you to set up assigns and render 35 | # a template. By assigning mock model data, you can specify view behaviour with no dependency on a database 36 | # or your real models. 37 | # 38 | # See Spec::Rails::Example::ViewExampleGroup 39 | # 40 | # == Helper Examples 41 | # 42 | # These let you specify directly methods that live in your helpers. 43 | # 44 | # See Spec::Rails::Example::HelperExampleGroup 45 | module Example 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/spec/rails/example/assigns_hash_proxy.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Example 4 | class AssignsHashProxy #:nodoc: 5 | def initialize(example_group, &block) 6 | @target = block.call 7 | @example_group = example_group 8 | end 9 | 10 | def [](key) 11 | return false if false == assigns[key] || false == assigns[key.to_s] 12 | assigns[key] || assigns[key.to_s] || @target.instance_variable_get("@#{key}") 13 | end 14 | 15 | def []=(key, val) 16 | @target.instance_variable_set("@#{key}", val) 17 | end 18 | 19 | def delete(key) 20 | assigns.delete(key.to_s) 21 | @target.instance_variable_set("@#{key}", nil) 22 | end 23 | 24 | def each(&block) 25 | assigns.each &block 26 | end 27 | 28 | def has_key?(key) 29 | assigns.key?(key.to_s) 30 | end 31 | 32 | protected 33 | def assigns 34 | @example_group.orig_assigns 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/spec/rails/example/cookies_proxy.rb: -------------------------------------------------------------------------------- 1 | require 'action_controller/cookies' 2 | 3 | module Spec 4 | module Rails 5 | module Example 6 | class CookiesProxy 7 | def initialize(example) 8 | @example = example 9 | end 10 | 11 | def[]=(name, value) 12 | if ::Rails::VERSION::STRING >= '2.3' 13 | @example.request.cookies[name.to_s] = value 14 | else 15 | @example.request.cookies[name.to_s] = CGI::Cookie.new(name.to_s, value) 16 | end 17 | end 18 | 19 | def [](name) 20 | @example.response.cookies[name.to_s] 21 | end 22 | 23 | def delete(name) 24 | @example.response.cookies.delete(name.to_s) 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/spec/rails/example/functional_example_group.rb: -------------------------------------------------------------------------------- 1 | require 'action_controller/test_case' 2 | 3 | module Spec 4 | module Rails 5 | module Example 6 | class FunctionalExampleGroup < ActionController::TestCase 7 | def setup 8 | # no-op to override AC::TC's setup w/ conflicts with the before(:each) below 9 | end 10 | 11 | attr_reader :request, :response 12 | 13 | # The params hash accessed within a view or helper. Use this before 14 | # rendering a view or calling a helper to provide data used by the 15 | # view or helper. 16 | # 17 | # == Examples 18 | # # in a view spec 19 | # params[:name] = "David" 20 | # render 21 | # response.should have_tag("div.name","David") 22 | # 23 | # # in a helper spec 24 | # params[:first_name] = "David" 25 | # params[:last_name] = "Chelimsky" 26 | # helper.full_name.should == "David Chelimsky" 27 | def params 28 | request.parameters 29 | end 30 | 31 | # Provides access to the flash hash. Use this after rendering a 32 | # view, calling a helper or calling a controller action. 33 | # 34 | # == Examples 35 | # post :create 36 | # flash[:notice].should == "Success!" 37 | def flash 38 | @controller.__send__ :flash 39 | end 40 | 41 | # Provides access to the session hash. Use this before or after 42 | # rendering a view, calling a helper or calling a controller action. 43 | def session 44 | request.session 45 | end 46 | 47 | # Overrides the cookies() method in 48 | # ActionController::TestResponseBehaviour, returning a proxy that 49 | # accesses the requests cookies when setting a cookie and the 50 | # responses cookies when reading one. This allows you to set and read 51 | # cookies in examples using the same API with which you set and read 52 | # them in controllers. 53 | # 54 | # == Examples (Rails 2.0 > 2.2) 55 | # 56 | # cookies[:user_id] = {:value => '1234', :expires => 1.minute.ago} 57 | # get :index 58 | # response.should be_redirect 59 | # 60 | # == Examples (Rails 2.3) 61 | # 62 | # Rails 2.3 changes the way cookies are made available to functional 63 | # tests (and therefore rspec controller specs), only making single 64 | # values available with no access to other aspects of the cookie. This 65 | # is backwards-incompatible, so you have to change your examples to 66 | # look like this: 67 | # 68 | # cookies[:foo] = 'bar' 69 | # get :index 70 | # cookies[:foo].should == 'bar' 71 | def cookies 72 | @cookies ||= Spec::Rails::Example::CookiesProxy.new(self) 73 | end 74 | 75 | alias_method :orig_assigns, :assigns 76 | 77 | # :call-seq: 78 | # assigns() 79 | # 80 | # Hash of instance variables to values that are made available to 81 | # views. == Examples 82 | # 83 | # #in thing_controller.rb 84 | # def new 85 | # @thing = Thing.new 86 | # end 87 | # 88 | # #in thing_controller_spec 89 | # get 'new' 90 | # assigns[:registration].should == Thing.new 91 | #-- 92 | # NOTE - Even though docs only use assigns[:key] format, this supports 93 | # assigns(:key) for backwards compatibility. 94 | #++ 95 | def assigns(key = nil) 96 | if key.nil? 97 | _assigns_hash_proxy 98 | else 99 | _assigns_hash_proxy[key] 100 | end 101 | end 102 | 103 | end 104 | end 105 | end 106 | end 107 | -------------------------------------------------------------------------------- /lib/spec/rails/example/helper_example_group.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Example 4 | class HelperExampleGroupController < ApplicationController #:nodoc: 5 | attr_accessor :request, :url 6 | end 7 | 8 | # Helper Specs live in $RAILS_ROOT/spec/helpers/. 9 | # 10 | # Helper Specs use Spec::Rails::Example::HelperExampleGroup, which allows you to 11 | # include your Helper directly in the context and write specs directly 12 | # against its methods. 13 | # 14 | # HelperExampleGroup also includes the standard lot of ActionView::Helpers in case your 15 | # helpers rely on any of those. 16 | # 17 | # == Example 18 | # 19 | # module ThingHelper 20 | # def number_of_things 21 | # Thing.count 22 | # end 23 | # end 24 | # 25 | # describe "ThingHelper example_group" do 26 | # include ThingHelper 27 | # it "should tell you the number of things" do 28 | # Thing.should_receive(:count).and_return(37) 29 | # number_of_things.should == 37 30 | # end 31 | # end 32 | class HelperExampleGroup < FunctionalExampleGroup 33 | tests HelperExampleGroupController 34 | attr_accessor :output_buffer 35 | 36 | class HelperObject < ActionView::Base 37 | def initialize(*args) 38 | @template = self 39 | super 40 | end 41 | def protect_against_forgery? 42 | false 43 | end 44 | 45 | attr_writer :session, :request, :flash, :params, :controller 46 | 47 | private 48 | attr_reader :session, :request, :flash, :params, :controller 49 | end 50 | 51 | class << self 52 | # The helper name.... 53 | def helper_name(name=nil) 54 | @helper_being_described = "#{name}_helper".camelize.constantize 55 | send :include, @helper_being_described 56 | end 57 | 58 | def helper 59 | HelperObject.new.tap do |helper_object| 60 | if @helper_being_described.nil? 61 | if described_type.class == Module 62 | helper_object.extend described_type 63 | end 64 | else 65 | helper_object.extend @helper_being_described 66 | end 67 | end 68 | end 69 | end 70 | 71 | # Returns an instance of ActionView::Base with the helper being spec'd 72 | # included. 73 | # 74 | # == Example 75 | # 76 | # describe PersonHelper do 77 | # it "should write a link to person with the name" do 78 | # assigns[:person] = mock_model(Person, :full_name => "Full Name", :id => 37, :new_record? => false) 79 | # helper.link_to_person.should == %{Full Name} 80 | # end 81 | # end 82 | # 83 | # module PersonHelper 84 | # def link_to_person 85 | # link_to person.full_name, url_for(person) 86 | # end 87 | # end 88 | # 89 | def helper 90 | @helper ||= self.class.helper 91 | end 92 | 93 | def orig_assigns 94 | helper.assigns 95 | end 96 | 97 | # Reverse the load order so that custom helpers which are defined last 98 | # are also loaded last. 99 | ActionView::Base.included_modules.reverse.each do |mod| 100 | include mod if mod.parents.include?(ActionView::Helpers) 101 | end 102 | 103 | before(:each) do 104 | @controller.request = @request 105 | @controller.url = ActionController::UrlRewriter.new @request, {} # url_for 106 | 107 | @flash = ActionController::Flash::FlashHash.new 108 | session['flash'] = @flash 109 | 110 | @output_buffer = "" 111 | @template = helper 112 | ActionView::Helpers::AssetTagHelper::reset_javascript_include_default 113 | 114 | helper.session = session 115 | helper.request = @request 116 | helper.flash = flash 117 | helper.params = params 118 | helper.controller = @controller 119 | end 120 | 121 | def flash 122 | @flash 123 | end 124 | 125 | def eval_erb(text) 126 | erb_args = [text] 127 | if helper.respond_to?(:output_buffer) 128 | erb_args += [nil, nil, '@output_buffer'] 129 | end 130 | 131 | helper.instance_eval do 132 | ERB.new(*erb_args).result(binding) 133 | end 134 | end 135 | 136 | # TODO: BT - Helper Examples should proxy method_missing to a Rails View instance. 137 | # When that is done, remove this method 138 | def protect_against_forgery? 139 | false 140 | end 141 | 142 | Spec::Example::ExampleGroupFactory.register(:helper, self) 143 | 144 | protected 145 | 146 | def _assigns_hash_proxy 147 | @_assigns_hash_proxy ||= AssignsHashProxy.new(self) {helper} 148 | end 149 | 150 | end 151 | end 152 | end 153 | end 154 | -------------------------------------------------------------------------------- /lib/spec/rails/example/integration_example_group.rb: -------------------------------------------------------------------------------- 1 | class ActionController::IntegrationTest 2 | alias_method :orig_initialize, :initialize 3 | def initialize(*args) 4 | super 5 | end 6 | end 7 | 8 | module Spec 9 | module Rails 10 | module Example 11 | class IntegrationExampleGroup < ActionController::IntegrationTest 12 | Spec::Example::ExampleGroupFactory.register(:integration, self) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/spec/rails/example/model_example_group.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Example 4 | # Model examples live in $RAILS_ROOT/spec/models/. 5 | # 6 | # Model examples use Spec::Rails::Example::ModelExampleGroup, which 7 | # provides support for fixtures and some custom expectations via extensions 8 | # to ActiveRecord::Base. 9 | base = defined?(ActiveRecord::TestCase) ? ActiveRecord::TestCase : ActiveSupport::TestCase 10 | class ModelExampleGroup < base 11 | Spec::Example::ExampleGroupFactory.register(:model, self) 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/spec/rails/example/render_observer.rb: -------------------------------------------------------------------------------- 1 | require 'spec/mocks/framework' 2 | 3 | module Spec 4 | module Rails 5 | module Example 6 | # Extends the #should_receive, #should_not_receive and #stub! methods in rspec's 7 | # mocking framework to handle #render calls to controller in controller examples 8 | # and template and view examples 9 | module RenderObserver 10 | 11 | def verify_rendered # :nodoc: 12 | render_proxy.rspec_verify 13 | end 14 | 15 | def unregister_verify_after_each #:nodoc: 16 | proc = verify_rendered_proc 17 | Spec::Example::ExampleGroup.remove_after(:each, &proc) 18 | end 19 | 20 | def should_receive(*args) 21 | if args[0] == :render 22 | register_verify_after_each 23 | render_proxy.should_receive(:render, :expected_from => caller(1)[0]) 24 | else 25 | super 26 | end 27 | end 28 | 29 | def should_not_receive(*args) 30 | if args[0] == :render 31 | register_verify_after_each 32 | render_proxy.should_not_receive(:render) 33 | else 34 | super 35 | end 36 | end 37 | 38 | def stub(*args) 39 | if args[0] == :render 40 | register_verify_after_each 41 | render_proxy.stub(args.first, :expected_from => caller(1)[0]) 42 | else 43 | super 44 | end 45 | end 46 | 47 | # FIXME - for some reason, neither alias nor alias_method are working 48 | # as expected in the else branch, so this is a duplicate of stub() 49 | # above. Could delegate, but then we'd run into craziness handling 50 | # :expected_from. This will have to do for the moment. 51 | def stub!(*args) 52 | if args[0] == :render 53 | register_verify_after_each 54 | render_proxy.stub!(args.first, :expected_from => caller(1)[0]) 55 | else 56 | super 57 | end 58 | end 59 | 60 | def verify_rendered_proc #:nodoc: 61 | template = self 62 | @verify_rendered_proc ||= Proc.new do 63 | template.verify_rendered 64 | template.unregister_verify_after_each 65 | end 66 | end 67 | 68 | def register_verify_after_each #:nodoc: 69 | proc = verify_rendered_proc 70 | Spec::Example::ExampleGroup.after(:each, &proc) 71 | end 72 | 73 | def render_proxy #:nodoc: 74 | @render_proxy ||= Spec::Mocks::Mock.new("render_proxy") 75 | end 76 | 77 | end 78 | end 79 | end 80 | end 81 | -------------------------------------------------------------------------------- /lib/spec/rails/example/routing_example_group.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Example 4 | 5 | class RoutingExampleGroup < ActionController::TestCase 6 | class RoutingController < ActionController::Base 7 | end 8 | 9 | tests RoutingController 10 | 11 | Spec::Example::ExampleGroupFactory.register(:routing, self) 12 | end 13 | 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /lib/spec/rails/example/routing_helpers.rb: -------------------------------------------------------------------------------- 1 | require 'rack/utils' 2 | 3 | module Spec 4 | module Rails 5 | module Example 6 | module RoutingHelpers 7 | 8 | class RouteFor 9 | def initialize(example, options) 10 | @example, @options = example, options 11 | end 12 | 13 | def ==(expected) 14 | if Hash === expected 15 | path, querystring = expected[:path].split('?') 16 | path_string = path 17 | path = expected.merge(:path => path) 18 | else 19 | path, querystring = expected.split('?') 20 | path_string = path 21 | path = { :path => path, :method => :get } 22 | end 23 | params = querystring.blank? ? {} : Rack::Utils.parse_query(querystring).symbolize_keys! 24 | begin 25 | @example.assert_routing(path, @options, {}, params) 26 | true 27 | rescue ActionController::RoutingError, ::Test::Unit::AssertionFailedError => e 28 | raise e.class, "#{e}\nIf you're expecting this failure, we suggest {:#{path[:method]}=>\"#{path[:path]}\"}.should_not be_routable" 29 | end 30 | end 31 | end 32 | # Uses ActionController::Routing::Routes to generate 33 | # the correct route for a given set of options. 34 | # == Examples 35 | # route_for(:controller => 'registrations', :action => 'edit', :id => '1') 36 | # => '/registrations/1/edit' 37 | # route_for(:controller => 'registrations', :action => 'create') 38 | # => {:path => "/registrations", :method => :post} 39 | def route_for(options) 40 | RouteFor.new(self, options) 41 | end 42 | 43 | # Uses ActionController::Routing::Routes to parse 44 | # an incoming path so the parameters it generates can be checked 45 | # 46 | # Note that this method is obsoleted by the route_to matcher. 47 | # == Example 48 | # params_from(:get, '/registrations/1/edit') 49 | # => :controller => 'registrations', :action => 'edit', :id => '1' 50 | def params_from(method, path) 51 | ensure_that_routes_are_loaded 52 | path, querystring = path.split('?') 53 | params = ActionController::Routing::Routes.recognize_path(path, :method => method) 54 | querystring.blank? ? params : params.merge(Rack::Utils.parse_query(querystring).symbolize_keys!) 55 | end 56 | 57 | private 58 | 59 | def ensure_that_routes_are_loaded 60 | ActionController::Routing::Routes.reload if ActionController::Routing::Routes.empty? 61 | end 62 | 63 | end 64 | end 65 | end 66 | end 67 | -------------------------------------------------------------------------------- /lib/spec/rails/example/view_example_group.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Example 4 | class ViewExampleGroupController < ApplicationController #:nodoc: 5 | include Spec::Rails::Example::RenderObserver 6 | attr_reader :template 7 | 8 | def add_helper_for(template_path) 9 | add_helper(template_path.split('/')[0]) 10 | end 11 | 12 | def add_helper(name) 13 | begin 14 | helper_module = "#{name}_helper".camelize.constantize 15 | rescue 16 | return 17 | end 18 | (class << template; self; end).class_eval do 19 | include helper_module 20 | end 21 | end 22 | 23 | def forget_variables_added_to_assigns 24 | end 25 | end 26 | 27 | # View Examples live in $RAILS_ROOT/spec/views/. 28 | # 29 | # View Specs use Spec::Rails::Example::ViewExampleGroup, 30 | # which provides access to views without invoking any of your controllers. 31 | # See Spec::Rails::Expectations::Matchers for information about specific 32 | # expectations that you can set on views. 33 | # 34 | # == Example 35 | # 36 | # describe "login/login" do 37 | # before do 38 | # render 'login/login' 39 | # end 40 | # 41 | # it "should display login form" do 42 | # response.should have_tag("form[action=/login]") do 43 | # with_tag("input[type=text][name=email]") 44 | # with_tag("input[type=password][name=password]") 45 | # with_tag("input[type=submit][value=Login]") 46 | # end 47 | # end 48 | # end 49 | class ViewExampleGroup < FunctionalExampleGroup 50 | if ActionView::Base.respond_to?(:load_helpers) # Rails 2.0.x 51 | ActionView::Helpers.constants.each do |name| 52 | const = ActionView::Helpers.const_get(name) 53 | include const if name.include?("Helper") && Module === const 54 | end 55 | elsif ActionView::Base.respond_to?(:helper_modules) # Rails 2.1.x 56 | ActionView::Base.helper_modules.each do |helper_module| 57 | include helper_module 58 | end 59 | else # Rails 2.2.x 60 | include ActionView::Helpers 61 | end 62 | 63 | tests ViewExampleGroupController 64 | class << self 65 | def inherited(klass) # :nodoc: 66 | klass.subject { template } 67 | super 68 | end 69 | end 70 | 71 | before {ensure_that_flash_and_session_work_properly} 72 | after {ensure_that_base_view_path_is_not_set_across_example_groups} 73 | 74 | def ensure_that_flash_and_session_work_properly #:nodoc: 75 | # For some reason which I do not yet understand, when running 76 | # examples with rake on ruby-1.9.2, the @controller is not defined. 77 | @controller ||= ViewExampleGroupController.new 78 | 79 | @controller.class.__send__ :public, :flash 80 | @controller.__send__ :initialize_template_class, @response 81 | @controller.__send__ :assign_shortcuts, @request, @response 82 | @controller.__send__ :initialize_current_url 83 | @session = @controller.session 84 | end 85 | 86 | def ensure_that_base_view_path_is_not_set_across_example_groups #:nodoc: 87 | ActionView::Base.base_view_path = nil 88 | end 89 | 90 | def set_base_view_path(options) #:nodoc: 91 | ActionView::Base.base_view_path = base_view_path(options) 92 | end 93 | 94 | def base_view_path(options) #:nodoc: 95 | "/#{derived_controller_name(options)}/" 96 | end 97 | 98 | def derived_controller_name(options) #:nodoc: 99 | parts = subject_of_render(options).split('/').reject { |part| part.empty? } 100 | "#{parts[0..-2].join('/')}" 101 | end 102 | 103 | def derived_action_name(options) #:nodoc: 104 | parts = subject_of_render(options).split('/').reject { |part| part.empty? } 105 | "#{parts.last}".split('.').first 106 | end 107 | 108 | def subject_of_render(options) #:nodoc: 109 | [:template, :partial, :file].each do |render_type| 110 | if options.has_key?(render_type) 111 | return options[render_type] 112 | end 113 | end 114 | return "" 115 | end 116 | 117 | def add_helpers(options) #:nodoc: 118 | @controller.add_helper("application") 119 | @controller.add_helper(derived_controller_name(options)) 120 | @controller.add_helper(options[:helper]) if options[:helper] 121 | options[:helpers].each { |helper| @controller.add_helper(helper) } if options[:helpers] 122 | end 123 | 124 | # Renders a template for a View Spec, which then provides access to the result 125 | # through the +response+. Also supports render with :inline, which you can 126 | # use to spec custom form builders, helpers, etc, in the context of a view. 127 | # 128 | # == Examples 129 | # 130 | # render('/people/list') 131 | # render('/people/list', :helper => My) 132 | # render('/people/list', :helpers => [My, MyOther]) 133 | # render(:partial => '/people/_address') 134 | # render(:inline => "<% custom_helper 'argument', 'another argument' %>") 135 | # 136 | # See Spec::Rails::Example::ViewExampleGroup for more information. 137 | def render(*args) 138 | options = Hash === args.last ? args.pop : {} 139 | 140 | if args.empty? 141 | unless [:partial, :inline, :file, :template, :xml, :json, :update].any? {|k| options.has_key? k} 142 | args << self.class.description_parts.first 143 | end 144 | end 145 | 146 | options[:template] = args.first.to_s.sub(/^\//,'') unless args.empty? 147 | 148 | set_base_view_path(options) 149 | add_helpers(options) 150 | 151 | assigns[:action_name] = @action_name 152 | 153 | @request.path_parameters = @request.path_parameters.merge( 154 | :controller => derived_controller_name(options), 155 | :action => derived_action_name(options) 156 | ).merge(options[:path_parameters] || {}) 157 | 158 | defaults = { :layout => false } 159 | options = defaults.merge options 160 | 161 | @controller.__send__(:params).reverse_merge! @request.parameters 162 | 163 | @controller.class.instance_eval %{ 164 | def controller_path 165 | "#{derived_controller_name(options)}" 166 | end 167 | 168 | def controller_name 169 | "#{derived_controller_name(options).split('/').last}" 170 | end 171 | } 172 | 173 | @controller.__send__ :forget_variables_added_to_assigns 174 | @controller.__send__ :render, options 175 | @controller.__send__ :process_cleanup 176 | end 177 | 178 | # This provides the template. Use this to set mock 179 | # expectations for dealing with partials 180 | # 181 | # == Example 182 | # 183 | # describe "/person/new" do 184 | # it "should use the form partial" do 185 | # template.should_receive(:render).with(:partial => 'form') 186 | # render "/person/new" 187 | # end 188 | # end 189 | def template 190 | @controller.template 191 | end 192 | 193 | Spec::Example::ExampleGroupFactory.register(:view, self) 194 | 195 | protected 196 | def _assigns_hash_proxy 197 | @_assigns_hash_proxy ||= AssignsHashProxy.new(self) {@response.template} 198 | end 199 | end 200 | 201 | end 202 | end 203 | end 204 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions.rb: -------------------------------------------------------------------------------- 1 | require 'spec' 2 | 3 | require 'spec/rails/extensions/spec/runner/configuration' 4 | require 'spec/rails/extensions/spec/matchers/have' 5 | 6 | require 'spec/rails/extensions/active_support/test_case' 7 | require 'spec/rails/extensions/active_record/base' 8 | require 'spec/rails/extensions/action_controller/rescue' 9 | require 'spec/rails/extensions/action_controller/test_case' 10 | require 'spec/rails/extensions/action_controller/test_response' 11 | require 'spec/rails/extensions/action_view/base' 12 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions/action_controller/rescue.rb: -------------------------------------------------------------------------------- 1 | module ActionController 2 | module Rescue 3 | def use_rails_error_handling! 4 | Kernel.warn <<-WARNING 5 | DEPRECATION NOTICE: controller.use_rails_error_handling! is 6 | deprecated and will be removed from a future version of 7 | rspec-rails. 8 | 9 | Use rescue_action_in_public!, which is defined directly in 10 | rails' testing framework, instead. 11 | WARNING 12 | if ::Rails::VERSION::STRING =~ /^2\.0/ 13 | @use_rails_error_handling = true 14 | else 15 | # anything but 0.0.0.0 - borrowed from rails own rescue_action_in_public! 16 | request.remote_addr = '208.77.188.166' 17 | end 18 | end 19 | 20 | def use_rails_error_handling? 21 | @use_rails_error_handling ||= false 22 | end 23 | 24 | protected 25 | 26 | if ::Rails::VERSION::STRING =~ /^2\.0/ 27 | def rescue_action_in_public? 28 | request.respond_to?(:rescue_action_in_public?) and request.rescue_action_in_public? 29 | end 30 | 31 | def rescue_action_with_handler_with_fast_errors(exception) 32 | if (use_rails_error_handling? || rescue_action_in_public?) & !handler_for_rescue(exception) 33 | rescue_action_in_public(exception) 34 | else 35 | rescue_action_with_handler_without_fast_errors(exception) 36 | end 37 | end 38 | alias_method_chain :rescue_action_with_handler, :fast_errors 39 | end 40 | 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions/action_controller/test_case.rb: -------------------------------------------------------------------------------- 1 | module ActionController 2 | class TestCase 3 | include ::Spec::Rails::Example::RoutingHelpers 4 | 5 | if ::Rails::VERSION::STRING =~ /2\.0/ 6 | # Introduced in Rails 2.1, but we need it for 2.0 7 | def rescue_action_in_public! 8 | # See rescue.rb in this same directory 9 | def request.rescue_action_in_public? 10 | true 11 | end 12 | end 13 | 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /lib/spec/rails/extensions/action_controller/test_response.rb: -------------------------------------------------------------------------------- 1 | module ActionController #:nodoc: 2 | class TestResponse #:nodoc: 3 | attr_writer :controller_path 4 | 5 | def capture(name) 6 | template.instance_variable_get "@content_for_#{name.to_s}" 7 | end 8 | 9 | if ::Rails::VERSION::STRING < "2.3" 10 | def [](name) 11 | Kernel.warn <<-WARNING 12 | DEPRECATION NOTICE: [](name) as an alias for capture(name) (TestResponse 13 | extension in rspec-rails) is deprecated and will not be defined by rspec-rails 14 | when working with rails >= 2.3.0. It will also be removed entirely from 15 | a future version of rspec-rails. 16 | WARNING 17 | capture(name) 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions/action_view/base.rb: -------------------------------------------------------------------------------- 1 | module ActionView #:nodoc: 2 | class Base #:nodoc: 3 | include Spec::Rails::Example::RenderObserver 4 | cattr_accessor :base_view_path 5 | 6 | def render_partial_with_base_view_path_handling(partial_path, local_assigns = nil, deprecated_local_assigns = nil) #:nodoc: 7 | if partial_path.is_a?(String) 8 | unless partial_path.include?("/") 9 | unless self.class.base_view_path.nil? 10 | partial_path = "#{self.class.base_view_path}/#{partial_path}" 11 | end 12 | end 13 | end 14 | begin 15 | render_partial_without_base_view_path_handling(partial_path, local_assigns, deprecated_local_assigns) 16 | rescue ArgumentError # edge rails > 2.1 changed render_partial to accept only one arg 17 | render_partial_without_base_view_path_handling(partial_path) 18 | end 19 | end 20 | alias_method_chain :render_partial, :base_view_path_handling 21 | 22 | def render_with_mock_proxy(options = {}, old_local_assigns = {}, &block) 23 | if render_proxy.__send__(:__mock_proxy).__send__(:find_matching_expectation, :render, options, old_local_assigns) 24 | render_proxy.render(options, old_local_assigns) 25 | elsif render_proxy.__send__(:__mock_proxy).__send__(:find_matching_expectation, :render, options) 26 | render_proxy.render(options) 27 | else 28 | unless render_proxy.__send__(:__mock_proxy).__send__(:find_matching_method_stub, :render, options) 29 | render_without_mock_proxy(options, old_local_assigns, &block) 30 | end 31 | end 32 | end 33 | alias_method_chain :render, :mock_proxy 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions/active_record/base.rb: -------------------------------------------------------------------------------- 1 | if defined?(ActiveRecord::Base) 2 | module Spec 3 | module Rails 4 | module Extensions 5 | module ActiveRecord 6 | module ClassMethods 7 | # :call-seq: 8 | # ModelClass.should have(:no).records 9 | # ModelClass.should have(1).record 10 | # ModelClass.should have(n).records 11 | # 12 | # Extension to enhance should have on AR Model classes 13 | def records 14 | find(:all) 15 | end 16 | alias :record :records 17 | end 18 | 19 | module InstanceMethods 20 | # :call-seq: 21 | # model.should have(:no).errors_on(:attribute) 22 | # model.should have(1).error_on(:attribute) 23 | # model.should have(n).errors_on(:attribute) 24 | # 25 | # Extension to enhance should have on AR Model instances. 26 | # Calls model.valid? in order to prepare the object's errors 27 | # object. 28 | def errors_on(attribute) 29 | self.valid? 30 | [self.errors.on(attribute)].flatten.compact 31 | end 32 | alias :error_on :errors_on 33 | end 34 | end 35 | end 36 | end 37 | end 38 | 39 | module ActiveRecord #:nodoc: 40 | class Base 41 | extend Spec::Rails::Extensions::ActiveRecord::ClassMethods 42 | include Spec::Rails::Extensions::ActiveRecord::InstanceMethods 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /lib/spec/rails/extensions/active_support/test_case.rb: -------------------------------------------------------------------------------- 1 | module ActiveSupport 2 | class TestCase 3 | include ::Spec::Rails::Matchers 4 | include ::Spec::Rails::Mocks 5 | end 6 | end 7 | 8 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions/spec/matchers/have.rb: -------------------------------------------------------------------------------- 1 | require 'spec/matchers/have' 2 | 3 | module Spec #:nodoc: 4 | module Matchers #:nodoc: 5 | class Have #:nodoc: 6 | 7 | def failure_message_for_should_with_errors_on_extensions 8 | return "expected #{relativities[@relativity]}#{@expected} errors on :#{@args[0]}, got #{@actual}" if @collection_name == :errors_on 9 | return "expected #{relativities[@relativity]}#{@expected} error on :#{@args[0]}, got #{@actual}" if @collection_name == :error_on 10 | return failure_message_for_should_without_errors_on_extensions 11 | end 12 | alias_method_chain :failure_message_for_should, :errors_on_extensions 13 | 14 | def description_with_errors_on_extensions 15 | return "have #{relativities[@relativity]}#{@expected} errors on :#{@args[0]}" if @collection_name == :errors_on 16 | return "have #{relativities[@relativity]}#{@expected} error on :#{@args[0]}" if @collection_name == :error_on 17 | return description_without_errors_on_extensions 18 | end 19 | alias_method_chain :description, :errors_on_extensions 20 | 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/spec/rails/extensions/spec/runner/configuration.rb: -------------------------------------------------------------------------------- 1 | require 'spec/runner/configuration' 2 | require 'test_help' 3 | 4 | if defined?(ActiveRecord::Base) 5 | module Spec 6 | module Runner 7 | class Configuration 8 | 9 | def initialize 10 | super 11 | self.fixture_path = RAILS_ROOT + '/spec/fixtures' 12 | end 13 | 14 | def use_transactional_fixtures 15 | ActiveSupport::TestCase.use_transactional_fixtures 16 | end 17 | def use_transactional_fixtures=(value) 18 | ActiveSupport::TestCase.use_transactional_fixtures = value 19 | end 20 | 21 | def use_instantiated_fixtures 22 | ActiveSupport::TestCase.use_instantiated_fixtures 23 | end 24 | def use_instantiated_fixtures=(value) 25 | ActiveSupport::TestCase.use_instantiated_fixtures = value 26 | end 27 | 28 | def fixture_path 29 | ActiveSupport::TestCase.fixture_path 30 | end 31 | def fixture_path=(path) 32 | ActiveSupport::TestCase.fixture_path = path 33 | ActionController::IntegrationTest.fixture_path = path 34 | end 35 | 36 | def global_fixtures 37 | ActiveSupport::TestCase.fixture_table_names 38 | end 39 | def global_fixtures=(fixtures) 40 | ActiveSupport::TestCase.fixtures(*fixtures) 41 | end 42 | end 43 | end 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /lib/spec/rails/interop/testcase.rb: -------------------------------------------------------------------------------- 1 | module Test 2 | module Unit 3 | class TestCase 4 | # Edge rails (r8664) introduces class-wide setup & teardown callbacks for Test::Unit::TestCase. 5 | # Make sure these still get run when running TestCases under rspec: 6 | prepend_before(:each) do 7 | run_callbacks :setup if respond_to?(:run_callbacks) 8 | end 9 | append_after(:each) do 10 | run_callbacks :teardown if respond_to?(:run_callbacks) 11 | end 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/spec/rails/matchers.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | # Spec::Rails::Expectations::Matchers provides several expectation matchers 4 | # intended to work with Rails components like models and responses. For example: 5 | # 6 | # response.should redirect_to("some/url") #redirect_to(url) is the matcher. 7 | # 8 | # In addition to those you see below, the arbitrary predicate feature of RSpec 9 | # makes the following available as well: 10 | # 11 | # response.should be_success #passes if response.success? 12 | # response.should be_redirect #passes if response.redirect? 13 | # 14 | # Note that many of these matchers are part of a wrapper of assert_select, so 15 | # the documentation comes straight from that with some slight modifications. 16 | # assert_select is a Test::Unit extension originally contributed to the 17 | # Rails community as a plugin by Assaf Arkin and eventually shipped as part of Rails. 18 | # 19 | # For more info on assert_select, see the relevant Rails documentation. 20 | module Matchers 21 | end 22 | end 23 | end 24 | 25 | require 'spec/rails/matchers/ar_be_valid' 26 | require 'spec/rails/matchers/assert_select' 27 | require 'spec/rails/matchers/change' 28 | require 'spec/rails/matchers/have_text' 29 | require 'spec/rails/matchers/include_text' 30 | require 'spec/rails/matchers/redirect_to' 31 | require 'spec/rails/matchers/route_to' 32 | require 'spec/rails/matchers/render_template' 33 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/ar_be_valid.rb: -------------------------------------------------------------------------------- 1 | if defined?(ActiveRecord::Base) 2 | module Spec 3 | module Rails 4 | module Matchers 5 | # :call-seq: 6 | # response.should be_valid 7 | # response.should_not be_valid 8 | def be_valid 9 | ::Spec::Matchers::Matcher.new :be_valid do 10 | match do |actual| 11 | actual.valid? 12 | end 13 | 14 | failure_message_for_should do |actual| 15 | if actual.respond_to?(:errors) && ActiveRecord::Errors === actual.errors 16 | "Expected #{actual.inspect} to be valid, but it was not\nErrors: " + actual.errors.full_messages.join(", ") 17 | else 18 | "Expected #{actual.inspect} to be valid" 19 | end 20 | end 21 | end 22 | end 23 | 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/assert_select.rb: -------------------------------------------------------------------------------- 1 | # This is a wrapper of assert_select for rspec. 2 | 3 | module Spec # :nodoc: 4 | module Rails 5 | module Matchers 6 | 7 | class AssertSelect #:nodoc: 8 | attr_reader :options 9 | 10 | def initialize(selector_assertion, spec_scope, *args, &block) 11 | @args, @options = args_and_options(args) 12 | @spec_scope = spec_scope 13 | @selector_assertion = selector_assertion 14 | @block = block 15 | end 16 | 17 | def matches?(response_or_text, &block) 18 | @block = block if block 19 | 20 | if doc = doc_from(response_or_text) 21 | @args.unshift(doc) 22 | end 23 | 24 | begin 25 | @spec_scope.__send__(@selector_assertion, *@args, &@block) 26 | true 27 | rescue ::Test::Unit::AssertionFailedError => @error 28 | false 29 | end 30 | end 31 | 32 | def failure_message_for_should; @error.message; end 33 | def failure_message_for_should_not; "should not #{description}, but did"; end 34 | 35 | def description 36 | { 37 | :assert_select => "have tag#{format_args(*@args)}", 38 | :assert_select_email => "send email#{format_args(*@args)}", 39 | }[@selector_assertion] 40 | end 41 | 42 | private 43 | 44 | module TestResponseOrString 45 | def test_response? 46 | ActionController::TestResponse === self and 47 | !self.headers['Content-Type'].blank? and 48 | self.headers['Content-Type'].to_sym == :xml 49 | end 50 | 51 | def string? 52 | String === self 53 | end 54 | end 55 | 56 | def doc_from(response_or_text) 57 | response_or_text.extend TestResponseOrString 58 | if response_or_text.test_response? 59 | HTML::Document.new(response_or_text.body, @options[:strict], @options[:xml]).root 60 | elsif response_or_text.string? 61 | HTML::Document.new(response_or_text, @options[:strict], @options[:xml]).root 62 | end 63 | end 64 | 65 | def format_args(*args) 66 | args.empty? ? "" : "(#{arg_list(*args)})" 67 | end 68 | 69 | def arg_list(*args) 70 | args.map do |arg| 71 | arg.respond_to?(:description) ? arg.description : arg.inspect 72 | end.join(", ") 73 | end 74 | 75 | def args_and_options(args) 76 | opts = {:xml => false, :strict => false} 77 | if args.last.is_a?(::Hash) 78 | opts[:strict] = args.last.delete(:strict) unless args.last[:strict].nil? 79 | opts[:xml] = args.last.delete(:xml) unless args.last[:xml].nil? 80 | args.pop if args.last.empty? 81 | end 82 | return [args, opts] 83 | end 84 | 85 | end 86 | 87 | # :call-seq: 88 | # response.should have_tag(*args, &block) 89 | # string.should have_tag(*args, &block) 90 | # 91 | # wrapper for assert_select with additional support for using 92 | # css selectors to set expectation on Strings. Use this in 93 | # helper specs, for example, to set expectations on the results 94 | # of helper methods. Also allow specification of how the 95 | # response is parsed using the options :xml and :strict options. 96 | # By default, these options are set to false. 97 | # 98 | # == Examples 99 | # 100 | # # in a controller spec 101 | # response.should have_tag("div", "some text") 102 | # 103 | # # to force xml and/or strict parsing of the response 104 | # response.should have_tag("div", "some text", :xml => true) 105 | # response.should have_tag("div", "some text", :strict => true) 106 | # response.should have_tag("div", "some text", :xml => true, :strict => false) 107 | # 108 | # # in a helper spec (person_address_tag is a method in the helper) 109 | # person_address_tag.should have_tag("input#person_address") 110 | # 111 | # see documentation for assert_select at http://api.rubyonrails.org/ 112 | def have_tag(*args, &block) 113 | @__current_scope_for_assert_select = AssertSelect.new(:assert_select, self, *args, &block) 114 | end 115 | 116 | # wrapper for a nested assert_select 117 | # 118 | # response.should have_tag("div#form") do 119 | # with_tag("input#person_name[name=?]", "person[name]") 120 | # end 121 | # 122 | # see documentation for assert_select at http://api.rubyonrails.org/ 123 | def with_tag(*args, &block) 124 | args = prepare_args(args, @__current_scope_for_assert_select) 125 | @__current_scope_for_assert_select.should have_tag(*args, &block) 126 | end 127 | 128 | # wrapper for a nested assert_select with false 129 | # 130 | # response.should have_tag("div#1") do 131 | # without_tag("span", "some text that shouldn't be there") 132 | # end 133 | # 134 | # see documentation for assert_select at http://api.rubyonrails.org/ 135 | def without_tag(*args, &block) 136 | args = prepare_args(args, @__current_scope_for_assert_select) 137 | @__current_scope_for_assert_select.should_not have_tag(*args, &block) 138 | end 139 | 140 | # :call-seq: 141 | # response.should have_rjs(*args, &block) 142 | # 143 | # wrapper for assert_select_rjs 144 | # 145 | # see documentation for assert_select_rjs at http://api.rubyonrails.org/ 146 | def have_rjs(*args, &block) 147 | AssertSelect.new(:assert_select_rjs, self, *args, &block) 148 | end 149 | 150 | # :call-seq: 151 | # response.should send_email(*args, &block) 152 | # 153 | # wrapper for assert_select_email 154 | # 155 | # see documentation for assert_select_email at http://api.rubyonrails.org/ 156 | def send_email(*args, &block) 157 | AssertSelect.new(:assert_select_email, self, *args, &block) 158 | end 159 | 160 | # wrapper for assert_select_encoded 161 | # 162 | # see documentation for assert_select_encoded at http://api.rubyonrails.org/ 163 | def with_encoded(*args, &block) 164 | should AssertSelect.new(:assert_select_encoded, self, *args, &block) 165 | end 166 | 167 | private 168 | 169 | def prepare_args(args, current_scope = nil) 170 | return args if current_scope.nil? 171 | defaults = current_scope.options || {:strict => false, :xml => false} 172 | args << {} unless args.last.is_a?(::Hash) 173 | args.last[:strict] = defaults[:strict] if args.last[:strict].nil? 174 | args.last[:xml] = defaults[:xml] if args.last[:xml].nil? 175 | args 176 | end 177 | 178 | end 179 | end 180 | end 181 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/change.rb: -------------------------------------------------------------------------------- 1 | if defined?(ActiveRecord::Base) 2 | module Spec 3 | module Matchers 4 | class Change 5 | def evaluate_value_proc_with_ensured_evaluation_of_proxy 6 | value = evaluate_value_proc_without_ensured_evaluation_of_proxy 7 | ActiveRecord::Associations::AssociationProxy === value ? value.dup : value 8 | end 9 | alias_method_chain :evaluate_value_proc, :ensured_evaluation_of_proxy 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/have_text.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Matchers 4 | 5 | class HaveText #:nodoc: 6 | 7 | def initialize(expected) 8 | @expected = expected 9 | end 10 | 11 | def matches?(response_or_text) 12 | @actual = response_or_text.respond_to?(:body) ? response_or_text.body : response_or_text 13 | return actual =~ expected if Regexp === expected 14 | return actual == expected unless Regexp === expected 15 | end 16 | 17 | def failure_message_for_should 18 | "expected #{expected.inspect}, got #{actual.inspect}" 19 | end 20 | 21 | def failure_message_for_should_not 22 | "expected not to have text #{expected.inspect}" 23 | end 24 | 25 | def description 26 | "have text #{expected.inspect}" 27 | end 28 | 29 | private 30 | attr_reader :expected 31 | attr_reader :actual 32 | 33 | end 34 | 35 | # :call-seq: 36 | # response.should have_text(expected) 37 | # response.should_not have_text(expected) 38 | # 39 | # Accepts a String or a Regexp, matching a String using == 40 | # and a Regexp using =~. 41 | # 42 | # If response_or_text has a #body, then that is used as to match against 43 | # else it uses response_or_text 44 | # 45 | # Use this instead of response.should have_tag() 46 | # when you want to match the whole string or whole body 47 | # 48 | # == Examples 49 | # 50 | # response.should have_text("This is the expected text") 51 | def have_text(text) 52 | HaveText.new(text) 53 | end 54 | 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/include_text.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Matchers 4 | 5 | class IncludeText #:nodoc: 6 | 7 | def initialize(expected) 8 | @expected = expected 9 | end 10 | 11 | def matches?(response_or_text) 12 | @actual = response_or_text.respond_to?(:body) ? response_or_text.body : response_or_text 13 | return actual.include?(expected) 14 | end 15 | 16 | def failure_message_for_should 17 | "expected to find #{expected.inspect} in #{actual.inspect}" 18 | end 19 | 20 | def failure_message_for_should_not 21 | "expected not to include text #{expected.inspect}" 22 | end 23 | 24 | def description 25 | "include text #{expected.inspect}" 26 | end 27 | 28 | private 29 | attr_reader :expected 30 | attr_reader :actual 31 | 32 | end 33 | 34 | 35 | # :call-seq: 36 | # response.should include_text(expected) 37 | # response.should_not include_text(expected) 38 | # 39 | # Accepts a String, matching using include? 40 | # 41 | # Use this instead of response.should have_text() 42 | # when you either don't know or don't care where on the page 43 | # this text appears. 44 | # 45 | # == Examples 46 | # 47 | # response.should include_text("This text will be in the actual string") 48 | def include_text(text) 49 | IncludeText.new(text) 50 | end 51 | 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/redirect_to.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Matchers 4 | 5 | class RedirectTo #:nodoc: 6 | 7 | include ActionController::StatusCodes 8 | 9 | def initialize(request, expected) 10 | @expected = expected 11 | @request = request 12 | end 13 | 14 | def matches?(response_or_controller) 15 | response = response_or_controller.respond_to?(:response) ? 16 | response_or_controller.response : 17 | response_or_controller 18 | 19 | @redirected = response.redirect? 20 | @actual = response.redirect_url 21 | return false unless @redirected 22 | 23 | if @expected_status 24 | @actual_status = interpret_status(response.code.to_i) 25 | @status_matched = @expected_status == @actual_status 26 | else 27 | @status_matched = true 28 | end 29 | 30 | if @expected.instance_of? Hash 31 | return false unless @actual =~ %r{^\w+://#{@request.host}} 32 | return false unless actual_redirect_to_valid_route 33 | return actual_hash == expected_hash && @status_matched 34 | else 35 | return @actual == expected_url && @status_matched 36 | end 37 | end 38 | 39 | def actual_hash 40 | hash_from_url @actual 41 | end 42 | 43 | def expected_hash 44 | hash_from_url expected_url 45 | end 46 | 47 | def actual_redirect_to_valid_route 48 | actual_hash 49 | end 50 | 51 | def hash_from_url(url) 52 | query_hash(url).merge(path_hash(url)).with_indifferent_access 53 | end 54 | 55 | def path_hash(url) 56 | path = url.sub(%r{^\w+://#{@request.host}(?::\d+)?}, "").split("?", 2)[0] 57 | ActionController::Routing::Routes.recognize_path path, { :method => :get } 58 | end 59 | 60 | def query_hash(url) 61 | query = url.split("?", 2)[1] || "" 62 | Rack::Utils.parse_query(query) 63 | end 64 | 65 | def with(options) 66 | @expected_status = interpret_status(options[:status]) 67 | self 68 | end 69 | 70 | def expected_url 71 | case @expected 72 | when Hash 73 | return ActionController::UrlRewriter.new(@request, {}).rewrite(@expected) 74 | when :back 75 | return @request.env['HTTP_REFERER'] 76 | when %r{^\w+://.*} 77 | return @expected 78 | else 79 | return "http://#{@request.host}" + (@expected.split('')[0] == '/' ? '' : '/') + @expected 80 | end 81 | end 82 | 83 | def failure_message_for_should 84 | if @redirected 85 | if @status_matched 86 | return %Q{expected redirect to #{@expected.inspect}, got redirect to #{@actual.inspect}} 87 | else 88 | return %Q{expected redirect to #{@expected.inspect} with status #{@expected_status}, got #{@actual_status}} 89 | end 90 | else 91 | return %Q{expected redirect to #{@expected.inspect}, got no redirect} 92 | end 93 | end 94 | 95 | def failure_message_for_should_not 96 | return %Q{expected not to be redirected to #{@expected.inspect}, but was} if @redirected 97 | end 98 | 99 | def description 100 | "redirect to #{@expected.inspect}" 101 | end 102 | end 103 | 104 | # :call-seq: 105 | # response.should redirect_to(url) 106 | # response.should redirect_to(:action => action_name) 107 | # response.should redirect_to(:controller => controller_name, :action => action_name) 108 | # response.should_not redirect_to(url) 109 | # response.should_not redirect_to(:action => action_name) 110 | # response.should_not redirect_to(:controller => controller_name, :action => action_name) 111 | # 112 | # Passes if the response is a redirect to the url, action or controller/action. 113 | # Useful in controller specs (integration or isolation mode). 114 | # 115 | # == Examples 116 | # 117 | # response.should redirect_to("path/to/action") 118 | # response.should redirect_to("http://test.host/path/to/action") 119 | # response.should redirect_to(:action => 'list') 120 | def redirect_to(opts) 121 | RedirectTo.new(request, opts) 122 | end 123 | end 124 | 125 | end 126 | end 127 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/render_template.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | module Matchers 4 | 5 | class RenderTemplate #:nodoc: 6 | 7 | def initialize(expected, controller) 8 | @controller = controller 9 | @expected = expected 10 | end 11 | 12 | def matches?(response_or_controller) 13 | response = response_or_controller.respond_to?(:response) ? 14 | response_or_controller.response : 15 | response_or_controller 16 | 17 | if response.respond_to?(:redirect?) && response.redirect? 18 | @redirect_url = response.redirect_url 19 | elsif response.respond_to?(:rendered_file) 20 | @actual = response.rendered_file 21 | elsif response.respond_to?(:rendered) 22 | case template = response.rendered[:template] 23 | when nil 24 | unless response.rendered[:partials].empty? 25 | @actual = path_and_file(response.rendered[:partials].keys.first).join("/_") 26 | end 27 | when ActionView::Template 28 | @actual = template.path 29 | when String 30 | @actual = template 31 | end 32 | else 33 | @actual = response.rendered_template.to_s 34 | end 35 | return false if @actual.blank? 36 | given_controller_path, given_file = path_and_file(@actual) 37 | expected_controller_path, expected_file = path_and_file(@expected) 38 | given_controller_path == expected_controller_path && match_files(given_file, expected_file) 39 | end 40 | 41 | def match_files(actual, expected) 42 | actual_parts = actual.split('.') 43 | expected_parts = expected.split('.') 44 | expected_parts.each_with_index do |expected_part, index| 45 | return false unless expected_part == actual_parts[index] 46 | end 47 | true 48 | end 49 | 50 | def failure_message_for_should 51 | if @redirect_url 52 | "expected #{@expected.inspect}, got redirected to #{@redirect_url.inspect}" 53 | else 54 | "expected #{@expected.inspect}, got #{@actual.inspect}" 55 | end 56 | end 57 | 58 | def failure_message_for_should_not 59 | "expected not to render #{@expected.inspect}, but did" 60 | end 61 | 62 | def description 63 | "render template #{@expected.inspect}" 64 | end 65 | 66 | private 67 | def path_and_file(path) 68 | parts = path.split('/') 69 | file = parts.pop 70 | controller = parts.empty? ? current_controller_path : parts.join('/') 71 | return controller, file 72 | end 73 | 74 | def controller_path_from(path) 75 | parts = path.split('/') 76 | parts.pop 77 | parts.join('/') 78 | end 79 | 80 | def current_controller_path 81 | @controller.class.to_s.underscore.gsub(/_controller$/,'') 82 | end 83 | 84 | end 85 | 86 | # :call-seq: 87 | # response.should render_template(template) 88 | # response.should_not render_template(template) 89 | # 90 | # For use in controller code examples (integration or isolation mode). 91 | # 92 | # Passes if the specified template (view file) is rendered by the 93 | # response. This file can be any view file, including a partial. However 94 | # if it is a partial it must be rendered directly i.e. you can't detect 95 | # that a partial has been rendered as part of a view using 96 | # render_template. For that you should use a message expectation 97 | # (mock) instead: 98 | # 99 | # controller.should_receive(:render).with(:partial => 'path/to/partial') 100 | # 101 | # template can include the controller path. It can also 102 | # include an optional extension, which you only need to use when there 103 | # is ambiguity. 104 | # 105 | # Note that partials must be spelled with the preceding underscore. 106 | # 107 | # == Examples 108 | # 109 | # response.should render_template('list') 110 | # response.should render_template('same_controller/list') 111 | # response.should render_template('other_controller/list') 112 | # 113 | # # with extensions 114 | # response.should render_template('list.rjs') 115 | # response.should render_template('list.haml') 116 | # response.should render_template('same_controller/list.rjs') 117 | # response.should render_template('other_controller/list.rjs') 118 | # 119 | # # partials 120 | # response.should render_template('_a_partial') 121 | # response.should render_template('same_controller/_a_partial') 122 | # response.should render_template('other_controller/_a_partial') 123 | def render_template(path) 124 | RenderTemplate.new(path.to_s, @controller) 125 | end 126 | 127 | end 128 | end 129 | end 130 | -------------------------------------------------------------------------------- /lib/spec/rails/matchers/route_to.rb: -------------------------------------------------------------------------------- 1 | require 'rack/utils' 2 | 3 | module Spec 4 | module Rails 5 | module Matchers 6 | USAGE = ArgumentError.new( 'usage: { :method => "path" }.should route_to( :controller => "controller", :action => "action", [ args ] )' ) 7 | 8 | class PathDecomposer 9 | def self.decompose_path(path) 10 | method, path = if Hash === path 11 | raise USAGE if path.keys.size > 1 12 | path.entries.first 13 | else 14 | [:get, path] 15 | end 16 | path, querystring = path.split('?') 17 | return method, path, querystring 18 | end 19 | end 20 | 21 | class RouteTo #:nodoc: 22 | def initialize(expected, example) 23 | @route, @example = expected,example 24 | end 25 | 26 | def matches?(path) 27 | begin 28 | @actual = path 29 | method, path, querystring = PathDecomposer.decompose_path(path) 30 | params = querystring.blank? ? {} : Rack::Utils.parse_query(querystring).symbolize_keys! 31 | @example.assert_routing({ :method => method, :path => path }, @route, {}, params) 32 | true 33 | rescue ActionController::RoutingError, ::Test::Unit::AssertionFailedError, ActionController::MethodNotAllowed => e 34 | raise e.class, "#{e}\nIf you're expecting this failure, we suggest { :#{method} => \"#{path}\" }.should_not be_routable" 35 | rescue Exception => e 36 | raise e.class, "#{e}\n#{e.backtrace.join( "\n" )}" 37 | end 38 | end 39 | 40 | def does_not_match(path) 41 | raise ArgumentError, "Don't test a negative route like this." 42 | end 43 | 44 | def failure_message_for_should 45 | "Expected #{@expected.inspect} to route to #{@actual.inspect}, but it didn't.\n"+ 46 | "In this case, we expected you to get an exception. So this message probably means something weird happened." 47 | end 48 | 49 | def failure_message_for_should_not 50 | "Expected a routing error, but the route passed instead. \nNote, when expecting routes to fail, you should use 'should_not be_routable' instead." 51 | end 52 | 53 | def description 54 | "route to #{@expected.inspect}" 55 | end 56 | 57 | private 58 | attr_reader :expected 59 | attr_reader :actual 60 | 61 | end 62 | 63 | # :call-seq: 64 | # "path".should route_to(expected) # assumes GET 65 | # { :get => "path" }.should route_to(expected) 66 | # { :put => "path" }.should route_to(expected) 67 | # 68 | # Uses ActionController::Routing::Routes to verify that 69 | # the path-and-method routes to a given set of options. 70 | # Also verifies route-generation, so that the expected options 71 | # do generate a pathname consisten with the indicated path/method. 72 | # 73 | # For negative tests, only the route recognition failure can be 74 | # tested; since route generation via path_to() will always generate 75 | # a path as requested. Use .should_not be_routable() in this case. 76 | # 77 | # == Examples 78 | # { :get => '/registrations/1/edit' }. 79 | # should route_to(:controller => 'registrations', :action => 'edit', :id => '1') 80 | # { :put => "/registrations/1" }.should 81 | # route_to(:controller => 'registrations', :action => 'update', :id => 1) 82 | # { :post => "/registrations/" }.should 83 | # route_to(:controller => 'registrations', :action => 'create') 84 | 85 | def route_to(expected) 86 | RouteTo.new(expected, self) 87 | end 88 | 89 | class BeRoutable 90 | def initialize(example) 91 | @example = example 92 | end 93 | 94 | def matches?(path) 95 | begin 96 | @actual = path 97 | method, path = PathDecomposer.decompose_path(path) 98 | @example.assert_recognizes({}, { :method => method, :path => path }, {} ) 99 | true 100 | rescue ActionController::RoutingError, ActionController::MethodNotAllowed 101 | false 102 | rescue ::Test::Unit::AssertionFailedError => e 103 | # the second thingy will always be "<{}>" becaues of the way we called assert_recognizes({}...) above. 104 | e.to_s =~ /<(.*)> did not match <\{\}>/m and @actual_place = $1 or raise 105 | true 106 | end 107 | end 108 | def failure_message_for_should 109 | "Expected '#{@actual.keys.first.to_s.upcase} #{@actual.values.first}' to be routable, but it wasn't.\n"+ 110 | "To really test routability, we recommend #{@actual.inspect}.\n"+ 111 | " should route_to( :action => 'action', :controller => 'controller' )\n\n"+ 112 | 113 | "That way, you'll verify where your route goes to. Plus, we'll verify\n"+ 114 | "the generation of the expected path from the action/controller, as in\n"+ 115 | "the url_for() helper." 116 | end 117 | 118 | def failure_message_for_should_not 119 | "Expected '#{@actual.keys.first.to_s.upcase} #{@actual.values.first}' to fail, but it routed to #{@actual_place} instead" 120 | end 121 | 122 | end 123 | # :call-seq: 124 | # { "path" }.should_not be_routable # assumes GET 125 | # { :get => "path" }.should_not be_routable 126 | # { :put => "path" }.should_not be_routable 127 | # 128 | # Uses ActionController::Routing::Routes to verify that 129 | # the path-and-method cannot be routed to a controller. 130 | # Since url_for() will always generate a path, even if that 131 | # path is not routable, the negative test only needs to be 132 | # performed on the route recognition. 133 | # 134 | # Don't use this matcher for testing expected routability - 135 | # use .should route_to( :controller => "controller", :action => "action" ) instead 136 | # 137 | # == Examples 138 | # { :get => '/registrations/1/attendees/3/edit' }.should_not be_routable 139 | # { :get => '/attendees/3/edit' }.should route_to( ...... ) 140 | 141 | def be_routable 142 | BeRoutable.new(self) 143 | end 144 | 145 | alias_method :be_routeable, :be_routable 146 | end 147 | end 148 | end 149 | 150 | -------------------------------------------------------------------------------- /lib/spec/rails/mocks.rb: -------------------------------------------------------------------------------- 1 | module Spec 2 | module Rails 3 | 4 | class IllegalDataAccessException < StandardError; end 5 | 6 | module Mocks 7 | 8 | # Creates a mock object instance for a +model_class+ with common 9 | # methods stubbed out. Additional methods may be easily stubbed (via 10 | # add_stubs) if +stubs+ is passed. 11 | def mock_model(model_class, options_and_stubs = {}) 12 | id = options_and_stubs[:id] || next_id 13 | options_and_stubs = options_and_stubs.reverse_merge({ 14 | :id => id, 15 | :to_param => id.to_s, 16 | :new_record? => false, 17 | :destroyed? => false, 18 | :marked_for_destruction? => false, 19 | :errors => stub("errors", :count => 0) 20 | }) 21 | m = mock("#{model_class.name}_#{id}", options_and_stubs) 22 | m.__send__(:__mock_proxy).instance_eval <<-CODE 23 | def @target.as_new_record 24 | self.stub(:id).and_return nil 25 | self.stub(:to_param).and_return nil 26 | self.stub(:new_record?).and_return true 27 | self 28 | end 29 | def @target.to_str 30 | self.to_s 31 | end 32 | def @target.is_a?(other) 33 | #{model_class}.ancestors.include?(other) 34 | end 35 | def @target.kind_of?(other) 36 | #{model_class}.ancestors.include?(other) 37 | end 38 | def @target.instance_of?(other) 39 | other == #{model_class} 40 | end 41 | def @target.class 42 | #{model_class} 43 | end 44 | CODE 45 | yield m if block_given? 46 | m 47 | end 48 | 49 | module ModelStubber 50 | def connection 51 | raise Spec::Rails::IllegalDataAccessException.new("stubbed models are not allowed to access the database") 52 | end 53 | def new_record? 54 | id.nil? 55 | end 56 | def as_new_record 57 | self.id = nil 58 | self 59 | end 60 | end 61 | 62 | # :call-seq: 63 | # stub_model(Model) 64 | # stub_model(Model).as_new_record 65 | # stub_model(Model, hash_of_stubs) 66 | # stub_model(Model, instance_variable_name, hash_of_stubs) 67 | # 68 | # Creates an instance of +Model+ that is prohibited from accessing the 69 | # database*. For each key in +hash_of_stubs+, if the model has a 70 | # matching attribute (determined by asking it) are simply assigned the 71 | # submitted values. If the model does not have a matching attribute, the 72 | # key/value pair is assigned as a stub return value using RSpec's 73 | # mocking/stubbing framework. 74 | # 75 | # new_record? is overridden to return the result of id.nil? 76 | # This means that by default new_record? will return false. If you want 77 | # the object to behave as a new record, sending it +as_new_record+ will 78 | # set the id to nil. You can also explicitly set :id => nil, in which 79 | # case new_record? will return true, but using +as_new_record+ makes the 80 | # example a bit more descriptive. 81 | # 82 | # While you can use stub_model in any example (model, view, controller, 83 | # helper), it is especially useful in view examples, which are 84 | # inherently more state-based than interaction-based. 85 | # 86 | # == Database Independence 87 | # 88 | # +stub_model+ does not make your examples entirely 89 | # database-independent. It does not stop the model class itself from 90 | # loading up its columns from the database. It just prevents data access 91 | # from the object itself. To completely decouple from the database, take 92 | # a look at libraries like unit_record or NullDB. 93 | # 94 | # == Examples 95 | # 96 | # stub_model(Person) 97 | # stub_model(Person).as_new_record 98 | # stub_model(Person, :id => 37) 99 | # stub_model(Person) do |person| 100 | # person.first_name = "David" 101 | # end 102 | def stub_model(model_class, stubs={}) 103 | stubs = {:id => next_id}.merge(stubs) 104 | model_class.new.tap do |model| 105 | model.id = stubs.delete(:id) 106 | model.extend ModelStubber 107 | stubs.each do |k,v| 108 | if model.has_attribute?(k) 109 | model[k] = stubs.delete(k) 110 | end 111 | end 112 | model.stub!(stubs) 113 | yield model if block_given? 114 | end 115 | end 116 | 117 | # DEPRECATED - use object.stub!(:method => value, :method2 => value) 118 | # 119 | # Stubs methods on +object+ (if +object+ is a symbol or string a new mock 120 | # with that name will be created). +stubs+ is a Hash of +method=>value+ 121 | def add_stubs(object, stubs = {}) #:nodoc: 122 | Kernel.warn <<-WARNING 123 | DEPRECATION NOTICE: add_stubs is deprecated and will be removed 124 | from a future version of rspec-rails. Use this instead: 125 | 126 | object.stub!(:method => value, :method2 => value) 127 | 128 | WARNING 129 | object.stub!(stubs) 130 | end 131 | 132 | private 133 | @@model_id = 1000 134 | def next_id 135 | @@model_id += 1 136 | end 137 | 138 | end 139 | end 140 | end 141 | -------------------------------------------------------------------------------- /lib/spec/rails/version.rb: -------------------------------------------------------------------------------- 1 | module Spec # :nodoc: 2 | module Rails # :nodoc: 3 | module VERSION # :nodoc: 4 | unless defined? MAJOR 5 | MAJOR = 1 6 | MINOR = 3 7 | TINY = 4 8 | PRE = nil 9 | 10 | STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') 11 | 12 | SUMMARY = "rspec-rails #{STRING}" 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /rspec-rails.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "spec/rails/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "rspec-rails" 7 | s.version = Spec::Rails::VERSION::STRING 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["RSpec Development Team"] 10 | s.email = ["rspec-devel@rubyforge.org"] 11 | s.homepage = "http://github.com/dchelimsky/rspec-rails" 12 | s.summary = Spec::Rails::VERSION::SUMMARY 13 | s.description = "Behaviour Driven Development for Ruby on Rails." 14 | 15 | s.rubyforge_project = "rspec" 16 | 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 20 | s.require_paths = ["lib"] 21 | 22 | s.add_dependency "rspec", "~> 1.3.1" 23 | s.add_dependency "rack", ">= 1.0.0" 24 | s.add_development_dependency "cucumber",">= 0.3.99" 25 | end 26 | -------------------------------------------------------------------------------- /spec/autotest/mappings_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require File.dirname(__FILE__) + '/../../lib/autotest/rails_rspec' 3 | require File.dirname(__FILE__) + '/../../../rspec/spec/autotest/autotest_matchers' 4 | 5 | describe Autotest::RailsRspec, "file mapping" do 6 | before(:each) do 7 | @autotest = Autotest::RailsRspec.new 8 | @autotest.hook :initialize 9 | end 10 | 11 | it "should map model example to model" do 12 | @autotest.should map_specs(['spec/models/thing_spec.rb']). 13 | to('app/models/thing.rb') 14 | end 15 | 16 | it "should map controller example to controller" do 17 | @autotest.should map_specs(['spec/controllers/things_controller_spec.rb']). 18 | to('app/controllers/things_controller.rb') 19 | end 20 | 21 | it "should map view.rhtml" do 22 | @autotest.should map_specs(['spec/views/things/index.rhtml_spec.rb']). 23 | to('app/views/things/index.rhtml') 24 | end 25 | 26 | it "should map view.rhtml with underscores in example filename" do 27 | @autotest.should map_specs(['spec/views/things/index_rhtml_spec.rb']). 28 | to('app/views/things/index.rhtml') 29 | end 30 | 31 | it "should map view.html.erb" do 32 | @autotest.should map_specs(['spec/views/things/index.html.erb_spec.rb']). 33 | to('app/views/things/index.html.erb') 34 | end 35 | 36 | describe "between routes.rb and things which depend on routes" do 37 | it "should map routes.rb to controllers" do 38 | @autotest.should map_specs(['spec/controllers/things_controller_spec.rb']). 39 | to('config/routes.rb') 40 | end 41 | 42 | it "should map routes.rb to views" do 43 | @autotest.should map_specs(['spec/views/things/action.html.erb_spec.rb']). 44 | to('config/routes.rb') 45 | end 46 | 47 | it "should map routes.rb to helpers" do 48 | @autotest.should map_specs(['spec/helpers/things_helper_spec.rb']). 49 | to('config/routes.rb') 50 | end 51 | 52 | it "should map routing example to routes" do 53 | @autotest.should map_specs(['spec/routing/thing_spec.rb']). 54 | to('config/routes.rb') 55 | end 56 | end 57 | 58 | describe "between the config and specs" do 59 | ['spec/controllers/things_controller_spec.rb', 60 | 'spec/views/things/action.html.erb_spec.rb', 61 | 'spec/helpers/things_helper_spec.rb', 62 | 'spec/routing/thing_spec.rb', 63 | 'spec/models/thing_spec.rb'].each do |file_path| 64 | 65 | it "should map environment.rb to #{file_path}" do 66 | @autotest.should map_specs([file_path]). 67 | to('config/environment.rb') 68 | end 69 | 70 | it "should map environments/test.rb to #{file_path}" do 71 | @autotest.should map_specs([file_path]). 72 | to('config/environments/test.rb') 73 | end 74 | 75 | it "should map boot.rb to #{file_path}" do 76 | @autotest.should map_specs([file_path]). 77 | to('config/boot.rb') 78 | end 79 | 80 | it "should map spec_helper.rb to #{file_path}" do 81 | @autotest.should map_specs([file_path]). 82 | to('spec/spec_helper.rb') 83 | end 84 | end 85 | end 86 | end 87 | -------------------------------------------------------------------------------- /spec/rails_suite.rb: -------------------------------------------------------------------------------- 1 | dir = File.dirname(__FILE__) 2 | Dir["#{dir}/**/*_example.rb"].each do |file| 3 | require file 4 | end 5 | Dir["#{dir}/**/*_spec.rb"].each do |file| 6 | require file 7 | end 8 | -------------------------------------------------------------------------------- /spec/resources/controllers/action_view_base_spec_controller.rb: -------------------------------------------------------------------------------- 1 | class ActionViewBaseSpecController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /spec/resources/controllers/application.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | before_filter :i_should_only_be_run_once, 3 | :only => 'action_with_inherited_before_filter' 4 | 5 | def i_should_only_be_run_once 6 | true 7 | end 8 | private :i_should_only_be_run_once 9 | end -------------------------------------------------------------------------------- /spec/resources/controllers/controller_spec_controller.rb: -------------------------------------------------------------------------------- 1 | class ControllerSpecController < ActionController::Base 2 | before_filter :raise_error, :only => :action_with_skipped_before_filter 3 | 4 | def raise_error 5 | raise "from a before filter" 6 | end 7 | 8 | skip_before_filter :raise_error 9 | 10 | prepend_view_path File.join(File.dirname(__FILE__), "..", "views") 11 | 12 | def some_action 13 | render :template => "template/that/does/not/actually/exist" 14 | end 15 | 16 | def some_action_with_implied_template 17 | end 18 | 19 | def action_with_template 20 | render :template => "controller_spec/action_with_template" 21 | end 22 | 23 | def action_which_sets_flash 24 | flash[:flash_key] = "flash value" 25 | render :text => "" 26 | end 27 | 28 | def action_which_gets_session 29 | raise "expected #{params[:session_key].inspect}\ngot #{session[:session_key].inspect}" unless (session[:session_key] == params[:expected]) 30 | render :text => "" 31 | end 32 | 33 | def action_which_sets_session 34 | session[:session_key] = "session value" 35 | end 36 | 37 | def action_which_gets_cookie 38 | raise "expected #{params[:expected].inspect}, got #{cookies[:cookie_key].inspect}" unless (cookies[:cookie_key] == params[:expected]) 39 | render :text => "" 40 | end 41 | 42 | def action_which_sets_cookie 43 | cookies['cookie_key'] = params[:value] 44 | render :text => "" 45 | end 46 | 47 | def action_with_partial 48 | render :partial => "controller_spec/partial" 49 | end 50 | 51 | def action_with_partial_with_object 52 | render :partial => "controller_spec/partial", :object => params[:thing] 53 | end 54 | 55 | def action_with_partial_with_locals 56 | render :partial => "controller_spec/partial", :locals => {:thing => params[:thing]} 57 | end 58 | 59 | def action_with_errors_in_template 60 | render :template => "controller_spec/action_with_errors_in_template" 61 | end 62 | 63 | def action_setting_the_assigns_hash 64 | @indirect_assigns_key = :indirect_assigns_key_value 65 | end 66 | 67 | def action_setting_flash_after_session_reset 68 | reset_session 69 | flash[:after_reset] = "available" 70 | end 71 | 72 | def action_setting_flash_before_session_reset 73 | flash[:before_reset] = 'available' 74 | reset_session 75 | end 76 | 77 | def action_with_render_update 78 | render :update do |page| 79 | page.replace :bottom, 'replace_me', 80 | :partial => 'non_existent_partial' 81 | end 82 | end 83 | 84 | def action_with_skipped_before_filter 85 | render :text => "" 86 | end 87 | 88 | def action_that_renders_inline 89 | render :inline => "<%= 'inline code' %>" 90 | end 91 | 92 | def action_that_assigns_false_to_a_variable 93 | @a_variable = false 94 | render :text => "" 95 | end 96 | 97 | def action_with_two_arg_render 98 | render :update, :status => 404 do |page| 99 | page.visual_effect :highlight, 'user_list' 100 | end 101 | end 102 | 103 | class RescuedError < Exception; end 104 | class UnRescuedError < Exception; end 105 | 106 | rescue_from RescuedError do |e| 107 | render :text => 'Rescued!' 108 | end 109 | 110 | def rescued_error_action 111 | raise ControllerSpecController::RescuedError 112 | end 113 | 114 | def un_rescued_error_action 115 | raise ControllerSpecController::UnRescuedError 116 | end 117 | 118 | def action_that_returns_headers 119 | render :text => request.headers[params[:header]] 120 | end 121 | end 122 | 123 | class ControllerInheritingFromApplicationControllerController < ApplicationController 124 | def action_with_inherited_before_filter 125 | render :text => "" 126 | end 127 | end 128 | -------------------------------------------------------------------------------- /spec/resources/controllers/example.txt: -------------------------------------------------------------------------------- 1 | This is an example file to download. -------------------------------------------------------------------------------- /spec/resources/controllers/redirect_spec_controller.rb: -------------------------------------------------------------------------------- 1 | class RedirectSpecController < ApplicationController 2 | 3 | def action_with_no_redirect 4 | render :text => "this is just here to keep this from causing a MissingTemplate error" 5 | end 6 | 7 | def action_with_redirect_to_somewhere 8 | redirect_to :action => 'somewhere' 9 | end 10 | 11 | def action_with_redirect_to_other_somewhere 12 | redirect_to :controller => 'render_spec', :action => 'text_action' 13 | end 14 | 15 | def action_with_redirect_to_somewhere_and_return 16 | redirect_to :action => 'somewhere' and return 17 | render :text => "this is after the return" 18 | end 19 | 20 | def somewhere 21 | render :text => "this is just here to keep this from causing a MissingTemplate error" 22 | end 23 | 24 | def action_with_redirect_to_rspec_site 25 | redirect_to "http://rspec.rubyforge.org" 26 | end 27 | 28 | def action_with_redirect_back 29 | redirect_to :back 30 | end 31 | 32 | def action_with_redirect_in_respond_to 33 | respond_to do |wants| 34 | wants.html { redirect_to :action => 'somewhere' } 35 | end 36 | end 37 | 38 | def action_with_redirect_which_creates_query_string 39 | redirect_to :action => "somewhere", :id => 1111, :param1 => "value1", :param2 => "value2" 40 | end 41 | 42 | # note: sometimes this is the URL which rails will generate from the hash in 43 | # action_with_redirect_which_creates_query_string 44 | def action_with_redirect_with_query_string_order1 45 | redirect_to "http://test.host/redirect_spec/somewhere/1111?param1=value1¶m2=value2" 46 | end 47 | 48 | # note: sometimes this is the URL which rails will generate from the hash in 49 | # action_with_redirect_which_creates_query_string 50 | def action_with_redirect_with_query_string_order2 51 | redirect_to "http://test.host/redirect_spec/somewhere/1111?param2=value2¶m1=value1" 52 | end 53 | 54 | def action_with_redirect_to_unroutable_url_inside_app 55 | redirect_to :controller => "nonexistant", :action => "none" 56 | end 57 | 58 | def action_with_method_restriction 59 | render :text => '' 60 | end 61 | 62 | def action_to_redirect_to_action_with_method_restriction 63 | redirect_to :action => 'action_with_method_restriction' 64 | end 65 | 66 | def action_with_redirect_to_somewhere_with_status 67 | redirect_to :action => 'somewhere', :status => 301 68 | end 69 | end 70 | 71 | -------------------------------------------------------------------------------- /spec/resources/controllers/render_spec_controller.rb: -------------------------------------------------------------------------------- 1 | class RenderSpecController < ApplicationController 2 | prepend_view_path File.join(File.dirname(__FILE__), "..", "views") 3 | 4 | def some_action 5 | respond_to do |format| 6 | format.html 7 | format.js 8 | end 9 | end 10 | 11 | def action_which_renders_template_from_other_controller 12 | render :template => 'controller_spec/action_with_template' 13 | end 14 | 15 | def text_action 16 | render :text => "this is the text for this action" 17 | end 18 | 19 | def action_with_redirect 20 | redirect_to :action => :some_action 21 | end 22 | 23 | def action_with_partial 24 | render :partial => "a_partial" 25 | end 26 | 27 | def action_that_renders_nothing 28 | render :nothing => true 29 | end 30 | 31 | def action_with_alternate_layout 32 | render :layout => 'simple' 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /spec/resources/controllers/rjs_spec_controller.rb: -------------------------------------------------------------------------------- 1 | class RjsSpecController < ApplicationController 2 | prepend_view_path File.join(File.dirname(__FILE__), "..", "views") 3 | 4 | def replace_html 5 | end 6 | 7 | def insert_html 8 | end 9 | 10 | def replace 11 | end 12 | 13 | def hide_div 14 | end 15 | 16 | def hide_page_element 17 | end 18 | 19 | def replace_html_with_partial 20 | end 21 | 22 | def render_replace_html 23 | render :update do |page| 24 | page.replace_html 'mydiv', 'replacement text' 25 | page.replace_html 'myotherdiv', 'other replacement text' 26 | end 27 | end 28 | 29 | def render_replace_html_with_partial 30 | render :update do |page| 31 | page.replace_html 'mydiv', :partial => 'rjs_spec/replacement_partial' 32 | end 33 | end 34 | 35 | def render_insert_html 36 | render :update do |page| 37 | page.insert_html 'mydiv', 'replacement text' 38 | end 39 | end 40 | 41 | def render_replace 42 | render :update do |page| 43 | page.replace 'mydiv', 'replacement text' 44 | end 45 | end 46 | 47 | def render_hide_div 48 | render :update do |page| 49 | page.hide 'mydiv' 50 | end 51 | end 52 | 53 | def render_hide_page_element 54 | render :update do |page| 55 | page['mydiv'].hide 56 | end 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /spec/resources/helpers/addition_helper.rb: -------------------------------------------------------------------------------- 1 | module AdditionHelper 2 | def plus(addend) 3 | @addend + addend 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/resources/helpers/explicit_helper.rb: -------------------------------------------------------------------------------- 1 | module ExplicitHelper 2 | def method_in_explicit_helper 3 | "

This is text from a method in the ExplicitHelper
" 4 | end 5 | 6 | # this is an example of a method spec'able with eval_erb in helper specs 7 | def prepend(arg, &block) 8 | begin # rails edge after 2.1.0 eliminated need for block.binding 9 | concat(arg) + block.call 10 | rescue 11 | concat(arg, block.binding) + block.call 12 | end 13 | end 14 | 15 | def named_url 16 | rspec_on_rails_specs_url 17 | end 18 | 19 | def named_path 20 | rspec_on_rails_specs_path 21 | end 22 | 23 | def params_foo 24 | params[:foo] 25 | end 26 | 27 | def session_foo 28 | session[:foo] 29 | end 30 | 31 | def request_thing 32 | request.thing 33 | end 34 | 35 | def flash_thing 36 | flash[:thing] 37 | end 38 | 39 | def method_using_output_buffer 40 | concat("the_text_from_concat") 41 | end 42 | 43 | def method_using_template 44 | update_page { |p| p["#some_id"].replace_html "" } 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /spec/resources/helpers/more_explicit_helper.rb: -------------------------------------------------------------------------------- 1 | module MoreExplicitHelper 2 | def method_in_more_explicit_helper 3 | "
This is text from a method in the MoreExplicitHelper
" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/resources/helpers/plugin_application_helper.rb: -------------------------------------------------------------------------------- 1 | # Methods added to this helper will be available to all templates in the application. 2 | module ApplicationHelper 3 | def method_in_plugin_application_helper 4 | "
This is text from a method in the ApplicationHelper
" 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/resources/helpers/view_spec_helper.rb: -------------------------------------------------------------------------------- 1 | module ViewSpecHelper 2 | def method_in_helper 3 | "
This is text from a method in the ViewSpecHelper
" 4 | end 5 | 6 | def method_in_template_with_partial 7 | "
method_in_template_with_partial in ViewSpecHelper
" 8 | end 9 | 10 | def method_in_partial 11 | "
method_in_partial in ViewSpecHelper
" 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/resources/models/animal.rb: -------------------------------------------------------------------------------- 1 | class Animal < ActiveRecord::Base 2 | belongs_to :person 3 | validates_uniqueness_of :name 4 | end 5 | -------------------------------------------------------------------------------- /spec/resources/models/person.rb: -------------------------------------------------------------------------------- 1 | class Person < ActiveRecord::Base 2 | has_many :animals do 3 | def pups 4 | find(:all, :conditions => 'age < 1') 5 | end 6 | def adults 7 | find(:all, :conditions => 'age >= 1') 8 | end 9 | end 10 | validates_presence_of :name 11 | 12 | def add_animal animal 13 | animal.person = self 14 | animals << animal 15 | animal.save 16 | end 17 | 18 | end 19 | -------------------------------------------------------------------------------- /spec/resources/models/thing.rb: -------------------------------------------------------------------------------- 1 | class Thing < ActiveRecord::Base 2 | validates_presence_of :name 3 | end 4 | -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/_partial.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/controller_spec/_partial.html.erb -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/action_setting_flash_after_session_reset.html.erb: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/action_setting_flash_before_session_reset.html.erb: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/action_setting_the_assigns_hash.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/controller_spec/action_setting_the_assigns_hash.html.erb -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/action_with_errors_in_template.html.erb: -------------------------------------------------------------------------------- 1 | <% raise %> -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/action_with_template.html.erb: -------------------------------------------------------------------------------- 1 |
This is action_with_template.rhtml
2 | -------------------------------------------------------------------------------- /spec/resources/views/controller_spec/non_existent_action_with_existent_template.html.erb: -------------------------------------------------------------------------------- 1 | <%- raise "THIS TEMPLATE SHOULD NOT BE RENDERED" -%> -------------------------------------------------------------------------------- /spec/resources/views/layouts/application.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/layouts/application.html.erb -------------------------------------------------------------------------------- /spec/resources/views/layouts/simple.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/layouts/simple.html.erb -------------------------------------------------------------------------------- /spec/resources/views/objects/_object.html.erb: -------------------------------------------------------------------------------- 1 | <%= object.name %> -------------------------------------------------------------------------------- /spec/resources/views/render_spec/_a_partial.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/render_spec/_a_partial.html.erb -------------------------------------------------------------------------------- /spec/resources/views/render_spec/action_with_alternate_layout.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/render_spec/action_with_alternate_layout.html.erb -------------------------------------------------------------------------------- /spec/resources/views/render_spec/some_action.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/render_spec/some_action.html.erb -------------------------------------------------------------------------------- /spec/resources/views/render_spec/some_action.js.rjs: -------------------------------------------------------------------------------- 1 | # This is used for rails > 1.2.3 -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/_replacement_partial.html.erb: -------------------------------------------------------------------------------- 1 | This is the text in the replacement partial. -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/hide_div.js.rjs: -------------------------------------------------------------------------------- 1 | page.hide 'mydiv' 2 | -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/hide_page_element.js.rjs: -------------------------------------------------------------------------------- 1 | page['mydiv'].hide 2 | -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/insert_html.js.rjs: -------------------------------------------------------------------------------- 1 | page.insert_html 'mydiv', 'replacement text' 2 | -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/replace.js.rjs: -------------------------------------------------------------------------------- 1 | page.replace 'mydiv', 'replacement text' 2 | -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/replace_html.js.rjs: -------------------------------------------------------------------------------- 1 | page.replace_html 'mydiv', 'replacement text' -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/replace_html_with_partial.js.rjs: -------------------------------------------------------------------------------- 1 | page.replace_html 'mydiv', :partial => 'rjs_spec/replacement_partial' -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/visual_effect.js.rjs: -------------------------------------------------------------------------------- 1 | page.visual_effect :fade, 'mydiv' 2 | -------------------------------------------------------------------------------- /spec/resources/views/rjs_spec/visual_toggle_effect.js.rjs: -------------------------------------------------------------------------------- 1 | page.visual_effect :toggle_blind, 'mydiv' 2 | -------------------------------------------------------------------------------- /spec/resources/views/tag_spec/no_tags.html.erb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/resources/views/tag_spec/single_div_with_no_attributes.html.erb: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /spec/resources/views/tag_spec/single_div_with_one_attribute.html.erb: -------------------------------------------------------------------------------- 1 |
-------------------------------------------------------------------------------- /spec/resources/views/view_spec/_partial.html.erb: -------------------------------------------------------------------------------- 1 | <%= method_in_plugin_application_helper %> 2 | <%= method_in_partial %> -------------------------------------------------------------------------------- /spec/resources/views/view_spec/_partial_used_twice.html.erb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchelimsky/rspec-rails/dcabc8b245085d5b7bb073feadc110413016a7ea/spec/resources/views/view_spec/_partial_used_twice.html.erb -------------------------------------------------------------------------------- /spec/resources/views/view_spec/_partial_with_local_variable.html.erb: -------------------------------------------------------------------------------- 1 |
<%= x %>
-------------------------------------------------------------------------------- /spec/resources/views/view_spec/_partial_with_sub_partial.html.erb: -------------------------------------------------------------------------------- 1 | <%= render :partial => 'partial', :object => partial %> -------------------------------------------------------------------------------- /spec/resources/views/view_spec/_spacer.html.erb: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/accessor.html.erb: -------------------------------------------------------------------------------- 1 |
<%= session[:key] %>
2 |
<%= params[:key] %>
3 |
<%= flash[:key] %>
4 |
<%= flash[:now_key] %>
5 |
<%= params[:controller] %>
6 |
<%= params[:action] %>
7 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/block_helper.html.erb: -------------------------------------------------------------------------------- 1 | <% if_allowed do %> 2 |
block helper was rendered
3 | <% end %> -------------------------------------------------------------------------------- /spec/resources/views/view_spec/entry_form.html.erb: -------------------------------------------------------------------------------- 1 | <% form_tag do %> 2 | <% end %> -------------------------------------------------------------------------------- /spec/resources/views/view_spec/explicit_helper.html.erb: -------------------------------------------------------------------------------- 1 | <%= method_in_plugin_application_helper %> 2 | <%= method_in_explicit_helper %> 3 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/foo/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= method_in_plugin_application_helper %> 2 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/implicit_helper.html.erb: -------------------------------------------------------------------------------- 1 | <%= method_in_plugin_application_helper %> 2 | <%= method_in_helper %> 3 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/multiple_helpers.html.erb: -------------------------------------------------------------------------------- 1 | <%= method_in_plugin_application_helper %> 2 | <%= method_in_explicit_helper %> 3 | <%= method_in_more_explicit_helper %> -------------------------------------------------------------------------------- /spec/resources/views/view_spec/path_params.html.erb: -------------------------------------------------------------------------------- 1 | <%= params[:controller] %> -------------------------------------------------------------------------------- /spec/resources/views/view_spec/should_not_receive.html.erb: -------------------------------------------------------------------------------- 1 | <% if @obj.render_partial? %> 2 | <%= render :partial => 'some_partial' %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/template_with_partial.html.erb: -------------------------------------------------------------------------------- 1 | <%= method_in_template_with_partial %> 2 | <%= render :partial => 'partial' %> 3 | 4 | <%= render :partial => 'partial_used_twice' %> 5 | <%= render :partial => 'partial_used_twice' %> 6 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/template_with_partial_using_collection.html.erb: -------------------------------------------------------------------------------- 1 | <%= render :partial => 'partial', 2 | :collection => ['Alice', 'Bob'], 3 | :spacer_template => 'spacer' %> 4 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/template_with_partial_with_array.html.erb: -------------------------------------------------------------------------------- 1 | <%= render :partial => @array %> 2 | -------------------------------------------------------------------------------- /spec/resources/views/view_spec/view_helpers.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to "edit", "this_is_the_link" %> 2 | -------------------------------------------------------------------------------- /spec/spec/rails/example/assigns_hash_proxy_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "AssignsHashProxy" do 4 | def orig_assigns 5 | @object.assigns 6 | end 7 | 8 | class Foo 9 | def initialize(bar) 10 | @bar = bar 11 | end 12 | attr_reader :bar 13 | 14 | def ==(other) 15 | self.bar == other.bar 16 | end 17 | end 18 | 19 | before(:each) do 20 | @object = Class.new do 21 | def assigns; @assigns ||= Hash.new; end 22 | end.new 23 | @proxy = Spec::Rails::Example::AssignsHashProxy.new(self) {@object} 24 | end 25 | 26 | it "doesn't wig out on objects that define their own == method" do 27 | @object.assigns['foo'] = Foo.new(1) 28 | @proxy['foo'].should == Foo.new(1) 29 | end 30 | 31 | it "should set ivars on object using string" do 32 | @proxy['foo'] = 'bar' 33 | @object.instance_eval{@foo}.should == 'bar' 34 | end 35 | 36 | it "should set ivars on object using symbol" do 37 | @proxy[:foo] = 'bar' 38 | @object.instance_eval{@foo}.should == 'bar' 39 | end 40 | 41 | it "should access object's assigns with a string" do 42 | @object.assigns['foo'] = 'bar' 43 | @proxy['foo'].should == 'bar' 44 | end 45 | 46 | it "should access object's assigns with a symbol" do 47 | @object.assigns['foo'] = 'bar' 48 | @proxy[:foo].should == 'bar' 49 | end 50 | 51 | it "should access object's ivars with a string" do 52 | @object.instance_variable_set('@foo', 'bar') 53 | @proxy['foo'].should == 'bar' 54 | end 55 | 56 | it "should access object's ivars with a symbol" do 57 | @object.instance_variable_set('@foo', 'bar') 58 | @proxy[:foo].should == 'bar' 59 | end 60 | 61 | it "should iterate through each element like a Hash" do 62 | values = { 63 | 'foo' => 1, 64 | 'bar' => 2, 65 | 'baz' => 3 66 | } 67 | @proxy['foo'] = values['foo'] 68 | @proxy['bar'] = values['bar'] 69 | @proxy['baz'] = values['baz'] 70 | 71 | @proxy.each do |key, value| 72 | key.should == key 73 | value.should == values[key] 74 | end 75 | end 76 | 77 | it "should delete the ivar of passed in key" do 78 | @object.instance_variable_set('@foo', 'bar') 79 | @proxy.delete('foo') 80 | @proxy['foo'].should be_nil 81 | end 82 | 83 | it "should delete the assigned element of passed in key" do 84 | @object.assigns['foo'] = 'bar' 85 | @proxy.delete('foo') 86 | @proxy['foo'].should be_nil 87 | end 88 | 89 | it "should detect the presence of a key in assigns" do 90 | @object.assigns['foo'] = 'bar' 91 | @proxy.has_key?('foo').should == true 92 | @proxy.has_key?('bar').should == false 93 | end 94 | 95 | it "should expose values set in example back to the example" do 96 | @proxy[:foo] = 'bar' 97 | @proxy[:foo].should == 'bar' 98 | end 99 | 100 | it "should allow assignment of false via proxy" do 101 | @proxy['foo'] = false 102 | @proxy['foo'].should be_false 103 | end 104 | 105 | it "should allow assignment of false" do 106 | @object.instance_variable_set('@foo',false) 107 | @proxy['foo'].should be_false 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /spec/spec/rails/example/configuration_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Spec 4 | module Runner 5 | describe Configuration do 6 | 7 | def config 8 | @config ||= Configuration.new 9 | end 10 | 11 | describe "#use_transactional_fixtures" do 12 | it "should return ActiveSupport::TestCase.use_transactional_fixtures" do 13 | config.use_transactional_fixtures.should == ActiveSupport::TestCase.use_transactional_fixtures 14 | end 15 | 16 | it "should set ActiveSupport::TestCase.use_transactional_fixtures to false" do 17 | ActiveSupport::TestCase.should_receive(:use_transactional_fixtures=).with(false) 18 | config.use_transactional_fixtures = false 19 | end 20 | 21 | it "should set ActiveSupport::TestCase.use_transactional_fixtures to true" do 22 | ActiveSupport::TestCase.should_receive(:use_transactional_fixtures=).with(true) 23 | config.use_transactional_fixtures = true 24 | end 25 | end 26 | 27 | describe "#use_instantiated_fixtures" do 28 | it "should return ActiveSupport::TestCase.use_transactional_fixtures" do 29 | config.use_instantiated_fixtures.should == ActiveSupport::TestCase.use_instantiated_fixtures 30 | end 31 | 32 | it "should set ActiveSupport::TestCase.use_instantiated_fixtures to false" do 33 | ActiveSupport::TestCase.should_receive(:use_instantiated_fixtures=).with(false) 34 | config.use_instantiated_fixtures = false 35 | end 36 | 37 | it "should set ActiveSupport::TestCase.use_instantiated_fixtures to true" do 38 | ActiveSupport::TestCase.should_receive(:use_instantiated_fixtures=).with(true) 39 | config.use_instantiated_fixtures = true 40 | end 41 | end 42 | 43 | describe "#fixture_path" do 44 | it "should default to RAILS_ROOT + '/spec/fixtures'" do 45 | config.fixture_path.should == RAILS_ROOT + '/spec/fixtures' 46 | ActiveSupport::TestCase.fixture_path.should == RAILS_ROOT + '/spec/fixtures' 47 | ActionController::IntegrationTest.fixture_path.should == RAILS_ROOT + '/spec/fixtures' 48 | end 49 | 50 | it "should set fixture_path" do 51 | config.fixture_path = "/new/path" 52 | config.fixture_path.should == "/new/path" 53 | ActiveSupport::TestCase.fixture_path.should == "/new/path" 54 | ActionController::IntegrationTest.fixture_path.should == "/new/path" 55 | end 56 | end 57 | 58 | describe "#global_fixtures" do 59 | it "should set fixtures on TestCase" do 60 | ActiveSupport::TestCase.should_receive(:fixtures).with(:blah) 61 | config.global_fixtures = [:blah] 62 | end 63 | end 64 | 65 | end 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /spec/spec/rails/example/controller_isolation_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'controller_spec_controller' 3 | 4 | describe "a controller spec running in isolation mode", :type => :controller do 5 | controller_name :controller_spec 6 | 7 | it "does not care if the specified template doesn't exist" do 8 | get 'some_action' 9 | response.should be_success 10 | response.should render_template("template/that/does/not/actually/exist") 11 | end 12 | 13 | it "does not care if the implied template doesn't exist" do 14 | get 'some_action_with_implied_template' 15 | response.should be_success 16 | response.should render_template("some_action_with_implied_template") 17 | end 18 | 19 | it "does not care if the template has errors" do 20 | get 'action_with_errors_in_template' 21 | response.should be_success 22 | response.should render_template("action_with_errors_in_template") 23 | end 24 | 25 | it "does not care if the template exists but the action doesn't" do 26 | get 'non_existent_action_with_existent_template' 27 | response.should be_success 28 | end 29 | 30 | it "fails if the neither the action nor the template exist" do 31 | expect {get 'non_existent_action'}.to raise_error(ActionController::UnknownAction) 32 | end 33 | end 34 | 35 | describe "a controller spec running in integration mode", :type => :controller do 36 | controller_name :controller_spec 37 | integrate_views 38 | 39 | it "renders a template" do 40 | get 'action_with_template' 41 | response.should be_success 42 | response.should have_tag('div', 'This is action_with_template.rhtml') 43 | end 44 | 45 | it "fails if the template doesn't exist" do 46 | error = defined?(ActionController::MissingTemplate) ? ActionController::MissingTemplate : ActionView::MissingTemplate 47 | lambda { get 'some_action' }.should raise_error(error) 48 | end 49 | 50 | it "fails if the template has errors" do 51 | lambda { get 'action_with_errors_in_template' }.should raise_error(ActionView::TemplateError) 52 | end 53 | 54 | it "fails if the action doesn't exist" do 55 | expect {get 'non_existent_action'}.to raise_error(ActionController::UnknownAction) 56 | end 57 | 58 | describe "nested" do 59 | it "should render a template" do 60 | get 'action_with_template' 61 | response.should be_success 62 | response.should have_tag('div', 'This is action_with_template.rhtml') 63 | end 64 | 65 | describe "with integrate_views turned off" do 66 | integrate_views false 67 | 68 | it "should not care if the template doesn't exist" do 69 | get 'some_action' 70 | response.should be_success 71 | response.should render_template("template/that/does/not/actually/exist") 72 | end 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /spec/spec/rails/example/cookies_proxy_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class CookiesProxyExamplesController < ActionController::Base 4 | def index 5 | cookies[:key] = cookies[:key] 6 | render :text => "" 7 | end 8 | end 9 | 10 | module Spec 11 | module Rails 12 | module Example 13 | describe CookiesProxy, :type => :controller do 14 | controller_name :cookies_proxy_examples 15 | 16 | describe "with a String key" do 17 | 18 | it "should accept a String value" do 19 | proxy = CookiesProxy.new(self) 20 | proxy['key'] = 'value' 21 | get :index 22 | if ::Rails::VERSION::STRING >= "2.3" 23 | proxy['key'].should == 'value' 24 | else 25 | proxy['key'].should == ['value'] 26 | end 27 | end 28 | 29 | it "should accept a Hash value" do 30 | proxy = CookiesProxy.new(self) 31 | proxy['key'] = { :value => 'value', :expires => expiration = 1.hour.from_now, :path => path = '/path' } 32 | get :index 33 | if ::Rails::VERSION::STRING >= "2.3" 34 | proxy['key'].should == 'value' 35 | else 36 | proxy['key'].should == ['value'] 37 | proxy['key'].value.should == ['value'] 38 | proxy['key'].expires.should == expiration 39 | proxy['key'].path.should == path 40 | end 41 | end 42 | 43 | end 44 | 45 | describe "with a Symbol key" do 46 | 47 | it "should accept a String value" do 48 | proxy = CookiesProxy.new(self) 49 | proxy[:key] = 'value' 50 | get :index 51 | if ::Rails::VERSION::STRING >= "2.3" 52 | proxy[:key].should == 'value' 53 | else 54 | proxy[:key].should == ['value'] 55 | end 56 | end 57 | 58 | it "should accept a Hash value" do 59 | proxy = CookiesProxy.new(self) 60 | proxy[:key] = { :value => 'value', :expires => expiration = 1.hour.from_now, :path => path = '/path' } 61 | get :index 62 | if ::Rails::VERSION::STRING >= "2.3" 63 | proxy[:key].should == 'value' 64 | else 65 | proxy[:key].should == ['value'] 66 | proxy[:key].value.should == ['value'] 67 | proxy[:key].expires.should == expiration 68 | proxy[:key].path.should == path 69 | end 70 | end 71 | 72 | end 73 | 74 | describe "#delete" do 75 | it "should delete from the response cookies" do 76 | proxy = CookiesProxy.new(self) 77 | response_cookies = mock('cookies') 78 | response.should_receive(:cookies).and_return(response_cookies) 79 | response_cookies.should_receive(:delete).with('key') 80 | proxy.delete :key 81 | end 82 | end 83 | end 84 | 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /spec/spec/rails/example/error_handling_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'controller_spec_controller' 3 | 4 | ['integration', 'isolation'].each do |mode| 5 | describe "A controller example running in #{mode} mode", :type => :controller do 6 | controller_name :controller_spec 7 | integrate_views if mode == 'integration' 8 | 9 | describe "without use_rails_error_handling!" do 10 | describe "with an error that is *not* rescued" do 11 | it "raises the error" do 12 | lambda do 13 | get 'un_rescued_error_action' 14 | end.should raise_error(ControllerSpecController::UnRescuedError) 15 | end 16 | end 17 | describe "with an error that *is* rescued" do 18 | it "returns a 200" do 19 | get 'rescued_error_action' 20 | response.response_code.should == 200 21 | end 22 | end 23 | end 24 | 25 | describe "with deprecated use_rails_error_handling!" do 26 | before(:each) do 27 | Kernel.stub!(:warn) 28 | end 29 | 30 | it "warns of deprecation" do 31 | Kernel.should_receive(:warn).with(/DEPRECATION NOTICE/) 32 | controller.use_rails_error_handling! 33 | end 34 | 35 | describe "with an error that is *not* rescued" do 36 | it "returns the error code" do 37 | controller.use_rails_error_handling! 38 | get 'un_rescued_error_action' 39 | response.response_code.should == 500 40 | end 41 | end 42 | 43 | describe "with an error that *is* rescued" do 44 | it "returns a 200" do 45 | controller.use_rails_error_handling! 46 | get 'rescued_error_action' 47 | response.response_code.should == 200 48 | end 49 | end 50 | end 51 | 52 | describe "with rescue_action_in_public!" do 53 | describe "with an error that is *not* rescued" do 54 | it "returns the error code" do 55 | rescue_action_in_public! 56 | get 'un_rescued_error_action' 57 | response.response_code.should == 500 58 | end 59 | end 60 | 61 | describe "with an error that *is* rescued" do 62 | it "returns a 200" do 63 | rescue_action_in_public! 64 | get 'rescued_error_action' 65 | response.response_code.should == 200 66 | end 67 | end 68 | end 69 | 70 | describe "with bypass_rescue" do 71 | describe "with an error that is *not* rescued" do 72 | it "raises the error" do 73 | bypass_rescue 74 | lambda do 75 | get 'un_rescued_error_action' 76 | end.should raise_error(ControllerSpecController::UnRescuedError) 77 | end 78 | end 79 | 80 | describe "with an error that *is* rescued" do 81 | it "raises the error" do 82 | bypass_rescue 83 | lambda do 84 | get 'rescued_error_action' 85 | end.should raise_error(ControllerSpecController::RescuedError) 86 | end 87 | end 88 | end 89 | end 90 | end -------------------------------------------------------------------------------- /spec/spec/rails/example/example_group_factory_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Spec 4 | module Example 5 | describe ExampleGroupFactory do 6 | it "should return a ModelExampleGroup when given :type => :model" do 7 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 8 | "name", :type => :model 9 | ) {} 10 | example_group.superclass.should == Spec::Rails::Example::ModelExampleGroup 11 | end 12 | 13 | it "should return a ModelExampleGroup when given :location => '/blah/spec/models/'" do 14 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 15 | "name", :location => '/blah/spec/models/blah.rb' 16 | ) {} 17 | example_group.superclass.should == Spec::Rails::Example::ModelExampleGroup 18 | end 19 | 20 | it "should return a ModelExampleGroup when given :location => '\\blah\\spec\\models\\' (windows format)" do 21 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 22 | "name", :location => '\\blah\\spec\\models\\blah.rb' 23 | ) {} 24 | example_group.superclass.should == Spec::Rails::Example::ModelExampleGroup 25 | end 26 | 27 | it "should return an ActiveSupport::TestCase when given :location => '/blah/spec/foo/' (anything other than controllers, views and helpers)" do 28 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 29 | "name", :location => '/blah/spec/foo/blah.rb' 30 | ) {} 31 | example_group.superclass.should == ActiveSupport::TestCase 32 | end 33 | 34 | it "should return an ActiveSupport::TestCase when given :location => '\\blah\\spec\\foo\\' (windows format) (anything other than controllers, views and helpers)" do 35 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 36 | "name", :location => '\\blah\\spec\\foo\\blah.rb' 37 | ) {} 38 | example_group.superclass.should == ActiveSupport::TestCase 39 | end 40 | 41 | it "should return a ViewExampleGroup when given :type => :view" do 42 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 43 | "name", :type => :view 44 | ) {} 45 | example_group.superclass.should == Spec::Rails::Example::ViewExampleGroup 46 | end 47 | 48 | it "should return a ViewExampleGroup when given :location => '/blah/spec/views/'" do 49 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 50 | "name", :location => '/blah/spec/views/blah.rb' 51 | ) {} 52 | example_group.superclass.should == Spec::Rails::Example::ViewExampleGroup 53 | end 54 | 55 | it "should return a ModelExampleGroup when given :location => '\\blah\\spec\\views\\' (windows format)" do 56 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 57 | "name", :location => '\\blah\\spec\\views\\blah.rb' 58 | ) {} 59 | example_group.superclass.should == Spec::Rails::Example::ViewExampleGroup 60 | end 61 | 62 | it "should return a HelperExampleGroup when given :type => :helper" do 63 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 64 | "name", :type => :helper 65 | ) {} 66 | example_group.superclass.should == Spec::Rails::Example::HelperExampleGroup 67 | end 68 | 69 | it "should return a HelperExampleGroup when given :location => '/blah/spec/helpers/'" do 70 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 71 | "name", :location => '/blah/spec/helpers/blah.rb' 72 | ) {} 73 | example_group.superclass.should == Spec::Rails::Example::HelperExampleGroup 74 | end 75 | 76 | it "should return a ModelExampleGroup when given :location => '\\blah\\spec\\helpers\\' (windows format)" do 77 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 78 | "name", :location => '\\blah\\spec\\helpers\\blah.rb' 79 | ) {} 80 | example_group.superclass.should == Spec::Rails::Example::HelperExampleGroup 81 | end 82 | 83 | it "should return a ControllerExampleGroup when given :type => :controller" do 84 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 85 | "name", :type => :controller 86 | ) {} 87 | example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup 88 | end 89 | 90 | it "should return a ControllerExampleGroup when given :location => '/blah/spec/controllers/'" do 91 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 92 | "name", :location => '/blah/spec/controllers/blah.rb' 93 | ) {} 94 | example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup 95 | end 96 | 97 | it "should return a ModelExampleGroup when given :location => '\\blah\\spec\\controllers\\' (windows format)" do 98 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 99 | "name", :location => '\\blah\\spec\\controllers\\blah.rb' 100 | ) {} 101 | example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup 102 | end 103 | 104 | it "should favor the :type over the :location" do 105 | example_group = Spec::Example::ExampleGroupFactory.create_example_group( 106 | "name", :location => '/blah/spec/models/blah.rb', :type => :controller 107 | ) {} 108 | example_group.superclass.should == Spec::Rails::Example::ControllerExampleGroup 109 | end 110 | end 111 | end 112 | end 113 | -------------------------------------------------------------------------------- /spec/spec/rails/example/model_example_group_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | module Spec 4 | module Rails 5 | module Example 6 | describe ModelExampleGroup do 7 | accesses_configured_helper_methods 8 | 9 | if defined?(ActiveRecord::TestCase) 10 | it "derives from ActiveRecord::TestCase" do 11 | group = describe("foo", :type => :model) do; end 12 | group.ancestors.should include(ActiveRecord::TestCase) 13 | end 14 | else 15 | it "derives from ActiveSupport::TestCase" do 16 | group = describe("foo", :type => :model) do; end 17 | group.ancestors.should include(ActiveSupport::TestCase) 18 | end 19 | end 20 | 21 | it "clears its name from the description" do 22 | group = describe("foo", :type => :model) do 23 | $nested_group = describe("bar") do 24 | end 25 | end 26 | group.description.to_s.should == "foo" 27 | $nested_group.description.to_s.should == "foo bar" 28 | end 29 | end 30 | end 31 | end 32 | end -------------------------------------------------------------------------------- /spec/spec/rails/example/routing_example_group_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'controller_spec_controller' 3 | require File.join(File.dirname(__FILE__), "/shared_routing_example_group_examples.rb") 4 | 5 | describe "Routing Examples", :type => :routing do 6 | it_should_behave_like "a routing example" 7 | it_should_behave_like "a be routable spec" 8 | it_should_behave_like "a route to spec" 9 | end 10 | -------------------------------------------------------------------------------- /spec/spec/rails/example/test_unit_assertion_accessibility_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "assert_equal", :shared => true do 4 | it "like assert_equal" do 5 | assert_equal 1, 1 6 | lambda { 7 | assert_equal 1, 2 8 | }.should raise_error(::Test::Unit::AssertionFailedError) 9 | end 10 | end 11 | 12 | describe "A model spec should be able to access 'test/unit' assertions", :type => :model do 13 | it_should_behave_like "assert_equal" 14 | end 15 | 16 | describe "A view spec should be able to access 'test/unit' assertions", :type => :view do 17 | it_should_behave_like "assert_equal" 18 | end 19 | 20 | describe "A helper spec should be able to access 'test/unit' assertions", :type => :helper do 21 | it_should_behave_like "assert_equal" 22 | end 23 | 24 | describe "A controller spec with integrated views should be able to access 'test/unit' assertions", :type => :controller do 25 | controller_name :controller_spec 26 | integrate_views 27 | it_should_behave_like "assert_equal" 28 | end 29 | 30 | describe "A controller spec should be able to access 'test/unit' assertions", :type => :controller do 31 | controller_name :controller_spec 32 | it_should_behave_like "assert_equal" 33 | end 34 | -------------------------------------------------------------------------------- /spec/spec/rails/extensions/action_view_base_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require 'spec/mocks/errors' 3 | 4 | describe ActionView::Base, "with RSpec extensions:", :type => :view do 5 | 6 | describe "should_receive(:render)" do 7 | it "should not raise when render has been received" do 8 | template.should_receive(:render).with(:partial => "name") 9 | template.render :partial => "name" 10 | end 11 | 12 | it "should not raise when render with local assignments has been received" do 13 | template.should_receive(:render).with('name', :param => 1) 14 | template.render 'name', :param => 1 15 | end 16 | 17 | it "should raise when render has NOT been received" do 18 | template.should_receive(:render).with(:partial => "name") 19 | lambda { 20 | template.verify_rendered 21 | }.should raise_error 22 | end 23 | 24 | it "should return something (like a normal mock)" do 25 | template.should_receive(:render).with(:partial => "name").and_return("Little Johnny") 26 | result = template.render :partial => "name" 27 | result.should == "Little Johnny" 28 | end 29 | end 30 | 31 | [:stub!, :stub].each do |method| 32 | describe "#{method}(:render)" do 33 | it "should not raise when stubbing and render has been received" do 34 | template.send(method, :render).with(:partial => "name") 35 | template.render :partial => "name" 36 | end 37 | 38 | it "should not raise when stubbing and render has NOT been received" do 39 | template.send(method, :render).with(:partial => "name") 40 | end 41 | 42 | it "should not raise when stubbing and render has been received with different options" do 43 | template.send(method, :render).with(:partial => "name") 44 | template.render :partial => "view_spec/spacer" 45 | end 46 | 47 | it "should not raise when stubbing and expecting and render has been received" do 48 | template.send(method, :render).with(:partial => "name") 49 | template.should_receive(:render).with(:partial => "name") 50 | template.render(:partial => "name") 51 | end 52 | end 53 | 54 | describe "#{method}(:helper_method)" do 55 | it "should not raise when stubbing and helper_method has been received" do 56 | template.send(method, :helper_method).with(:arg => "value") 57 | template.helper_method :arg => "value" 58 | end 59 | 60 | it "should not raise when stubbing and helper_method has NOT been received" do 61 | template.send(method, :helper_method).with(:arg => "value") 62 | end 63 | 64 | it "SHOULD raise when stubbing and helper_method has been received with different options" do 65 | template.send(method, :helper_method).with(:arg => "value") 66 | expect { template.helper_method :arg => "other_value" }. 67 | to raise_error(/received :helper_method with unexpected arguments/) 68 | end 69 | 70 | it "should not raise when stubbing and expecting and helper_method has been received" do 71 | template.send(method, :helper_method).with(:arg => "value") 72 | template.should_receive(:helper_method).with(:arg => "value") 73 | template.helper_method(:arg => "value") 74 | end 75 | end 76 | 77 | end 78 | 79 | end 80 | -------------------------------------------------------------------------------- /spec/spec/rails/extensions/active_record_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "A model" do 4 | fixtures :things 5 | it "should tell you its required fields" do 6 | Thing.new.should have(1).error_on(:name) 7 | end 8 | 9 | it "should tell you how many records it has" do 10 | Thing.should have(:no).records 11 | Thing.create(:name => "THE THING") 12 | Thing.should have(1).record 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /spec/spec/rails/interop/testcase_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | 4 | if ActiveSupport.const_defined?(:Callbacks) && Test::Unit::TestCase.include?(ActiveSupport::Callbacks) 5 | 6 | class TestUnitTesting < Test::Unit::TestCase 7 | @@setup_callback_count = 0 8 | @@setup_method_count = 0 9 | @@teardown_callback_count = 0 10 | @@teardown_method_count = 0 11 | cattr_accessor :setup_callback_count, :setup_method_count, :teardown_callback_count, :teardown_method_count 12 | 13 | setup :do_some_setup 14 | teardown :do_some_teardown 15 | 16 | @@has_been_run = false 17 | def self.run? 18 | @@has_been_run 19 | end 20 | 21 | def self.run(options=Spec::Runner.options) 22 | super options 23 | end 24 | 25 | def do_some_setup 26 | @@setup_callback_count += 1 27 | end 28 | 29 | def setup 30 | @@setup_method_count += 1 31 | end 32 | 33 | def test_something 34 | assert_equal true, true 35 | @@has_been_run = true 36 | end 37 | 38 | def teardown 39 | @@teardown_method_count += 1 40 | end 41 | 42 | def do_some_teardown 43 | @@teardown_callback_count += 1 44 | end 45 | end 46 | 47 | module Test 48 | module Unit 49 | describe "Running TestCase tests" do 50 | before(:all) do 51 | TestUnitTesting.run unless TestUnitTesting.run? 52 | end 53 | 54 | it "should call the setup callbacks" do 55 | TestUnitTesting.setup_callback_count.should == 1 56 | end 57 | it "should still only call the normal setup method once" do 58 | TestUnitTesting.setup_method_count.should == 1 59 | end 60 | it "should call the teardown callbacks" do 61 | TestUnitTesting.teardown_callback_count.should == 1 62 | end 63 | it "should still only call the normal teardown method once" do 64 | TestUnitTesting.teardown_method_count.should == 1 65 | end 66 | end 67 | end 68 | end 69 | 70 | end 71 | -------------------------------------------------------------------------------- /spec/spec/rails/matchers/ar_be_valid_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "be_valid" do 4 | context "with valid attributes" do 5 | it "returns true" do 6 | be_valid.matches?(Thing.new(:name => 'thing')).should == true 7 | end 8 | end 9 | 10 | context "with invalid attributes" do 11 | it "returns false" do 12 | be_valid.matches?(Thing.new).should == false 13 | end 14 | 15 | it "adds errors to the errors " do 16 | expect { Thing.new.should be_valid }.to raise_error(/can't be blank/) 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /spec/spec/rails/matchers/errors_on_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "error_on" do 4 | it "should provide a description including the name of what the error is on" do 5 | have(1).error_on(:whatever).description.should == "have 1 error on :whatever" 6 | end 7 | 8 | it "should provide a failure message including the number actually given" do 9 | lambda { 10 | [].should have(1).error_on(:whatever) 11 | }.should fail_with("expected 1 error on :whatever, got 0") 12 | end 13 | end 14 | 15 | describe "errors_on" do 16 | it "should provide a description including the name of what the error is on" do 17 | have(2).errors_on(:whatever).description.should == "have 2 errors on :whatever" 18 | end 19 | 20 | it "should provide a failure message including the number actually given" do 21 | lambda { 22 | [1].should have(3).errors_on(:whatever) 23 | }.should fail_with("expected 3 errors on :whatever, got 1") 24 | end 25 | end 26 | 27 | describe "have something other than error_on or errors_on" do 28 | it "has a standard rspec failure message" do 29 | lambda { 30 | [1,2,3].should have(2).elements 31 | }.should fail_with("expected 2 elements, got 3") 32 | end 33 | 34 | it "has a standard rspec description" do 35 | have(2).elements.description.should == "have 2 elements" 36 | end 37 | end -------------------------------------------------------------------------------- /spec/spec/rails/matchers/have_text_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "have_text" do 4 | 5 | it "should have a helpful description" do 6 | matcher = have_text("foo bar") 7 | matcher.description.should == 'have text "foo bar"' 8 | end 9 | 10 | describe "where target is a Regexp" do 11 | it 'should should match submitted text using a regexp' do 12 | matcher = have_text(/fo*/) 13 | matcher.matches?('foo').should be_true 14 | matcher.matches?('bar').should be_nil 15 | end 16 | end 17 | 18 | describe "where target is a String" do 19 | it 'should match submitted text using a string' do 20 | matcher = have_text('foo') 21 | matcher.matches?('foo').should be_true 22 | matcher.matches?('foo bar').should be_false 23 | end 24 | end 25 | 26 | end 27 | 28 | describe "have_text", 29 | :type => :controller do 30 | ['isolation','integration'].each do |mode| 31 | if mode == 'integration' 32 | integrate_views 33 | end 34 | 35 | describe "where target is a response (in #{mode} mode)" do 36 | controller_name :render_spec 37 | 38 | it "should pass with exactly matching text" do 39 | post 'text_action' 40 | response.should have_text("this is the text for this action") 41 | end 42 | 43 | it "should pass with matching text (using Regexp)" do 44 | post 'text_action' 45 | response.should have_text(/is the text/) 46 | end 47 | 48 | it "should fail with matching text" do 49 | post 'text_action' 50 | lambda { 51 | response.should have_text("this is NOT the text for this action") 52 | }.should fail_with("expected \"this is NOT the text for this action\", got \"this is the text for this action\"") 53 | end 54 | 55 | it "should fail when a template is rendered" do 56 | post 'some_action' 57 | lambda { 58 | response.should have_text("this is the text for this action") 59 | }.should fail_with(/expected \"this is the text for this action\", got .*/) 60 | end 61 | 62 | it "should pass using should_not with incorrect text" do 63 | post 'text_action' 64 | response.should_not have_text("the accordian guy") 65 | end 66 | end 67 | end 68 | end 69 | 70 | -------------------------------------------------------------------------------- /spec/spec/rails/matchers/include_text_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "include_text" do 4 | 5 | it "should have a helpful description" do 6 | matcher = include_text("foo bar") 7 | matcher.description.should == 'include text "foo bar"' 8 | end 9 | 10 | it 'should match if the text is contained' do 11 | matcher = include_text('big piece') 12 | matcher.matches?('I am a big piece of text').should be_true 13 | end 14 | 15 | it 'should not match if text is not contained' do 16 | matcher = include_text('foo bar') 17 | matcher.matches?('hello world').should be_false 18 | end 19 | 20 | end 21 | 22 | describe "include_text", :type => :controller do 23 | ['isolation','integration'].each do |mode| 24 | if mode == 'integration' 25 | integrate_views 26 | end 27 | 28 | describe "where target is a response (in #{mode} mode)" do 29 | controller_name :render_spec 30 | 31 | it "should pass with exactly matching text" do 32 | post 'text_action' 33 | response.should include_text("this is the text for this action") 34 | end 35 | 36 | it 'should pass with substring matching text' do 37 | post 'text_action' 38 | response.should include_text('text for this') 39 | end 40 | 41 | it "should fail with incorrect text" do 42 | post 'text_action' 43 | lambda { 44 | response.should include_text("the accordian guy") 45 | }.should fail_with("expected to find \"the accordian guy\" in \"this is the text for this action\"") 46 | end 47 | 48 | it "should pass using should_not with incorrect text" do 49 | post 'text_action' 50 | response.should_not include_text("the accordian guy") 51 | end 52 | 53 | it "should fail when a template is rendered" do 54 | get 'some_action' 55 | lambda { 56 | response.should include_text("this is the text for this action") 57 | }.should fail_with(/expected to find \"this is the text for this action\"/) 58 | end 59 | end 60 | end 61 | end 62 | 63 | -------------------------------------------------------------------------------- /spec/spec/rails/matchers/should_change_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "should change" do 4 | describe "handling association proxies" do 5 | it "should match expected collection with proxied collection" do 6 | person = Person.create!(:name => 'David') 7 | koala = person.animals.create!(:name => 'Koala') 8 | zebra = person.animals.create!(:name => 'Zebra') 9 | 10 | lambda { 11 | person.animals.delete(koala) 12 | }.should change{person.animals}.to([zebra]) 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /spec/spec/rails/mocks/ar_classes.rb: -------------------------------------------------------------------------------- 1 | class MockableModel < ActiveRecord::Base 2 | has_one :associated_model 3 | end 4 | 5 | class SubMockableModel < MockableModel 6 | end 7 | 8 | class AssociatedModel < ActiveRecord::Base 9 | belongs_to :mockable_model 10 | end 11 | -------------------------------------------------------------------------------- /spec/spec/rails/mocks/mock_model_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require File.dirname(__FILE__) + '/ar_classes' 3 | 4 | describe "mock_model" do 5 | describe "responding to interrogation" do 6 | before(:each) do 7 | @model = mock_model(SubMockableModel) 8 | end 9 | it "should say it is_a? if it is" do 10 | @model.is_a?(SubMockableModel).should be(true) 11 | end 12 | it "should say it is_a? if it's ancestor is" do 13 | @model.is_a?(MockableModel).should be(true) 14 | end 15 | it "should say it is kind_of? if it is" do 16 | @model.kind_of?(SubMockableModel).should be(true) 17 | end 18 | it "should say it is kind_of? if it's ancestor is" do 19 | @model.kind_of?(MockableModel).should be(true) 20 | end 21 | it "should say it is instance_of? if it is" do 22 | @model.instance_of?(SubMockableModel).should be(true) 23 | end 24 | it "should not say it instance_of? if it isn't, even if it's ancestor is" do 25 | @model.instance_of?(MockableModel).should be(false) 26 | end 27 | it "should say it is not destroyed" do 28 | @model.destroyed?(SubMockableModel).should be(false) 29 | end 30 | it "should say it is not marked_for_destruction" do 31 | @model.marked_for_destruction?.should be(false) 32 | end 33 | end 34 | 35 | describe "with params" do 36 | it "should not mutate its parameters" do 37 | params = {:a => 'b'} 38 | model = mock_model(MockableModel, params) 39 | params.should == {:a => 'b'} 40 | end 41 | end 42 | 43 | describe "with #id stubbed", :type => :view do 44 | before(:each) do 45 | @model = mock_model(MockableModel, :id => 1) 46 | end 47 | it "should be named using the stubbed id value" do 48 | @model.instance_variable_get(:@name).should == "MockableModel_1" 49 | end 50 | it "should return string of id value for to_param" do 51 | @model.to_param.should == "1" 52 | end 53 | end 54 | 55 | describe "as association", :type => :view do 56 | before(:each) do 57 | @real = AssociatedModel.create! 58 | @mock_model = mock_model(MockableModel) 59 | @real.mockable_model = @mock_model 60 | end 61 | 62 | it "should pass associated_model == mock" do 63 | @mock_model.should == @real.mockable_model 64 | end 65 | 66 | it "should pass mock == associated_model" do 67 | @real.mockable_model.should == @mock_model 68 | end 69 | end 70 | 71 | describe "with :null_object => true", :type => :view do 72 | before(:each) do 73 | @model = mock_model(MockableModel, :null_object => true, :mocked_method => "mocked") 74 | end 75 | 76 | it "should be able to mock methods" do 77 | @model.mocked_method.should == "mocked" 78 | end 79 | it "should return itself to unmocked methods" do 80 | @model.unmocked_method.should equal(@model) 81 | end 82 | end 83 | 84 | describe "#as_null_object", :type => :view do 85 | before(:each) do 86 | @model = mock_model(MockableModel, :mocked_method => "mocked").as_null_object 87 | end 88 | 89 | it "should be able to mock methods" do 90 | @model.mocked_method.should == "mocked" 91 | end 92 | it "should return itself to unmocked methods" do 93 | @model.unmocked_method.should equal(@model) 94 | end 95 | end 96 | 97 | describe "#as_new_record" do 98 | it "should say it is a new record" do 99 | mock_model(MockableModel).as_new_record.should be_new_record 100 | end 101 | 102 | it "should have a nil id" do 103 | mock_model(MockableModel).as_new_record.id.should be(nil) 104 | end 105 | 106 | it "should return nil for #to_param" do 107 | mock_model(MockableModel).as_new_record.to_param.should be(nil) 108 | end 109 | end 110 | end 111 | 112 | 113 | -------------------------------------------------------------------------------- /spec/spec/rails/mocks/stub_model_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | require File.dirname(__FILE__) + '/ar_classes' 3 | 4 | describe "stub_model" do 5 | describe "defaults" do 6 | it "should have an id" do 7 | stub_model(MockableModel).id.should be > 0 8 | end 9 | 10 | it "should say it is not a new record" do 11 | stub_model(MockableModel).should_not be_new_record 12 | end 13 | end 14 | 15 | it "should accept a stub id" do 16 | stub_model(MockableModel, :id => 37).id.should == 37 17 | end 18 | 19 | it "should say it is a new record when id is set to nil" do 20 | stub_model(MockableModel, :id => nil).should be_new_record 21 | end 22 | 23 | it "should accept any arbitrary stub" do 24 | stub_model(MockableModel, :foo => "bar").foo.should == "bar" 25 | end 26 | 27 | it "should accept a stub for save" do 28 | stub_model(MockableModel, :save => false).save.should be(false) 29 | end 30 | 31 | describe "#as_new_record" do 32 | it "should say it is a new record" do 33 | stub_model(MockableModel).as_new_record.should be_new_record 34 | end 35 | 36 | it "should have a nil id" do 37 | stub_model(MockableModel).as_new_record.id.should be(nil) 38 | end 39 | end 40 | 41 | it "should raise when hitting the db" do 42 | lambda do 43 | model = stub_model(MockableModel, :changed => true, :attributes_with_quotes => {'this' => 'that'}) 44 | model.save 45 | end.should raise_error(Spec::Rails::IllegalDataAccessException, /stubbed models are not allowed to access the database/) 46 | end 47 | 48 | it "should increment the id" do 49 | first = stub_model(MockableModel) 50 | second = stub_model(MockableModel) 51 | second.id.should == (first.id + 1) 52 | end 53 | 54 | describe "as association" do 55 | before(:each) do 56 | @real = AssociatedModel.create! 57 | @stub_model = stub_model(MockableModel) 58 | @real.mockable_model = @stub_model 59 | end 60 | 61 | it "should pass associated_model == mock" do 62 | @stub_model.should == @real.mockable_model 63 | end 64 | 65 | it "should pass mock == associated_model" do 66 | @real.mockable_model.should == @stub_model 67 | end 68 | end 69 | 70 | describe "with a block" do 71 | it "should yield the model" do 72 | model = stub_model(MockableModel) do |block_arg| 73 | @block_arg = block_arg 74 | end 75 | model.should be(@block_arg) 76 | end 77 | end 78 | end 79 | 80 | 81 | -------------------------------------------------------------------------------- /spec/spec/rails/sample_modified_fixture.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "A sample spec", :type => :model do 4 | fixtures :animals 5 | it "should pass" do 6 | animals(:pig).name.should == "Piggy" 7 | end 8 | end -------------------------------------------------------------------------------- /spec/spec/rails/sample_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "A sample spec", :type => :model do 4 | fixtures :animals 5 | it "should pass" do 6 | animals(:pig).name.should == "Pig" 7 | end 8 | end -------------------------------------------------------------------------------- /spec/spec/rails/spec_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe "script/spec file" do 4 | it "should run a spec" do 5 | dir = File.dirname(__FILE__) 6 | output = `#{RAILS_ROOT}/script/spec #{dir}/sample_spec.rb` 7 | unless $?.exitstatus == 0 8 | flunk "command 'script/spec spec/sample_spec' failed\n#{output}" 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift '../rspec/lib' 2 | $LOAD_PATH.unshift '../../../' 3 | $LOAD_PATH.unshift 'spec/resources/controllers' 4 | $LOAD_PATH.unshift 'spec/resources/helpers' 5 | 6 | require File.expand_path('../../../../../spec/spec_helper', __FILE__) 7 | 8 | require 'spec/resources/controllers/application' 9 | require 'spec/resources/controllers/render_spec_controller' 10 | require 'spec/resources/controllers/controller_spec_controller' 11 | require 'spec/resources/controllers/rjs_spec_controller' 12 | require 'spec/resources/controllers/redirect_spec_controller' 13 | require 'spec/resources/controllers/action_view_base_spec_controller' 14 | require 'spec/resources/helpers/addition_helper' 15 | require 'spec/resources/helpers/explicit_helper' 16 | require 'spec/resources/helpers/more_explicit_helper' 17 | require 'spec/resources/helpers/view_spec_helper' 18 | require 'spec/resources/helpers/plugin_application_helper' 19 | require 'spec/resources/models/animal' 20 | require 'spec/resources/models/person' 21 | require 'spec/resources/models/thing' 22 | 23 | unless ActionController::Routing.controller_paths.include?('spec/resources/controllers') 24 | ActionController::Routing.instance_eval {@possible_controllers = nil} 25 | ActionController::Routing.controller_paths << 'spec/resources/controllers' 26 | end 27 | 28 | module Spec 29 | module Rails 30 | module Example 31 | class ViewExampleGroupController 32 | prepend_view_path 'spec/resources/views' 33 | end 34 | end 35 | end 36 | end 37 | 38 | def fail() 39 | raise_error(Spec::Expectations::ExpectationNotMetError) 40 | end 41 | 42 | def fail_with(message) 43 | raise_error(Spec::Expectations::ExpectationNotMetError,message) 44 | end 45 | 46 | class Proc 47 | def should_pass 48 | lambda { self.call }.should_not raise_error 49 | end 50 | end 51 | 52 | ActionController::Routing::Routes.draw do |map| 53 | map.connect 'action_with_method_restriction', :controller => 'redirect_spec', :action => 'action_with_method_restriction', :conditions => { :method => :get } 54 | map.connect 'action_to_redirect_to_action_with_method_restriction', :controller => 'redirect_spec', :action => 'action_to_redirect_to_action_with_method_restriction' 55 | 56 | map.resources :rspec_on_rails_specs 57 | map.custom_route 'custom_route', :controller => 'custom_route_spec', :action => 'custom_route' 58 | map.connect ':controller/:action/:id' 59 | end 60 | 61 | module HelperMethods 62 | def method_in_module_included_in_configuration 63 | end 64 | end 65 | 66 | module HelperMacros 67 | def accesses_configured_helper_methods 68 | it "has access to methods in modules included in configuration" do 69 | method_in_module_included_in_configuration 70 | end 71 | end 72 | end 73 | 74 | Spec::Runner.configure do |config| 75 | config.include HelperMethods 76 | config.extend HelperMacros 77 | end 78 | 79 | --------------------------------------------------------------------------------