rspec-rails 2.6.1 → 2.7.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/README.md +5 -5
  2. data/features/Transactions.md +84 -0
  3. data/features/controller_specs/Cookies.md +57 -0
  4. data/features/controller_specs/anonymous_controller.feature +104 -61
  5. data/features/controller_specs/bypass_rescue.feature +75 -0
  6. data/features/matchers/relation_match_array.feature +20 -0
  7. data/features/mocks/mock_model.feature +6 -6
  8. data/features/support/env.rb +2 -2
  9. data/features/view_specs/view_spec.feature +2 -8
  10. data/lib/autotest/rails_rspec2.rb +1 -1
  11. data/lib/generators/rspec/controller/templates/controller_spec.rb +1 -1
  12. data/lib/generators/rspec/install/templates/spec/spec_helper.rb +6 -0
  13. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +6 -6
  14. data/lib/generators/rspec/view/templates/view_spec.rb +1 -1
  15. data/lib/rspec/rails/example/controller_example_group.rb +19 -1
  16. data/lib/rspec/rails/fixture_support.rb +11 -0
  17. data/lib/rspec/rails/matchers.rb +1 -0
  18. data/lib/rspec/rails/matchers/relation_match_array.rb +3 -0
  19. data/lib/rspec/rails/matchers/routing_matchers.rb +16 -14
  20. data/lib/rspec/rails/mocks.rb +12 -7
  21. data/lib/rspec/rails/version.rb +1 -1
  22. data/spec/generators/rspec/controller/controller_generator_spec.rb +86 -0
  23. data/spec/generators/rspec/helper/helper_generator_spec.rb +30 -0
  24. data/spec/generators/rspec/install/install_generator_spec.rb +18 -0
  25. data/spec/generators/rspec/integration/integration_generator_spec.rb +44 -0
  26. data/spec/generators/rspec/mailer/mailer_generator_spec.rb +48 -0
  27. data/spec/generators/rspec/model/model_generator_spec.rb +52 -0
  28. data/spec/generators/rspec/observer/observer_generator_spec.rb +21 -0
  29. data/spec/generators/rspec/scaffold/scaffold_generator_spec.rb +113 -0
  30. data/spec/generators/rspec/view/view_generator_spec.rb +41 -0
  31. data/spec/rspec/rails/example/controller_example_group_spec.rb +39 -3
  32. data/spec/rspec/rails/matchers/relation_match_array_spec.rb +19 -0
  33. data/spec/rspec/rails/matchers/route_to_spec.rb +25 -3
  34. data/spec/rspec/rails/mocks/mock_model_spec.rb +62 -2
  35. data/spec/rspec/rails/mocks/stub_model_spec.rb +0 -1
  36. data/spec/spec_helper.rb +2 -1
  37. data/spec/{rspec/rails/mocks → support}/ar_classes.rb +5 -2
  38. metadata +102 -99
  39. data/.document +0 -5
  40. data/.gitignore +0 -14
  41. data/.rspec +0 -1
  42. data/.travis.yml +0 -11
  43. data/History.md +0 -1
  44. data/License.txt +0 -23
  45. data/README_DEV.md +0 -43
  46. data/Rakefile +0 -152
  47. data/Thorfile +0 -45
  48. data/Upgrade.md +0 -1
  49. data/cucumber.yml +0 -3
  50. data/features/.nav +0 -35
  51. data/features/Changelog.md +0 -162
  52. data/gemfiles/.bundle/config +0 -2
  53. data/gemfiles/base.rb +0 -60
  54. data/gemfiles/rails-3-0-stable +0 -6
  55. data/gemfiles/rails-3.0.0 +0 -5
  56. data/gemfiles/rails-3.0.1 +0 -5
  57. data/gemfiles/rails-3.0.2 +0 -5
  58. data/gemfiles/rails-3.0.3 +0 -5
  59. data/gemfiles/rails-3.0.4 +0 -5
  60. data/gemfiles/rails-3.0.5 +0 -5
  61. data/gemfiles/rails-3.0.6 +0 -5
  62. data/gemfiles/rails-3.0.7 +0 -5
  63. data/gemfiles/rails-3.1.0.rc1 +0 -5
  64. data/gemfiles/rails-master +0 -5
  65. data/rspec-rails.gemspec +0 -34
  66. data/templates/generate_stuff.rb +0 -21
  67. data/templates/run_specs.rb +0 -9
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  rspec-2 for rails-3 with lightweight extensions to each
4
4
 
