rspec-sleeping_king_studios 1.0.0.rc.2

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 (35) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +323 -0
  4. data/lib/rspec/sleeping_king_studios.rb +5 -0
  5. data/lib/rspec/sleeping_king_studios/matchers.rb +5 -0
  6. data/lib/rspec/sleeping_king_studios/matchers/active_model.rb +5 -0
  7. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb +219 -0
  8. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors/error_expectation.rb +60 -0
  9. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors/message_expectation.rb +17 -0
  10. data/lib/rspec/sleeping_king_studios/matchers/active_model/have_errors/require.rb +7 -0
  11. data/lib/rspec/sleeping_king_studios/matchers/active_model/require.rb +8 -0
  12. data/lib/rspec/sleeping_king_studios/matchers/base_matcher.rb +43 -0
  13. data/lib/rspec/sleeping_king_studios/matchers/built_in.rb +5 -0
  14. data/lib/rspec/sleeping_king_studios/matchers/built_in/be_kind_of.rb +68 -0
  15. data/lib/rspec/sleeping_king_studios/matchers/built_in/include.rb +92 -0
  16. data/lib/rspec/sleeping_king_studios/matchers/built_in/require.rb +7 -0
  17. data/lib/rspec/sleeping_king_studios/matchers/built_in/respond_to.rb +187 -0
  18. data/lib/rspec/sleeping_king_studios/matchers/core.rb +5 -0
  19. data/lib/rspec/sleeping_king_studios/matchers/core/be_boolean.rb +41 -0
  20. data/lib/rspec/sleeping_king_studios/matchers/core/construct.rb +138 -0
  21. data/lib/rspec/sleeping_king_studios/matchers/core/have_property.rb +84 -0
  22. data/lib/rspec/sleeping_king_studios/matchers/core/have_reader.rb +76 -0
  23. data/lib/rspec/sleeping_king_studios/matchers/core/have_writer.rb +101 -0
  24. data/lib/rspec/sleeping_king_studios/matchers/core/require.rb +7 -0
  25. data/lib/rspec/sleeping_king_studios/matchers/meta.rb +5 -0
  26. data/lib/rspec/sleeping_king_studios/matchers/meta/fail_with_actual.rb +142 -0
  27. data/lib/rspec/sleeping_king_studios/matchers/meta/pass_with_actual.rb +96 -0
  28. data/lib/rspec/sleeping_king_studios/matchers/meta/require.rb +7 -0
  29. data/lib/rspec/sleeping_king_studios/matchers/require.rb +12 -0
  30. data/lib/rspec/sleeping_king_studios/matchers/shared/match_parameters.rb +69 -0
  31. data/lib/rspec/sleeping_king_studios/matchers/shared/require.rb +7 -0
  32. data/lib/rspec/sleeping_king_studios/mocks/custom_double.rb +13 -0
  33. data/lib/rspec/sleeping_king_studios/require.rb +7 -0
  34. data/lib/rspec/sleeping_king_studios/version.rb +7 -0
  35. metadata +151 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a201081c88d39452f78afa3150316e817901a52d
