rspec-rails 2.0.0.beta.22 → 2.6.0
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/.gitignore +10 -4
- data/.rspec +1 -0
- data/.travis.yml +10 -0
- data/History.md +1 -33
- data/License.txt +23 -0
- data/{README.markdown → README.md} +27 -7
- data/README_DEV.md +43 -0
- data/Rakefile +105 -35
- data/Thorfile +40 -0
- data/Upgrade.md +1 -0
- data/features/.nav +34 -0
- data/features/Autotest.md +24 -0
- data/features/Changelog.md +151 -0
- data/features/Generators.md +8 -0
- data/features/GettingStarted.md +84 -0
- data/features/README.md +58 -0
- data/features/Upgrade.md +117 -0
- data/features/controller_specs/README.md +45 -0
- data/features/controller_specs/anonymous_controller.feature +7 -7
- data/features/controller_specs/controller_spec.feature +18 -0
- data/features/controller_specs/isolation_from_views.feature +55 -8
- data/features/controller_specs/render_views.feature +63 -52
- data/features/helper_specs/helper_spec.feature +40 -6
- data/features/mailer_specs/url_helpers.feature +4 -4
- data/features/matchers/README.md +4 -0
- data/features/matchers/new_record_matcher.feature +6 -48
- data/features/matchers/redirect_to_matcher.feature +5 -6
- data/features/matchers/render_template_matcher.feature +13 -10
- data/features/mocks/mock_model.feature +29 -13
- data/features/mocks/stub_model.feature +4 -4
- data/features/model_specs/README.md +21 -0
- data/features/model_specs/errors_on.feature +2 -2
- data/features/model_specs/transactional_examples.feature +14 -9
- data/features/request_specs/request_spec.feature +49 -0
- data/features/routing_specs/README.md +17 -0
- data/features/{matchers → routing_specs}/be_routable_matcher.feature +25 -25
- data/features/routing_specs/named_routes.feature +18 -0
- data/features/routing_specs/route_to_matcher.feature +58 -0
- data/features/step_definitions/additional_cli_steps.rb +4 -0
- data/features/support/env.rb +14 -6
- data/features/view_specs/inferred_controller_path.feature +6 -6
- data/features/view_specs/stub_template.feature +51 -0
- data/features/view_specs/view_spec.feature +23 -42
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/base.rb +58 -0
- data/gemfiles/rails-3-0-stable +6 -0
- data/gemfiles/rails-3.0.0 +5 -0
- data/gemfiles/rails-3.0.1 +5 -0
- data/gemfiles/rails-3.0.2 +5 -0
- data/gemfiles/rails-3.0.3 +5 -0
- data/gemfiles/rails-3.0.4 +5 -0
- data/gemfiles/rails-3.0.5 +5 -0
- data/gemfiles/rails-3.0.6 +5 -0
- data/gemfiles/rails-3.0.7 +5 -0
- data/gemfiles/rails-3.1.0.beta1 +5 -0
- data/gemfiles/rails-master +7 -0
- data/lib/autotest/rails_rspec2.rb +1 -1
- data/lib/generators/rspec/controller/controller_generator.rb +4 -4
- data/lib/generators/rspec/helper/helper_generator.rb +3 -3
- data/lib/generators/rspec/install/install_generator.rb +0 -8
- data/lib/generators/rspec/integration/integration_generator.rb +15 -1
- data/lib/generators/rspec/integration/templates/request_spec.rb +7 -1
- data/lib/generators/rspec/mailer/mailer_generator.rb +2 -2
- data/lib/generators/rspec/model/model_generator.rb +1 -1
- data/lib/generators/rspec/observer/observer_generator.rb +1 -1
- data/lib/generators/rspec/scaffold/scaffold_generator.rb +40 -11
- data/lib/generators/rspec/scaffold/templates/controller_spec.rb +90 -58
- data/lib/generators/rspec/scaffold/templates/edit_spec.rb +15 -7
- data/lib/generators/rspec/scaffold/templates/index_spec.rb +7 -2
- data/lib/generators/rspec/scaffold/templates/new_spec.rb +14 -7
- data/lib/generators/rspec/scaffold/templates/routing_spec.rb +14 -14
- data/lib/generators/rspec/scaffold/templates/show_spec.rb +7 -2
- data/lib/generators/rspec/view/view_generator.rb +1 -1
- data/lib/rspec/rails/example/controller_example_group.rb +25 -34
- data/lib/rspec/rails/example/helper_example_group.rb +5 -11
- data/lib/rspec/rails/example/mailer_example_group.rb +0 -14
- data/lib/rspec/rails/example/model_example_group.rb +0 -4
- data/lib/rspec/rails/example/rails_example_group.rb +0 -2
- data/lib/rspec/rails/example/request_example_group.rb +5 -30
- data/lib/rspec/rails/example/routing_example_group.rb +3 -5
- data/lib/rspec/rails/example/view_example_group.rb +20 -11
- data/lib/rspec/rails/example.rb +31 -1
- data/lib/rspec/rails/extensions/active_record/base.rb +28 -32
- data/lib/rspec/rails/fixture_support.rb +1 -1
- data/lib/rspec/rails/matchers/be_new_record.rb +5 -0
- data/lib/rspec/rails/matchers/redirect_to.rb +6 -2
- data/lib/rspec/rails/matchers/render_template.rb +5 -1
- data/lib/rspec/rails/matchers/routing_matchers.rb +24 -3
- data/lib/rspec/rails/matchers.rb +1 -1
- data/lib/rspec/rails/mocks.rb +118 -79
- data/lib/rspec/rails/module_inclusion.rb +17 -0
- data/lib/rspec/rails/tasks/rspec.rake +1 -1
- data/lib/rspec/rails/vendor/capybara.rb +29 -0
- data/lib/rspec/rails/vendor/webrat.rb +33 -0
- data/lib/rspec/rails/version.rb +1 -1
- data/lib/rspec/rails/view_assigns.rb +23 -4
- data/lib/rspec/rails/view_rendering.rb +50 -13
- data/lib/rspec/rails.rb +7 -10
- data/lib/rspec-rails.rb +4 -2
- data/rspec-rails.gemspec +11 -39
- data/spec/autotest/rails_rspec2_spec.rb +25 -14
- data/spec/rspec/rails/configuration_spec.rb +26 -0
- data/spec/rspec/rails/deprecations_spec.rb +18 -0
- data/spec/rspec/rails/example/controller_example_group_spec.rb +47 -5
- data/spec/rspec/rails/example/helper_example_group_spec.rb +19 -1
- data/spec/rspec/rails/example/request_example_group_spec.rb +2 -0
- data/spec/rspec/rails/extensions/active_model/errors_on_spec.rb +23 -0
- data/spec/rspec/rails/extensions/active_record/records_spec.rb +9 -0
- data/spec/rspec/rails/matchers/be_new_record_spec.rb +17 -0
- data/spec/rspec/rails/matchers/be_routable_spec.rb +41 -0
- data/spec/rspec/rails/matchers/redirect_to_spec.rb +67 -8
- data/spec/rspec/rails/matchers/render_template_spec.rb +67 -10
- data/spec/rspec/rails/matchers/route_to_spec.rb +77 -31
- data/spec/rspec/rails/mocks/ar_classes.rb +17 -25
- data/spec/rspec/rails/mocks/mock_model_spec.rb +50 -13
- data/spec/rspec/rails/mocks/stub_model_spec.rb +121 -67
- data/spec/rspec/rails/view_rendering_spec.rb +105 -0
- data/spec/spec_helper.rb +0 -22
- data/spec/support/matchers.rb +9 -0
- data/templates/generate_stuff.rb +10 -2
- data/templates/run_specs.rb +2 -2
- metadata +141 -79
- data/Gemfile +0 -24
- data/Gotchas.markdown +0 -14
- data/Upgrade.markdown +0 -31
- data/autotest/discover.rb +0 -1
- data/features/README.markdown +0 -12
- data/features/controller_specs/readers.feature +0 -18
- data/features/routing_specs/access_to_named_routes.feature +0 -15
- data/lib/generators/rspec/install/templates/autotest/discover.rb +0 -2
- data/lib/rspec/rails/browser_simulators.rb +0 -30
- data/spec/rspec/rails/example/view_rendering_spec.rb +0 -110
- data/specs.watchr +0 -59
- data/templates/Gemfile +0 -18
|
@@ -13,51 +13,26 @@ module RSpec::Rails
|
|
|
13
13
|
# => delegates to assert_redirected_to(destination)
|
|
14
14
|
module RequestExampleGroup
|
|
15
15
|
extend ActiveSupport::Concern
|
|
16
|
-
extend RSpec::Rails::ModuleInclusion
|
|
17
|
-
|
|
18
16
|
include RSpec::Rails::RailsExampleGroup
|
|
19
|
-
|
|
20
17
|
include ActionDispatch::Integration::Runner
|
|
21
18
|
include ActionDispatch::Assertions
|
|
22
|
-
include RSpec::Rails::BrowserSimulators
|
|
23
|
-
|
|
24
|
-
webrat do
|
|
25
|
-
include Webrat::Matchers
|
|
26
|
-
include Webrat::Methods
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
capybara do
|
|
30
|
-
include Capybara
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
include RSpec::Rails::Matchers::RedirectTo
|
|
34
|
-
include RSpec::Rails::Matchers::RenderTemplate
|
|
35
|
-
include ActionController::TemplateAssertions
|
|
36
19
|
|
|
37
20
|
module InstanceMethods
|
|
38
21
|
def app
|
|
39
22
|
::Rails.application
|
|
40
23
|
end
|
|
41
|
-
|
|
42
|
-
def last_response
|
|
43
|
-
response
|
|
44
|
-
end
|
|
45
24
|
end
|
|
46
25
|
|
|
26
|
+
include RSpec::Rails::Matchers::RedirectTo
|
|
27
|
+
include RSpec::Rails::Matchers::RenderTemplate
|
|
28
|
+
include ActionController::TemplateAssertions
|
|
29
|
+
|
|
47
30
|
included do
|
|
48
31
|
metadata[:type] = :request
|
|
49
32
|
|
|
50
33
|
before do
|
|
51
|
-
@
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
webrat do
|
|
55
|
-
Webrat.configure do |config|
|
|
56
|
-
config.mode = :rack
|
|
57
|
-
end
|
|
34
|
+
@routes = ::Rails.application.routes
|
|
58
35
|
end
|
|
59
36
|
end
|
|
60
|
-
|
|
61
|
-
RSpec.configure &include_self_when_dir_matches('spec','requests')
|
|
62
37
|
end
|
|
63
38
|
end
|
|
@@ -3,16 +3,16 @@ require "action_dispatch/testing/assertions/routing"
|
|
|
3
3
|
module RSpec::Rails
|
|
4
4
|
module RoutingExampleGroup
|
|
5
5
|
extend ActiveSupport::Concern
|
|
6
|
-
extend RSpec::Rails::ModuleInclusion
|
|
7
|
-
|
|
8
6
|
include RSpec::Rails::RailsExampleGroup
|
|
9
|
-
|
|
10
7
|
include ActionDispatch::Assertions::RoutingAssertions
|
|
11
8
|
include RSpec::Rails::Matchers::RoutingMatchers
|
|
9
|
+
include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers
|
|
12
10
|
|
|
13
11
|
module InstanceMethods
|
|
14
12
|
attr_reader :routes
|
|
15
13
|
|
|
14
|
+
private
|
|
15
|
+
|
|
16
16
|
def method_missing(m, *args, &block)
|
|
17
17
|
routes.url_helpers.respond_to?(m) ? routes.url_helpers.send(m, *args) : super
|
|
18
18
|
end
|
|
@@ -25,7 +25,5 @@ module RSpec::Rails
|
|
|
25
25
|
@routes = ::Rails.application.routes
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
|
-
|
|
29
|
-
RSpec.configure &include_self_when_dir_matches('spec','routing')
|
|
30
28
|
end
|
|
31
29
|
end
|
|
@@ -19,21 +19,14 @@ module RSpec::Rails
|
|
|
19
19
|
# end
|
|
20
20
|
module ViewExampleGroup
|
|
21
21
|
extend ActiveSupport::Concern
|
|
22
|
-
extend RSpec::Rails::ModuleInclusion
|
|
23
|
-
|
|
24
22
|
include RSpec::Rails::RailsExampleGroup
|
|
25
23
|
include ActionView::TestCase::Behavior
|
|
26
24
|
include RSpec::Rails::ViewAssigns
|
|
27
25
|
include RSpec::Rails::Matchers::RenderTemplate
|
|
28
|
-
include RSpec::Rails::BrowserSimulators
|
|
29
|
-
|
|
30
|
-
webrat do
|
|
31
|
-
include Webrat::Matchers
|
|
32
|
-
end
|
|
33
26
|
|
|
34
27
|
module ClassMethods
|
|
35
28
|
def _default_helper
|
|
36
|
-
base = metadata[:
|
|
29
|
+
base = metadata[:example_group][:description].split('/').first
|
|
37
30
|
(base.camelize + 'Helper').constantize if base
|
|
38
31
|
rescue NameError
|
|
39
32
|
nil
|
|
@@ -85,6 +78,18 @@ module RSpec::Rails
|
|
|
85
78
|
_view
|
|
86
79
|
end
|
|
87
80
|
|
|
81
|
+
# Simulates the presence of a template on the file system by adding a
|
|
82
|
+
# Rails' FixtureResolver to the front of the view_paths list. Designed to
|
|
83
|
+
# help isolate view examples from partials rendered by the view template
|
|
84
|
+
# that is the subject of the example.
|
|
85
|
+
#
|
|
86
|
+
# == Example
|
|
87
|
+
#
|
|
88
|
+
# stub_template("widgets/_widget.html.erb" => "This content.")
|
|
89
|
+
def stub_template(hash)
|
|
90
|
+
view.view_paths.unshift(ActionView::FixtureResolver.new(hash))
|
|
91
|
+
end
|
|
92
|
+
|
|
88
93
|
# Provides access to the params hash that will be available within the
|
|
89
94
|
# view:
|
|
90
95
|
#
|
|
@@ -137,13 +142,17 @@ module RSpec::Rails
|
|
|
137
142
|
|
|
138
143
|
before do
|
|
139
144
|
_include_controller_helpers
|
|
140
|
-
|
|
145
|
+
if view.lookup_context.respond_to?(:prefixes)
|
|
146
|
+
# rails 3.1
|
|
147
|
+
view.lookup_context.prefixes << _controller_path
|
|
148
|
+
else
|
|
149
|
+
# rails 3.0
|
|
150
|
+
controller.controller_path = _controller_path
|
|
151
|
+
end
|
|
141
152
|
controller.request.path_parameters["controller"] = _controller_path
|
|
142
153
|
controller.request.path_parameters["action"] = _inferred_action unless _inferred_action =~ /^_/
|
|
143
154
|
end
|
|
144
155
|
end
|
|
145
|
-
|
|
146
|
-
RSpec.configure &include_self_when_dir_matches('spec','views')
|
|
147
156
|
end
|
|
148
157
|
end
|
|
149
158
|
|
data/lib/rspec/rails/example.rb
CHANGED
|
@@ -5,4 +5,34 @@ require 'rspec/rails/example/helper_example_group'
|
|
|
5
5
|
require 'rspec/rails/example/view_example_group'
|
|
6
6
|
require 'rspec/rails/example/mailer_example_group'
|
|
7
7
|
require 'rspec/rails/example/routing_example_group'
|
|
8
|
-
require 'rspec/rails/example/model_example_group'
|
|
8
|
+
require 'rspec/rails/example/model_example_group'
|
|
9
|
+
|
|
10
|
+
RSpec::configure do |c|
|
|
11
|
+
def c.escaped_path(*parts)
|
|
12
|
+
Regexp.compile(parts.join('[\\\/]'))
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
c.include RSpec::Rails::ControllerExampleGroup, :type => :controller, :example_group => {
|
|
16
|
+
:file_path => c.escaped_path(%w[spec controllers])
|
|
17
|
+
}
|
|
18
|
+
c.include RSpec::Rails::HelperExampleGroup, :type => :helper, :example_group => {
|
|
19
|
+
:file_path => c.escaped_path(%w[spec helpers])
|
|
20
|
+
}
|
|
21
|
+
if defined?(RSpec::Rails::MailerExampleGroup)
|
|
22
|
+
c.include RSpec::Rails::MailerExampleGroup, :type => :mailer, :example_group => {
|
|
23
|
+
:file_path => c.escaped_path(%w[spec mailers])
|
|
24
|
+
}
|
|
25
|
+
end
|
|
26
|
+
c.include RSpec::Rails::ModelExampleGroup, :type => :model, :example_group => {
|
|
27
|
+
:file_path => c.escaped_path(%w[spec models])
|
|
28
|
+
}
|
|
29
|
+
c.include RSpec::Rails::RequestExampleGroup, :type => :request, :example_group => {
|
|
30
|
+
:file_path => c.escaped_path(%w[spec (requests|integration)])
|
|
31
|
+
}
|
|
32
|
+
c.include RSpec::Rails::RoutingExampleGroup, :type => :routing, :example_group => {
|
|
33
|
+
:file_path => c.escaped_path(%w[spec routing])
|
|
34
|
+
}
|
|
35
|
+
c.include RSpec::Rails::ViewExampleGroup, :type => :view, :example_group => {
|
|
36
|
+
:file_path => c.escaped_path(%w[spec views])
|
|
37
|
+
}
|
|
38
|
+
end
|
|
@@ -1,44 +1,40 @@
|
|
|
1
1
|
module RSpec
|
|
2
2
|
module Rails
|
|
3
|
-
if
|
|
3
|
+
if defined?(ActiveRecord)
|
|
4
4
|
module Extensions
|
|
5
5
|
module ActiveRecord
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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 <tt>should have</tt> 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[attribute]].flatten.compact
|
|
31
|
-
end
|
|
32
|
-
alias :error_on :errors_on
|
|
6
|
+
# :call-seq:
|
|
7
|
+
# ModelClass.should have(:no).records
|
|
8
|
+
# ModelClass.should have(1).record
|
|
9
|
+
# ModelClass.should have(n).records
|
|
10
|
+
#
|
|
11
|
+
# Extension to enhance <tt>should have</tt> on AR Model classes
|
|
12
|
+
def records
|
|
13
|
+
find(:all)
|
|
33
14
|
end
|
|
15
|
+
alias :record :records
|
|
34
16
|
end
|
|
35
|
-
end
|
|
36
17
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
18
|
+
class ::ActiveRecord::Base #:nodoc:
|
|
19
|
+
extend RSpec::Rails::Extensions::ActiveRecord
|
|
20
|
+
end
|
|
40
21
|
end
|
|
41
22
|
end
|
|
42
23
|
end
|
|
43
24
|
end
|
|
44
25
|
|
|
26
|
+
module ::ActiveModel::Validations
|
|
27
|
+
# :call-seq:
|
|
28
|
+
# model.should have(:no).errors_on(:attribute)
|
|
29
|
+
# model.should have(1).error_on(:attribute)
|
|
30
|
+
# model.should have(n).errors_on(:attribute)
|
|
31
|
+
#
|
|
32
|
+
# Extension to enhance <tt>should have</tt> on AR Model instances.
|
|
33
|
+
# Calls model.valid? in order to prepare the object's errors
|
|
34
|
+
# object.
|
|
35
|
+
def errors_on(attribute)
|
|
36
|
+
self.valid?
|
|
37
|
+
[self.errors[attribute]].flatten.compact
|
|
38
|
+
end
|
|
39
|
+
alias :error_on :errors_on
|
|
40
|
+
end
|
|
@@ -3,13 +3,17 @@ module RSpec::Rails::Matchers
|
|
|
3
3
|
extend RSpec::Matchers::DSL
|
|
4
4
|
|
|
5
5
|
matcher :redirect_to do |destination|
|
|
6
|
-
match_unless_raises
|
|
6
|
+
match_unless_raises ActiveSupport::TestCase::Assertion do |_|
|
|
7
7
|
assert_redirected_to destination
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
failure_message_for_should do
|
|
10
|
+
failure_message_for_should do |_|
|
|
11
11
|
rescued_exception.message
|
|
12
12
|
end
|
|
13
|
+
|
|
14
|
+
failure_message_for_should_not do |_|
|
|
15
|
+
"expected not to redirect to #{destination.inspect}, but did"
|
|
16
|
+
end
|
|
13
17
|
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
@@ -3,7 +3,7 @@ module RSpec::Rails::Matchers
|
|
|
3
3
|
extend RSpec::Matchers::DSL
|
|
4
4
|
|
|
5
5
|
matcher :render_template do |options, message|
|
|
6
|
-
match_unless_raises
|
|
6
|
+
match_unless_raises ActiveSupport::TestCase::Assertion do |_|
|
|
7
7
|
options = options.to_s if Symbol === options
|
|
8
8
|
assert_template options, message
|
|
9
9
|
end
|
|
@@ -11,6 +11,10 @@ module RSpec::Rails::Matchers
|
|
|
11
11
|
failure_message_for_should do
|
|
12
12
|
rescued_exception.message
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
failure_message_for_should_not do |_|
|
|
16
|
+
"expected not to render #{options.inspect}, but did"
|
|
17
|
+
end
|
|
14
18
|
end
|
|
15
19
|
end
|
|
16
20
|
end
|
|
@@ -2,10 +2,21 @@ module RSpec::Rails::Matchers
|
|
|
2
2
|
module RoutingMatchers
|
|
3
3
|
extend RSpec::Matchers::DSL
|
|
4
4
|
|
|
5
|
-
matcher :route_to do
|
|
6
|
-
match_unless_raises
|
|
5
|
+
matcher :route_to do |*route_options|
|
|
6
|
+
match_unless_raises ActiveSupport::TestCase::Assertion do |path|
|
|
7
7
|
assertion_path = { :method => path.keys.first, :path => path.values.first }
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
path, options = *route_options
|
|
10
|
+
|
|
11
|
+
if path.is_a?(String)
|
|
12
|
+
controller, action = path.split("#")
|
|
13
|
+
options ||= {}
|
|
14
|
+
options.merge!(:controller => controller, :action => action)
|
|
15
|
+
else
|
|
16
|
+
options = path
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
assert_recognizes(options, assertion_path)
|
|
9
20
|
end
|
|
10
21
|
|
|
11
22
|
failure_message_for_should do
|
|
@@ -24,5 +35,15 @@ module RSpec::Rails::Matchers
|
|
|
24
35
|
"expected #{path.inspect} not to be routable, but it routes to #{@routing_options.inspect}"
|
|
25
36
|
end
|
|
26
37
|
end
|
|
38
|
+
|
|
39
|
+
module RouteHelpers
|
|
40
|
+
|
|
41
|
+
%w(get post put delete options head).each do |method|
|
|
42
|
+
define_method method do |path|
|
|
43
|
+
{ method.to_sym => path }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
27
48
|
end
|
|
28
49
|
end
|
data/lib/rspec/rails/matchers.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'rspec/core/deprecation'
|
|
2
|
-
require 'rspec/core/backward_compatibility'
|
|
3
2
|
require 'rspec/matchers'
|
|
4
3
|
|
|
5
4
|
module RSpec::Rails
|
|
@@ -21,5 +20,6 @@ end
|
|
|
21
20
|
require 'rspec/rails/matchers/render_template'
|
|
22
21
|
require 'rspec/rails/matchers/redirect_to'
|
|
23
22
|
require 'rspec/rails/matchers/routing_matchers'
|
|
23
|
+
require 'rspec/rails/matchers/be_new_record'
|
|
24
24
|
require 'rspec/rails/matchers/be_a_new'
|
|
25
25
|
require 'rspec/rails/matchers/have_extension'
|
data/lib/rspec/rails/mocks.rb
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
require 'active_support/core_ext'
|
|
2
|
+
require 'active_model'
|
|
3
|
+
|
|
1
4
|
module RSpec
|
|
2
5
|
module Rails
|
|
3
6
|
|
|
@@ -5,39 +8,55 @@ module RSpec
|
|
|
5
8
|
|
|
6
9
|
module Mocks
|
|
7
10
|
|
|
8
|
-
module
|
|
9
|
-
def valid?
|
|
10
|
-
true
|
|
11
|
-
end
|
|
12
|
-
|
|
11
|
+
module ActiveModelInstanceMethods
|
|
13
12
|
def as_new_record
|
|
13
|
+
self.stub(:persisted?) { false }
|
|
14
14
|
self.stub(:id) { nil }
|
|
15
15
|
self
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def
|
|
19
|
-
|
|
18
|
+
def persisted?
|
|
19
|
+
true
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def
|
|
23
|
-
|
|
22
|
+
def respond_to?(message, include_private=false)
|
|
23
|
+
message.to_s =~ /_before_type_cast$/ ? false : super
|
|
24
24
|
end
|
|
25
|
+
end
|
|
25
26
|
|
|
27
|
+
module ActiveRecordInstanceMethods
|
|
26
28
|
def destroy
|
|
29
|
+
self.stub(:persisted?) { false }
|
|
27
30
|
self.stub(:id) { nil }
|
|
28
31
|
end
|
|
32
|
+
|
|
33
|
+
def [](key)
|
|
34
|
+
send(key)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def new_record?
|
|
38
|
+
!persisted?
|
|
39
|
+
end
|
|
29
40
|
end
|
|
30
41
|
|
|
31
|
-
# Creates a
|
|
32
|
-
#
|
|
33
|
-
# (via add_stubs) if +stubs+ is passed.
|
|
42
|
+
# Creates a test double representing +string_or_model_class+ with common
|
|
43
|
+
# ActiveModel methods stubbed out. Additional methods may be easily
|
|
44
|
+
# stubbed (via add_stubs) if +stubs+ is passed. This is most useful for
|
|
45
|
+
# impersonating models that don't exist yet.
|
|
34
46
|
#
|
|
35
|
-
#
|
|
47
|
+
# NOTE that only ActiveModel's methods, plus <tt>new_record?</tt>, are
|
|
48
|
+
# stubbed out implicitly. <tt>new_record?</tt> returns the inverse of
|
|
49
|
+
# <tt>persisted?</tt>, and is present only for compatibility with
|
|
50
|
+
# extension frameworks that have yet to update themselves to the
|
|
51
|
+
# ActiveModel API (which declares <tt>persisted?</tt>, not
|
|
52
|
+
# <tt>new_record?</tt>).
|
|
53
|
+
#
|
|
54
|
+
# +string_or_model_class+ can be any of:
|
|
36
55
|
#
|
|
37
56
|
# * A String representing a Class that does not exist
|
|
38
57
|
# * A String representing a Class that extends ActiveModel::Naming
|
|
39
58
|
# * A Class that extends ActiveModel::Naming
|
|
40
|
-
def mock_model(string_or_model_class,
|
|
59
|
+
def mock_model(string_or_model_class, stubs = {})
|
|
41
60
|
if String === string_or_model_class
|
|
42
61
|
if Object.const_defined?(string_or_model_class)
|
|
43
62
|
model_class = Object.const_get(string_or_model_class)
|
|
@@ -61,57 +80,72 @@ It received #{model_class.inspect}
|
|
|
61
80
|
EOM
|
|
62
81
|
end
|
|
63
82
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
83
|
+
stubs = stubs.reverse_merge(:id => next_id)
|
|
84
|
+
stubs = stubs.reverse_merge(:persisted? => !!stubs[:id])
|
|
85
|
+
stubs = stubs.reverse_merge(:destroyed? => false)
|
|
86
|
+
stubs = stubs.reverse_merge(:marked_for_destruction? => false)
|
|
87
|
+
stubs = stubs.reverse_merge(:blank? => false)
|
|
88
|
+
|
|
89
|
+
mock("#{model_class.name}_#{stubs[:id]}", stubs).tap do |m|
|
|
90
|
+
m.extend ActiveModelInstanceMethods
|
|
91
|
+
m.singleton_class.__send__ :include, ActiveModel::Conversion
|
|
92
|
+
m.singleton_class.__send__ :include, ActiveModel::Validations
|
|
93
|
+
if defined?(ActiveRecord)
|
|
94
|
+
m.extend ActiveRecordInstanceMethods
|
|
95
|
+
[:save, :update_attributes].each do |key|
|
|
96
|
+
if stubs[key] == false
|
|
97
|
+
m.errors.stub(:empty?) { false }
|
|
98
|
+
end
|
|
99
|
+
end
|
|
78
100
|
end
|
|
101
|
+
m.__send__(:__mock_proxy).instance_eval(<<-CODE, __FILE__, __LINE__)
|
|
102
|
+
def @object.is_a?(other)
|
|
103
|
+
#{model_class}.ancestors.include?(other)
|
|
104
|
+
end
|
|
105
|
+
def @object.kind_of?(other)
|
|
106
|
+
#{model_class}.ancestors.include?(other)
|
|
107
|
+
end
|
|
108
|
+
def @object.instance_of?(other)
|
|
109
|
+
other == #{model_class}
|
|
110
|
+
end
|
|
111
|
+
def @object.respond_to?(method_name, include_private=false)
|
|
112
|
+
#{model_class}.respond_to?(:column_names) && #{model_class}.column_names.include?(method_name.to_s) || super
|
|
113
|
+
end
|
|
114
|
+
def @object.class
|
|
115
|
+
#{model_class}
|
|
116
|
+
end
|
|
117
|
+
def @object.to_s
|
|
118
|
+
"#{model_class.name}_#{to_param}"
|
|
119
|
+
end
|
|
120
|
+
CODE
|
|
121
|
+
yield m if block_given?
|
|
79
122
|
end
|
|
80
|
-
m.stub(:errors) { errors }
|
|
81
|
-
m.__send__(:__mock_proxy).instance_eval(<<-CODE, __FILE__, __LINE__)
|
|
82
|
-
def @object.is_a?(other)
|
|
83
|
-
#{model_class}.ancestors.include?(other)
|
|
84
|
-
end
|
|
85
|
-
def @object.kind_of?(other)
|
|
86
|
-
#{model_class}.ancestors.include?(other)
|
|
87
|
-
end
|
|
88
|
-
def @object.instance_of?(other)
|
|
89
|
-
other == #{model_class}
|
|
90
|
-
end
|
|
91
|
-
def @object.respond_to?(method_name)
|
|
92
|
-
#{model_class}.respond_to?(:column_names) && #{model_class}.column_names.include?(method_name.to_s) || super
|
|
93
|
-
end
|
|
94
|
-
def @object.class
|
|
95
|
-
#{model_class}
|
|
96
|
-
end
|
|
97
|
-
def @object.to_s
|
|
98
|
-
"#{model_class.name}_#{id}"
|
|
99
|
-
end
|
|
100
|
-
CODE
|
|
101
|
-
yield m if block_given?
|
|
102
|
-
m
|
|
103
123
|
end
|
|
104
124
|
|
|
105
|
-
module
|
|
106
|
-
def
|
|
107
|
-
|
|
125
|
+
module ActiveModelStubExtensions
|
|
126
|
+
def as_new_record
|
|
127
|
+
self.stub(:persisted?) { false }
|
|
128
|
+
self.stub(:id) { nil }
|
|
129
|
+
self
|
|
108
130
|
end
|
|
109
|
-
|
|
110
|
-
|
|
131
|
+
|
|
132
|
+
def persisted?
|
|
133
|
+
true
|
|
111
134
|
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
module ActiveRecordStubExtensions
|
|
112
138
|
def as_new_record
|
|
113
139
|
self.__send__("#{self.class.primary_key}=", nil)
|
|
114
|
-
|
|
140
|
+
super
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def new_record?
|
|
144
|
+
!persisted?
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def connection
|
|
148
|
+
raise RSpec::Rails::IllegalDataAccessException.new("stubbed models are not allowed to access the database")
|
|
115
149
|
end
|
|
116
150
|
end
|
|
117
151
|
|
|
@@ -121,46 +155,51 @@ EOM
|
|
|
121
155
|
# stub_model(Model, hash_of_stubs)
|
|
122
156
|
# stub_model(Model, instance_variable_name, hash_of_stubs)
|
|
123
157
|
#
|
|
124
|
-
# Creates an instance of +Model+
|
|
125
|
-
#
|
|
126
|
-
#
|
|
127
|
-
# submitted values. If the model does not have a matching attribute, the
|
|
128
|
-
# key/value pair is assigned as a stub return value using RSpec's
|
|
129
|
-
# mocking/stubbing framework.
|
|
158
|
+
# Creates an instance of +Model+ with +to_param+ stubbed using a
|
|
159
|
+
# generated value that is unique to each object.. If +Model+ is an
|
|
160
|
+
# +ActiveRecord+ model, it is prohibited from accessing the database*.
|
|
130
161
|
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
162
|
+
# For each key in +hash_of_stubs+, if the model has a matching attribute
|
|
163
|
+
# (determined by asking it) are simply assigned the submitted values. If
|
|
164
|
+
# the model does not have a matching attribute, the key/value pair is
|
|
165
|
+
# assigned as a stub return value using RSpec's mocking/stubbing
|
|
166
|
+
# framework.
|
|
167
|
+
#
|
|
168
|
+
# <tt>persisted?</tt> is overridden to return the result of !id.nil?
|
|
169
|
+
# This means that by default persisted? will return true. If you want
|
|
133
170
|
# the object to behave as a new record, sending it +as_new_record+ will
|
|
134
171
|
# set the id to nil. You can also explicitly set :id => nil, in which
|
|
135
|
-
# case
|
|
172
|
+
# case persisted? will return false, but using +as_new_record+ makes the
|
|
136
173
|
# example a bit more descriptive.
|
|
137
174
|
#
|
|
138
175
|
# While you can use stub_model in any example (model, view, controller,
|
|
139
176
|
# helper), it is especially useful in view examples, which are
|
|
140
177
|
# inherently more state-based than interaction-based.
|
|
141
178
|
#
|
|
142
|
-
# == Database Independence
|
|
143
|
-
#
|
|
144
|
-
# +stub_model+ does not make your examples entirely
|
|
145
|
-
# database-independent. It does not stop the model class itself from
|
|
146
|
-
# loading up its columns from the database. It just prevents data access
|
|
147
|
-
# from the object itself. To completely decouple from the database, take
|
|
148
|
-
# a look at libraries like unit_record or NullDB.
|
|
149
|
-
#
|
|
150
179
|
# == Examples
|
|
151
180
|
#
|
|
152
181
|
# stub_model(Person)
|
|
153
182
|
# stub_model(Person).as_new_record
|
|
154
|
-
# stub_model(Person, :
|
|
183
|
+
# stub_model(Person, :to_param => 37)
|
|
155
184
|
# stub_model(Person) do |person|
|
|
156
185
|
# person.first_name = "David"
|
|
157
186
|
# end
|
|
158
187
|
def stub_model(model_class, stubs={})
|
|
159
|
-
primary_key = model_class.primary_key.to_sym
|
|
160
|
-
stubs = {primary_key => next_id}.merge(stubs)
|
|
161
188
|
model_class.new.tap do |m|
|
|
162
|
-
m.
|
|
163
|
-
|
|
189
|
+
m.extend ActiveModelStubExtensions
|
|
190
|
+
if defined?(ActiveRecord) && model_class < ActiveRecord::Base
|
|
191
|
+
m.extend ActiveRecordStubExtensions
|
|
192
|
+
primary_key = model_class.primary_key.to_sym
|
|
193
|
+
stubs = stubs.reverse_merge(primary_key => next_id)
|
|
194
|
+
stubs = stubs.reverse_merge(:persisted? => !!stubs[primary_key])
|
|
195
|
+
else
|
|
196
|
+
stubs = stubs.reverse_merge(:id => next_id)
|
|
197
|
+
stubs = stubs.reverse_merge(:persisted? => !!stubs[:id])
|
|
198
|
+
end
|
|
199
|
+
stubs = stubs.reverse_merge(:blank? => false)
|
|
200
|
+
stubs.each do |k,v|
|
|
201
|
+
m.__send__("#{k}=", stubs.delete(k)) if m.respond_to?("#{k}=")
|
|
202
|
+
end
|
|
164
203
|
m.stub(stubs)
|
|
165
204
|
yield m if block_given?
|
|
166
205
|
end
|
|
@@ -1,7 +1,24 @@
|
|
|
1
1
|
module RSpec::Rails
|
|
2
2
|
module ModuleInclusion
|
|
3
|
+
# Deprecated as of rspec-rails-2.4
|
|
4
|
+
# Will be removed from rspec-rails-3.0
|
|
5
|
+
#
|
|
6
|
+
# This was never intended to be a public API and is no longer needed
|
|
7
|
+
# internally. As it happens, there are a few blog posts citing its use, so
|
|
8
|
+
# I'm leaving it here, but deprecated.
|
|
3
9
|
def include_self_when_dir_matches(*path_parts)
|
|
10
|
+
instead = <<-INSTEAD
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
RSpec.configure do |c|
|
|
14
|
+
c.include self, :example_group => {
|
|
15
|
+
:file_path => /#{path_parts.join('\/')}/
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
INSTEAD
|
|
4
20
|
lambda do |c|
|
|
21
|
+
RSpec.deprecate('include_self_when_dir_matches', instead, 'rails-3.0')
|
|
5
22
|
c.include self, :example_group => {
|
|
6
23
|
:file_path => Regexp.compile(path_parts.join('[\\\/]'))
|
|
7
24
|
}
|
|
@@ -41,7 +41,7 @@ namespace :spec do
|
|
|
41
41
|
::CodeStatistics::TEST_TYPES << "Controller specs" if File.exist?('spec/controllers')
|
|
42
42
|
::CodeStatistics::TEST_TYPES << "Helper specs" if File.exist?('spec/helpers')
|
|
43
43
|
::CodeStatistics::TEST_TYPES << "Library specs" if File.exist?('spec/lib')
|
|
44
|
-
::CodeStatistics::TEST_TYPES << "Mailer specs" if File.exist?('spec/
|
|
44
|
+
::CodeStatistics::TEST_TYPES << "Mailer specs" if File.exist?('spec/mailers')
|
|
45
45
|
::CodeStatistics::TEST_TYPES << "Routing specs" if File.exist?('spec/routing')
|
|
46
46
|
::CodeStatistics::TEST_TYPES << "Request specs" if File.exist?('spec/requests')
|
|
47
47
|
end
|