rspec-sleeping_king_studios 2.1.1 → 2.2.0.rc.1

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -0
  3. data/DEVELOPMENT.md +26 -17
  4. data/LICENSE +1 -1
  5. data/README.md +198 -19
  6. data/lib/rspec/sleeping_king_studios/configuration.rb +63 -2
  7. data/lib/rspec/sleeping_king_studios/examples/property_examples.rb +115 -27
  8. data/lib/rspec/sleeping_king_studios/examples/rspec_matcher_examples.rb +66 -51
  9. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +8 -269
  10. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher.rb +268 -0
  11. data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +5 -15
  12. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +3 -63
  13. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of_matcher.rb +65 -0
  14. data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +3 -108
  15. data/lib/rspec/sleeping_king_studios/matchers/built_in/include_matcher.rb +134 -0
  16. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +3 -258
  17. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to_matcher.rb +116 -0
  18. data/lib/rspec/sleeping_king_studios/matchers/core/alias_method.rb +11 -0
  19. data/lib/rspec/sleeping_king_studios/matchers/core/alias_method_matcher.rb +107 -0
  20. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +9 -36
  21. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean_matcher.rb +37 -0
  22. data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +3 -210
  23. data/lib/rspec/sleeping_king_studios/matchers/core/construct_matcher.rb +113 -0
  24. data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method.rb +11 -0
  25. data/lib/rspec/sleeping_king_studios/matchers/core/delegate_method_matcher.rb +311 -0
  26. data/lib/rspec/sleeping_king_studios/matchers/core/have_constant.rb +16 -0
  27. data/lib/rspec/sleeping_king_studios/matchers/core/have_constant_matcher.rb +225 -0
  28. data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate.rb +11 -0
  29. data/lib/rspec/sleeping_king_studios/matchers/core/have_predicate_matcher.rb +97 -0
  30. data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +3 -104
  31. data/lib/rspec/sleeping_king_studios/matchers/core/have_property_matcher.rb +108 -0
  32. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +3 -74
  33. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader_matcher.rb +96 -0
  34. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +4 -59
  35. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer_matcher.rb +55 -0
  36. data/lib/rspec/sleeping_king_studios/matchers/description.rb +62 -0
  37. data/lib/rspec/sleeping_king_studios/matchers/macros.rb +32 -0
  38. data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +168 -66
  39. data/lib/rspec/sleeping_king_studios/matchers/shared/match_property.rb +25 -0
  40. data/lib/rspec/sleeping_king_studios/matchers.rb +0 -4
  41. data/lib/rspec/sleeping_king_studios/support/method_signature.rb +51 -0
  42. data/lib/rspec/sleeping_king_studios/support/method_signature_expectation.rb +158 -0
  43. data/lib/rspec/sleeping_king_studios/support.rb +9 -0
  44. data/lib/rspec/sleeping_king_studios/version.rb +10 -4
  45. metadata +46 -30
@@ -2,6 +2,9 @@
2
2
 
3
3
  require 'rspec/sleeping_king_studios/concerns/shared_example_group'
4
4
  require 'rspec/sleeping_king_studios/examples'
5
+ require 'rspec/sleeping_king_studios/matchers/core/have_constant'
6
+ require 'rspec/sleeping_king_studios/matchers/core/have_predicate'
7
+ require 'rspec/sleeping_king_studios/matchers/core/have_property'
5
8
  require 'rspec/sleeping_king_studios/matchers/core/have_reader'
6
9
  require 'rspec/sleeping_king_studios/matchers/core/have_writer'
7
10
  require 'sleeping_king_studios/tools/object_tools'
@@ -15,50 +18,135 @@ module RSpec::SleepingKingStudios::Examples::PropertyExamples
15
18
  #
16
19
  # Internal object used to differentiate a nil expectation from a default
17
20
  # value expectation.
18
- UNDEFINED_PROPERTY_EXPECTATION = Object.new.freeze
21
+ UNDEFINED_VALUE_EXPECTATION = Object.new.freeze
19
22
 
