rspec-rails 2.8.0.rc1 → 2.8.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/License.txt +22 -0
  2. data/README.md +253 -119
  3. data/features/README.md +0 -2
  4. data/features/Upgrade.md +1 -1
  5. data/lib/generators/rspec/install/templates/spec/spec_helper.rb +1 -1
  6. data/lib/generators/rspec/integration/integration_generator.rb +1 -0
  7. data/lib/generators/rspec/scaffold/scaffold_generator.rb +1 -0
  8. data/lib/generators/rspec/scaffold/templates/controller_spec.rb +23 -16
  9. data/lib/rspec/rails/adapters.rb +25 -13
  10. data/lib/rspec/rails/example/controller_example_group.rb +65 -122
  11. data/lib/rspec/rails/example/helper_example_group.rb +11 -36
  12. data/lib/rspec/rails/example/mailer_example_group.rb +1 -1
  13. data/lib/rspec/rails/example/rails_example_group.rb +5 -0
  14. data/lib/rspec/rails/example/request_example_group.rb +4 -19
  15. data/lib/rspec/rails/example/routing_example_group.rb +8 -10
  16. data/lib/rspec/rails/example/view_example_group.rb +21 -35
  17. data/lib/rspec/rails/extensions/active_record/base.rb +15 -12
  18. data/lib/rspec/rails/fixture_support.rb +1 -1
  19. data/lib/rspec/rails/matchers/be_a_new.rb +63 -30
  20. data/lib/rspec/rails/matchers/be_new_record.rb +18 -3
  21. data/lib/rspec/rails/matchers/have_extension.rb +26 -14
  22. data/lib/rspec/rails/matchers/redirect_to.rb +26 -7
  23. data/lib/rspec/rails/matchers/relation_match_array.rb +1 -1
  24. data/lib/rspec/rails/matchers/render_template.rb +27 -8
  25. data/lib/rspec/rails/matchers/routing_matchers.rb +72 -24
  26. data/lib/rspec/rails/mocks.rb +42 -34
  27. data/lib/rspec/rails/module_inclusion.rb +2 -1
  28. data/lib/rspec/rails/version.rb +1 -1
  29. data/lib/rspec/rails/view_assigns.rb +31 -34
  30. data/lib/rspec/rails/view_rendering.rb +10 -6
  31. data/spec/rspec/rails/example/controller_example_group_spec.rb +2 -2
  32. data/spec/rspec/rails/example/helper_example_group_spec.rb +5 -5
  33. data/spec/rspec/rails/example/view_example_group_spec.rb +5 -5
  34. data/spec/rspec/rails/matchers/be_a_new_spec.rb +2 -0
  35. data/spec/rspec/rails/matchers/be_new_record_spec.rb +2 -0
  36. data/spec/rspec/rails/matchers/render_template_spec.rb +3 -5
  37. data/spec/rspec/rails/mocks/mock_model_spec.rb +28 -0
  38. metadata +22 -19
@@ -1,30 +1,6 @@
1
1
  require 'rspec/rails/view_assigns'
2
2
 
3
3
  module RSpec::Rails
4
- # Extends ActionView::TestCase::Behavior
5
- #
6
- # == Examples
7
- #
8
- # describe RoleBasedDisplayHelper do
9
- # describe "display_for" do
10
- # context "given the role of the current user" do
11
- # it "yields to the block" do
12
- # helper.stub(:current_user) { double(:roles => ['admin'] }
13
- # text = helper.display_for('admin') { "this text" }
14
- # text.should eq("this text")
15
- # end
16
- # end
17
- #
18
- # context "given a different role that that of the current user" do
19
- # it "renders an empty String" do
20
- # helper.stub(:current_user) { double(:roles => ['manager'] }
21
- # text = helper.display_for('admin') { "this text" }
22
- # text.should eq("")
23
- # end
24
- # end
25
- # end
26
- # end
27
- #
28
4
  module HelperExampleGroup
