mongoid-rspec 3.0.0 → 4.0.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 (62) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +217 -111
  4. data/Rakefile +8 -5
  5. data/lib/matchers/accept_nested_attributes.rb +22 -23
  6. data/lib/matchers/allow_mass_assignment.rb +12 -12
  7. data/lib/matchers/associations.rb +36 -37
  8. data/lib/matchers/be_dynamic_document.rb +26 -0
  9. data/lib/matchers/be_mongoid_document.rb +26 -0
  10. data/lib/matchers/be_stored_in.rb +55 -0
  11. data/lib/matchers/have_field.rb +90 -0
  12. data/lib/matchers/have_timestamps.rb +61 -0
  13. data/lib/matchers/indexes/have_index_for.rb +16 -0
  14. data/lib/matchers/indexes/v3/have_index_for.rb +59 -0
  15. data/lib/matchers/indexes/v4/have_index_for.rb +54 -0
  16. data/lib/matchers/validations.rb +30 -11
  17. data/lib/matchers/validations/associated.rb +1 -1
  18. data/lib/matchers/validations/confirmation_of.rb +0 -7
  19. data/lib/matchers/validations/custom_validation_of.rb +1 -4
  20. data/lib/matchers/validations/exclusion_of.rb +5 -5
  21. data/lib/matchers/validations/format_of.rb +2 -2
  22. data/lib/matchers/validations/inclusion_of.rb +5 -5
  23. data/lib/matchers/validations/length_of.rb +13 -35
  24. data/lib/matchers/validations/numericality_of.rb +32 -16
  25. data/lib/matchers/validations/presence_of.rb +1 -1
  26. data/lib/matchers/validations/uniqueness_of.rb +7 -10
  27. data/lib/mongoid/rspec.rb +17 -5
  28. data/lib/mongoid/rspec/version.rb +2 -2
  29. data/spec/models/article.rb +6 -6
  30. data/spec/models/comment.rb +1 -1
  31. data/spec/models/log.rb +3 -3
  32. data/spec/models/message.rb +11 -0
  33. data/spec/models/movie_article.rb +1 -2
  34. data/spec/models/person.rb +1 -1
  35. data/spec/models/profile.rb +2 -2
  36. data/spec/models/record.rb +1 -1
  37. data/spec/models/user.rb +11 -11
  38. data/spec/spec_helper.rb +9 -9
  39. data/spec/unit/accept_nested_attributes_spec.rb +1 -1
  40. data/spec/unit/associations_spec.rb +11 -7
  41. data/spec/unit/be_dynamic_document_spec.rb +21 -0
  42. data/spec/unit/be_mongoid_document_spec.rb +25 -0
  43. data/spec/unit/be_stored_in.rb +54 -0
  44. data/spec/unit/document_spec.rb +5 -14
  45. data/spec/unit/have_index_for_spec.rb +46 -0
  46. data/spec/unit/have_timestamps_spec.rb +71 -0
  47. data/spec/unit/validations_spec.rb +22 -15
  48. data/spec/validators/ssn_validator.rb +6 -6
  49. metadata +63 -29
  50. data/.document +0 -5
  51. data/.gitignore +0 -6
  52. data/.ruby-gemset +0 -1
  53. data/.ruby-version +0 -1
  54. data/.travis.yml +0 -10
  55. data/Gemfile +0 -4
  56. data/lib/matchers/collections.rb +0 -9
  57. data/lib/matchers/document.rb +0 -173
  58. data/lib/matchers/indexes.rb +0 -69
  59. data/lib/matchers/validations/with_message.rb +0 -27
  60. data/mongoid-rspec.gemspec +0 -26
  61. data/spec/unit/collections_spec.rb +0 -7
  62. data/spec/unit/indexes_spec.rb +0 -17
@@ -3,7 +3,7 @@ module Mongoid
3
3
  module Matchers
4
4
  class AllowMassAssignmentOfMatcher # :nodoc:
5
5
  attr_reader :failure_message, :negative_failure_message
6
- alias :failure_message_when_negated :negative_failure_message
6
+ alias failure_message_when_negated negative_failure_message
7
7
 
8
8
  def initialize(attribute)
9
9
  @attribute = attribute.to_s
@@ -12,7 +12,7 @@ module Mongoid
12
12
 
13
13
  def as(role)
14
14
  if active_model_less_than_3_1?
15
- raise "You can specify role only in Rails 3.1 or greater"
15
+ raise 'You can specify role only in Rails 3.1 or greater'
16
16
  end