20
- shared_examples 'has reader' do |property, expected_value = UNDEFINED_PROPERTY_EXPECTATION|
21
- it "has reader :#{property}" do
22
- object = defined?(instance) ? instance : subject
23
+ private def format_expected_value expected_value
24
+ if expected_value.is_a?(Proc)
25
+ object_tools = SleepingKingStudios::Tools::ObjectTools
26
+
27
+ if 0 == expected_value.arity
28
+ comparable_value = object_tools.apply self, expected_value
29
+ else
30
+ comparable_value = satisfy do |actual_value|
31
+ object_tools.apply self, expected_value, actual_value
32
+ end # satisfy
33
+ end # if-else
34
+ else
35
+ comparable_value = expected_value
36
+ end # if
37
+
38
+ comparable_value
39
+ end # method format_expected_value
40
+
41
+ shared_examples 'should have constant' do |constant_name, expected_value = UNDEFINED_VALUE_EXPECTATION|
42
+ it "should have constant :#{constant_name}" do
43
+ if defined?(described_class) && described_class.is_a?(Module)
44
+ object = described_class
45
+ else
46
+ object = subject
47
+ end # if-else
48
+
49
+ if expected_value == UNDEFINED_VALUE_EXPECTATION
50
+ expect(object).to have_constant(constant_name)
51
+ else
52
+ expected_value = format_expected_value(expected_value)
23
53
 
24
- expect(object).to have_reader(property)
54
+ expect(object).to have_constant(constant_name).with_value(expected_value)
55
+ end # if-else
56
+ end # it
57
+ end # shared_examples
25
58
 
26
- next if expected_value == UNDEFINED_PROPERTY_EXPECTATION
59
+ shared_examples 'should have immutable constant' do |constant_name, expected_value = UNDEFINED_VALUE_EXPECTATION|
60
+ it "should have immutable constant :#{constant_name}" do
61
+ if defined?(described_class) && described_class.is_a?(Module)
62
+ object = described_class
63
+ else
64
+ object = subject
65
+ end # if-else
27
66
 
28
- actual_value = instance.send property
67
+ if expected_value == UNDEFINED_VALUE_EXPECTATION
68
+ expect(object).to have_immutable_constant(constant_name)
69
+ else
70
+ expected_value = format_expected_value(expected_value)
29
71
 
30
- if expected_value.is_a?(Proc)
31
- args = [self, expected_value]
32
- args.push actual_value unless 0 == expected_value.arity
72
+ expect(object).to have_immutable_constant(constant_name).with_value(expected_value)
73
+ end # if-else
74
+ end # it
75
+ end # shared_examples
33
76
 
34
- expected_value = SleepingKingStudios::Tools::ObjectTools.apply *args
35
- end # if
77
+ shared_examples 'should have predicate' do |property, expected_value = UNDEFINED_VALUE_EXPECTATION|
78
+ it "should have predicate :#{property}?" do
79
+ object = defined?(instance) ? instance : subject
36
80
 
37
- case expected_value
38
- when ->(obj) { obj.respond_to?(:matches?) }
39
- expect(actual_value).to expected_value
40
- when true, false
41
- expected_value
81
+ if expected_value == UNDEFINED_VALUE_EXPECTATION
82
+ expect(object).to have_predicate(property)
42
83
  else
43
- expect(actual_value).to be == expected_value
44
- end # case
84
+ expected_value = format_expected_value(expected_value)
85
+
86
+ expect(object).to have_predicate(property).with_value(expected_value)
87
+ end # if-else
45
88
  end # it
46
89
  end # shared_examples
47
- alias_shared_examples 'should have reader', 'has reader'
90
+ alias_shared_examples 'has predicate', 'should have predicate'
48
91
 