29
5
  extend ActiveSupport::Concern
30
6
  include RSpec::Rails::RailsExampleGroup
@@ -32,26 +8,25 @@ module RSpec::Rails
32
8
  include RSpec::Rails::ViewAssigns
33
9
 
34
10
  module ClassMethods
11
+ # @api private
35
12
  def determine_default_helper_class(ignore)
36
- describes
13
+ described_class
37
14
  end
38
15
  end
39
16
 
40
- module InstanceMethods
41
- # Returns an instance of ActionView::Base with the helper being specified
42
- # mixed in, along with any of the built-in rails helpers.
43
- def helper
44
- _view.tap do |v|
45
- v.extend(ApplicationHelper) if defined?(ApplicationHelper)
46
- v.assign(view_assigns)
47
- end
17
+ # Returns an instance of ActionView::Base with the helper being specified
18
+ # mixed in, along with any of the built-in rails helpers.
19
+ def helper
20
+ _view.tap do |v|
21
+ v.extend(ApplicationHelper) if defined?(ApplicationHelper)
22
+ v.assign(view_assigns)
48
23
  end
24
+ end
49
25
 
50
26
  private
51
27
 
52
- def _controller_path
53
- example.example_group.describes.to_s.sub(/Helper/,'').underscore
54
- end
28
+ def _controller_path
29
+ example.example_group.described_class.to_s.sub(/Helper/,'').underscore
55
30
  end
56
31
 
57
32
  included do
@@ -14,7 +14,7 @@ if defined?(ActionMailer)
14
14
 
15
15
  module ClassMethods
16
16
  def mailer_class
17
- describes
17
+ described_class
18
18
  end
19
19
  end
20
20
  end
@@ -1,9 +1,14 @@
1
+ # Temporary workaround to resolve circular dependency between rspec-rails' spec
2
+ # suite and ammeter.
3
+ require 'rspec/rails/matchers'
4
+
1
5
  module RSpec
2
6
  module Rails
3
7
  module RailsExampleGroup
4
8
  extend ActiveSupport::Concern
5
9
  include RSpec::Rails::SetupAndTeardownAdapter
6
10
  include RSpec::Rails::TestUnitAssertionAdapter
11
+ include RSpec::Rails::Matchers
7
12
  end
8
13
  end
9
14
  end
@@ -1,32 +1,17 @@
1
1
  module RSpec::Rails
2
- # Extends ActionDispatch::Integration::Runner to work with RSpec.
3
- #
4
- # == Matchers
5
- #
6
- # In addition to the stock matchers from rspec-expectations, request
7
- # specs add these matchers, which delegate to rails' assertions:
8
- #
9
- # response.should render_template(*args)
10
- # => delegates to assert_template(*args)
11
- #
12
- # response.should redirect_to(destination)
13
- # => delegates to assert_redirected_to(destination)
14
2
  module RequestExampleGroup
15
3
  extend ActiveSupport::Concern
16
4
  include RSpec::Rails::RailsExampleGroup
17
5
  include ActionDispatch::Integration::Runner
18
6
  include ActionDispatch::Assertions
19
-
20
- module InstanceMethods
21
- def app
22
- ::Rails.application
23
- end
24
- end
25
-
26
7
  include RSpec::Rails::Matchers::RedirectTo
27
8
  include RSpec::Rails::Matchers::RenderTemplate
28
9
  include ActionController::TemplateAssertions
29
10
 
11
+ def app
12
+ ::Rails.application
13
+ end
14
+
30
15
  included do
31
16
  metadata[:type] = :request
32
17
 
@@ -8,16 +8,6 @@ module RSpec::Rails
8
8
  include RSpec::Rails::Matchers::RoutingMatchers
9
9
  include RSpec::Rails::Matchers::RoutingMatchers::RouteHelpers
10
10
 