17
17
  @options[:role] = role
18
18
  self
@@ -25,20 +25,20 @@ module Mongoid
25
25
  @negative_failure_message = "#{@attribute} was made accessible"
26
26
  else
27
27
  if protected_attributes.empty?
28
- @negative_failure_message = "no attributes were protected"
28
+ @negative_failure_message = 'no attributes were protected'
29
29
  else
30
- @negative_failure_message = "#{class_name} is protecting " <<
31
- "#{protected_attributes.to_a.to_sentence}, " <<
32
- "but not #{@attribute}."
30
+ @negative_failure_message = "#{class_name} is protecting " \
31
+ "#{protected_attributes.to_a.to_sentence}, " \
32
+ "but not #{@attribute}."
33
33
  end
34
34
  end
35
35
  true
36
36
  else
37
- if whitelisting?
38
- @failure_message = "Expected #{@attribute} to be accessible"
39
- else
40
- @failure_message = "Did not expect #{@attribute} to be protected"
41
- end
37
+ @failure_message = if whitelisting?
38
+ "Expected #{@attribute} to be accessible"
39
+ else
40
+ "Did not expect #{@attribute} to be protected"
41
+ end
42
42
  false
43
43
  end
44
44
  end
@@ -62,7 +62,7 @@ module Mongoid
62
62
  end
63
63
 
64
64
  def whitelisting?
65
- authorizer.kind_of?(::ActiveModel::MassAssignmentSecurity::WhiteList)
65
+ authorizer.is_a?(::ActiveModel::MassAssignmentSecurity::WhiteList)
66
66
  end
67
67
 
68
68
  def attr_mass_assignable?
@@ -3,7 +3,6 @@ require 'mongoid/relations'
3
3
  module Mongoid
4
4
  module Matchers
5
5
  module Associations
6
-
7
6
  HAS_MANY = Mongoid::Relations::Referenced::Many
8
7
  HAS_AND_BELONGS_TO_MANY = Mongoid::Relations::Referenced::ManyToMany
9
8
  HAS_ONE = Mongoid::Relations::Referenced::One
@@ -28,7 +27,6 @@ module Mongoid
28
27
  end
29
28
 
30
29
  def as_inverse_of(association_inverse_name)
31
- raise "#{@association[:type].inspect} does not respond to :inverse_of" unless [HAS_MANY, HAS_AND_BELONGS_TO_MANY, BELONGS_TO, EMBEDDED_IN].include?(@association[:type])
32
30
  @association[:inverse_of] = association_inverse_name.to_s
33
31
  @expectation_message << " which is an inverse of #{@association[:inverse_of].inspect}"
34
32
  self
@@ -39,7 +37,7 @@ module Mongoid
39
37
  @association[:order] = association_field_name.to_s
40
38
  @expectation_message << " ordered by #{@association[:order].inspect}"
41
39
 
42
- if association_field_name.is_a? Origin::Key
40
+ if association_field_name.is_a? Mongoid::Criteria::Queryable::Key
43
41
  @association[:order_operator] = association_field_name.operator
44
42
  @expectation_message << " #{order_way(@association[:order_operator])}"
45
43
  end
@@ -49,43 +47,43 @@ module Mongoid
49
47
 
50
48
  def with_dependent(method_name)
51
49
  @association[:dependent] = method_name
52
- @expectation_message << " which specifies dependent as #{@association[:dependent].to_s}"
50
+ @expectation_message << " which specifies dependent as #{@association[:dependent]}"
53
51
  self
54
52
  end
55
53
 
56
54
  def with_autosave
57
55
  @association[:autosave] = true
58
- @expectation_message << " which specifies autosave as #{@association[:autosave].to_s}"
56
+ @expectation_message << " which specifies autosave as #{@association[:autosave]}"
59
57
  self
60
58
  end
61
59
 
62
60
  def with_index
63
61
  @association[:index] = true
64
- @expectation_message << " which specifies index as #{@association[:index].to_s}"
62
+ @expectation_message << " which specifies index as #{@association[:index]}"
65
63
  self
66
64
  end
67
65
 
68
66
  def with_autobuild
69
67
  @association[:autobuild] = true
70
- @expectation_message << " which specifies autobuild as #{@association[:autobuild].to_s}"
68
+ @expectation_message << " which specifies autobuild as #{@association[:autobuild]}"
71
69
  self
72
70
  end
73
71
 
74
72
  def with_polymorphism
75
73
  @association[:polymorphic] = true
