shoulda-matchers 2.6.2 → 2.7.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +6 -1
  3. data/Gemfile +1 -1
  4. data/Gemfile.lock +26 -22
  5. data/NEWS.md +52 -1
  6. data/README.md +8 -6
  7. data/Rakefile +1 -1
  8. data/doc_config/gh-pages/index.html.erb +1 -1
  9. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +1 -1
  10. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +26 -0
  11. data/features/rails_integration.feature +18 -3
  12. data/features/step_definitions/rails_steps.rb +21 -3
  13. data/gemfiles/3.0.gemfile +1 -1
  14. data/gemfiles/3.0.gemfile.lock +30 -24
  15. data/gemfiles/3.1.gemfile +1 -1
  16. data/gemfiles/3.1.gemfile.lock +32 -26
  17. data/gemfiles/3.1_1.9.2.gemfile +1 -1
  18. data/gemfiles/3.1_1.9.2.gemfile.lock +22 -19
  19. data/gemfiles/3.2.gemfile +1 -1
  20. data/gemfiles/3.2.gemfile.lock +32 -26
  21. data/gemfiles/3.2_1.9.2.gemfile +1 -1
  22. data/gemfiles/3.2_1.9.2.gemfile.lock +8 -8
  23. data/gemfiles/4.0.0.gemfile +2 -2
  24. data/gemfiles/4.0.0.gemfile.lock +35 -31
  25. data/gemfiles/4.0.1.gemfile +2 -2
  26. data/gemfiles/4.0.1.gemfile.lock +24 -22
  27. data/gemfiles/4.1.gemfile +1 -1
  28. data/gemfiles/4.1.gemfile.lock +26 -22
  29. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +10 -3
  30. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +24 -6
  31. data/lib/shoulda/matchers/active_model.rb +2 -2
  32. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +1 -1
  33. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +1 -1
  34. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +5 -3
  35. data/lib/shoulda/matchers/active_model/{ensure_exclusion_of_matcher.rb → validate_exclusion_of_matcher.rb} +20 -10
  36. data/lib/shoulda/matchers/active_model/{ensure_inclusion_of_matcher.rb → validate_inclusion_of_matcher.rb} +52 -28
  37. data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +28 -19
  38. data/lib/shoulda/matchers/active_record.rb +18 -16
  39. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +4 -4
  40. data/lib/shoulda/matchers/active_record/association_matcher.rb +17 -12
  41. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +86 -0
  42. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +19 -0
  43. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +2 -1
  44. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +138 -0
  45. data/lib/shoulda/matchers/independent.rb +3 -2
  46. data/lib/shoulda/matchers/independent/{delegate_matcher.rb → delegate_method_matcher.rb} +69 -49
  47. data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +37 -0
  48. data/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
  49. data/lib/shoulda/matchers/version.rb +1 -1
  50. data/lib/shoulda/matchers/warn.rb +30 -2
  51. data/spec/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +6 -0
  52. data/spec/shoulda/matchers/action_controller/set_session_matcher_spec.rb +67 -5
  53. data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +9 -9
  54. data/spec/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +30 -3
  55. data/spec/shoulda/matchers/active_model/{ensure_exclusion_of_matcher_spec.rb → validate_exclusion_of_matcher_spec.rb} +29 -13
  56. data/spec/shoulda/matchers/active_model/{ensure_inclusion_of_matcher_spec.rb → validate_inclusion_of_matcher_spec.rb} +34 -16
  57. data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +35 -0
  58. data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +56 -1
  59. data/spec/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +101 -0
  60. data/spec/shoulda/matchers/doublespeak/object_double_spec.rb +6 -6
  61. data/spec/shoulda/matchers/independent/{delegate_matcher → delegate_method_matcher}/stubbed_target_spec.rb +1 -1
  62. data/spec/shoulda/matchers/independent/{delegate_matcher_spec.rb → delegate_method_matcher_spec.rb} +88 -29
  63. data/spec/spec_helper.rb +2 -3
  64. data/spec/support/fail_with_message_including_matcher.rb +14 -3
  65. data/spec/support/fail_with_message_matcher.rb +14 -2
  66. data/spec/support/rails_versions.rb +4 -0
  67. metadata +19 -14
  68. data/lib/shoulda/matchers/independent/delegate_matcher/stubbed_target.rb +0 -35