11
- module InstanceMethods
12
- attr_reader :routes
13
-
14
- private
15
-
16
- def method_missing(m, *args, &block)
17
- routes.url_helpers.respond_to?(m) ? routes.url_helpers.send(m, *args) : super
18
- end
19
- end
20
-
21
11
  included do
22
12
  metadata[:type] = :routing
23
13
 
@@ -25,5 +15,13 @@ module RSpec::Rails
25
15
  @routes = ::Rails.application.routes
26
16
  end
27
17
  end
18
+
19
+ attr_reader :routes
20
+
21
+ private
22
+
23
+ def method_missing(m, *args, &block)
24
+ routes.url_helpers.respond_to?(m) ? routes.url_helpers.send(m, *args) : super
25
+ end
28
26
  end
29
27
  end
@@ -1,22 +1,6 @@
1
1
  require 'rspec/rails/view_assigns'
2
2
 
3
3
  module RSpec::Rails
4
- # Extends ActionView::TestCase::Behavior
5
- #
6
- # == Examples
7
- #
8
- # describe "widgets/index.html.erb" do
9
- # it "renders the @widgets" do
10
- # widgets = [
11
- # stub_model(Widget, :name => "Foo"),
12
- # stub_model(Widget, :name => "Bar")
13
- # ]
14
- # assign(:widgets, widgets)
15
- # render
16
- # rendered.should contain("Foo")
17
- # rendered.should contain("Bar")
18
- # end
19
- # end
20
4
  module ViewExampleGroup
21
5
  extend ActiveSupport::Concern
22
6
  include RSpec::Rails::RailsExampleGroup
@@ -39,7 +23,7 @@ module RSpec::Rails
39
23
  end
40
24
  end
41
25
 
42
- module InstanceMethods
26
+ module ExampleMethods
43
27
  # @overload render
44
28
  # @overload render({:partial => path_to_file})
45
29
  # @overload render({:partial => path_to_file}, {... locals ...})
@@ -51,27 +35,27 @@ module RSpec::Rails
51
35
  # The only addition is that you can call render with no arguments, and RSpec
52
36
  # will pass the top level description to render:
53
37
  #
54
- # describe "widgets/new.html.erb" do
55
- # it "shows all the widgets" do
56
- # render # => view.render(:file => "widgets/new.html.erb")
57
- # ...
38
+ # describe "widgets/new.html.erb" do
39
+ # it "shows all the widgets" do
40
+ # render # => view.render(:file => "widgets/new.html.erb")
41
+ # # ...
42
+ # end
58
43
  # end
59
- # end
60
44
  def render(options={}, local_assigns={}, &block)
61
45
  options = {:template => _default_file_to_render} if Hash === options and options.empty?
62
46
  super(options, local_assigns, &block)
63
47
  end
64
48
 
65
- # The instance of +ActionView::Base+ that is used to render the template.
66
- # Use this to stub methods _before_ calling +render+.
49
+ # The instance of `ActionView::Base` that is used to render the template.
50
+ # Use this to stub methods _before_ calling `render`.
67
51
  #
68
- # describe "widgets/new.html.erb" do
69
- # it "shows all the widgets" do
70
- # view.stub(:foo) { "foo" }
71
- # render
72
- # ...
52
+ # describe "widgets/new.html.erb" do
53
+ # it "shows all the widgets" do
54
+ # view.stub(:foo) { "foo" }
55
+ # render
56
+ # # ...
57
+ # end
73
58
  # end
74
- # end
75
59
  def view
76
60
  _view
77
61
  end
@@ -81,9 +65,9 @@ module RSpec::Rails
81
65
  # help isolate view examples from partials rendered by the view template
82
66
  # that is the subject of the example.
83
67
  #
84
- # == Example
68
+ # @example
85
69
  #
86
- # stub_template("widgets/_widget.html.erb" => "This content.")
70
+ # stub_template("widgets/_widget.html.erb" => "This content.")
87
71
  def stub_template(hash)