76
- @expectation_message << " which specifies polymorphic as #{@association[:polymorphic].to_s}"
74
+ @expectation_message << " which specifies polymorphic as #{@association[:polymorphic]}"
77
75
  self
78
76
  end
79
77
 
80
78
  def with_cascading_callbacks
81
79
  @association[:cascade_callbacks] = true
82
- @expectation_message << " which specifies cascade_callbacks as #{@association[:cascade_callbacks].to_s}"
80
+ @expectation_message << " which specifies cascade_callbacks as #{@association[:cascade_callbacks]}"
83
81
  self
84
82
  end
85
83
 
86
84
  def cyclic
87
85
  @association[:cyclic] = true
88
- @expectation_message << " which specifies cyclic as #{@association[:cyclic].to_s}"
86
+ @expectation_message << " which specifies cyclic as #{@association[:cyclic]}"
89
87
  self
90
88
  end
91
89
 
@@ -103,7 +101,7 @@ module Mongoid
103
101
 
104
102
  def with_counter_cache
105
103
  @association[:counter_cache] = true
106
- @expectation_message << " which specifies counter_cache as #{@association[:counter_cache].to_s}"
104
+ @expectation_message << " which specifies counter_cache as #{@association[:counter_cache]}"
107
105
  self
108
106
  end
109
107
 
@@ -126,7 +124,7 @@ module Mongoid
126
124
  @positive_result_message = "#{@actual.inspect} #{type_description(relation, false)} #{@association[:name]}"
127
125
  end
128
126
 
129
- if !@association[:class].nil? and @association[:class] != metadata.klass
127
+ if !@association[:class].nil? && (@association[:class] != metadata.klass)
130
128
  @negative_result_message = "#{@positive_result_message} of type #{metadata.klass.inspect}"
131
129
  return false
132
130
  else
@@ -250,7 +248,7 @@ module Mongoid
250
248
  end
251
249
  end
252
250
 
253
- return true
251
+ true
254
252
  end
255
253
 
256
254
  def failure_message_for_should
@@ -261,8 +259,8 @@ module Mongoid
261
259
  "Expected #{@actual.inspect} to not #{@expectation_message}, got #{@positive_result_message}"
262
260
  end
263
261
 
264
- alias :failure_message :failure_message_for_should
265
- alias :failure_message_when_negated :failure_message_for_should_not
262
+ alias failure_message failure_message_for_should
263
+ alias failure_message_when_negated failure_message_for_should_not
266
264
 
267
265
  def description
268
266
  @expectation_message
@@ -271,29 +269,30 @@ module Mongoid
271
269
  def type_description(type = nil, passive = true)
272
270
  type ||= @association[:type]
273
271
  case type.name
274
- when EMBEDS_ONE.name
275
- (passive ? 'embed' : 'embeds') << ' one'
276
- when EMBEDS_MANY.name
277
- (passive ? 'embed' : 'embeds') << ' many'
278
- when EMBEDDED_IN.name
279
- (passive ? 'be' : 'is') << ' embedded in'
280
- when HAS_ONE.name
281
- (passive ? 'reference' : 'references') << ' one'
282
- when HAS_MANY.name
283
- (passive ? 'reference' : 'references') << ' many'
284
- when HAS_AND_BELONGS_TO_MANY.name
285
- (passive ? 'reference' : 'references') << ' and referenced in many'
286
- when BELONGS_TO.name
287
- (passive ? 'be referenced in' : 'referenced in')
288
- else
289
- raise "Unknown association type '%s'" % type
272
+ when EMBEDS_ONE.name
273
+ (passive ? 'embed' : 'embeds') << ' one'
274
+ when EMBEDS_MANY.name
275
+ (passive ? 'embed' : 'embeds') << ' many'
276
+ when EMBEDDED_IN.name
277
+ (passive ? 'be' : 'is') << ' embedded in'
278
+ when HAS_ONE.name
279
+ (passive ? 'reference' : 'references') << ' one'
280
+ when HAS_MANY.name
281
+ (passive ? 'reference' : 'references') << ' many'
282
+ when HAS_AND_BELONGS_TO_MANY.name
283
+ (passive ? 'reference' : 'references') << ' and referenced in many'
284
+ when BELONGS_TO.name
285
+ (passive ? 'be referenced in' : 'referenced in')
286
+ else
287
+ raise format("Unknown association type '%s'", type)
290
288
  end
291
289
  end
292
290
 
293
291
  private