@@ -1,19 +1,21 @@
1
- require 'shoulda/matchers/active_record/association_matcher'
2
- require 'shoulda/matchers/active_record/association_matchers'
3
- require 'shoulda/matchers/active_record/association_matchers/counter_cache_matcher'
4
- require 'shoulda/matchers/active_record/association_matchers/inverse_of_matcher'
5
- require 'shoulda/matchers/active_record/association_matchers/order_matcher'
6
- require 'shoulda/matchers/active_record/association_matchers/through_matcher'
7
- require 'shoulda/matchers/active_record/association_matchers/dependent_matcher'
8
- require 'shoulda/matchers/active_record/association_matchers/source_matcher'
9
- require 'shoulda/matchers/active_record/association_matchers/model_reflector'
10
- require 'shoulda/matchers/active_record/association_matchers/model_reflection'
11
- require 'shoulda/matchers/active_record/association_matchers/option_verifier'
12
- require 'shoulda/matchers/active_record/have_db_column_matcher'
13
- require 'shoulda/matchers/active_record/have_db_index_matcher'
14
- require 'shoulda/matchers/active_record/have_readonly_attribute_matcher'
15
- require 'shoulda/matchers/active_record/serialize_matcher'
16
- require 'shoulda/matchers/active_record/accept_nested_attributes_for_matcher'
1
+ require "shoulda/matchers/active_record/association_matcher"
2
+ require "shoulda/matchers/active_record/association_matchers"
3
+ require "shoulda/matchers/active_record/association_matchers/counter_cache_matcher"
4
+ require "shoulda/matchers/active_record/association_matchers/inverse_of_matcher"
5
+ require "shoulda/matchers/active_record/association_matchers/join_table_matcher"
6
+ require "shoulda/matchers/active_record/association_matchers/order_matcher"
7
+ require "shoulda/matchers/active_record/association_matchers/through_matcher"
8
+ require "shoulda/matchers/active_record/association_matchers/dependent_matcher"
9
+ require "shoulda/matchers/active_record/association_matchers/source_matcher"
10
+ require "shoulda/matchers/active_record/association_matchers/model_reflector"
11
+ require "shoulda/matchers/active_record/association_matchers/model_reflection"
12
+ require "shoulda/matchers/active_record/association_matchers/option_verifier"
13
+ require "shoulda/matchers/active_record/have_db_column_matcher"
14
+ require "shoulda/matchers/active_record/have_db_index_matcher"
15
+ require "shoulda/matchers/active_record/have_readonly_attribute_matcher"
16
+ require "shoulda/matchers/active_record/serialize_matcher"
17
+ require "shoulda/matchers/active_record/accept_nested_attributes_for_matcher"
18
+ require "shoulda/matchers/active_record/define_enum_for_matcher"
17
19
 
18
20
  module Shoulda
19
21
  module Matchers
@@ -5,7 +5,7 @@ module Shoulda
5
5
  # `accepts_nested_attributes_for` macro.
6
6
  #
7
7
  # class Car < ActiveRecord::Base
8
- # accept_nested_attributes_for :doors
8
+ # accepts_nested_attributes_for :doors
9
9
  # end
10
10
  #
11
11
  # # RSpec
@@ -26,7 +26,7 @@ module Shoulda
26
26
  # specified.
27
27
  #
28
28
  # class Car < ActiveRecord::Base
29
- # accept_nested_attributes_for :mirrors, allow_destroy: true
29
+ # accepts_nested_attributes_for :mirrors, allow_destroy: true
30
30
  # end
31
31
  #
32
32
  # # RSpec
@@ -48,7 +48,7 @@ module Shoulda
48
48
  # Use `limit` to assert that the `:limit` option was specified.
49
49
  #
50
50
  # class Car < ActiveRecord::Base
51
- # accept_nested_attributes_for :windows, limit: 3
51
+ # accepts_nested_attributes_for :windows, limit: 3
52
52
  # end
53
53
  #
54
54
  # # RSpec
@@ -71,7 +71,7 @@ module Shoulda
71
71
  # specified.
72
72
  #
73
73
  # class Car < ActiveRecord::Base
74
- # accept_nested_attributes_for :engine, update_only: true
74
+ # accepts_nested_attributes_for :engine, update_only: true
75
75
  # end