88
72
  view.view_paths.unshift(ActionView::FixtureResolver.new(hash))
89
73
  end
@@ -91,18 +75,18 @@ module RSpec::Rails
91
75
  # Provides access to the params hash that will be available within the
92
76
  # view:
93
77
  #
94
- # params[:foo] = 'bar'
78
+ # params[:foo] = 'bar'
95
79
  def params
96
80
  controller.params
97
81
  end
98
82
 
99
- # @deprecated # use +view+ instead.
83
+ # @deprecated Use `view` instead.
100
84
  def template
101
85
  RSpec.deprecate("template","view")
102
86
  view
103
87
  end
104
88
 
105
- # @deprecated # use +rendered+ instead.
89
+ # @deprecated Use `rendered` instead.
106
90
  def response
107
91
  RSpec.deprecate("response", "rendered")
108
92
  rendered
@@ -135,6 +119,8 @@ module RSpec::Rails
135
119
  end
136
120
 
137
121
  included do
122
+ include ExampleMethods
123
+
138
124
  metadata[:type] = :view
139
125
  helper *_default_helpers
140
126
 
@@ -3,12 +3,13 @@ module RSpec
3
3
  if defined?(ActiveRecord)
4
4
  module Extensions
5
5
  module ActiveRecord
6
- # Extension to enhance +should have+ on AR Model classes
6
+ # Extension to enhance `should have` on AR Model classes
7
7
  #
8
- # == Examples
9
- # ModelClass.should have(:no).records
10
- # ModelClass.should have(1).record
11
- # ModelClass.should have(n).records
8
+ # @example
9
+ #
10
+ # ModelClass.should have(:no).records
11
+ # ModelClass.should have(1).record
12
+ # ModelClass.should have(n).records
12
13
  def records
13
14
  find(:all)
14
15
  end
@@ -24,16 +25,18 @@ module RSpec
24
25
  end
25
26
 
26
27
  module ::ActiveModel::Validations
27
- # Extension to enhance <tt>should have</tt> on AR Model instances.
28
- # Calls model.valid? in order to prepare the object's errors
29
- # object.
28
+ # Extension to enhance `should have` on AR Model instances. Calls
29
+ # model.valid? in order to prepare the object's errors object.
30
+ #
31
+ # You can also use this to specify the content of the error messages.
30
32
  #
31
- # == Examples
33
+ # @example
32
34
  #
33
- # model.should have(:no).errors_on(:attribute)
34
- # model.should have(1).error_on(:attribute)
35
- # model.should have(n).errors_on(:attribute)
35
+ # model.should have(:no).errors_on(:attribute)
36
+ # model.should have(1).error_on(:attribute)
37
+ # model.should have(n).errors_on(:attribute)
36
38
  #
39
+ # model.errors_on(:attribute).should include("can't be blank")
37
40
  def errors_on(attribute)
38
41
  self.valid?
39
42
  [self.errors[attribute]].flatten.compact
@@ -1,6 +1,6 @@
1
1
  module RSpec
2
2
  module Rails
3
- if defined?(ActiveRecord)
3
+ if defined?(ActiveRecord::TestFixtures)
4
4
  module FixtureSupport
5
5
  extend ActiveSupport::Concern
6
6
 
@@ -1,40 +1,73 @@
1
- RSpec::Matchers.define :be_a_new do |model_klass|
2
- match do |actual|
3
- actual.is_a?(model_klass) && actual.new_record? && attributes_match?(actual)
4
- end
1
+ module RSpec::Rails::Matchers
2
+ class BeANew
3
+ include RSpec::Matchers::BaseMatcher
5
4
 
6
- chain :with do |expected_attributes|
7
- attributes.merge!(expected_attributes)
8
- end
5
+ # @api private
6
+ def matches?(actual)
7
+ super
8
+ actual.is_a?(expected) && actual.new_record? && attributes_match?(actual)
9
+ end
9
10
 