294
- def order_way(operator)
295
- [nil, "ascending", "descending"][operator]
296
- end
292
+
293
+ def order_way(operator)
294
+ [nil, 'ascending', 'descending'][operator]
295
+ end
297
296
  end
298
297
 
299
298
  def embed_one(association_name)
@@ -311,12 +310,12 @@ module Mongoid
311
310
  def have_one_related(association_name)
312
311
  HaveAssociationMatcher.new(association_name, HAS_ONE)
313
312
  end
314
- alias :have_one :have_one_related
313
+ alias have_one have_one_related
315
314
 
316
315
  def have_many_related(association_name)
317
316
  HaveAssociationMatcher.new(association_name, HAS_MANY)
318
317
  end
319
- alias :have_many :have_many_related
318
+ alias have_many have_many_related
320
319
 
321
320
  def have_and_belong_to_many(association_name)
322
321
  HaveAssociationMatcher.new(association_name, HAS_AND_BELONGS_TO_MANY)
@@ -325,7 +324,7 @@ module Mongoid
325
324
  def belong_to_related(association_name)
326
325
  HaveAssociationMatcher.new(association_name, BELONGS_TO)
327
326
  end
328
- alias :belong_to :belong_to_related
327
+ alias belong_to belong_to_related
329
328
  end
330
329
  end
331
330
  end