76
76
  #
77
77
  # # RSpec
@@ -847,9 +847,9 @@ module Shoulda
847
847
  (polymorphic? || class_exists?) &&
848
848
  foreign_key_exists? &&
849
849
  class_name_correct? &&
850
+ join_table_correct? &&
850
851
  autosave_correct? &&
851
852
  conditions_correct? &&
852
- join_table_exists? &&
853
853
  validate_correct? &&
854
854
  touch_correct? &&
855
855
  submatchers_match?
@@ -889,7 +889,8 @@ module Shoulda
889
889
  end
890
890
 
891
891
  def missing_options
892
- [missing, failing_submatchers.map(&:missing_option)].flatten.join
892
+ missing_options = [missing, failing_submatchers.map(&:missing_option)]
893
+ missing_options.flatten.compact.join(', ')
893
894
  end
894
895
 
895
896
  def failing_submatchers
@@ -946,6 +947,20 @@ module Shoulda
946
947
  end
947
948
  end
948
949
 
950
+ def join_table_correct?
951
+ if macro != :has_and_belongs_to_many || join_table_matcher.matches?(@subject)
952
+ true
953
+ else
954
+ @missing = join_table_matcher.failure_message
955
+ false
956
+ end
957
+ end
958
+
959
+ def join_table_matcher
960
+ @join_table_matcher ||=
961
+ AssociationMatchers::JoinTableMatcher.new(self, reflector)
962
+ end
963
+
949
964
  def class_exists?
950
965
  associated_class
951
966
  true
@@ -980,16 +995,6 @@ module Shoulda
980
995
  end
981
996
  end
982
997
 
983
- def join_table_exists?
984
- if macro != :has_and_belongs_to_many ||
985
- model_class.connection.tables.include?(join_table)
986
- true
987
- else
988
- @missing = "join table #{join_table} doesn't exist"
989
- false
990
- end
991
- end
992
-
993
998
  def validate_correct?
994
999
  if option_verifier.correct_for_boolean?(:validate, options[:validate])
995
1000
  true
@@ -0,0 +1,86 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ module AssociationMatchers
5
+ # @private
6
+ class JoinTableMatcher
7
+ attr_reader :failure_message
8
+
9
+ alias :missing_option :failure_message
10
+
11
+ delegate :model_class, :join_table, :associated_class,
12
+ to: :association_matcher
13
+
14
+ delegate :connection, to: :model_class
15
+
16
+ def initialize(association_matcher, reflector)
17
+ @association_matcher = association_matcher
18
+ @reflector = reflector
19
+ end
20
+
21
+ def matches?(subject)
22
+ join_table_exists? &&
23
+ join_table_has_correct_columns?
24
+ end
25
+
26
+ def join_table_exists?
27
+ if connection.tables.include?(join_table)
28
+ true
29
+ else
30
+ @failure_message = missing_table_message
31
+ false
32
+ end
33
+ end
34
+
35
+ def join_table_has_correct_columns?
36
+ if missing_columns.empty?
37
+ true
38
+ else
39
+ @failure_message = missing_columns_message
40
+ false
41
+ end
42
+ end
43
+
44
+ protected
45
+
46
+ attr_reader :association_matcher, :reflector
47
+
48
+ private
49
+
50
+ delegate :foreign_key, :association_foreign_key, to: :reflector
51
+
52
+ def missing_columns
53
+ @missing_columns ||= expected_join_table_columns.select do |key|
54
+ !actual_join_table_columns.include?(key)
55
+ end
56
+ end
57
+
58
+ def expected_join_table_columns
59
+ [foreign_key, association_foreign_key]
60
+ end
61
+
62
+ def actual_join_table_columns
63
+ connection.columns(join_table).map(&:name)
64
+ end
65
+
66
+ def missing_table_message
67
+ "join table #{join_table} doesn't exist"
68
+ end
69
+
70
+ def missing_columns_message
71
+ missing = missing_columns.join(', ')
72
+ "join table #{join_table} missing #{column_label}: #{missing}"
73
+ end
74
+
75
+ def column_label
76
+ if missing_columns.count > 1
77
+ 'columns'
78
+ else
79
+ 'column'
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -45,6 +45,25 @@ module Shoulda
45
45
  end
46
46
  end