49
- shared_examples 'has writer' do |property|
50
- it "has writer :#{property}=" do
92
+ shared_examples 'should have reader' do |property, expected_value = UNDEFINED_VALUE_EXPECTATION|
93
+ it "should have reader :#{property}" do
94
+ object = defined?(instance) ? instance : subject
95
+
96
+ if expected_value == UNDEFINED_VALUE_EXPECTATION
97
+ expect(object).to have_reader(property)
98
+ else
99
+ expected_value = format_expected_value(expected_value)
100
+
101
+ expect(object).to have_reader(property).with_value(expected_value)
102
+ end # if-else
103
+ end # it
104
+ end # shared_examples
105
+ alias_shared_examples 'has reader', 'should have reader'
106
+
107
+ shared_examples 'should not have reader' do |property|
108
+ it "should not have reader :#{property}" do
109
+ object = defined?(instance) ? instance : subject
110
+
111
+ expect(object).not_to have_reader(property)
112
+ end # it
113
+ end # shared_examples
114
+ alias_shared_examples 'does not have reader', 'should not have reader'
115
+
116
+ shared_examples 'should have writer' do |property|
117
+ property_name = property.to_s.sub /\=\z/, ''
118
+
119
+ it "should have writer :#{property_name}=" do
51
120
  object = defined?(instance) ? instance : subject
52
121
 
53
122
  expect(object).to have_writer(property)
54
123
  end # it
55
124
  end # shared_examples
56
- alias_shared_examples 'should have writer', 'has writer'
125
+ alias_shared_examples 'has writer', 'should have writer'
57
126
 
58
- shared_examples 'has property' do |property, expected_value = UNDEFINED_PROPERTY_EXPECTATION|
59
- include_examples 'has reader', property, expected_value
127
+ shared_examples 'should not have writer' do |property|
128
+ property_name = property.to_s.sub /\=\z/, ''
60
129
 
61
- include_examples 'has writer', property
130
+ it "should not have writer :#{property}=" do
131
+ object = defined?(instance) ? instance : subject
132
+
133
+ expect(object).not_to have_writer(property)
134
+ end # it
135
+ end # shared_examples
136
+ alias_shared_examples 'does not have writer', 'should not have writer'
137
+
138
+ shared_examples 'should have property' do |property, expected_value = UNDEFINED_VALUE_EXPECTATION|
139
+ it "should have property :#{property}" do
140
+ object = defined?(instance) ? instance : subject
141
+
142
+ if expected_value == UNDEFINED_VALUE_EXPECTATION
143
+ expect(object).to have_property(property)
144
+ else
145
+ expected_value = format_expected_value(expected_value)
146
+
147
+ expect(object).to have_property(property).with_value(expected_value)
148
+ end # if-else
149
+ end # it
62
150
  end # shared_examples
63
- alias_shared_examples 'should have property', 'has property'
151
+ alias_shared_examples 'has property', 'should have property'
64
152
  end # module
@@ -8,54 +8,74 @@ require 'rspec/sleeping_king_studios/matchers/base_matcher'
8
8
  module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
9
9
  extend RSpec::SleepingKingStudios::Concerns::SharedExampleGroup
10
10
 
11
- shared_examples 'passes with a positive expectation' do
11
+ private def config
12
+ RSpec.configuration.sleeping_king_studios
13
+ end # method config
14
+
15
+ private def compare_message actual, expected
16
+ case expected
17
+ when String
18
+ if config.examples.match_string_failure_message_as == :exact
19
+ expect(actual).to be == expected
20
+ else
21
+ expect(actual).to include expected
22
+ end # if-else
23
+ when Regexp
24
+ expect(actual).to be =~ expected
25
+ when ->(obj) { obj.respond_to?(:matches?) && obj.respond_to?(:failure_message) }
26
+ expect(actual).to expected
27
+ else
28
+ expect(actual).to match expected
29
+ end # when
30
+ end # method compare_message
31
+
32
+ private def handle_missing_failure_message message
33
+ case config.examples.handle_missing_failure_message_with
34
+ when :pending
35
+ skip message
36
+ when :exception
37
+ raise StandardError.new message
38
+ end # case
39
+ end # method handle_missing_failure_message
40
+
41
+ shared_examples 'should pass with a positive expectation' do
12
42
  let(:matcher_being_examined) { defined?(instance) ? instance : subject }
13
43
 
