rspec-rails 2.6.1 → 2.7.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +5 -5
- data/features/Transactions.md +84 -0
- data/features/controller_specs/Cookies.md +57 -0
- data/features/controller_specs/anonymous_controller.feature +104 -61
- data/features/controller_specs/bypass_rescue.feature +75 -0
- data/features/matchers/relation_match_array.feature +20 -0
- data/features/mocks/mock_model.feature +6 -6
- data/features/support/env.rb +2 -2
- data/features/view_specs/view_spec.feature +2 -8
- data/lib/autotest/rails_rspec2.rb +1 -1
- data/lib/generators/rspec/controller/templates/controller_spec.rb +1 -1
- data/lib/generators/rspec/install/templates/spec/spec_helper.rb +6 -0
- data/lib/generators/rspec/scaffold/templates/controller_spec.rb +6 -6
- data/lib/generators/rspec/view/templates/view_spec.rb +1 -1
- data/lib/rspec/rails/example/controller_example_group.rb +19 -1
- data/lib/rspec/rails/fixture_support.rb +11 -0
- data/lib/rspec/rails/matchers.rb +1 -0
- data/lib/rspec/rails/matchers/relation_match_array.rb +3 -0
- data/lib/rspec/rails/matchers/routing_matchers.rb +16 -14
- data/lib/rspec/rails/mocks.rb +12 -7
- data/lib/rspec/rails/version.rb +1 -1
- data/spec/generators/rspec/controller/controller_generator_spec.rb +86 -0
- data/spec/generators/rspec/helper/helper_generator_spec.rb +30 -0
- data/spec/generators/rspec/install/install_generator_spec.rb +18 -0
- data/spec/generators/rspec/integration/integration_generator_spec.rb +44 -0
- data/spec/generators/rspec/mailer/mailer_generator_spec.rb +48 -0
- data/spec/generators/rspec/model/model_generator_spec.rb +52 -0
- data/spec/generators/rspec/observer/observer_generator_spec.rb +21 -0
- data/spec/generators/rspec/scaffold/scaffold_generator_spec.rb +113 -0
- data/spec/generators/rspec/view/view_generator_spec.rb +41 -0
- data/spec/rspec/rails/example/controller_example_group_spec.rb +39 -3
- data/spec/rspec/rails/matchers/relation_match_array_spec.rb +19 -0
- data/spec/rspec/rails/matchers/route_to_spec.rb +25 -3
- data/spec/rspec/rails/mocks/mock_model_spec.rb +62 -2
- data/spec/rspec/rails/mocks/stub_model_spec.rb +0 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/{rspec/rails/mocks → support}/ar_classes.rb +5 -2
- metadata +102 -99
- data/.document +0 -5
- data/.gitignore +0 -14
- data/.rspec +0 -1
- data/.travis.yml +0 -11
- data/History.md +0 -1
- data/License.txt +0 -23
- data/README_DEV.md +0 -43
- data/Rakefile +0 -152
- data/Thorfile +0 -45
- data/Upgrade.md +0 -1
- data/cucumber.yml +0 -3
- data/features/.nav +0 -35
- data/features/Changelog.md +0 -162
- data/gemfiles/.bundle/config +0 -2
- data/gemfiles/base.rb +0 -60
- data/gemfiles/rails-3-0-stable +0 -6
- data/gemfiles/rails-3.0.0 +0 -5
- data/gemfiles/rails-3.0.1 +0 -5
- data/gemfiles/rails-3.0.2 +0 -5
- data/gemfiles/rails-3.0.3 +0 -5
- data/gemfiles/rails-3.0.4 +0 -5
- data/gemfiles/rails-3.0.5 +0 -5
- data/gemfiles/rails-3.0.6 +0 -5
- data/gemfiles/rails-3.0.7 +0 -5
- data/gemfiles/rails-3.1.0.rc1 +0 -5
- data/gemfiles/rails-master +0 -5
- data/rspec-rails.gemspec +0 -34
- data/templates/generate_stuff.rb +0 -21
- 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
|
-
[](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.
|
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
|
-
|
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
|
5
|
-
|
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
|
-
|
24
|
+
"""
|
25
|
+
require "spec_helper"
|
11
26
|
|
12
|
-
|
13
|
-
|
27
|
+
class ApplicationController < ActionController::Base
|
28
|
+
class AccessDenied < StandardError; end
|
14
29
|
|
15
|
-
|
30
|
+
rescue_from AccessDenied, :with => :access_denied
|
16
31
|
|
17
|
-
|
32
|
+
private
|
18
33
|
|
19
|
-
|
20
|
-
|
34
|
+
def access_denied
|
35
|
+
redirect_to "/401.html"
|
36
|
+
end
|
21
37
|
end
|
22
|
-
end
|
23
38
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
39
|
+
describe ApplicationController do
|
40
|
+
controller do
|
41
|
+
def index
|
42
|
+
raise ApplicationController::AccessDenied
|
43
|
+
end
|
28
44
|
end
|
29
|
-
end
|
30
45
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
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
|
-
|
59
|
+
"""
|
60
|
+
require "spec_helper"
|
46
61
|
|
47
|
-
|
48
|
-
|
49
|
-
|
62
|
+
class ApplicationController < ActionController::Base
|
63
|
+
class AccessDenied < StandardError; end
|
64
|
+
end
|
50
65
|
|
51
|
-
|
66
|
+
class ApplicationControllerSubclass < ApplicationController
|
52
67
|
|
53
|
-
|
68
|
+
rescue_from ApplicationController::AccessDenied, :with => :access_denied
|
54
69
|
|
55
70
|
private
|
56
71
|
|
57
|
-
|
58
|
-
|
72
|
+
def access_denied
|
73
|
+
redirect_to "/401.html"
|
74
|
+
end
|
59
75
|
end
|
60
|
-
end
|
61
76
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
-
|
76
|
-
"""
|
119
|
+
"""
|
77
120
|
When I run `rspec spec`
|
78
121
|
Then the examples should all pass
|
79
122
|
|
80
|
-
Scenario:
|
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
|
-
|
125
|
+
"""
|
126
|
+
require "spec_helper"
|
84
127
|
|
85
|
-
|
86
|
-
|
128
|
+
class ApplicationController < ActionController::Base
|
129
|
+
around_filter :an_around_filter
|
87
130
|
|
88
|
-
|
89
|
-
|
90
|
-
|
131
|
+
def an_around_filter
|
132
|
+
@callback_invoked = true
|
133
|
+
yield
|
134
|
+
end
|
91
135
|
end
|
92
|
-
end
|
93
136
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
137
|
+
describe ApplicationController do
|
138
|
+
controller do
|
139
|
+
def index
|
140
|
+
render :nothing => true
|
141
|
+
end
|
98
142
|
end
|
99
|
-
end
|
100
143
|
|
101
|
-
|
102
|
-
|
144
|
+
it "invokes the callback" do
|
145
|
+
get :index
|
103
146
|
|
104
|
-
|
147
|
+
assigns[:callback_invoked].should be_true
|
148
|
+
end
|
105
149
|
end
|
106
|
-
|
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
|
+
|