10
- failure_message_for_should do |actual|
11
- [].tap do |message|
12
- unless actual.is_a?(model_klass) && actual.new_record?
13
- message << "expected #{actual.inspect} to be a new #{model_klass.inspect}"
14
- end
15
- unless attributes_match?(actual)
16
- if unmatched_attributes.size > 1
17
- message << "attributes #{unmatched_attributes.inspect} were not set on #{actual.inspect}"
18
- else
19
- message << "attribute #{unmatched_attributes.inspect} was not set on #{actual.inspect}"
11
+ # Use this to specify the specific attributes to match on the new record.
12
+ #
13
+ # @example
14
+ #
15
+ # it "assigns a new Thing with the submitted attributes" do
16
+ # post :create, :thing => { :name => "Illegal Value" }
17
+ # assigns(:thing).should be_a_new(Thing).with(:name => nil)
18
+ # end
19
+ def with(expected_attributes)
20
+ attributes.merge!(expected_attributes)
21
+ self
22
+ end
23
+
24
+ # @api private
25
+ def failure_message_for_should
26
+ [].tap do |message|
27
+ unless actual.is_a?(expected) && actual.new_record?
28
+ message << "expected #{actual.inspect} to be a new #{expected.inspect}"
20
29
  end
21
- end
22
- end.join(' and ')
23
- end
30
+ unless attributes_match?(actual)
31
+ if unmatched_attributes.size > 1
32
+ message << "attributes #{unmatched_attributes.inspect} were not set on #{actual.inspect}"
33
+ else
34
+ message << "attribute #{unmatched_attributes.inspect} was not set on #{actual.inspect}"
35
+ end
36
+ end
37
+ end.join(' and ')
38
+ end
24
39
 
25
- def attributes
26
- @attributes ||= {}
27
- end
40
+ private
28
41
 
29
- def attributes_match?(actual)
30
- attributes.stringify_keys.all? do |key, value|
31
- actual.attributes[key].eql?(value)
42
+ def attributes
43
+ @attributes ||= {}
32
44
  end
33
- end
34
45
 
35
- def unmatched_attributes
36
- attributes.stringify_keys.reject do |key, value|
37
- actual.attributes[key].eql?(value)
46
+ def attributes_match?(actual)
47
+ attributes.stringify_keys.all? do |key, value|
48
+ actual.attributes[key].eql?(value)
49
+ end
38
50
  end
51
+
52
+ def unmatched_attributes
53
+ attributes.stringify_keys.reject do |key, value|
54
+ actual.attributes[key].eql?(value)
55
+ end
56
+ end
57
+ end
58
+
59
+ # Passes if actual is an instance of `model_class` and returns `false` for
60
+ # `persisted?`. Typically used to specify instance variables assigned to
61
+ # views by controller actions
62
+ #
63
+ # @example
64
+ #
65
+ # get :new
66
+ # assigns(:thing).should be_a_new(Thing)
67
+ #
68
+ # post :create, :thing => { :name => "Illegal Value" }
69
+ # assigns(:thing).should be_a_new(Thing).with(:name => nil)
70
+ def be_a_new(model_class)
71
+ BeANew.new(model_class)
39
72
  end
40
73
  end
@@ -1,5 +1,20 @@
1
- RSpec::Matchers.define :be_new_record do
2
- match do |actual|
3
- !actual.persisted?
1
+ module RSpec::Rails::Matchers
2
+ class BeANewRecord
3
+ include RSpec::Matchers::BaseMatcher
4
+
5
+ # @api private
6
+ def matches?(actual)
7
+ !actual.persisted?
8
+ end
9
+ end
10
+
11
+ # Passes if actual returns `false` for `persisted?`.
12
+ #
13
+ # @example
14
+ #
15
+ # get :new
16
+ # assigns(:thing).should be_new_record
17
+ def be_new_record
18
+ BeANewRecord.new
4
19
  end
5
20
  end