14
- it 'passes with a positive expectation' do
44
+ it 'should pass with positive expectation' do
15
45
  expect(matcher_being_examined.matches? actual).to be true
16
46
  end # it
17
47
  end # shared_examples
18
- alias_shared_examples 'should pass with a positive expectation', 'passes with a positive expectation'
48
+ alias_shared_examples 'passes with a positive expectation', 'should pass with a positive expectation'
19
49
 
20
- shared_examples 'fails with a positive expectation' do
50
+ shared_examples 'should fail with a positive expectation' do
21
51
  let(:matcher_being_examined) { defined?(instance) ? instance : subject }
22
52
 
23
- it 'fails with a positive expectation' do
53
+ it 'should fail with a positive expectation' do
24
54
  expect(matcher_being_examined.matches? actual).to be false
25
55
  end # it
26
56
 
27
- it 'has a failure message with a positive expectation' do
57
+ it 'should have a failure message with a positive expectation' do
28
58
  if defined?(failure_message)
29
59
  matcher_being_examined.matches?(actual)
30
60
 
31
- expected = failure_message.is_a?(String) ?
32
- Regexp.new(Regexp.escape(failure_message)) :
33
- failure_message
34
-
35
- expect(matcher_being_examined.failure_message).to match expected
61
+ compare_message(matcher_being_examined.failure_message, failure_message)
36
62
  else
37
- message = <<-MESSAGE
38
- expected to match #{matcher_being_examined.class}#failure_message, but the expected
39
- value was undefined. Define a failure message using
40
- let(:failure_message) or set
41
- config.handle_missing_failure_message_with to :ignore or :pending.
42
- MESSAGE
43
- message = message.split("\n").map(&:strip).join(' ')
44
- case RSpec.configuration.sleeping_king_studios.examples.handle_missing_failure_message_with
45
- when :pending
46
- skip message
47
- when :exception
48
- raise StandardError.new message
49
- end # case
63
+ message =
64
+ "expected to match #{matcher_being_examined.class}#failure_message, "\
65
+ "but the expected value was undefined. Define a failure message "\
66
+ "using let(:failure_message) or set "\
67
+ "config.handle_missing_failure_message_with to :ignore or :pending."
68
+
69
+ handle_missing_failure_message(message)
50
70
  end # if
51
71
  end # it
52
72
  end # shared_examples
53
- alias_shared_examples 'should fail with a positive expectation', 'fails with a positive expectation'
73
+ alias_shared_examples 'fails with a positive expectation', 'should fail with a positive expectation'
54
74
 
55
- shared_examples 'passes with a negative expectation' do
75
+ shared_examples 'should pass with a negative expectation' do
56
76
  let(:matcher_being_examined) { defined?(instance) ? instance : subject }
57
77
 
58
- it 'passes with a negative expectation' do
78
+ it 'should pass with a negative expectation' do
59
79
  if matcher_being_examined.respond_to?(:does_not_match?)
60
80
  expect(matcher_being_examined.does_not_match? actual).to be true
61
81
  else
@@ -63,12 +83,12 @@ module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
63
83
  end # if-else
64
84
  end # it
65
85
  end # shared_examples
66
- alias_shared_examples 'should pass with a negative expectation', 'passes with a negative expectation'
86
+ alias_shared_examples 'passes with a negative expectation', 'should pass with a negative expectation'
67
87
 
68
- shared_examples 'fails with a negative expectation' do
88
+ shared_examples 'should fail with a negative expectation' do
69
89
  let(:matcher_being_examined) { defined?(instance) ? instance : subject }
70
90
 
71
- it 'fails with a negative expectation' do
91
+ it 'should fail with a negative expectation' do
72
92
  if matcher_being_examined.respond_to?(:does_not_match?)
73
93
  expect(matcher_being_examined.does_not_match? actual).to be false
74
94
  else
@@ -76,31 +96,26 @@ module RSpec::SleepingKingStudios::Examples::RSpecMatcherExamples
76
96
  end # if-else
77
97
  end # it
78
98
 