47
47
 
48
+ def foreign_key
49
+ if has_and_belongs_to_many_reflection
50
+ has_and_belongs_to_many_reflection.foreign_key
51
+ elsif reflection.respond_to?(:primary_key_name)
52
+ reflection.primary_key_name
53
+ else
54
+ reflection.foreign_key
55
+ end
56
+ end
57
+
58
+ def association_foreign_key
59
+ if has_and_belongs_to_many_reflection
60
+ join_model = has_and_belongs_to_many_reflection.options[:class]
61
+ join_model.right_reflection.foreign_key
62
+ else
63
+ reflection.association_foreign_key
64
+ end
65
+ end
66
+
48
67
  protected
49
68
 
50
69
  attr_reader :reflection, :subject
@@ -5,7 +5,8 @@ module Shoulda
5
5
  # @private
6
6
  class ModelReflector
7
7
  delegate :associated_class, :through?, :join_table,
8
- :association_relation, :polymorphic?, to: :reflection
8
+ :association_relation, :polymorphic?, :foreign_key,
9
+ :association_foreign_key, to: :reflection
9
10
 
10
11
  def initialize(subject, name)
11
12
  @subject = subject
@@ -0,0 +1,138 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `define_enum_for` matcher is used to test that the `enum` macro has
5
+ # been used to decorate an attribute with enum methods.
6
+ #
7
+ # class Process < ActiveRecord::Base
8
+ # enum status: [:running, :stopped, :suspended]
9
+ # end
10
+ #
11
+ # # RSpec
12
+ # describe Process do
13
+ # it { should define_enum_for(:status) }
14
+ # end
15
+ # end
16
+ #
17
+ # # Test::Unit
18
+ # class ProcessTest < ActiveSupport::TestCase
19
+ # should define_enum_for(:status)
20
+ # end
21
+ #
22
+ # #### Qualifiers
23
+ #
24
+ # ##### with
25
+ #
26
+ # Use `with` to test that the enum has been defined with a certain set of
27
+ # known values.
28
+ #
29
+ # class Process < ActiveRecord::Base
30
+ # enum status: [:running, :stopped, :suspended]
31
+ # end
32
+ #
33
+ # # RSpec
34
+ # describe Process do
35
+ # it do
36
+ # should define_enum_for(:status).
37
+ # with([:running, :stopped, :suspended])
38
+ # end
39
+ # end
40
+ #
41
+ # # Test::Unit
42
+ # class ProcessTest < ActiveSupport::TestCase
43
+ # should define_enum_for(:status).
44
+ # with([:running, :stopped, :suspended])
45
+ # end
46
+ #
47
+ # @return [DefineEnumForMatcher]
48
+ #
49
+ def define_enum_for(attribute_name)
50
+ DefineEnumForMatcher.new(attribute_name)
51
+ end
52
+
53
+ # @private
54
+ class DefineEnumForMatcher
55
+ def initialize(attribute_name)
56
+ @attribute_name = attribute_name
57
+ @options = {}
58
+ end
59
+
60
+ def with(expected_enum_values)
61
+ options[:expected_enum_values] = expected_enum_values
62
+ self
63
+ end
64
+
65
+ def matches?(subject)
66
+ @model = subject
67
+ enum_defined? && enum_values_match?
68
+ end
69
+
70
+ def failure_message
71
+ "Expected #{expectation}"
72
+ end
73
+ alias :failure_message_for_should :failure_message
74
+
75
+ def failure_message_when_negated
76
+ "Did not expect #{expectation}"
77
+ end
78
+ alias :failure_message_for_should_not :failure_message_when_negated
79
+
80
+ def description
81
+ desc = "define :#{attribute_name} as an enum"
82
+
83
+ if options[:expected_enum_values]
84
+ desc << " with #{options[:expected_enum_values]}"
85
+ end
86
+
87
+ desc
88
+ end
89
+
90
+ protected
91
+
92
+ attr_reader :model, :attribute_name, :options
93
+
94
+ def expectation
95
+ "#{model.class.name} to #{description}"
96
+ end
97
+
98
+ def expected_enum_values
99
+ hashify(options[:expected_enum_values]).with_indifferent_access
100
+ end
101
+
102
+ def enum_method
103
+ attribute_name.to_s.pluralize
104
+ end
105
+
106
+ def actual_enum_values
107
+ model.class.send(enum_method)
108
+ end
109
+
110
+ def enum_defined?
111
+ model.class.respond_to?(enum_method)
112
+ end
113
+
114
+ def enum_values_match?
115
+ expected_enum_values.empty? || actual_enum_values == expected_enum_values
116
+ end
117
+
118
+ def hashify(value)
119
+ if value.nil?
120
+ return {}
121
+ end
122
+
123
+ if value.is_a?(Array)
124
+ new_value = {}
125
+
126
+ value.each_with_index do |v, i|
127
+ new_value[v] = i
128
+ end
129
+
130
+ new_value
131
+ else
132
+ value
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -1,5 +1,6 @@
1
- require 'shoulda/matchers/independent/delegate_matcher'
2
- require 'shoulda/matchers/independent/delegate_matcher/stubbed_target'
1
+ require 'shoulda/matchers/independent/delegate_method_matcher'
2
+ require 'shoulda/matchers/independent/delegate_method_matcher/stubbed_target'
3
+ require 'shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error'
3
4
 