4
+ data.tar.gz: 1ea674d3e88024e1d945b17e1ecd10d5c09d722a
5
+ SHA512:
6
+ metadata.gz: ee4bdd1817d0d128b1e30304be501c63990545464bb7fa69dc272939073f487f26e5c32480aa7d00324c4d32d24a2cbc27738bb8ec374a671801ff09c03c1756
7
+ data.tar.gz: 8003b45634d319d7619a712dfece3d51df24e91394c294667e64e26e73770a2b99d6ae8986ded60be8902a055f5829a1fc25777d16f5a281d8ec2a404a47b523
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2013 Rob Smith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,323 @@
1
+ # RSpec::SleepingKingStudios
2
+
3
+ A collection of matchers and extensions to ease TDD/BDD using RSpec.
4
+
5
+ ## The Extensions
6
+
7
+ To enable an extension, simply require the associated file.
8
+
9
+ ### Mocks
10
+
11
+ These extensions support the creation and use of mock objects.
12
+
13
+ #### custom\_double
14
+
15
+ require 'rspec/sleeping_king_studios/mocks/custom_double'
16
+
17
+ As the built-in 'double' method, but accepts a block that is passed to
18
+ Class.new when the double is created, allowing you to create functional class
19
+ and instance methods on the double. Useful when you need to test a function or
20
+ sequence that repeatedly updates or checks the state of the injected object.
21
+
22
+ **How To Use:**
23
+
24
+ custom_double('My Double', :foo => "Foo") { attr_accessor :bar }
25
+
26
+ ## The Matchers
27
+
28
+ To enable a custom matcher, simply require the associated file. Matchers can be
29
+ required individually or by category:
30
+
31
+ require 'rspec/sleeping_king_studios/matchers/core'
32
+ #=> requires all of the core matchers
33
+
34
+ require 'rspec/sleeping_king_studios/matchers/core/construct'
35
+ #=> requires only the :construct matcher
36
+
37
+ ### ActiveModel
38
+
39
+ require 'rspec/sleeping_king_studios/matchers/active_model'
40
+
41
+ These matchers validate ActiveModel functionality, such as validations.
42
+
43
+ #### have\_errors Matcher
44
+
45
+ require 'rspec/sleeping_king_studios/matchers/active_model/have_errors'
46
+
47
+ Verifies that the actual object has validation errors. Optionally can specify
48
+ individual fields to validate, or even specific messages for each attribute.
49
+
50
+ **How To Use:**
51
+
52
+ expect(instance).to have_errors
53
+
54
+ expect(instance).to have_errors.on(:name)
55
+
56
+ expect(instance).to have_errors.on(:name).with_message('not to be nil')
57
+
58
+ **Chaining:**
59
+
60
+ * **on:** [String, Symbol] Adds a field to validate; the matcher only passes if
61
+ all validated fields have errors.
62
+ * **with\_message:** [String] Adds a message to the previously-defined field
63
+ validation. Raises ArgumentError if no field was previously set.
64
+
65
+ ### BuiltIn
66
+
67
+ require 'rspec/sleeping_king_studios/matchers/built_in'
68
+
69
+ These extend the built-in RSpec matchers with additional functionality.
70
+
71
+ #### be\_kind\_of Matcher
72
+
73
+ require 'rspec/sleeping_king_studios/matchers/built_in/be_kind_of'
74
+
75
+ Now accepts an Array of types. The matcher passes if the actual object is
76
+ any of the parameter types.
77
+
78
+ Also allows nil parameter as a shortcut for NilClass.
79
+
80
+ **How To Use:**
81
+
82
+ expect(instance).to be_kind_of [String, Symbol, nil]
83
+ #=> passes iff instance is a String, a Symbol, or is nil
84
+
85
+ #### include Matcher
86
+
87
+ require 'rspec/sleeping_king_studios/matchers/built_in/include'
88
+
89
+ Now accepts Proc parameters; items in the actual object are passed into
90
+ proc#call, with a truthy response considered a match to the item. In addition,
91
+ now accepts an optional block as a shortcut for adding a proc expectation.
92
+
93
+ **How To Use:**
94
+
95
+ expect(instance).to include { |item| item =~ /pattern/ }
96
+
97
+ #### respond\_to Matcher
98
+
99
+ require 'rspec/sleeping_king_studios/matchers/built_in/respond_to'
100
+
101
+ Now has additional chaining functionality to validate the number of arguments
102
+ accepted by the method, and whether the method accepts a block argument.
103
+
104
+ **How To Use:**
105
+
106
+ expect(instance).to respond_to(:foo).with(2..3).arguments.and.a_block
107
+
108
+ **Chaining:**
109
+
110
+ * **a\_block:** No parameters. Verifies that the method requires a block
111
+ argument of the form &my_argument. _Important note:_ A negative result does
112
+ _not* mean the method cannot accept a block, merely that it does not require
113
+ one. Also, does _not_ check whether the block is called or yielded.
114
+ * **with:** Expects one Integer or Range argument. If an Integer, verifies that
115
+ the method accepts that number of arguments; if a Range, verifies that the
116
+ method accepts both the minimum and maximum number of arguments.
117
+
118
+ ##### Ruby 2.0
119
+
120
+ Has additional functionality to support Ruby 2.0 keyword arguments.
121
+
122
+ **How To Use:**
123
+ expect(instance).to respond_to(:foo).with(0, :bar, :baz)
124
+
125
+ **Chaining:**
126
+
127
+ * **with:** Expects one Integer, Range, or nil argument, and zero or more
128
+ Symbol arguments corresponding to optional keywords. Verifies that the method
129
+ accepts that keyword, or has a variadic keyword of the form \*\*params.
130
+
131
+ _Important note:_ If you do not wish to validate the number of arguments,
132
+ make sure to use nil as the first argument to #with; otherwise, the matcher
133
+ will interpret your first keyword as the number of arguments to expect. And
134
+ then explode.
135
+
136
+ ### Core
137
+
138
+ require 'rspec/sleeping_king_studios/matchers/core'
139
+
140
+ These matchers check core functionality, such as object boolean-ness, the
141
+ existence of properties, and so on.
142
+
143
+ #### be_boolean Matcher
144
+
145
+ require 'rspec/sleeping_king_studios/matchers/core/be_boolean'
146
+
147
+ Checks if the provided object is true or false.
148
+
149
+ **How To Use:**
150
+
151
+ expect(object).to be_boolean
152
+
153
+ **Parameters:** None.
154
+
155
+ #### construct Matcher
156
+
157
+ require 'rspec/sleeping_king_studios/matchers/core/construct'
158
+
159
+ Verifies that the actual object can be constructed using :new. Can take an
160
+ optional number of arguments.
161
+
162
+ **How To Use:**
163
+
164
+ expect(described_class).to construct.with(1).arguments
165
+
166
+ **Parameters:** None.
167
+
168
+ **Chaining:**
169
+
170
+ * **with:** Expects one Integer or Range argument. If an Integer, verifies that
171
+ the class's constructor accepts that number of arguments; if a Range,
172
+ verifies that the constructor accepts both the minimum and maximum number of
173
+ arguments.
174
+
175
+ ##### Ruby 2.0
176
+
177
+ Has additional functionality to support Ruby 2.0 keyword arguments.
178
+
179
+ **How To Use:**
180
+ expect(instance).to construct.with(0, :bar, :baz)
181
+
182
+ **Chaining:**
183
+
184
+ * **with:** Expects one Integer, Range, or nil argument, and zero or more
185
+ Symbol arguments corresponding to optional keywords. Verifies that the
186
+ class's constructor accepts that keyword, or has a variadic keyword of the
187
+ form \*\*params.
188
+
189
+ _Important note:_ If you do not wish to validate the number of arguments,
190
+ make sure to use nil as the first argument to #with; otherwise, the matcher
191
+ will interpret your first keyword as the number of arguments to expect. And
192
+ then explode.
193
+
194
+ #### have\_property Matcher
195
+
196
+ require 'rspec/sleeping_king_studios/matchers/core/have_property'
197
+
198
+ Checks if the actual object responds to :property and :property=, and
199
+ optionally if a value written to actual.property= can then be read by
200
+ actual.property.
201
+
202
+ **How To Use:**
203
+
204
+ expect(instance).to have_property(:foo).with("foo")
205
+
206
+ **Parameters:** Property. Expects a string or symbol that is a valid
207
+ identifier.
208
+
209
+ **Chaining:**
210
+
211
+ * **with:** Expects one object, which is written to actual.property= and then
212
+ read from actual.property.
213
+
214
+ #### have\_reader Matcher
215
+
216
+ require 'rspec/sleeping_king_studios/matchers/core/have_reader'
217
+
218
+ Checks if the actual object responds to :property, and optionally if the
219
+ current value of actual.property is equal to a specified value.
220
+
221
+ **How To Use:**
222
+
223
+ expect(instance).to have_reader(:foo).with("foo")
224
+
225
+ **Parameters:** Property. Expects a string or symbol that is a valid
226
+ identifier.
227
+
228
+ **Chaining:**
229
+
230
+ * **with:** Expects one object, which is checked against the current value of
231
+ actual.property if actual responds to :property.
232
+
233
+ #### have\_writer Matcher
234
+
235
+ require 'rspec/sleeping_king_studios/matchers/core/have_writer'
236
+
237
+ Checks if the actual object responds to :property=, and optionally if setting
238
+ object.property = value sets object.property to value.
239
+
240
+ **How To Use:**
241
+
242
+ expect(instance).to have_writer(:foo=).with("foo")
243
+
244
+ **Parameters:** Property. Expects a string or symbol that is a valid
245
+ identifier. An equals sign '=' is automatically added if the identifier does
246
+ not already terminate in '='.
247
+
248
+ **Chaining:**
249
+
250
+ * **with:** Expects one object. The matcher attempts to set the actual's value
251
+ using actual.property=, then compare the value with actual.property.
252
+
253
+ _Note:_ Currently, write-only properties cannot be checked using with().
254
+ Attempting to do so will raise an exception.
255
+
256
+ #### include\_matching Matcher
257
+
258
+ require 'rspec/sleeping_king_studios/matchers/core/include_matching'
259
+
260
+ Loops through an enumerable actual object and checks if any of the items
261
+ matches the given pattern.
262
+
263
+ **How To Use:**
264
+
265
+ expect(instance).to include_matching(/[01]+/)
266
+
267
+ **Parameters:** Pattern. Expects a Regexp.
268
+
269
+ ### Meta
270
+
271
+ require 'rspec/sleeping_king_studios/matchers/meta'
272
+
273
+ These meta-matchers are used to test other custom matchers.
274
+
275
+ #### fail\_with\_actual Matcher
276
+
277
+ require 'rspec/sleeping_king_studios/matchers/meta/fail_with_actual'
278
+
279
+ Checks if the given matcher will fail to match a specified actual object. Can
280
+ take an optional string to check the expected failure message when the matcher
281
+ is expected to pass, but does not.
282
+
283
+ _Note:_ Do not use the not\_to syntax for this matcher; instead, use the
284
+ pass\_with\_actual matcher, below.
285
+
286
+ **How To Use:**
287
+
288
+ expect(matcher).to fail_with_actual(actual).with_message(/expected to/)
289
+
290
+ **Parameters:** Matcher. Expects an object that, at minimum, responds to
291
+ :matches? and :failure\_message\_for\_should.
292
+
293
+ **Chaining:**
294
+
295
+ * **with\_message:** Expects one String or Regexp argument, which is matched
296
+ against the given matcher's failure\_message\_for\_should.
297
+
298
+ #### pass\_with\_actual Matcher
299
+
300
+ require 'rspec/sleeping_king_studios/matchers/meta/pass_with_actual'
301
+
302
+ Checks if the given matcher will match a specified actual object. Can take an
303
+ optional string to check the expected failure message when the matcher is
304
+ expected to fail, but does not.
305
+
306
+ _Note:_ Do not use the not\_to syntax for this matcher; instead, use the
307
+ fail\_with\_actual matcher, above.
308
+
309
+ **How To Use:**
310
+
311
+ expect(matcher).to pass_with_actual(actual)
312
+
313
+ **Parameters:** Matcher. Expects an object that, at minimum, responds to
314
+ :matches? and :failure\_message\_for\_should\_not.
315
+
316
+ **Chaining:**
317
+
318
+ * **with\_message:** Expects one String or Regexp argument, which is matched
319
+ against the given matcher's failure\_message\_for\_should\_not.
320
+
321
+ ## License
322
+
323
+ RSpec::SleepingKingStudios is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,5 @@
1
+ # lib/rspec/sleeping_king_studios.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers'
4
+
5
+ require 'rspec/sleeping_king_studios/mocks/custom_double'
@@ -0,0 +1,5 @@
1
+ # lib/rspec/sleeping_king_studios/matchers.rb
2
+
3
+ %w(active_model built_in core meta).each do |dir_name|
4
+ require File.join File.dirname(__FILE__), 'matchers', dir_name
5
+ end # each
@@ -0,0 +1,5 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/active_model.rb
2
+
3
+ Dir[File.join File.dirname(__FILE__), 'active_model', '*.rb'].each do |file|
4
+ require file
5
+ end # end each
@@ -0,0 +1,219 @@
1
+ # lib/rspec/sleeping_king_studios/matchers/active_model/have_errors.rb
2
+
3
+ require 'rspec/sleeping_king_studios/matchers/base_matcher'
4
+ require 'rspec/sleeping_king_studios/matchers/active_model/require'
5
+ require 'rspec/sleeping_king_studios/matchers/active_model/have_errors/error_expectation'
6
+
7
+ module RSpec::SleepingKingStudios::Matchers::ActiveModel
8
+ # Matcher for testing ActiveModel object validations.
9
+ #
10
+ # @since 1.0.0
11
+ class HaveErrorsMatcher < RSpec::SleepingKingStudios::Matchers::BaseMatcher
12
+ include RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrors
13
+
14
+ def initialize
15
+ super
16
+
17
+ # The error and message expectations set up through #on and
18
+ # #with_message.
19
+ @error_expectations = []
20
+ end # constructor
21
+
22
+ # Checks if the object can be validated, whether the object is valid, and
23
+ # checks the errors on the object against the expected errors and messages
24
+ # from #on and #with_message, if any.
25
+ #
26
+ # @param [Object] actual the object to test against the matcher
27
+ #
28
+ # @return [Boolean] true if the object responds to :valid?, is not valid,
29
+ # and object.errors matches the specified errors and messages (if any);
30
+ # otherwise false
31
+ # @see RSpec::SleepingKingStudios::Matchers::BaseMatcher#matches?
32
+ def matches? actual
33
+ super
34
+
35
+ return false unless @validates = actual.respond_to?(:valid?)
36
+
37
+ @actual.invalid? && attributes_have_errors?
38
+ end # method matches?
39
+
40
+ # Adds an error expectation. If the actual object does not have an error on
41
+ # the specified attribute, #matches? will return false.
42
+ #
43
+ # @param [String, Symbol] attribute
44
+ #
45
+ # @return [HaveErrorsMatcher] self
46
+ #
47
+ # @example Setting an error expectation
48
+ # expect(actual).to have_errors.on(:foo)
49
+ def on attribute
50
+ @error_expectations << ErrorExpectation.new(attribute)
51
+
52
+ self
53
+ end # method on
54
+
55
+ # Adds a message expectation for the most recently added error attribute.
56
+ # If the actual object does not have an error on the that attribute with
57
+ # the specified message, #matches? will return false.
58
+ #
59
+ # @param [String, Regexp] message the expected error message. If a string,
60
+ # matcher will check for an exact match; if a regular expression, matcher
61
+ # will check if the message matches the regexp
62
+ #
63
+ # @raise [ArgumentError] if no error attribute has been added
64
+ #
65
+ # @return [HaveErrorsMatcher] self
66
+ #
67
+ # @example Setting an error and a message expectation
68
+ # expect(actual).to have_errors.on(:foo).with("can't be blank")
69
+ #
70
+ # @see #on
71
+ def with_message message
72
+ raise ArgumentError.new "no attribute specified for error message" if
73
+ @error_expectations.empty?
74
+
75
+ @error_expectations.last.messages << MessageExpectation.new(message)
76
+
77
+ self
78
+ end # method with_message
79
+
80
+ # Adds a set of message expectations for the most recently added error
81
+ # attribute.
82
+ #
83
+ # @param [Array<String, Regexp>] messages
84
+ #
85
+ # @see #with_message
86
+ def with_messages *messages
87
+ messages.each do |message| self.with_message(message); end
88
+
89
+ self
90
+ end # method with_message
91
+
92
+ # @see BaseMatcher#failure_message_for_should
93
+ def failure_message_for_should
94
+ # Failure cases:
95
+ # * object is not a model ("to respond to valid")
96
+ # * expected one or more errors, but received none ("to have errors")
97
+ # * expected one or more messages on :attribute, but received none or a
98
+ # subset ("to have errors on")
99
+
100
+ if !@validates
101
+ "expected #{@actual.inspect} to respond to :valid?"
102
+ elsif expected_errors.empty?
103
+ "expected #{@actual.inspect} to have errors"
104
+ else
105
+ "expected #{@actual.inspect} to have errors#{expected_errors_message}#{received_errors_message}"
106
+ end # if-elsif-else
107
+ end # method failure_message_for_should
108
+
109
+ # @see BaseMatcher#failure_message_for_should_not
110
+ def failure_message_for_should_not
111
+ # Failure cases:
112
+ # * expected one or more errors, received one or more ("not to have
113
+ # errors")
114
+ # * expected one or more messages on attribute, received one or more
115
+ # ("not to have errors on")
116
+ # * expected specific messages on attribute, received all ("not to have
117
+ # errors on")
118
+
119
+ if expected_errors.empty?
120
+ return "expected #{@actual.inspect} not to have errors#{received_errors_message}"
121
+ else
122
+ return "expected #{@actual.inspect} not to have errors#{expected_errors_message}#{received_errors_message}"
123
+ end # if-else
124
+ end # method failure_message_for_should_not
125
+
126
+ private
127
+
128
+ def attributes_have_errors?
129
+ # Iterate through the received errors and match them against the expected
130
+ # errors and messages.
131
+ @actual.errors.messages.each do |attribute, messages|
132
+ # Find the matching error expectation, if any.
133
+ error_expectation = @error_expectations.detect do |error_expectation|
134
+ error_expectation.attribute == attribute
135
+ end # detect
136
+
137
+ if error_expectation
138
+ error_expectation.received = true
139
+
140
+ # If the error includes message expectations, iterate through the
141
+ # received messages.
142
+ unless error_expectation.messages.empty?
143
+ messages.each do |message|
144
+ # Find the matching message expectation, if any.
145
+ message_expectation = error_expectation.messages.detect do |message_expectation|
146
+ if Regexp === message_expectation.message
147
+ message =~ message_expectation.message
148
+ else
149
+ message == message_expectation.message
150
+ end # if-else
151
+ end # detect
152
+
153
+ if message_expectation
154
+ message_expectation.received = true
155
+ else
156
+ error_expectation.messages << MessageExpectation.new(message, false, true)
157
+ end # if-else
158
+ end # each
159
+ end # unless
160
+ else
161
+ error_expectation = ErrorExpectation.new attribute, false, true
162
+ messages.each do |message|
163
+ error_expectation.messages << MessageExpectation.new(message, false, true)
164
+ end # each
165
+
166
+ @error_expectations << error_expectation
167
+ end # if-else
168
+ end # each
169
+
170
+ missing_errors.empty? && missing_messages.empty?
171
+ end # method attributes_have_errors
172
+
173
+ def expected_errors
174
+ @error_expectations.select do |error_expectation|
175
+ error_expectation.expected
176
+ end # select
177
+ end # method expected_errors
178
+
179
+ def missing_errors
180
+ @error_expectations.select do |error_expectation|
181
+ error_expectation.expected && !error_expectation.received
182
+ end # select
183
+ end # method missing_errors
184
+
185
+ def missing_messages
186
+ @error_expectations.select do |error_expectation|
187
+ !error_expectation.messages.missing.empty?
188
+ end # select
189
+ end # method missing_messages
190
+
191
+ def unexpected_errors
192
+ @error_expectations.select do |error_expectation|
193
+ !error_expectation.expected && error_expectation.received
194
+ end # select
195
+ end # method unexpected_errors
196
+
197
+ def expected_errors_message
198
+ "\n expected errors:" + expected_errors.map do |error_expectation|
199
+ "\n #{error_expectation.attribute}: " + (error_expectation.messages.empty? ?
200
+ "(any)" :
201
+ error_expectation.messages.expected.map(&:message).map(&:inspect).join(", "))
202
+ end.join # map
203
+ end # method expected_errors_message
204
+
205
+ def received_errors_message
206
+ return "" unless @validates
207
+ "\n received errors:" + @actual.errors.messages.map do |attr, ary|
208
+ "\n #{attr}: " + ary.map(&:inspect).join(", ")
209
+ end.join # map
210
+ end # method received_errors_message
211
+ end # class
212
+
213
+ module RSpec::SleepingKingStudios::Matchers
214
+ # @see RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher#matches?
215
+ def have_errors
216
+ RSpec::SleepingKingStudios::Matchers::ActiveModel::HaveErrorsMatcher.new
217
+ end # method have_errors
218
+ end # module
219
+ end # module