79
- it 'has a failure message with a negative expectation' do
99
+ it 'should have a failure message with a negative expectation' do
80
100
  if defined?(failure_message_when_negated)
81
- matcher_being_examined.respond_to?(:does_not_match?) ? matcher_being_examined.does_not_match?(actual) : matcher_being_examined.matches?(actual)
82
-
83
- expected = failure_message_when_negated.is_a?(String) ?
84
- Regexp.new(Regexp.escape(failure_message_when_negated)) :
85
- failure_message_when_negated
101
+ if matcher_being_examined.respond_to?(:does_not_match?)
102
+ matcher_being_examined.does_not_match?(actual)
103
+ else
104
+ matcher_being_examined.matches?(actual)
105
+ end # if-else
86
106
 
87
- expect(matcher_being_examined.failure_message_when_negated).to match expected
107
+ compare_message(matcher_being_examined.failure_message_when_negated, failure_message_when_negated)
88
108
  else
89
- message = <<-MESSAGE
90
- expected to match #{matcher_being_examined.class}#failure_message_when_negated, but
91
- the expected value was undefined. Define a failure message using
92
- let(:failure_message_when_negated) or set
93
- config.handle_missing_failure_message_with to :ignore or :pending.
94
- MESSAGE
95
- message = message.split("\n").map(&:strip).join(' ')
96
- case RSpec.configuration.sleeping_king_studios.examples.handle_missing_failure_message_with
97
- when :pending
98
- skip message
99
- when :exception
100
- raise StandardError.new message
101
- end # case
109
+ message =
110
+ "expected to match #{matcher_being_examined.class}#"\
111
+ "failure_message_when_negated, but the expected value was undefined."\
112
+ " Define a failure message using let(:failure_message_when_negated) "\
113
+ "or set config.handle_missing_failure_message_with to :ignore or "\
114
+ ":pending."
115
+
116
+ handle_missing_failure_message(message)
102
117
  end # if
103
118
  end # it
104
119
  end # shared_examples
105
- alias_shared_examples 'should fail with a negative expectation', 'fails with a negative expectation'
120
+ alias_shared_examples 'fails with a negative expectation', 'should fail with a negative expectation'
106
121
  end # module
@@ -1,272 +1,11 @@
1
1
  # lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb
2
2
 
