mongoid-rspec 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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