rspec-rails 2.11.4 → 2.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Capybara.md +2 -2
- data/Changelog.md +25 -1
- data/README.md +61 -25
- data/features/controller_specs/anonymous_controller.feature +25 -25
- data/features/controller_specs/bypass_rescue.feature +4 -4
- data/features/controller_specs/controller_spec.feature +4 -4
- data/features/controller_specs/isolation_from_views.feature +13 -13
- data/features/controller_specs/render_views.feature +11 -11
- data/features/feature_specs/feature_spec.feature +34 -0
- data/features/helper_specs/helper_spec.feature +10 -10
- data/features/mailer_specs/url_helpers.feature +7 -7
- data/features/matchers/new_record_matcher.feature +20 -7
- data/features/matchers/redirect_to_matcher.feature +6 -6
- data/features/matchers/relation_match_array.feature +8 -6
- data/features/matchers/render_template_matcher.feature +25 -4
- data/features/mocks/mock_model.feature +21 -21
- data/features/mocks/stub_model.feature +8 -8
- data/features/model_specs/errors_on.feature +25 -7
- data/features/model_specs/transactional_examples.feature +13 -13
- data/features/request_specs/request_spec.feature +8 -8
- data/features/routing_specs/be_routable_matcher.feature +10 -10
- data/features/routing_specs/named_routes.feature +3 -3
- data/features/routing_specs/route_to_matcher.feature +17 -17
- data/features/view_specs/inferred_controller_path.feature +7 -6
- data/features/view_specs/stub_template.feature +5 -5
- data/features/view_specs/view_spec.feature +50 -18
- data/lib/autotest/rails_rspec2.rb +1 -1
- data/lib/generators/rspec.rb +6 -0
- data/lib/generators/rspec/controller/templates/controller_spec.rb +2 -0
- data/lib/generators/rspec/helper/templates/helper_spec.rb +2 -0
- data/lib/generators/rspec/mailer/templates/mailer_spec.rb +2 -0
- data/lib/generators/rspec/model/templates/model_spec.rb +2 -0
- data/lib/generators/rspec/observer/templates/observer_spec.rb +2 -0
- data/lib/generators/rspec/scaffold/scaffold_generator.rb +37 -3
- data/lib/generators/rspec/scaffold/templates/controller_spec.rb +9 -7
- data/lib/generators/rspec/scaffold/templates/routing_spec.rb +2 -0
- data/lib/rspec/rails/example.rb +5 -1
- data/lib/rspec/rails/example/feature_example_group.rb +30 -0
- data/lib/rspec/rails/example/view_example_group.rb +23 -12
- data/lib/rspec/rails/extensions.rb +1 -0
- data/lib/rspec/rails/extensions/active_record/base.rb +5 -3
- data/lib/rspec/rails/extensions/active_record/proxy.rb +17 -0
- data/lib/rspec/rails/matchers/be_new_record.rb +8 -0
- data/lib/rspec/rails/tasks/rspec.rake +1 -2
- data/lib/rspec/rails/vendor/capybara.rb +2 -8
- data/lib/rspec/rails/version.rb +1 -1
- data/spec/autotest/rails_rspec2_spec.rb +4 -4
- data/spec/generators/rspec/model/model_generator_spec.rb +1 -1
- data/spec/generators/rspec/scaffold/scaffold_generator_spec.rb +8 -0
- data/spec/rspec/rails/example/feature_example_group_spec.rb +56 -0
- data/spec/rspec/rails/example/view_example_group_spec.rb +7 -1
- data/spec/rspec/rails/matchers/be_new_record_spec.rb +16 -2
- data/spec/rspec/rails/matchers/has_spec.rb +29 -0
- data/spec/rspec/rails/matchers/relation_match_array_spec.rb +18 -7
- metadata +66 -10
@@ -9,7 +9,7 @@ Feature: bypass rescue
|
|
9
9
|
|
10
10
|
Background:
|
11
11
|
Given a file named "spec/controllers/gadgets_controller_spec_context.rb" with:
|
12
|
-
"""
|
12
|
+
"""ruby
|
13
13
|
class AccessDenied < StandardError; end
|
14
14
|
|
15
15
|
class ApplicationController < ActionController::Base
|
@@ -25,7 +25,7 @@ Feature: bypass rescue
|
|
25
25
|
|
26
26
|
Scenario: standard exception handling using `rescue_from`
|
27
27
|
Given a file named "spec/controllers/gadgets_controller_spec.rb" with:
|
28
|
-
"""
|
28
|
+
"""ruby
|
29
29
|
require "spec_helper"
|
30
30
|
|
31
31
|
require 'controllers/gadgets_controller_spec_context'
|
@@ -40,7 +40,7 @@ Feature: bypass rescue
|
|
40
40
|
describe "index" do
|
41
41
|
it "redirects to the /401.html page" do
|
42
42
|
get :index
|
43
|
-
response.
|
43
|
+
expect(response).to redirect_to("/401.html")
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -50,7 +50,7 @@ Feature: bypass rescue
|
|
50
50
|
|
51
51
|
Scenario: bypass `rescue_from` handling with `bypass_rescue`
|
52
52
|
Given a file named "spec/controllers/gadgets_controller_spec.rb" with:
|
53
|
-
"""
|
53
|
+
"""ruby
|
54
54
|
require "spec_helper"
|
55
55
|
|
56
56
|
require 'controllers/gadgets_controller_spec_context'
|
@@ -2,14 +2,14 @@ Feature: controller spec
|
|
2
2
|
|
3
3
|
Scenario: simple passing example
|
4
4
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
5
|
-
"""
|
5
|
+
"""ruby
|
6
6
|
require "spec_helper"
|
7
7
|
|
8
8
|
describe WidgetsController do
|
9
9
|
describe "GET index" do
|
10
10
|
it "has a 200 status code" do
|
11
11
|
get :index
|
12
|
-
response.code.
|
12
|
+
expect(response.code).to eq("200")
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -19,10 +19,10 @@ Feature: controller spec
|
|
19
19
|
|
20
20
|
Scenario: controller is exposed to global before hooks
|
21
21
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
22
|
-
"""
|
22
|
+
"""ruby
|
23
23
|
require "spec_helper"
|
24
24
|
|
25
|
-
RSpec.configure {|c| c.before { controller.
|
25
|
+
RSpec.configure {|c| c.before { expect(controller).not_to be_nil }}
|
26
26
|
|
27
27
|
describe WidgetsController do
|
28
28
|
describe "GET index" do
|
@@ -9,20 +9,20 @@ Feature: views are stubbed by default
|
|
9
9
|
|
10
10
|
Scenario: expect template that is rendered by controller action (passes)
|
11
11
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
12
|
-
"""
|
12
|
+
"""ruby
|
13
13
|
require "spec_helper"
|
14
14
|
|
15
15
|
describe WidgetsController do
|
16
16
|
describe "index" do
|
17
17
|
it "renders the index template" do
|
18
18
|
get :index
|
19
|
-
response.
|
20
|
-
response.body.
|
19
|
+
expect(response).to render_template("index")
|
20
|
+
expect(response.body).to eq ""
|
21
21
|
end
|
22
22
|
it "renders the widgets/index template" do
|
23
23
|
get :index
|
24
|
-
response.
|
25
|
-
response.body.
|
24
|
+
expect(response).to render_template("widgets/index")
|
25
|
+
expect(response.body).to eq ""
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -32,14 +32,14 @@ Feature: views are stubbed by default
|
|
32
32
|
|
33
33
|
Scenario: expect template that is not rendered by controller action (fails)
|
34
34
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
35
|
-
"""
|
35
|
+
"""ruby
|
36
36
|
require "spec_helper"
|
37
37
|
|
38
38
|
describe WidgetsController do
|
39
39
|
describe "index" do
|
40
40
|
it "renders the 'new' template" do
|
41
41
|
get :index
|
42
|
-
response.
|
42
|
+
expect(response).to render_template("new")
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -49,7 +49,7 @@ Feature: views are stubbed by default
|
|
49
49
|
|
50
50
|
Scenario: expect empty templates to render when view path is changed at runtime (passes)
|
51
51
|
Given a file named "spec/controllers/things_controller_spec.rb" with:
|
52
|
-
"""
|
52
|
+
"""ruby
|
53
53
|
require "spec_helper"
|
54
54
|
|
55
55
|
describe ThingsController do
|
@@ -58,8 +58,8 @@ Feature: views are stubbed by default
|
|
58
58
|
controller.prepend_view_path 'app/views'
|
59
59
|
controller.append_view_path 'app/views'
|
60
60
|
get :custom_action
|
61
|
-
response.
|
62
|
-
response.body.
|
61
|
+
expect(response).to render_template("custom_action")
|
62
|
+
expect(response.body).to eq ""
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -69,7 +69,7 @@ Feature: views are stubbed by default
|
|
69
69
|
|
70
70
|
Scenario: expect template to render the real template with render_views when view path is changed at runtime
|
71
71
|
Given a file named "spec/controllers/things_controller_spec.rb" with:
|
72
|
-
"""
|
72
|
+
"""ruby
|
73
73
|
require "spec_helper"
|
74
74
|
|
75
75
|
describe ThingsController do
|
@@ -78,8 +78,8 @@ Feature: views are stubbed by default
|
|
78
78
|
it "renders the real custom_action template" do
|
79
79
|
controller.prepend_view_path 'app/views'
|
80
80
|
get :custom_action
|
81
|
-
response.
|
82
|
-
response.body.
|
81
|
+
expect(response).to render_template("custom_action")
|
82
|
+
expect(response.body).to match(/template for a custom action/)
|
83
83
|
end
|
84
84
|
end
|
85
85
|
"""
|
@@ -5,7 +5,7 @@ Feature: render_views
|
|
5
5
|
|
6
6
|
Scenario: render_views directly in a single group
|
7
7
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
8
|
-
"""
|
8
|
+
"""ruby
|
9
9
|
require "spec_helper"
|
10
10
|
|
11
11
|
describe WidgetsController do
|
@@ -14,7 +14,7 @@ Feature: render_views
|
|
14
14
|
describe "GET index" do
|
15
15
|
it "says 'Listing widgets'" do
|
16
16
|
get :index
|
17
|
-
response.body.
|
17
|
+
expect(response.body).to match /Listing widgets/m
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -24,7 +24,7 @@ Feature: render_views
|
|
24
24
|
|
25
25
|
Scenario: render_views on and off in nested groups
|
26
26
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
27
|
-
"""
|
27
|
+
"""ruby
|
28
28
|
require "spec_helper"
|
29
29
|
|
30
30
|
describe WidgetsController do
|
@@ -34,7 +34,7 @@ Feature: render_views
|
|
34
34
|
describe "GET index" do
|
35
35
|
it "renders the actual template" do
|
36
36
|
get :index
|
37
|
-
response.body.
|
37
|
+
expect(response.body).to match /Listing widgets/m
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
@@ -44,7 +44,7 @@ Feature: render_views
|
|
44
44
|
describe "GET index" do
|
45
45
|
it "renders the RSpec generated template" do
|
46
46
|
get :index
|
47
|
-
response.body.
|
47
|
+
expect(response.body).to eq("")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -54,7 +54,7 @@ Feature: render_views
|
|
54
54
|
describe "GET index" do
|
55
55
|
it "renders the RSpec generated template" do
|
56
56
|
get :index
|
57
|
-
response.body.
|
57
|
+
expect(response.body).to eq("")
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -65,7 +65,7 @@ Feature: render_views
|
|
65
65
|
describe "GET index" do
|
66
66
|
it "renders the actual template" do
|
67
67
|
get :index
|
68
|
-
response.body.
|
68
|
+
expect(response.body).to match /Listing widgets/m
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -73,7 +73,7 @@ Feature: render_views
|
|
73
73
|
"""
|
74
74
|
When I run `rspec spec --order default --format documentation`
|
75
75
|
Then the output should contain:
|
76
|
-
"""
|
76
|
+
"""ruby
|
77
77
|
WidgetsController
|
78
78
|
with render_views
|
79
79
|
GET index
|
@@ -91,20 +91,20 @@ Feature: render_views
|
|
91
91
|
|
92
92
|
Scenario: render_views globally
|
93
93
|
Given a file named "spec/support/render_views.rb" with:
|
94
|
-
"""
|
94
|
+
"""ruby
|
95
95
|
RSpec.configure do |config|
|
96
96
|
config.render_views
|
97
97
|
end
|
98
98
|
"""
|
99
99
|
And a file named "spec/controllers/widgets_controller_spec.rb" with:
|
100
|
-
"""
|
100
|
+
"""ruby
|
101
101
|
require "spec_helper"
|
102
102
|
|
103
103
|
describe WidgetsController do
|
104
104
|
describe "GET index" do
|
105
105
|
it "renders the index template" do
|
106
106
|
get :index
|
107
|
-
response.body.
|
107
|
+
expect(response.body).to match /Listing widgets/m
|
108
108
|
end
|
109
109
|
end
|
110
110
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
Feature: feature spec
|
2
|
+
|
3
|
+
Feature specs are high-level tests meant to exercise slices of functionality
|
4
|
+
through an application. They should drive the application only via its
|
5
|
+
external interface, usually web pages.
|
6
|
+
|
7
|
+
Feature specs require the [capybara](http://github.com/jnicklas/capybara)
|
8
|
+
gem, version 2.0.0 or later. Refer to the [capybara API
|
9
|
+
documentation](http://rubydoc.info/github/jnicklas/capybara/master) for more
|
10
|
+
information on the methods and matchers that can be used in feature specs.
|
11
|
+
|
12
|
+
The `feature` and `scenario` DSL correspond to `describe` and `it`,
|
13
|
+
respectively. These methods are simply aliases that allow feature specs to
|
14
|
+
read more as [customer tests](http://c2.com/cgi/wiki?CustomerTest) and
|
15
|
+
[acceptance tests](http://c2.com/cgi/wiki?AcceptanceTest).
|
16
|
+
|
17
|
+
Scenario: specify creating a Widget by driving the application with capybara
|
18
|
+
Given a file named "spec/features/widget_management_spec.rb" with:
|
19
|
+
"""ruby
|
20
|
+
require "spec_helper"
|
21
|
+
|
22
|
+
feature "Widget management" do
|
23
|
+
scenario "User creates a new widget" do
|
24
|
+
visit "/widgets/new"
|
25
|
+
|
26
|
+
fill_in "Name", :with => "My Widget"
|
27
|
+
click_button "Create Widget"
|
28
|
+
|
29
|
+
expect(page).to have_text("Widget was successfully created.")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
"""
|
33
|
+
When I run `rspec spec/features/widget_management_spec.rb`
|
34
|
+
Then the example should pass
|
@@ -15,19 +15,19 @@ Feature: helper spec
|
|
15
15
|
|
16
16
|
Scenario: helper method that returns a value
|
17
17
|
Given a file named "spec/helpers/application_helper_spec.rb" with:
|
18
|
-
"""
|
18
|
+
"""ruby
|
19
19
|
require "spec_helper"
|
20
20
|
|
21
21
|
describe ApplicationHelper do
|
22
22
|
describe "#page_title" do
|
23
23
|
it "returns the default title" do
|
24
|
-
helper.page_title.
|
24
|
+
expect(helper.page_title).to eq("RSpec is your friend")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
28
|
"""
|
29
29
|
And a file named "app/helpers/application_helper.rb" with:
|
30
|
-
"""
|
30
|
+
"""ruby
|
31
31
|
module ApplicationHelper
|
32
32
|
def page_title
|
33
33
|
"RSpec is your friend"
|
@@ -39,20 +39,20 @@ Feature: helper spec
|
|
39
39
|
|
40
40
|
Scenario: helper method that accesses an instance variable
|
41
41
|
Given a file named "spec/helpers/application_helper_spec.rb" with:
|
42
|
-
"""
|
42
|
+
"""ruby
|
43
43
|
require "spec_helper"
|
44
44
|
|
45
45
|
describe ApplicationHelper do
|
46
46
|
describe "#page_title" do
|
47
47
|
it "returns the instance variable" do
|
48
48
|
assign(:title, "My Title")
|
49
|
-
helper.page_title.
|
49
|
+
expect(helper.page_title).to eql("My Title")
|
50
50
|
end
|
51
51
|
end
|
52
52
|
end
|
53
53
|
"""
|
54
54
|
And a file named "app/helpers/application_helper.rb" with:
|
55
|
-
"""
|
55
|
+
"""ruby
|
56
56
|
module ApplicationHelper
|
57
57
|
def page_title
|
58
58
|
@title || nil
|
@@ -64,20 +64,20 @@ Feature: helper spec
|
|
64
64
|
|
65
65
|
Scenario: application helper is included in helper object
|
66
66
|
Given a file named "spec/helpers/widgets_helper_spec.rb" with:
|
67
|
-
"""
|
67
|
+
"""ruby
|
68
68
|
require "spec_helper"
|
69
69
|
|
70
70
|
describe WidgetsHelper do
|
71
71
|
describe "#widget_title" do
|
72
72
|
it "includes the app name" do
|
73
73
|
assign(:title, "This Widget")
|
74
|
-
helper.widget_title.
|
74
|
+
expect(helper.widget_title).to eq("The App: This Widget")
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
78
|
"""
|
79
79
|
And a file named "app/helpers/application_helper.rb" with:
|
80
|
-
"""
|
80
|
+
"""ruby
|
81
81
|
module ApplicationHelper
|
82
82
|
def app_name
|
83
83
|
"The App"
|
@@ -85,7 +85,7 @@ Feature: helper spec
|
|
85
85
|
end
|
86
86
|
"""
|
87
87
|
And a file named "app/helpers/widgets_helper.rb" with:
|
88
|
-
"""
|
88
|
+
"""ruby
|
89
89
|
module WidgetsHelper
|
90
90
|
def widget_title
|
91
91
|
"#{app_name}: #{@title}"
|
@@ -2,16 +2,16 @@ Feature: URL helpers in mailer examples
|
|
2
2
|
|
3
3
|
Scenario: using URL helpers with default options
|
4
4
|
Given a file named "config/initializers/mailer_defaults.rb" with:
|
5
|
-
"""
|
5
|
+
"""ruby
|
6
6
|
Rails.configuration.action_mailer.default_url_options = { :host => 'example.com' }
|
7
7
|
"""
|
8
8
|
And a file named "spec/mailers/notifications_spec.rb" with:
|
9
|
-
"""
|
9
|
+
"""ruby
|
10
10
|
require 'spec_helper'
|
11
11
|
|
12
12
|
describe Notifications do
|
13
13
|
it 'should have access to URL helpers' do
|
14
|
-
|
14
|
+
expect { gadgets_url }.not_to raise_error
|
15
15
|
end
|
16
16
|
end
|
17
17
|
"""
|
@@ -20,17 +20,17 @@ Feature: URL helpers in mailer examples
|
|
20
20
|
|
21
21
|
Scenario: using URL helpers without default options
|
22
22
|
Given a file named "config/initializers/mailer_defaults.rb" with:
|
23
|
-
"""
|
23
|
+
"""ruby
|
24
24
|
# no default options
|
25
25
|
"""
|
26
26
|
And a file named "spec/mailers/notifications_spec.rb" with:
|
27
|
-
"""
|
27
|
+
"""ruby
|
28
28
|
require 'spec_helper'
|
29
29
|
|
30
30
|
describe Notifications do
|
31
31
|
it 'should have access to URL helpers' do
|
32
|
-
|
33
|
-
|
32
|
+
expect { gadgets_url :host => 'example.com' }.not_to raise_error
|
33
|
+
expect { gadgets_url }.to raise_error
|
34
34
|
end
|
35
35
|
end
|
36
36
|
"""
|
@@ -8,19 +8,32 @@ Feature: be_a_new matcher
|
|
8
8
|
|
9
9
|
Scenario: example spec with four be_a_new possibilities
|
10
10
|
Given a file named "spec/models/widget_spec.rb" with:
|
11
|
-
"""
|
11
|
+
"""ruby
|
12
12
|
require "spec_helper"
|
13
13
|
|
14
14
|
describe Widget do
|
15
15
|
context "when initialized" do
|
16
|
-
subject { Widget.new }
|
17
|
-
|
18
|
-
it
|
16
|
+
subject(:widget) { Widget.new }
|
17
|
+
|
18
|
+
it "is a new widget" do
|
19
|
+
expect(widget).to be_a_new(Widget)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "is not a new string" do
|
23
|
+
expect(widget).not_to be_a_new(String)
|
24
|
+
end
|
19
25
|
end
|
26
|
+
|
20
27
|
context "when saved" do
|
21
|
-
subject { Widget.create }
|
22
|
-
|
23
|
-
it
|
28
|
+
subject(:widget) { Widget.create }
|
29
|
+
|
30
|
+
it "is not a new widget" do
|
31
|
+
expect(widget).not_to be_a_new(Widget)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "is not a new string" do
|
35
|
+
expect(widget).not_to be_a_new(String)
|
36
|
+
end
|
24
37
|
end
|
25
38
|
end
|
26
39
|
"""
|
@@ -9,7 +9,7 @@ Feature: redirect_to matcher
|
|
9
9
|
|
10
10
|
Scenario: redirect_to with four possible options
|
11
11
|
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
|
12
|
-
"""
|
12
|
+
"""ruby
|
13
13
|
require "spec_helper"
|
14
14
|
|
15
15
|
describe WidgetsController do
|
@@ -18,20 +18,20 @@ Feature: redirect_to matcher
|
|
18
18
|
subject { post :create, :widget => { :name => "Foo" } }
|
19
19
|
|
20
20
|
it "redirects to widget_url(@widget)" do
|
21
|
-
subject.
|
21
|
+
expect(subject).to redirect_to(widget_url(assigns(:widget)))
|
22
22
|
end
|
23
23
|
|
24
24
|
it "redirects_to :action => :show" do
|
25
|
-
subject.
|
26
|
-
|
25
|
+
expect(subject).to redirect_to :action => :show,
|
26
|
+
:id => assigns(:widget).id
|
27
27
|
end
|
28
28
|
|
29
29
|
it "redirects_to(@widget)" do
|
30
|
-
subject.
|
30
|
+
expect(subject).to redirect_to(assigns(:widget))
|
31
31
|
end
|
32
32
|
|
33
33
|
it "redirects_to /widgets/:id" do
|
34
|
-
subject.
|
34
|
+
expect(subject).to redirect_to("/widgets/#{assigns(:widget).id}")
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|