4
5
  module Shoulda
5
6
  module Matchers
@@ -70,10 +70,12 @@ module Shoulda
70
70
  # ##### with_arguments
71
71
  #
72
72
  # Use `with_arguments` to assert that the delegate method is called with
73
- # certain arguments.
73
+ # certain arguments. Note that this qualifier can only be used when the
74
+ # delegating method takes no arguments; it does not support delegating
75
+ # or delegate methods that take arbitrary arguments.
74
76
  #
75
- # Here, when Courier#deliver calls PostOffice#ship, it adds an options
76
- # hash:
77
+ # Here, when Courier#deliver_package calls PostOffice#deliver_package, it
78
+ # adds an options hash:
77
79
  #
78
80
  # class Courier
79
81
  # attr_reader :post_office
@@ -82,39 +84,39 @@ module Shoulda
82
84
  # @post_office = PostOffice.new
83
85
  # end
84
86
  #
85
- # def deliver(package)
86
- # post_office.ship(package, expedited: true)
87
+ # def deliver_package
88
+ # post_office.deliver_package(expedited: true)
87
89
  # end
88
90
  # end
89
91
  #
90
92
  # # RSpec
91
93
  # describe Courier do
92
94
  # it do
93
- # should delegate_method(:deliver).
95
+ # should delegate_method(:deliver_package).
94
96
  # to(:post_office).
95
- # as(:ship).
96
97
  # with_arguments(expedited: true)
97
98
  # end
98
99
  # end
99
100
  #
100
101
  # # Test::Unit
101
102
  # class CourierTest < Test::Unit::TestCase
102
- # should delegate_method(:deliver).
103
+ # should delegate_method(:deliver_package).
103
104
  # to(:post_office).
104
- # as(:ship).
105
105
  # with_arguments(expedited: true)
106
106
  # end
107
107
  #
108
- # @return [DelegateMatcher]
108
+ # @return [DelegateMethodMatcher]
109
109
  #
110
110
  def delegate_method(delegating_method)
111
- DelegateMatcher.new(delegating_method)
111
+ DelegateMethodMatcher.new(delegating_method, self)
112
112
  end
113
113
 
114
114
  # @private
115
- class DelegateMatcher
116
- def initialize(delegating_method)
115
+ class DelegateMethodMatcher
116
+ def initialize(delegating_method, context)
117
117
  @delegating_method = delegating_method
118
+ @context = context
119
+
118
120
  @method_on_target = @delegating_method
119
121
  @target_double = Doublespeak::ObjectDouble.new
120
122
 
@@ -135,9 +137,18 @@ module Shoulda
135
137
  end
136
138
 
137
139
  def description
138
- add_clarifications_to(
139
- "delegate method ##{delegating_method} to :#{target_method}"
140
- )
140
+ string = "delegate #{formatted_delegating_method_name} to " +
141
+ "#{formatted_target_method_name} object"
142
+
143
+ if delegated_arguments.any?
144
+ string << " passing arguments #{delegated_arguments.inspect}"
145
+ end
146
+
147
+ if method_on_target != delegating_method
148
+ string << " as #{formatted_method_on_target}"
149
+ end
150
+
151
+ string
141
152
  end