@@ -0,0 +1,26 @@
1
+ module Mongoid
2
+ module Matchers
3
+ def be_dynamic_document
4
+ BeDynamicDocument.new
5
+ end
6
+
7
+ class BeDynamicDocument
8
+ def matches?(actual)
9
+ @model = actual.is_a?(Class) ? actual : actual.class
10
+ @model.included_modules.include?(Mongoid::Attributes::Dynamic)
11
+ end
12
+
13
+ def description
14
+ 'include Mongoid::Attributes::Dynamic'
15
+ end
16
+
17
+ def failure_message
18
+ "expect #{@model.inspect} class to #{description}"
19
+ end
20
+
21
+ def failure_message_when_negated
22
+ "expect #{@model.inspect} class to not #{description}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Mongoid
2
+ module Matchers
3
+ def be_mongoid_document
4
+ BeMongoidDocument.new
5
+ end
6
+
7
+ class BeMongoidDocument
8
+ def matches?(actual)
9
+ @model = actual.is_a?(Class) ? actual : actual.class
10
+ @model.included_modules.include?(Mongoid::Document)
11
+ end
12
+
13
+ def description
14
+ 'include Mongoid::Document'
15
+ end
16
+
17
+ def failure_message
18
+ "expect #{@model.inspect} class to #{description}"
19
+ end
20
+
21
+ def failure_message_when_negated
22
+ "expect #{@model.inspect} class to not #{description}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,55 @@
1
+ module Mongoid
2
+ module Matchers
3
+ def be_stored_in(options)
4
+ BeStoredIn.new(options)
5
+ end
6
+
7
+ class BeStoredIn
8
+ def initialize(expected)
9
+ @expected_options = expected.transform_values { |v| v.to_sym rescue v }.symbolize_keys
10
+ end
11
+
12
+ def matches?(actual)
13
+ @model = actual.is_a?(Class) ? actual : actual.class
14
+ actual_options == @expected_options
15
+ end
16
+
17
+ def description
18
+ "be stored in #{@expected_options.inspect}"
19
+ end
20
+
21
+ def failure_message
22
+ "Expected #{@model.inspect} to #{description}, got #{actual_options.inspect}"
23
+ end
24
+
25
+ def failure_message_when_negated
26
+ "Expected #{@model.inspect} not to #{description}, got #{actual_options.inspect}"
27
+ end
28
+
29
+ private
30
+
31
+ def actual_options
32
+ @actual_options ||= begin
33
+ hash = @model.storage_options.slice(*@expected_options.keys)
34
+ hash.each do |option, value|
35
+ hash[option] =
36
+ if value.is_a?(Proc)
37
+ evaluated_value = @model.persistence_context.send("#{option}_name")
38
+ begin
39
+ evaluated_value.to_sym
40
+ rescue StandardError
41
+ evaluated_value
42
+ end
43
+ else
44
+ begin
45
+ value.to_sym
46
+ rescue StandardError
47
+ value
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,90 @@
1
+ module Mongoid
2
+ module Matchers
3
+ class HaveField # :nodoc:
4
+ def initialize(*attrs)
5
+ @attributes = attrs.collect(&:to_s)
6
+ end
7
+
8
+ def localized
9
+ @localized = true
10
+ self
11
+ end
12
+
13
+ def of_type(type)
14
+ @type = type
15
+ self
16
+ end
17
+
18
+ def with_alias(field_alias)
19
+ @field_alias = field_alias
20
+ self
21
+ end
22
+
23
+ def with_default_value_of(default)
24
+ @default = default
25
+ self
26
+ end
27
+
28
+ def matches?(klass)
29
+ @klass = klass.is_a?(Class) ? klass : klass.class
30
+ @errors = []
31
+ @attributes.each do |attr|
32
+ if @klass.fields.include?(attr)
33
+ error = ''
34
+ if @type && (@klass.fields[attr].type != @type)
35
+ error << " of type #{@klass.fields[attr].type}"
36
+ end
37
+
38
+ unless @default.nil?
39
+ if @klass.fields[attr].default_val.nil?
40
+ error << ' with default not set'
41
+ elsif @klass.fields[attr].default_val != @default
42
+ error << " with default value of #{@klass.fields[attr].default_val}"
43
+ end
44
+ end
45
+
46
+ if @field_alias && (@klass.fields[attr].options[:as] != @field_alias)
47
+ error << " with alias #{@klass.fields[attr].options[:as]}"
48
+ end
49
+
50
+ @errors.push("field #{attr.inspect}" << error) unless error.blank?
51
+
52
+ if @localized
53
+ unless @klass.fields[attr].localized?
54
+ @errors.push "is not localized #{attr.inspect}"
55
+ end
56
+ end
57
+
58
+ else
59
+ @errors.push "no field named #{attr.inspect}"
60
+ end
61
+ end
62
+ @errors.empty?
63
+ end
64
+
65
+ def failure_message_for_should
66
+ "Expected #{@klass.inspect} to #{description}, got #{@errors.to_sentence}"
67
+ end
68
+
69
+ def failure_message_for_should_not
70
+ "Expected #{@klass.inspect} to not #{description}, got #{@klass.inspect} to #{description}"
71
+ end
72
+
73
+ alias failure_message failure_message_for_should
74
+ alias failure_message_when_negated failure_message_for_should_not
75
+
76
+ def description
77
+ desc = "have #{@attributes.size > 1 ? 'fields' : 'field'} named #{@attributes.collect(&:inspect).to_sentence}"
78
+ desc << " of type #{@type.inspect}" if @type
79
+ desc << " with alias #{@field_alias}" if @field_alias
80
+ desc << " with default value of #{@default.inspect}" unless @default.nil?
81
+ desc
82
+ end
83
+ end
84
+
85
+ def have_field(*args)
86
+ HaveField.new(*args)
87
+ end
88
+ alias have_fields have_field
89
+ end
90
+ end
@@ -0,0 +1,61 @@
1
+ module Mongoid
2
+ module Matchers
3
+ def have_timestamps
4
+ HaveTimestamps.new
5
+ end
6
+
7
+ class HaveTimestamps
8
+ def initialize
9
+ @root_module = 'Mongoid::Timestamps'
10
+ end
11
+
12
+ def matches?(actual)
13
+ @model = actual.is_a?(Class) ? actual : actual.class
14
+ @model.included_modules.include?(expected_module)
15
+ end
16
+
17
+ def for(phase)
18
+ raise('You\'ve already declared timetamp\'s sub-module via "for" clause') if @submodule
19
+
20
+ case @phase = phase.to_sym
21
+ when :creating then @submodule = 'Created'
22
+ when :updating then @submodule = 'Updated'
23
+ else
24
+ raise('Timestamps can be declared only for creating or updating')
25
+ end
26
+
27
+ self
28
+ end
29
+
30
+ def shortened
31
+ @shortened = true
32
+ self
33
+ end
34
+
35
+ def description
36
+ desc = 'be a Mongoid document with'
37
+ desc << ' shorted' if @shortened
38
+ desc << " #{@phase}" if @phase
39
+ desc << ' timestamps'
40
+ desc
41
+ end
42
+
43
+ def failure_message
44
+ "Expected #{@model.inspect} class to #{description}"
45
+ end
46
+
47
+ def failure_message_when_negated
48
+ "Expected #{@model.inspect} class to not #{description}"
49
+ end
50
+
51
+ private
52
+
53
+ def expected_module
54
+ expected_module = @root_module
55
+ expected_module << "::#{@submodule}" if @submodule
56
+ expected_module << '::Short' if @shortened
57
+ expected_module.constantize
58
+ end
59
+ end
60
+ end
61
+ end