3
- require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
- require 'rspec/sleeping_king_studios/matchers/active_model'
5
- require 'rspec/sleeping_king_studios/matchers/active_model/have_errors/error_expectation'
6
- require 'sleeping_king_studios/tools/enumerable_tools'
7
- require 'sleeping_king_studios/tools/string_tools'
8
-
9
- module RSpec::SleepingKingStudios::Matchers::ActiveModel
10
- # Matcher for testing ActiveModel object validations.
11
- #
12
- # @since 1.0.0
13
- class HaveErrorsMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
14
- include RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrors
15
- include SleepingKingStudios::Tools::EnumerableTools
16
- include SleepingKingStudios::Tools::StringTools
17
-
18
- def initialize
19
- super
20
-
21
- # The error and message expectations are set up through #on and
22
- # #with_message.
23
- @error_expectations = []
24
- end # constructor
25
-
26
- # (see BaseMatcher#description)
27
- def description
28
- message = 'have errors'
29
-
30
- attribute_messages = @error_expectations.select(&:expected).map do |expectation|
31
- attribute_message = ":#{expectation.attribute}"
32
-
33
- error_messages = expectation.messages.select(&:expected).map do |message_expectation|
34
- %{"#{message_expectation.message}"}
35
- end # map
36
-
37
- unless error_messages.empty?
38
- attribute_message << " with #{pluralize(error_messages.count, 'message', 'messages')} #{humanize_list error_messages}"
39
- end # unless
40
-
41
- attribute_message
42
- end # each
43
- message << " on #{attribute_messages.join(", and on ")}" unless attribute_messages.empty?
44
-
45
- message
46
- end # method description
47
-
48
- # Checks if the object can be validated, whether the object is valid, and
49
- # checks the errors on the object against the expected errors and messages
50
- # from #on and #with_message, if any.
51
- #
52
- # @param [Object] actual The object to test against the matcher.
53
- #
54
- # @return [Boolean] True if the object responds to :valid? and is valid
55
- # or object.errors does not match the specified errors and messages (if
56
- # any); otherwise false.
57
- #
58
- # @see #matches?
59
- def does_not_match? actual
60
- @negative_expectation = true
61
-
62
- return false unless @validates = actual.respond_to?(:valid?)
63
-
64
- !matches?(actual)
65
- end # method does_not_match?
66
-
67
- # Checks if the object can be validated, whether the object is valid, and
68
- # checks the errors on the object against the expected errors and messages
69
- # from #on and #with_message, if any.
70
- #
71
- # @param [Object] actual The object to test against the matcher.
72
- #
73
- # @return [Boolean] True if the object responds to :valid?, is not valid,
74
- # and object.errors matches the specified errors and messages (if any);
75
- # otherwise false.
76
- #
77
- # @see RSpec::SleepingKingStudios::Matchers::BaseMatcher#matches?
78
- def matches? actual
79
- super
80
-
81
- return false unless @validates = actual.respond_to?(:valid?)
82
-
83
- !@actual.valid? && attributes_have_errors?
84
- end # method matches?
85
-
86
- # Adds an error expectation. If the actual object does not have an error on
87
- # the specified attribute, #matches? will return false.
88
- #
89
- # @param [String, Symbol] attribute
90
- #
91
- # @return [HaveErrorsMatcher] self
92
- #
93
- # @example Setting an error expectation
94
- # expect(actual).to have_errors.on(:foo)
95
- def on attribute
96
- @error_expectations << ErrorExpectation.new(attribute)
97
-
98
- self
99
- end # method on
100
-
101
- # Adds a message expectation for the most recently added error attribute.
102
- # If the actual object does not have an error on the that attribute with
103
- # the specified message, #matches? will return false.
104
- #
105
- # @param [String, Regexp] message The expected error message. If a string,
106
- # matcher will check for an exact match; if a regular expression, matcher
107
- # will check if the message matches the regexp.
108
- #
109
- # @raise [ArgumentError] If no error attribute has been added.
110
- #
111
- # @return [HaveErrorsMatcher] self
112
- #
113
- # @example Setting an error and a message expectation
114
- # expect(actual).to have_errors.on(:foo).with("can't be blank")
115
- #
116
- # @see #on
117
- def with_message message
118
- raise ArgumentError.new "no attribute specified for error message" if
119
- @error_expectations.empty?
120
-
121
- @error_expectations.last.messages << MessageExpectation.new(message)
122
-
123
- self
124
- end # method with_message
125
-
126
- # Adds a set of message expectations for the most recently added error
127
- # attribute.
128
- #
129
- # @param [Array<String, Regexp>] messages
130
- #
131
- # @see #with_message
132
- def with_messages *messages
133
- messages.each do |message| self.with_message(message); end
134
-
135
- self
136
- end # method with_message
137
- alias_method :with, :with_messages
138
-
139
- # (see BaseMatcher#failure_message)
140
- def failure_message
141
- # Failure cases:
142
- # * object is not a model ("to respond to valid")
143
- # * expected one or more errors, but received none ("to have errors")
144
- # * expected one or more messages on :attribute, but received none or a
145
- # subset ("to have errors on")
146
-
147
- if !@validates
148
- "expected #{@actual.inspect} to respond to :valid?"
149
- elsif expected_errors.empty?
150
- "expected #{@actual.inspect} to have errors"
151
- else
152
- "expected #{@actual.inspect} to have errors#{expected_errors_message}#{received_errors_message}"
153
- end # if-elsif-else
154
- end # method failure_message
155
-
156
- # (see BaseMatcher#failure_message_when_negated)
157
- def failure_message_when_negated
158
- # Failure cases:
159
- # * object is not a model ("to respond to valid")
160
- # * expected one or more errors, received one or more ("not to have
161
- # errors")
162
- # * expected one or more messages on attribute, received one or more
163
- # ("not to have errors on")
164
- # * expected specific messages on attribute, received all ("not to have
165
- # errors on")
166
-
167
- if !@validates
168
- "expected #{@actual.inspect} to respond to :valid?"
169
- elsif expected_errors.empty?
170
- return "expected #{@actual.inspect} not to have errors#{received_errors_message}"
171
- else
172
- return "expected #{@actual.inspect} not to have errors#{expected_errors_message}#{received_errors_message}"
173
- end # if-else
174
- end # method failure_message_when_negated
175
-
176
- private
177
-
178
- def attributes_have_errors?
179
- # Iterate through the received errors and match them against the expected
180
- # errors and messages.
181
- @actual.errors.messages.each do |attribute, messages|
182
- # Find the matching error expectation, if any.
183
- error_expectation = @error_expectations.detect do |error_expectation|
184
- error_expectation.attribute == attribute
185
- end # detect
186
-
187
- if error_expectation
188
- error_expectation.received = true
189
-
190
- # If the error includes message expectations, iterate through the
191
- # received messages.
192
- unless error_expectation.messages.empty?
193
- messages.each do |message|
194
- # Find the matching message expectation, if any.
195
- message_expectation = error_expectation.messages.detect do |message_expectation|
196
- if Regexp === message_expectation.message
197
- message =~ message_expectation.message
198
- else
199
- message == message_expectation.message
200
- end # if-else
201
- end # detect
202
-
203
- if message_expectation
204
- message_expectation.received = true
205
- else
206
- error_expectation.messages << MessageExpectation.new(message, false, true)
207
- end # if-else
208
- end # each
209
- end # unless
210
- else
211
- error_expectation = ErrorExpectation.new attribute, false, true
212
- messages.each do |message|
213
- error_expectation.messages << MessageExpectation.new(message, false, true)
214
- end # each
215
-
216
- @error_expectations << error_expectation
217
- end # if-else
218
- end # each
219
-
220
- missing_errors.empty? && missing_messages.empty?
221
- end # method attributes_have_errors
222
-
223
- def expected_errors
224
- @error_expectations.select do |error_expectation|
225
- error_expectation.expected
226
- end # select
227
- end # method expected_errors
228
-
229
- def missing_errors
230
- @error_expectations.select do |error_expectation|
231
- error_expectation.expected && !error_expectation.received
232
- end # select
233
- end # method missing_errors
234
-
235
- def missing_messages
236
- @error_expectations.select do |error_expectation|
237
- !error_expectation.messages.missing.empty?
238
- end # select
239
- end # method missing_messages
240
-
241
- def unexpected_errors
242
- @error_expectations.select do |error_expectation|
243
- !error_expectation.expected && error_expectation.received
244
- end # select
245
- end # method unexpected_errors
246
-
247
- def expected_errors_message
248
- "\n expected errors:" + expected_errors.map do |error_expectation|
249
- "\n #{error_expectation.attribute}: " + (error_expectation.messages.empty? ?
250
- "(#{@negative_expectation ? 'none' : 'any'})" :
251
- error_expectation.messages.expected.map(&:message).map(&:inspect).join(", "))
252
- end.join # map
253
- end # method expected_errors_message
254
-
255
- def received_errors_message
256
- return "" unless @validates
257
-
258
- return "\n received errors:\n (none)" if @actual.errors.messages.empty?
259
-
260
- "\n received errors:" + @actual.errors.messages.map do |attr, ary|
261
- "\n #{attr}: " + ary.map(&:inspect).join(", ")
262
- end.join # map
263
- end # method received_errors_message
264
- end # class
265
-
266
- module RSpec::SleepingKingStudios::Matchers
267
- # @see RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher#matches?
268
- def have_errors
269
- RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher.new
270
- end # method have_errors
271
- end # module
3
+ require 'rspec/sleeping_king_studios/matchers/active_model/have_errors_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/macros'
5
+
6
+ module RSpec::SleepingKingStudios::Matchers::Macros
7
+ # @see RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher#matches?
8
+ def have_errors
9
+ RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher.new
10
+ end # method have_errors
272
11
  end # module