mongoid-rspec 4.1.0 → 4.3.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +54 -7
  3. data/Rakefile +3 -4
  4. data/lib/matchers/accept_nested_attributes.rb +2 -0
  5. data/lib/matchers/allow_mass_assignment.rb +2 -0
  6. data/lib/matchers/associations.rb +25 -8
  7. data/lib/matchers/be_dynamic_document.rb +2 -0
  8. data/lib/matchers/be_mongoid_document.rb +2 -0
  9. data/lib/matchers/be_stored_in.rb +2 -0
  10. data/lib/matchers/have_field.rb +5 -3
  11. data/lib/matchers/have_timestamps.rb +5 -3
  12. data/lib/matchers/indexes/have_index_for.rb +2 -0
  13. data/lib/matchers/indexes/v3/have_index_for.rb +4 -2
  14. data/lib/matchers/indexes/v4/have_index_for.rb +3 -1
  15. data/lib/matchers/validations/absence_of.rb +2 -0
  16. data/lib/matchers/validations/acceptance_of.rb +2 -0
  17. data/lib/matchers/validations/associated.rb +2 -0
  18. data/lib/matchers/validations/confirmation_of.rb +2 -0
  19. data/lib/matchers/validations/custom_validation_of.rb +4 -2
  20. data/lib/matchers/validations/exclusion_of.rb +5 -3
  21. data/lib/matchers/validations/format_of.rb +2 -0
  22. data/lib/matchers/validations/inclusion_of.rb +2 -0
  23. data/lib/matchers/validations/length_of.rb +2 -0
  24. data/lib/matchers/validations/numericality_of.rb +2 -0
  25. data/lib/matchers/validations/presence_of.rb +2 -0
  26. data/lib/matchers/validations/uniqueness_of.rb +2 -0
  27. data/lib/matchers/validations.rb +43 -7
  28. data/lib/mongoid/rspec/version.rb +3 -1
  29. data/lib/mongoid/rspec.rb +2 -0
  30. data/lib/mongoid-rspec.rb +2 -0
  31. metadata +58 -95
  32. data/spec/models/article.rb +0 -32
  33. data/spec/models/comment.rb +0 -6
  34. data/spec/models/log.rb +0 -9
  35. data/spec/models/message.rb +0 -17
  36. data/spec/models/movie_article.rb +0 -7
  37. data/spec/models/permalink.rb +0 -5
  38. data/spec/models/person.rb +0 -10
  39. data/spec/models/profile.rb +0 -16
  40. data/spec/models/record.rb +0 -5
  41. data/spec/models/site.rb +0 -13
  42. data/spec/models/user.rb +0 -38
  43. data/spec/spec_helper.rb +0 -35
  44. data/spec/unit/accept_nested_attributes_spec.rb +0 -12
  45. data/spec/unit/associations_spec.rb +0 -54
  46. data/spec/unit/be_dynamic_document_spec.rb +0 -21
  47. data/spec/unit/be_mongoid_document_spec.rb +0 -25
  48. data/spec/unit/be_stored_in.rb +0 -54
  49. data/spec/unit/document_spec.rb +0 -17
  50. data/spec/unit/have_index_for_spec.rb +0 -46
  51. data/spec/unit/have_timestamps_spec.rb +0 -71
  52. data/spec/unit/validations_spec.rb +0 -61
  53. data/spec/validators/ssn_validator.rb +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c59448b4e72ebb718332a28e7ddf77de5b792a09ea273b75959930e2c6c2918
4
- data.tar.gz: b1818ed7a513db7a4e31bcdd5a492504a75becfc866dd95505192da1db7a56cc
3
+ metadata.gz: 0ff9e91940ac839c482f01b93f825a4f30ed64dcf3f4210053a5cac6a490cbbc
4
+ data.tar.gz: 73b94988e7950e2097427412e1c4af87a1413cf891085a53a71924bbae9466ca
5
5
  SHA512:
6
- metadata.gz: 995c284d71146d52d554e8eff18e48605e76546ebce9428674d1fcefe4c560a73973651f4eb4496d21a839fb35944c37f98cc21eb78ddd1e1eea80a57d1392c4
7
- data.tar.gz: a2e400ead572f31c614a294f1d5d10116e08fa6f152b2f58cf112da45608a3d72be2c5893ceb035c8a6f514af8ef55bcfdffd0a55a81a2e0f97ad43fd0699cf2
6
+ metadata.gz: 14504bfe14678c3c4df1eb85438438ab5b705f22ad36bc209bfd15d1bbeb4cc59ab09c0e8227682f8960f8db6cadc7c8731e8ab617d7f1d075e98f06a1085bdc
7
+ data.tar.gz: 4ae265834c188a9236e6c697345f70c5e16fc27c250076c72486030ae3ebc3cb62f1da00df5fefbf5bfd8dabb4e8dd29c26d80d26a1638e9a7e58d8824c2aa03
data/README.md CHANGED
@@ -1,10 +1,20 @@
1
1
  # [mongoid-rspec](https://github.com/mongoid/mongoid-rspec "A collection of RSpec-compatible matchers that help to test Mongoid documents.")
2
2
 
3
- [![Build Status](https://travis-ci.org/mongoid/mongoid-rspec.svg?branch=master)](https://travis-ci.org/mongoid/mongoid-rspec)
4
3
  [![Gem Version](https://badge.fury.io/rb/mongoid-rspec.svg)](https://badge.fury.io/rb/mongoid-rspec)
4
+ [![Test Status](https://github.com/mongoid/mongoid-rspec/actions/workflows/rspec.yml/badge.svg?branch=master)](https://github.com/mongoid/mongoid-rspec/actions/workflows/rspec.yml?query=branch%3Amaster)
5
+ [![Rubocop Status](https://github.com/mongoid/mongoid-rspec/actions/workflows/rubocop.yml/badge.svg?branch=master)](https://github.com/mongoid/mongoid-rspec/actions/workflows/rubocop.yml?query=branch%3Amaster)
6
+ [![Coverage Status](https://coveralls.io/repos/github/mongoid/mongoid-rspec/badge.svg?branch=master)](https://coveralls.io/github/mongoid/mongoid-rspec?branch=master)
7
+
8
+ CI collects SimpleCov coverage on Ruby 3.4 with Mongoid 9 and MongoDB 8.0 and submits one report to Coveralls using GitHub's workflow token. To generate a local report, run `COVERAGE=true BUNDLE_GEMFILE=gemfiles/mongoid_9.gemfile bundle install` followed by `COVERAGE=true BUNDLE_GEMFILE=gemfiles/mongoid_9.gemfile bundle exec rake spec`. Reports are written to `coverage/`.
5
9
 
6
10
  The mongoid-rspec library provides a collection of RSpec-compatible matchers that help to test Mongoid documents.
7
11
 
12
+ [Tested](https://github.com/mongoid/mongoid-rspec/actions/workflows/rspec.yml) against:
13
+ - MRI: `2.6.x`, `2.7.x`, `3.0.x`, `3.1.x`, `3.2.x`
14
+ - Mongoid: `4`, `5`, `6`, `7`, `8`, `9`
15
+
16
+ See [.github/workflows/rspec.yml](.github/workflows/rspec.yml) for the latest test matrix.
17
+
8
18
  ## Installation
9
19
 
10
20
  Drop this line into your Gemfile:
@@ -18,7 +28,7 @@ end
18
28
 
19
29
  ## Compatibility
20
30
 
21
- This gem is compatible with Mongoid 3, 4, 5, 6 and 7.
31
+ This gem is compatible with Mongoid 3, 4, 5, 6, 7, 8, 9.
22
32
 
23
33
  ## Configuration
24
34
 
@@ -181,7 +191,7 @@ end
181
191
 
182
192
  ```ruby
183
193
  class Article
184
- index({ title: 1 }, { unique: true, background: true, drop_dups: true })
194
+ index({ title: 1 }, { unique: true, background: true })
185
195
  index({ title: 1, created_at: -1 })
186
196
  index({ category: 1 })
187
197
  end
@@ -190,7 +200,7 @@ RSpec.describe Article, type: :model do
190
200
  it do
191
201
  is_expected
192
202
  .to have_index_for(title: 1)
193
- .with_options(unique: true, background: true, drop_dups: true)
203
+ .with_options(unique: true, background: true)
194
204
  end
195
205
  it { is_expected.to have_index_for(title: 1, created_at: -1) }
196
206
  it { is_expected.to have_index_for(category: 1) }
@@ -201,9 +211,9 @@ end
201
211
 
202
212
  ```ruby
203
213
  RSpec.describe Article do
204
- it { is_expected.to have_field(:published).of_type(Boolean).with_default_value_of(false) }
205
- it { is_expected.to have_field(:allow_comments).of_type(Boolean).with_default_value_of(true) }
206
- it { is_expected.not_to have_field(:allow_comments).of_type(Boolean).with_default_value_of(false) }
214
+ it { is_expected.to have_field(:published).of_type(Mongoid::Boolean).with_default_value_of(false) }
215
+ it { is_expected.to have_field(:allow_comments).of_type(Mongoid::Boolean).with_default_value_of(true) }
216
+ it { is_expected.not_to have_field(:allow_comments).of_type(Mongoid::Boolean).with_default_value_of(false) }
207
217
  it { is_expected.not_to have_field(:number_of_comments).of_type(Integer).with_default_value_of(1) }
208
218
  end
209
219
 
@@ -249,6 +259,27 @@ RSpec.describe Article do
249
259
  it { is_expected.to embed_many(:comments) }
250
260
  end
251
261
 
262
+ # when the touch option is provided, then we can also verify that it is set
263
+
264
+ # by default, with_touch matches true when no parameters are provided
265
+ describe Article do
266
+ it { is_expected.to belong_to(:author).of_type(User).as_inverse_of(:articles).with_index.with_touch }
267
+ end
268
+
269
+ # parameters are supported for explicit matching
270
+ describe Comment do
271
+ it { is_expected.to be_embedded_in(:article).as_inverse_of(:comments).with_polymorphism.with_touch(true) }
272
+ end
273
+
274
+ describe Permalink do
275
+ it { is_expected.to be_embedded_in(:linkable).as_inverse_of(:link).with_touch(false) }
276
+ end
277
+
278
+ # touch can also take a symbol representing a field on the parent to touch
279
+ describe Record do
280
+ it { is_expected.to belong_to(:user).as_inverse_of(:record).with_touch(:record_updated_at) }
281
+ end
282
+
252
283
  RSpec.describe Comment do
253
284
  it { is_expected.to be_embedded_in(:article).as_inverse_of(:comments) }
254
285
  it { is_expected.to belong_to(:user).as_inverse_of(:comments) }
@@ -315,6 +346,22 @@ RSpec.describe Person do
315
346
  # should redefine the kind method to return :custom, i.e. "def self.kind() :custom end"
316
347
  it { is_expected.to custom_validate(:ssn).with_validator(SsnValidator) }
317
348
  end
349
+
350
+ # If you're using validators with if/unless conditionals, spec subject must be object instance
351
+ # This is supported on Mongoid 4 and newer
352
+ Rspec.describe User do
353
+ context 'when user has `admin` role' do
354
+ subject { User.new(role: 'admin') }
355
+
356
+ it { is_expected.to validate_length_of(:password).greater_than(20) }
357
+ end
358
+
359
+ context 'when user does not have `admin` role' do
360
+ subject { User.new(role: 'member') }
361
+
362
+ it { is_expected.not_to validate_length_of(:password) }
363
+ end
364
+ end
318
365
  ```
319
366
 
320
367
  ### Mass Assignment Matcher
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
4
 
3
5
  require 'bundler'
@@ -14,7 +16,4 @@ RSpec::Core::RakeTask.new(:rcov) do |spec|
14
16
  spec.rcov = true
15
17
  end
16
18
 
17
- require 'rubocop/rake_task'
18
- RuboCop::RakeTask.new(:rubocop)
19
-
20
- task default: %i[rubocop spec]
19
+ task default: %i[spec]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers # :nodoc:
3
5
  # Ensures that the model can accept nested attributes for the specified
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # this code is totally extracted from shoulda-matchers gem.
2
4
  module Mongoid
3
5
  module Matchers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if Mongoid::Compatibility::Version.mongoid7_or_newer?
2
4
  require 'mongoid/association'
3
5
  else
@@ -30,7 +32,7 @@ module Mongoid
30
32
  @association = {}
31
33
  @association[:name] = name.to_s
32
34
  @association[:type] = association_type
33
- @expectation_message = "#{type_description} #{@association[:name].inspect}"
35
+ @expectation_message = +"#{type_description} #{@association[:name].inspect}"
34
36
  @expectation_message << " of type #{@association[:class].inspect}" unless @association[:class].nil?
35
37
  end
36
38
 
@@ -119,6 +121,12 @@ module Mongoid
119
121
  self
120
122
  end
121
123
 
124
+ def with_touch(touch = true)
125
+ @association[:touch] = touch
126
+ @expectation_message << " which specifies touch as #{@association[:touch]}"
127
+ self
128
+ end
129
+
122
130
  def with_optional
123
131
  @association[:optional] = true
124
132
  @expectation_message << " which specifies optional as #{@association[:optional]}"
@@ -272,6 +280,15 @@ module Mongoid
272
280
  end
273
281
  end
274
282
 
283
+ unless @association[:touch].nil?
284
+ if metadata.options[:touch] != @association[:touch]
285
+ @negative_result_message = "#{@positive_result_message} which sets touch as #{metadata.options[:touch].inspect}"
286
+ return false
287
+ else
288
+ @positive_result_message = "#{@positive_result_message} which sets touch as #{metadata.options[:touch].inspect}"
289
+ end
290
+ end
291
+
275
292
  if @association[:optional]
276
293
  if metadata.options[:optional] != true
277
294
  @negative_result_message = "#{@positive_result_message} which did not set optional"
@@ -303,19 +320,19 @@ module Mongoid
303
320
  type ||= @association[:type]
304
321
  case type.name
305
322
  when EMBEDS_ONE.name
306
- (passive ? 'embed' : 'embeds') << ' one'
323
+ +(passive ? 'embed' : 'embeds') << ' one'
307
324
  when EMBEDS_MANY.name
308
- (passive ? 'embed' : 'embeds') << ' many'
325
+ +(passive ? 'embed' : 'embeds') << ' many'
309
326
  when EMBEDDED_IN.name
310
- (passive ? 'be' : 'is') << ' embedded in'
327
+ +(passive ? 'be' : 'is') << ' embedded in'
311
328
  when HAS_ONE.name
312
- (passive ? 'reference' : 'references') << ' one'
329
+ +(passive ? 'reference' : 'references') << ' one'
313
330
  when HAS_MANY.name
314
- (passive ? 'reference' : 'references') << ' many'
331
+ +(passive ? 'reference' : 'references') << ' many'
315
332
  when HAS_AND_BELONGS_TO_MANY.name
316
- (passive ? 'reference' : 'references') << ' and referenced in many'
333
+ +(passive ? 'reference' : 'references') << ' and referenced in many'
317
334
  when BELONGS_TO.name
318
- (passive ? 'be referenced in' : 'referenced in')
335
+ +(passive ? 'be referenced in' : 'referenced in')
319
336
  else
320
337
  raise format("Unknown association type '%s'", type)
321
338
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  def be_dynamic_document
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  def be_mongoid_document
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  def be_stored_in(options)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  class HaveField # :nodoc:
@@ -30,7 +32,7 @@ module Mongoid
30
32
  @errors = []
31
33
  @attributes.each do |attr|
32
34
  if @klass.fields.include?(attr)
33
- error = ''
35
+ error = +''
34
36
  if @type && (@klass.fields[attr].type != @type)
35
37
  error << " of type #{@klass.fields[attr].type}"
36
38
  end
@@ -47,7 +49,7 @@ module Mongoid
47
49
  error << " with alias #{@klass.fields[attr].options[:as]}"
48
50
  end
49
51
 
50
- @errors.push("field #{attr.inspect}" << error) unless error.blank?
52
+ @errors.push("field #{attr.inspect}#{error}") unless error.blank?
51
53
 
52
54
  if @localized
53
55
  unless @klass.fields[attr].localized?
@@ -74,7 +76,7 @@ module Mongoid
74
76
  alias failure_message_when_negated failure_message_for_should_not
75
77
 
76
78
  def description
77
- desc = "have #{@attributes.size > 1 ? 'fields' : 'field'} named #{@attributes.collect(&:inspect).to_sentence}"
79
+ desc = +"have #{@attributes.size > 1 ? 'fields' : 'field'} named #{@attributes.collect(&:inspect).to_sentence}"
78
80
  desc << " of type #{@type.inspect}" if @type
79
81
  desc << " with alias #{@field_alias}" if @field_alias
80
82
  desc << " with default value of #{@default.inspect}" unless @default.nil?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  def have_timestamps
@@ -6,7 +8,7 @@ module Mongoid
6
8
 
7
9
  class HaveTimestamps
8
10
  def initialize
9
- @root_module = 'Mongoid::Timestamps'
11
+ @root_module = +'Mongoid::Timestamps'
10
12
  end
11
13
 
12
14
  def matches?(actual)
@@ -15,7 +17,7 @@ module Mongoid
15
17
  end
16
18
 
17
19
  def for(phase)
18
- raise('You\'ve already declared timetamp\'s sub-module via "for" clause') if @submodule
20
+ raise('You\'ve already declared timestamp\'s sub-module via "for" clause') if @submodule
19
21
 
20
22
  case @phase = phase.to_sym
21
23
  when :creating then @submodule = 'Created'
@@ -33,7 +35,7 @@ module Mongoid
33
35
  end
34
36
 
35
37
  def description
36
- desc = 'be a Mongoid document with'
38
+ desc = +'be a Mongoid document with'
37
39
  desc << ' shorted' if @shortened
38
40
  desc << " #{@phase}" if @phase
39
41
  desc << ' timestamps'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  class HaveIndexForBase
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  def have_index_for(index_key)
@@ -36,7 +38,7 @@ module Mongoid
36
38
  alias failure_message_when_negated failure_message_for_should_not
37
39
 
38
40
  def description
39
- desc = "have an index for #{index_key.inspect}"
41
+ desc = +"have an index for #{index_key.inspect}"
40
42
  desc << " with options of #{index_options.inspect}" if index_options
41
43
  desc
42
44
  end
@@ -44,7 +46,7 @@ module Mongoid
44
46
  private
45
47
 
46
48
  MAPPINGS = {
47
- dropDups: :drop_dups
49
+ dropDups: :drop_dups # Deprecated from MongoDB 3.0
48
50
  }.freeze
49
51
 
50
52
  def denormalising_options(opts)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  def have_index_for(index_key)
@@ -15,7 +17,7 @@ module Mongoid
15
17
  end
16
18
 
17
19
  def failure_message
18
- message = "Expected #{model.inspect} to #{description},"
20
+ message = +"Expected #{model.inspect} to #{description},"
19
21
  message << if actual_index.nil?
20
22
  ' found no index'
21
23
  else
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if Mongoid::Compatibility::Version.mongoid4_or_newer?
2
4
  module Mongoid
3
5
  module Matchers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -19,9 +21,9 @@ module Mongoid
19
21
  end
20
22
 
21
23
  def description
22
- options_desc = []
24
+ options_desc = +"validate field #{@field.inspect}"
23
25
  options_desc << " with custom validator #{@custom_validator.name}" if @validator
24
- "validate field #{@field.inspect}" << options_desc.to_sentence
26
+ options_desc
25
27
  end
26
28
 
27
29
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -12,7 +14,7 @@ module Mongoid
12
14
  end
13
15
 
14
16
  def matches?(actual)
15
- return false unless result = super(actual)
17
+ return false unless (result = super(actual))
16
18
 
17
19
  if @not_allowed_values
18
20
  raw_validator_not_allowed_values = @validator.options[:in]
@@ -24,9 +26,9 @@ module Mongoid
24
26
 
25
27
  allowed_values = @not_allowed_values - validator_not_allowed_values
26
28
  if allowed_values.empty?
27
- @positive_result_message = @positive_result_message << ' not allowing all values mentioned'
29
+ @positive_result_message << ' not allowing all values mentioned'
28
30
  else
29
- @negative_result_message = @negative_result_message << " allowing the following the ff. values: #{allowed_values.inspect}"
31
+ @negative_result_message << " allowing the following the ff. values: #{allowed_values.inspect}"
30
32
  result = false
31
33
  end
32
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module Matchers
3
5
  module Validations
@@ -12,14 +14,15 @@ module Mongoid
12
14
  @klass = actual.is_a?(Class) ? actual : actual.class
13
15
 
14
16
  @validator = @klass.validators_on(@field).detect do |v|
15
- (v.kind.to_s == @type) && (!v.options[:on] || on_options_matches?(v))
17
+ (v.kind.to_s == @type) && (!v.options[:on] || on_options_matches?(v)) &&
18
+ if_condition_matches?(actual, v) && unless_condition_matches?(actual, v)
16
19
  end
17
20
 
18
21
  if @validator
19
- @negative_result_message = "#{@type.inspect} validator on #{@field.inspect}"
20
- @positive_result_message = "#{@type.inspect} validator on #{@field.inspect}"
22
+ @negative_result_message = +"#{@type.inspect} validator on #{@field.inspect}"
23
+ @positive_result_message = +"#{@type.inspect} validator on #{@field.inspect}"
21
24
  else
22
- @negative_result_message = "no #{@type.inspect} validator on #{@field.inspect}"
25
+ @negative_result_message = +"no #{@type.inspect} validator on #{@field.inspect}"
23
26
  return false
24
27
  end
25
28
  @result = true
@@ -40,10 +43,9 @@ module Mongoid
40
43
  alias failure_message_when_negated failure_message_for_should_not
41
44
 
42
45
  def description
43
- desc = "have #{@type.inspect} validator on #{@field.inspect}"
46
+ desc = +"have #{@type.inspect} validator on #{@field.inspect}"
44
47
  desc << " on #{@options[:on]}" if @options[:on]
45
48
  desc << " with message #{@expected_message.inspect}" if @expected_message
46
-
47
49
  desc
48
50
  end
49
51
 
@@ -57,13 +59,47 @@ module Mongoid
57
59
  self
58
60
  end
59
61
 
62
+ def check_conditions
63
+ @check_conditions = true
64
+ self
65
+ end
66
+
60
67
  private
61
68
 
69
+ def if_condition_matches?(actual, validator)
70
+ return true unless @check_conditions
71
+ return true unless validator.options[:if]
72
+
73
+ check_condition(actual, validator.options[:if])
74
+ end
75
+
76
+ def unless_condition_matches?(actual, validator)
77
+ return true unless @check_conditions
78
+ return true unless validator.options[:unless]
79
+
80
+ !check_condition(actual, validator.options[:unless])
81
+ end
82
+
83
+ def check_condition(actual, filter)
84
+ raise ArgumentError, 'Spec subject must be an instance when using .check_conditions' if actual.is_a?(Class)
85
+
86
+ case filter
87
+ when Symbol
88
+ actual.send(filter)
89
+ when ::Proc
90
+ filter.arity.zero? ? actual.instance_exec(&filter) : filter.call(actual)
91
+ when Array
92
+ filter.all? { |f| check_condition(actual, f) }
93
+ else
94
+ raise ArgumentError, "Unexpected filter: #{filter.inspect}"
95
+ end
96
+ end
97
+
62
98
  def check_on
63
99
  validator_on_methods = [@validator.options[:on]].flatten
64
100
 
65
101
  if validator_on_methods.any?
66
- message = " on methods: #{validator_on_methods}"
102
+ message = +" on methods: #{validator_on_methods}"
67
103
 
68
104
  if on_options_covered_by?(@validator)
69
105
  @positive_result_message << message
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Mongoid
2
4
  module RSpec
3
- VERSION = '4.1.0'.freeze
5
+ VERSION = '4.3.0'
4
6
  end
5
7
  end
data/lib/mongoid/rspec.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
4
 
3
5
  require 'mongoid'
data/lib/mongoid-rspec.rb CHANGED
@@ -1 +1,3 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mongoid/rspec'