5
- [![build status](http://travis-ci.org/rspec/rspec-rails.png)](http://travis-ci.org/rspec/rspec-rails)
5
+ [![build status](https://secure.travis-ci.org/rspec/rspec-rails.png)](http://travis-ci.org/rspec/rspec-rails)
6
6
 
7
7
  NOTE: rspec-2 does _not_ support rails-2. Use rspec-rails-1.3.x for rails-2.
8
8
 
@@ -36,18 +36,18 @@ This installs the following gems:
36
36
  Add `rspec-rails` to the `:test` and `:development` groups in the Gemfile:
37
37
 
38
38
  group :test, :development do
39
- gem "rspec-rails", "~> 2.4"
39
+ gem "rspec-rails", "~> 2.6"
40
40
  end
41
41
 
42
42
  It needs to be in the `:development` group to expose generators and rake
43
43
  tasks without having to type `RAILS_ENV=test`.
44
44
 
45
- Now you can run:
45
+ Now you can run:
46
46
 
47
- script/rails generate rspec:install
47
+ rails g rspec:install
48
48
 
49
49
  This adds the spec directory and some skeleton files, including
50
- the "rake spec" task.
50
+ the "rake spec" task.
51
51
 
52
52
  ### Generators
53
53
 
@@ -0,0 +1,84 @@
1
+ When you run `rails generate rspec:install`, the `spec/spec_helper.rb` file
2
+ includes the following configuration:
3
+
4
+ RSpec.configure do |config|
5
+ config.use_transactional_fixtures = true
6
+ end
7
+
8
+ The name of this setting is a bit misleading. What it really means in Rails
9
+ is "run every test method within a transaction." In the context of rspec-rails,
10
+ it means "run every example within a transaction."
11
+
12
+ The idea is to start each example with a clean database, create whatever data
13
+ is necessary for that example, and then remove that data by simply rolling back
14
+ the transaction at the end of the example.
15
+
16
+ ### Disabling transactions
17
+
18
+ If you prefer to manage the data yourself, or using another tool like
19
+ [database_cleaner](https://github.com/bmabey/database_cleaner) to do it for you,
20
+ simply tell RSpec to tell Rails not to manage transactions:
21
+
22
+ RSpec.configure do |config|
23
+ config.use_transactional_fixtures = false
24
+ end
25
+
26
+ ### Data created in `before(:each)` are rolled back
27
+
28
+ Any data you create in a `before(:each)` hook will be rolled back at the end of
29
+ the example. This is a good thing because it means that each example is
30
+ isolated from state that would otherwise be left around by the examples that
31
+ already ran. For example:
32
+
33
+ describe Widget do
34
+ before(:each) do
35
+ @widget = Widget.create
36
+ end
37
+
38
+ it "does something" do
39
+ @widget.should do_something
40
+ end
41
+
42
+ it "does something else" do
43
+ @widget.should do_something_else
44
+ end
45
+ end
46
+
47
+ The `@widget` is recreated in each of the two examples above, so each example
48
+ has a different object, _and_ the underlying data is rolled back so the data
49
+ backing the `@widget` in each example is new.
50
+
51
+ ### Data created in `before(:all)` are _not_ rolled back
52
+
53
+ `before(:all)` hooks are invoked before the transaction is opened. You can use
54
+ this to speed things up by creating data once before any example in a group is
55
+ run, however, this introduces a number of complications and you should only do
56
+ this if you have a firm grasp of the implications. Here are a couple of
57
+ guidelines:
58
+
59
+ 1. Be sure to clean up any data in an `after(:all)` hook:
60
+
61
+ before(:all) do
62
+ @widget = Widget.create!
63
+ end
64
+
65
+ after(:all) do
66
+ @widget.destroy
67
+ end
68
+
69
+ If you don't do that, you'll leave data lying around that will eventually
70
+ interfere with other examples.
71
+
72
+ 2. Reload the object in a `before(:each)` hook.
73
+
74
+ before(:all) do
75
+ @widget = Widget.create!
76
+ end
77
+
78
+ before(:each) do
79
+ @widget.reload
80
+ end
81
+
82
+ Even though database updates in each example will be rolled back, the
83
+ object won't _know_ about those rollbacks so the object and its backing
84
+ data can easily get out of sync.
@@ -0,0 +1,57 @@
1
+ Controller specs wrap Rails controller tests, which expose a few different ways
2
+ to access cookies:
3
+
4
+ @request.cookies['key']
5
+ @response.cookies['key']
6
+ cookies['key']
7
+
8
+ rails-3.0.x and 3.1 handle these slightly differently, so to avoid confusion, we recommend
9
+ the following guidelines:
10
+
11
+ ### Recommended guidelines for rails-3.0.0 to 3.1.0
12
+
13
+ * Access cookies through the `request` and `response` objects in the spec.
14
+ * Use `request.cookies` before the action to set up state.
15
+ * Use `response.cookies` after the action to specify outcomes.
16
+ * Use the `cookies` object in the controller action.
17
+ * Use String keys.
18
+
19
+ <pre>
20
+ # spec
21
+ request.cookies['foo'] = 'bar'
22
+ get :some_action
23
+ response.cookies['foo'].should eq('modified bar')
24
+
25
+ # controller
26
+ def some_action
27
+ cookies['foo'] = "modified #{cookies['foo']}"
28
+ end
29
+ </pre>
30
+
31
+ #### Why use Strings instead of Symbols?
32
+
33
+ The `cookies` objects in the spec come from Rack, and do not support
34
+ indifferent access (i.e. `:foo` and `"foo"` are different keys). The `cookies`
35
+ object in the controller _does_ support indifferent access, which is a bit
36
+ confusing.
37
+
38
+ This changed in rails-3.1, so you _can_ use symbol keys, but we recommend
39
+ sticking with string keys for consistency.
40
+
41
+ #### Why not use the `cookies` method?
42
+
43
+ The `cookies` method combines the `request` and `response` cookies. This can
44
+ lead to confusion when setting cookies in the example in order to set up state
45
+ for the controller action.
46
+
47
+ # does not work in rails 3.0.0 > 3.1.0
48
+ cookies['foo'] = 'bar' # this is not visible in the controller
49
+ get :some_action
50
+
51
+ ### Future versions of Rails
52
+
53
+ There is code in the master branch in rails that makes cookie access more
54
+ consistent so you can use the same `cookies` object before and after the action,
55
+ and you can use String or Symbol keys. We'll update these docs accordingly when
56
+ that is released.
57
+
@@ -1,109 +1,152 @@
1
1
  Feature: anonymous controller
2
2
 
3
3
  Use the `controller` method to define an anonymous controller derived from
4
- ApplicationController, or any other base controller. This is useful for
5
- specifying behavior like global error handling.
4
+ `ApplicationController`. This is useful for specifying behavior like global
5
+ error handling.
6
+
7
+ To specify a different base class, you can pass the class explicitly to the
8
+ controller method:
9
+
10
+ controller(BaseController)
11
+
12
+ You can also configure RSpec to use the described class:
13
+
14
+ RSpec.configure do |c|
15
+ c.infer_base_class_for_anonymous_controllers = true
16
+ end
17
+
18
+ describe BaseController do
19
+ controller { ... }
20
+ # ^^ creates an anonymous subclass of `BaseController`
6
21
 
7
22
  Scenario: specify error handling in ApplicationController
8
23
  Given a file named "spec/controllers/application_controller_spec.rb" with:
9
- """
10
- require "spec_helper"
24
+ """
25
+ require "spec_helper"
11
26
 
12
- class ApplicationController < ActionController::Base
13
- class AccessDenied < StandardError; end
27
+ class ApplicationController < ActionController::Base
28
+ class AccessDenied < StandardError; end
14
29
 
15
- rescue_from AccessDenied, :with => :access_denied
30
+ rescue_from AccessDenied, :with => :access_denied
16
31
 
17
- private
32
+ private
18
33
 
19
- def access_denied
20
- redirect_to "/401.html"
34
+ def access_denied
35
+ redirect_to "/401.html"
36
+ end
21
37
  end
22
- end
23
38
 
24
- describe ApplicationController do
25
- controller do
26
- def index
27
- raise ApplicationController::AccessDenied
39
+ describe ApplicationController do
40
+ controller do
41
+ def index
42
+ raise ApplicationController::AccessDenied
43
+ end
28
44
  end
29
- end
30
45
 
31
- describe "handling AccessDenied exceptions" do
32
- it "redirects to the /401.html page" do
33
- get :index
34
- response.should redirect_to("/401.html")
46
+ describe "handling AccessDenied exceptions" do
47
+ it "redirects to the /401.html page" do
48
+ get :index
49
+ response.should redirect_to("/401.html")
50
+ end
35
51
  end
36
52
  end
37
- end
38
- """
53
+ """
39
54
  When I run `rspec spec`
40
55
  Then the examples should all pass
41
56
 
42
57
  Scenario: specify error handling in subclass of ApplicationController
43
58
  Given a file named "spec/controllers/application_controller_subclass_spec.rb" with:
44
- """
45
- require "spec_helper"
59
+ """
60
+ require "spec_helper"
46
61
 
47
- class ApplicationController < ActionController::Base
48
- class AccessDenied < StandardError; end
49
- end
62
+ class ApplicationController < ActionController::Base
63
+ class AccessDenied < StandardError; end
64
+ end
50
65
 
51
- class ApplicationControllerSubclass < ApplicationController
66
+ class ApplicationControllerSubclass < ApplicationController
52
67
 
53
- rescue_from ApplicationController::AccessDenied, :with => :access_denied
68
+ rescue_from ApplicationController::AccessDenied, :with => :access_denied
54
69
 
55
70
  private
56
71
 
57
- def access_denied
58
- redirect_to "/401.html"
72
+ def access_denied
73
+ redirect_to "/401.html"
74
+ end
59
75
  end
60
- end
61
76
 
62
- describe ApplicationControllerSubclass do
63
- controller(ApplicationControllerSubclass) do
64
- def index
65
- raise ApplicationController::AccessDenied
77
+ describe ApplicationControllerSubclass do
78
+ controller(ApplicationControllerSubclass) do
79
+ def index
80
+ raise ApplicationController::AccessDenied
81
+ end
82
+ end
83
+
84
+ describe "handling AccessDenied exceptions" do
85
+ it "redirects to the /401.html page" do
86
+ get :index
87
+ response.should redirect_to("/401.html")
88
+ end
66
89
  end
67
90
  end
91
+ """
92
+ When I run `rspec spec`
93
+ Then the examples should all pass
68
94
 
69
- describe "handling AccessDenied exceptions" do
70
- it "redirects to the /401.html page" do
71
- get :index
72
- response.should redirect_to("/401.html")
95
+ Scenario: infer base class from the described class
96
+ Given a file named "spec/controllers/base_class_can_be_inferred_spec.rb" with:
97
+ """
98
+ require "spec_helper"
99
+
100
+ RSpec.configure do |c|
101
+ c.infer_base_class_for_anonymous_controllers = true
102
+ end
103
+
104
+ class ApplicationController < ActionController::Base; end
105
+
106
+ class ApplicationControllerSubclass < ApplicationController; end
107
+
108
+ describe ApplicationControllerSubclass do
109
+ controller do
110
+ def index
111
+ render :text => "Hello World"
112
+ end
113
+ end
114
+
115
+ it "creates an anonymous controller derived from ApplicationControllerSubclass" do
116
+ controller.should be_a_kind_of(ApplicationControllerSubclass)
73
117
  end
74
118
  end
75
- end
76
- """
119
+ """
77
120
  When I run `rspec spec`
78
121
  Then the examples should all pass
79
122
 
80
- Scenario: regression with ApplicationController around_filters
123
+ Scenario: invoke around filter in base class
81
124
  Given a file named "spec/controllers/application_controller_around_filter_spec.rb" with:
82
- """
83
- require "spec_helper"
125
+ """
126
+ require "spec_helper"
84
127
 
85
- class ApplicationController < ActionController::Base
86
- around_filter :some_around_filter
128
+ class ApplicationController < ActionController::Base
129
+ around_filter :an_around_filter
87
130
 
88
- def some_around_filter
89
- @callback_invoked = true
90
- yield
131
+ def an_around_filter
132
+ @callback_invoked = true
133
+ yield
134
+ end
91
135
  end
92
- end
93
136
 
94
- describe ApplicationController do
95
- controller do
96
- def index
97
- render :nothing => true
137
+ describe ApplicationController do
138
+ controller do
139
+ def index
140
+ render :nothing => true
141
+ end
98
142
  end
99
- end
100
143
 
101
- it "invokes the callback" do
102
- get :index
144
+ it "invokes the callback" do
145
+ get :index
103
146
 
104
- assigns[:callback_invoked].should be_true
147
+ assigns[:callback_invoked].should be_true
148
+ end
105
149
  end
106
- end
107
- """
150
+ """
108
151
  When I run `rspec spec`
109
152
  Then the examples should all pass
@@ -0,0 +1,75 @@
1
+ Feature: bypass rescue
2
+
3
+ Use `bypass_rescue` to bypass both Rails' default handling of errors in
4
+ controller actions, and any custom handling declared with a `rescue_from`
5
+ statement.
6
+
7
+ This lets you specify details of the exception being raised, regardless of
8
+ how it might be handled upstream.
9
+
10
+ Background:
11
+ Given a file named "spec/controllers/gadgets_controller_spec_context.rb" with:
12
+ """
13
+ class AccessDenied < StandardError; end
14
+
15
+ class ApplicationController < ActionController::Base
16
+ rescue_from AccessDenied, :with => :access_denied
17
+
18
+ private
19
+
20
+ def access_denied
21
+ redirect_to "/401.html"
22
+ end
23
+ end
24
+ """
25
+
26
+ Scenario: standard exception handling using `rescue_from`
27
+ Given a file named "spec/controllers/gadgets_controller_spec.rb" with:
28
+ """
29
+ require "spec_helper"
30
+
31
+ require 'controllers/gadgets_controller_spec_context'
32
+
33
+ describe GadgetsController do
34
+ before do
35
+ def controller.index
36
+ raise AccessDenied
37
+ end
38
+ end
39
+
40
+ describe "index" do
41
+ it "redirects to the /401.html page" do
42
+ get :index
43
+ response.should redirect_to("/401.html")
44
+ end
45
+ end
46
+ end
47
+ """
48
+ When I run `rspec spec/controllers/gadgets_controller_spec.rb`
49
+ Then the examples should all pass
50
+
51
+ Scenario: bypass `rescue_from` handling with `bypass_rescue`
52
+ Given a file named "spec/controllers/gadgets_controller_spec.rb" with:
53
+ """
54
+ require "spec_helper"
55
+
56
+ require 'controllers/gadgets_controller_spec_context'
57
+
58
+ describe GadgetsController do
59
+ before do
60
+ def controller.index
61
+ raise AccessDenied
62
+ end
63
+ end
64
+
65
+ describe "index" do
66
+ it "raises AccessDenied" do
67
+ bypass_rescue
68
+ expect { get :index }.to raise_error(AccessDenied)
69
+ end
70
+ end
71
+ end
72
+ """
73
+ When I run `rspec spec/controllers/gadgets_controller_spec.rb`
74
+ Then the examples should all pass
75
+