142
153
 
143
154
  def to(target_method)
@@ -156,58 +167,73 @@ module Shoulda
156
167
  end
157
168
 
158
169
  def failure_message
159
- base = "Expected #{formatted_delegating_method_name} to delegate to #{formatted_target_method_name}"
160
- add_clarifications_to(base)
161
- base << "\nCalls on #{formatted_target_method_name}:"
162
- base << formatted_calls_on_target
163
- base.strip
170
+ "Expected #{class_under_test} to #{description}\n" +
171
+ "Method calls sent to " +
172
+ "#{formatted_target_method_name(include_module: true)}:" +
173
+ formatted_calls_on_target
164
174
  end
165
175
  alias failure_message_for_should failure_message
166
176
 
167
177
  def failure_message_when_negated
168
- base = "Expected #{formatted_delegating_method_name} not to delegate to #{formatted_target_method_name}"
169
- add_clarifications_to(base)
170
- base << ', but it did'
178
+ "Expected #{class_under_test} not to #{description}, but it did"
171
179
  end
172
180
  alias failure_message_for_should_not failure_message_when_negated
173
181
 
174
182
  protected
175
183
 
176
184
  attr_reader \
185
+ :context,
177
186
  :delegated_arguments,
178
187
  :delegating_method,
179
188
  :method,
180
189
  :method_on_target,
181
- :subject,
182
190
  :subject_double_collection,
183
191
  :target_double,
184
192
  :target_method
185
193
 
186
- def add_clarifications_to(message)
187
- if delegated_arguments.any?
188
- message << " with arguments: #{delegated_arguments.inspect}"
189
- end
194
+ def subject
195
+ @subject || context.subject
196
+ end
190
197
 
191
- if method_on_target != delegating_method
192
- message << " as ##{method_on_target}"
198
+ def class_under_test
199
+ if subject.is_a?(Class)
200
+ subject
201
+ else
202
+ subject.class
193
203
  end
204
+ end
194
205
 
195
- message
206
+ def formatted_method_on_target(options = {})
207
+ formatted_method_name_for(method_on_target, options)
196
208
  end
197
209
 
198
- def formatted_delegating_method_name
199
- formatted_method_name_for(delegating_method)
210
+ def formatted_delegating_method_name(options = {})
211
+ formatted_method_name_for(delegating_method, options)
200
212
  end
201
213
 
202
- def formatted_target_method_name
203
- formatted_method_name_for(target_method)
214
+ def formatted_target_method_name(options = {})
215
+ formatted_method_name_for(target_method, options)
204
216
  end
205
217
 
206
- def formatted_method_name_for(method_name)
218
+ def formatted_method_name_for(method_name, options)
219
+ possible_class_under_test(options) +
220
+ class_or_instance_method_indicator +
221
+ method_name.to_s
222
+ end
223
+
224
+ def possible_class_under_test(options)
225
+ if options[:include_module]
226
+ class_under_test.to_s
227
+ else
228
+ ""
229
+ end
230
+ end
231
+
232
+ def class_or_instance_method_indicator
207
233
  if subject.is_a?(Class)
208
- subject.name + '.' + method_name.to_s
234
+ '.'
209
235
  else
210
- subject.class.name + '#' + method_name.to_s
236
+ '#'
211
237
  end
212
238
  end
213
239
 
@@ -226,11 +252,11 @@ module Shoulda
226
252
  end
227
253
 
228
254
  def subject_has_target_method?
229
- subject.respond_to?(target_method)
255
+ subject.respond_to?(target_method, true)
230
256
  end
231
257
 
232
258
  def ensure_target_method_is_present!
233
- if target_method.blank?
259
+ if target_method.to_s.empty?
234
260
  raise TargetNotDefinedError
235
261
  end
236
262
  end
@@ -280,15 +306,9 @@ module Shoulda
280
306
  string << " (none)"
281
307
  end
282
308
 
283
- string
284
- end
309
+ string.rstrip!
285
310
 
286
- # @private
287
- class TargetNotDefinedError < StandardError
288
- def message
289
- 'Delegation needs a target. Use the #to method to define one, e.g.
290
- `post_office.should delegate(:deliver_mail).to(:mailman)`'.squish
291
- end
311
+ string
292
312
  end
293
313
  end
294
314
  end