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
@@ -2,8 +2,19 @@ module Mongoid
2
2
  module Matchers
3
3
  module Validations
4
4
  class ValidateNumericalityOfMatcher < HaveValidationMatcher
5
- @@allowed_options = [:equal_to, :greater_than, :greater_than_or_equal_to, :less_than, :less_than_or_equal_to,
6
- :even, :odd, :only_integer, :allow_nil, :nil]
5
+ ALLOWED_OPTIONS =
6
+ %i[
7
+ allow_nil
8
+ equal_to
9
+ even
10
+ greater_than
11
+ greater_than_or_equal_to
12
+ less_than
13
+ less_than_or_equal_to
14
+ nil
15
+ odd
16
+ only_integer
17
+ ].freeze
7
18
 
8
19
  def initialize(field)
9
20
  super(field, :numericality)
@@ -12,9 +23,15 @@ module Mongoid
12
23
 
13
24
  def to_allow(options)
14
25
  options[:equal_to] = options if options.is_a?(Numeric)
15
- options[:allow_nil] = options.delete(:nil) if options.has_key?(:nil)
16
- raise ArgumentError, "validate_numericality_of#to_allow requires a Hash parameter containing any of the following keys: " <<
17
- @@allowed_options.map(&:inspect).join(", ") if !options.is_a?(Hash) or options.empty? or (options.keys - @@allowed_options).any?
26
+ options[:allow_nil] = options.delete(:nil) if options.key?(:nil)
27
+
28
+ if !options.is_a?(Hash) || options.empty? || (options.keys - ALLOWED_OPTIONS).any?
29
+ message =
30
+ 'validate_numericality_of#to_allow requires a Hash parameter containing' \
31
+ "any of the following keys: #{ALLOWED_OPTIONS.map(&:inspect).join(', ')}"
32
+ raise ArgumentError, message
33
+ end
34
+
18
35
  @options.merge!(options)
19
36
  self
20
37
  end
@@ -22,11 +39,10 @@ module Mongoid
22
39
  def matches?(actual)
23
40
  return false unless result = super(actual)
24
41
 
25
- @@allowed_options.each do |comparator|
26
- if @options.has_key?(comparator) and !([:even, :odd, :only_integer].include?(comparator) and !@validator.options.include?(comparator))
27
- result &= (@validator.options[comparator] == @options[comparator])
28
- end
42
+ @options.each do |comparator, expected_value|
43
+ result &= (@validator.options[comparator] == expected_value)
29
44
  end
45
+
30
46
  @positive_result_message <<= options_message(@validator.options)
31
47
  @negative_result_message <<= options_message(@validator.options)
32
48
  result
@@ -45,19 +61,19 @@ module Mongoid
45
61
  case key
46
62
  when :allow_nil
47
63
  when :only_integer
48
- type_msg << "integer" if value
64
+ type_msg << 'integer' if value
49
65
  when :odd, :even
50
- type_msg << "#{key.to_s}-numbered" if value
66
+ type_msg << "#{key}-numbered" if value
51
67
  else
52
- comp_msg << "#{key.to_s.gsub("_", " ")} #{value.inspect}"
68
+ comp_msg << "#{key.to_s.tr('_', ' ')} #{value.inspect}"
53
69
  end
54
70
  end
55
- allow_nil = (options[:allow_nil] ? "nil" : "non-nil") if options.has_key?(:allow_nil)
56
- ["", "allowing", allow_nil, type_msg.any? ? type_msg.to_sentence : nil, "values", comp_msg.any? ? comp_msg.to_sentence : nil].compact.join(" ")
71
+ allow_nil = (options[:allow_nil] ? 'nil' : 'non-nil') if options.key?(:allow_nil)
72
+ ['', 'allowing', allow_nil, type_msg.any? ? type_msg.to_sentence : nil, 'values', comp_msg.any? ? comp_msg.to_sentence : nil].compact.join(' ')
57
73
  end
58
74
 
59
75
  def method_missing(m, *args, &block)
60
- if @@allowed_options.include?(m.to_sym)
76
+ if ALLOWED_OPTIONS.include?(m.to_sym)
61
77
  raise ArgumentError, "wrong number of arguments (#{args.length} for 1)" if args.length > 1
62
78
  send :to_allow, m.to_sym => args.first
63
79
  else
@@ -71,4 +87,4 @@ module Mongoid
71
87
  end
72
88
  end
73
89
  end
74
- end
90
+ end
@@ -6,4 +6,4 @@ module Mongoid
6
6
  end
7
7
  end
8
8
  end
9
- end
9
+ end
@@ -2,7 +2,6 @@ module Mongoid
2
2
  module Matchers
3
3
  module Validations
4
4
  class ValidateUniquenessOfMatcher < HaveValidationMatcher
5
- include WithMessage
6
5
  def initialize(field)
7
6
  super(field, :uniqueness)
8
7
  end
@@ -11,7 +10,7 @@ module Mongoid
11
10
  @scope = [scope].flatten.map(&:to_sym)
12
11
  self
13
12
  end
14
- alias_method :scoped_on, :scoped_to
13
+ alias scoped_on scoped_to
15
14
 
16
15
  def case_insensitive
17
16
  @case_insensitive = true
@@ -29,7 +28,6 @@ module Mongoid
29
28
  check_scope if @scope
30
29
  check_allow_blank if @allow_blank
31
30
  check_case_sensitivity if @case_insensitive
32
- check_expected_message if @expected_message
33
31
 
34
32
  @result
35
33
  end
@@ -37,9 +35,8 @@ module Mongoid
37
35
  def description
38
36
  options_desc = []
39
37
  options_desc << " scoped to #{@scope.inspect}" if @scope
40
- options_desc << " allowing blank values" if @allow_blank
41
- options_desc << " allowing case insensitive values" if @case_insensitive
42
- options_desc << " with message '#{@expected_message}'" if @expected_message
38
+ options_desc << ' allowing blank values' if @allow_blank
39
+ options_desc << ' allowing case insensitive values' if @case_insensitive
43
40
  super << options_desc.to_sentence
44
41
  end
45
42
 
@@ -47,9 +44,9 @@ module Mongoid
47
44
 
48
45
  def check_allow_blank
49
46
  if @validator.options[:allow_blank] == @allow_blank
50
- @positive_result_message << " with blank values allowed"
47
+ @positive_result_message << ' with blank values allowed'
51
48
  else
52
- @negative_result_message << " with no blank values allowed"
49
+ @negative_result_message << ' with no blank values allowed'
53
50
  @result = false
54
51
  end
55
52
  end
@@ -66,9 +63,9 @@ module Mongoid
66
63
 
67
64
  def check_case_sensitivity
68
65
  if @validator.options[:case_sensitive] == false
69
- @positive_result_message << " with case insensitive values"
66
+ @positive_result_message << ' with case insensitive values'
70
67
  else
71
- @negative_result_message << " without case insensitive values"
68
+ @negative_result_message << ' without case insensitive values'
72
69
  @result = false
73
70
  end
74
71
  end
@@ -1,18 +1,19 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
 
3
3
  require 'mongoid'
4
+ require 'mongoid-compatibility'
4
5
  require 'rspec/core'
5
6
  require 'rspec/expectations'
6
7
  require 'rspec/mocks'
7
- require "active_model"
8
- require 'matchers/document'
8
+ require 'active_support/core_ext/hash/keys'
9
+ require 'active_support/core_ext/hash/transform_values' if Mongoid::Compatibility::Version.mongoid4_or_newer?
10
+ require 'active_support/core_ext/object/blank'
11
+ require 'active_support/core_ext/string/inflections'
12
+
9
13
  require 'matchers/associations'
10
- require 'matchers/collections'
11
- require 'matchers/indexes'
12
14
  require 'matchers/allow_mass_assignment'
13
15
  require 'matchers/accept_nested_attributes'
14
16
  require 'matchers/validations'
15
- require 'matchers/validations/with_message'
16
17
  require 'matchers/validations/associated'
17
18
  require 'matchers/validations/confirmation_of'
18
19
  require 'matchers/validations/exclusion_of'
@@ -24,6 +25,17 @@ require 'matchers/validations/presence_of'
24
25
  require 'matchers/validations/uniqueness_of'
25
26
  require 'matchers/validations/acceptance_of'
26
27
  require 'matchers/validations/custom_validation_of'
28
+ require 'matchers/be_mongoid_document'
29
+ require 'matchers/be_dynamic_document'
30
+ require 'matchers/be_stored_in'
31
+ require 'matchers/have_field'
32
+ require 'matchers/indexes/have_index_for'
33
+ if Mongoid::Compatibility::Version.mongoid3?
34
+ require 'matchers/indexes/v3/have_index_for'
35
+ else
36
+ require 'matchers/indexes/v4/have_index_for'
37
+ end
38
+ require 'matchers/have_timestamps'
27
39
 
28
40
  module Mongoid
29
41
  module Matchers
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
- module Rspec
3
- VERSION = '3.0.0'
2
+ module RSpec
3
+ VERSION = '4.0.0'.freeze
4
4
  end
5
5
  end
@@ -9,21 +9,21 @@ class Article
9
9
  field :number_of_comments, type: Integer
10
10
  field :status, type: Symbol
11
11
 
12
- embeds_many :comments, cascade_callbacks: true
13
- embeds_one :permalink
12
+ embeds_many :comments, cascade_callbacks: true, inverse_of: :article
13
+ embeds_one :permalink, inverse_of: :linkable
14
14
  belongs_to :author, class_name: 'User', inverse_of: :articles, index: true
15
15
 
16
16
  validates :title, presence: true
17
17
 
18
18
  validates_inclusion_of :status, in: [:pending], on: :create
19
- validates_inclusion_of :status, in: [:approved, :rejected ], on: :update
19
+ validates_inclusion_of :status, in: %i[approved rejected], on: :update
20
20
 
21
21
  validates_length_of :title, within: 8..16
22
22
  validates_length_of :content, minimum: 200
23
23
 
24
- index({ title: 1 }, { unique: true, background: true, drop_dups: true })
25
- index({ published: 1 })
26
- index({ 'permalink._id' => 1 })
24
+ index({ title: 1 }, unique: true, background: true, drop_dups: true)
25
+ index(published: 1)
26
+ index('permalink._id' => 1)
27
27
 
28
28
  accepts_nested_attributes_for :permalink
29
29
  end
@@ -3,4 +3,4 @@ class Comment
3
3
 
4
4
  embedded_in :article, inverse_of: :comments, polymorphic: true
5
5
  belongs_to :user, inverse_of: :comments
6
- end
6
+ end
@@ -1,9 +1,9 @@
1
1
  class Log
2
2
  include Mongoid::Document
3
3
  include Mongoid::Timestamps
4
- include Mongoid::Attributes::Dynamic
4
+ include Mongoid::Attributes::Dynamic if Mongoid::Compatibility::Version.mongoid4_or_newer?
5
5
 
6
- store_in collection: "logs"
6
+ store_in collection: 'logs'
7
7
 
8
- index({ created_at: 1 }, { bucket_size: 100, expire_after_seconds: 3600 } )
8
+ index({ created_at: 1 }, bucket_size: 100, expire_after_seconds: 3600)
9
9
  end
@@ -0,0 +1,11 @@
1
+ class Message
2
+ include Mongoid::Document
3
+
4
+ field :identifier
5
+ field :from
6
+ field :to
7
+
8
+ validates :identifier, uniqueness: { message: 'uniqueness' }
9
+ validates :from, presence: { message: 'required' }
10
+ validates :to, format: { with: /[a-z]+/, message: 'format' }
11
+ end
@@ -1,8 +1,7 @@
1
1
  class MovieArticle < Article
2
-
3
2
  field :rating, type: Float
4
3
  field :classification, type: Integer
5
4
 
6
5
  validates :rating, numericality: { greater_than: 0, less_than_or_equal_to: 5 }
7
6
  validates :classification, numericality: { even: true, only_integer: true, allow_nil: false }
8
- end
7
+ end
@@ -7,4 +7,4 @@ class Person
7
7
  field :ssn
8
8
 
9
9
  validates :ssn, ssn: true
10
- end
10
+ end
@@ -10,7 +10,7 @@ class Profile
10
10
 
11
11
  validates :age, numericality: { greater_than: 0 }
12
12
  validates :terms_of_service, acceptance: true
13
- validates :hobbies, length: { minimum: 1, message: "requires at least one hobby" }
13
+ validates :hobbies, length: { minimum: 1, message: 'requires at least one hobby' }
14
14
 
15
- index({ first_name: 1, last_name: 1 })
15
+ index(first_name: 1, last_name: 1)
16
16
  end
@@ -2,4 +2,4 @@ class Record
2
2
  include Mongoid::Document
3
3
 
4
4
  belongs_to :user, inverse_of: :record
5
- end
5
+ end
@@ -13,21 +13,21 @@ class User
13
13
  belongs_to :site, inverse_of: :users
14
14
  has_many :articles, foreign_key: :author_id, order: :title
15
15
  has_many :comments, dependent: :destroy, autosave: true
16
- has_and_belongs_to_many :children, class_name: "User"
17
- has_one :record, autobuild: true
16
+ has_and_belongs_to_many :children, class_name: 'User'
17
+ has_one :record, autobuild: true, inverse_of: :user
18
18
 
19
- embeds_one :profile
19
+ embeds_one :profile, inverse_of: :user
20
20
 
21
- validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: ["super", "index", "edit"] }
22
- validates :email, uniqueness: { case_sensitive: false, scope: :site, message: "is already taken" }, confirmation: true
23
- validates :role, presence: true, inclusion: { in: ["admin", "moderator", "member"] }
21
+ validates :login, presence: true, uniqueness: { scope: :site }, format: { with: /\A[\w\-]+\z/ }, exclusion: { in: %w[super index edit] }
22
+ validates :email, uniqueness: { case_sensitive: false, scope: :site, message: 'is already taken' }, confirmation: true
23
+ validates :role, presence: true, inclusion: { in: %w[admin moderator member] }
24
24
  validates :profile, presence: true, associated: true
25
- validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: [:create, :update]
26
- validates :password, presence: true, on: [:create, :update]
27
- validates :password, exclusion: { in: ->(user) { ['password'] } }
28
- validates :password, confirmation: { message: "Password confirmation must match given password" }
25
+ validates :age, presence: true, numericality: true, inclusion: { in: 23..42 }, on: %i[create update]
26
+ validates :password, presence: true, on: %i[create update]
27
+ validates :password, exclusion: { in: ->(_user) { ['password'] } }
28
+ validates :password, confirmation: { message: 'Password confirmation must match given password' }
29
29
  validates :provider_uid, presence: true
30
- validates :locale, inclusion: { in: ->(user) { [:en, :ru] } }
30
+ validates :locale, inclusion: { in: ->(_user) { %i[en ru] } }
31
31
 
32
32
  accepts_nested_attributes_for :articles, :comments
33
33
 
@@ -1,24 +1,24 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
3
- MODELS = File.join(File.dirname(__FILE__), "models")
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
3
+ MODELS = File.join(File.dirname(__FILE__), 'models')
4
4
  $LOAD_PATH.unshift(MODELS)
5
- VALIDATORS = File.join(File.dirname(__FILE__), "validators")
5
+ VALIDATORS = File.join(File.dirname(__FILE__), 'validators')
6
6
  $LOAD_PATH.unshift(VALIDATORS)
7
7
 
8
- require "rubygems"
9
- require "bundler"
8
+ require 'rubygems'
9
+ require 'bundler'
10
10
  Bundler.setup
11
11
 
12
12
  require 'mongoid'
13
13
  require 'rspec'
14
14
  require 'rspec/core'
15
15
  require 'rspec/expectations'
16
+ require 'mongoid/compatibility'
16
17
 
17
- Mongoid.configure do |config|
18
- config.connect_to("mongoid-rspec-test")
19
- end
18
+ Mongoid::Config.connect_to('mongoid-rspec-test') if Mongoid::Compatibility::Version.mongoid3_or_newer?
19
+ Mongo::Logger.logger.level = ::Logger::INFO if Mongoid::Compatibility::Version.mongoid5_or_newer?
20
20
 
21
- Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
21
+ Dir[File.join(MODELS, '*.rb')].sort.each { |file| require File.basename(file) }
22
22
 
23
23
  require 'mongoid-rspec'
24
24
 
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe "AcceptsNestedAttributes" do
3
+ RSpec.describe 'AcceptsNestedAttributes' do
4
4
  describe User do
5
5
  it { is_expected.to accept_nested_attributes_for(:articles) }
6
6
  it { is_expected.to accept_nested_attributes_for(:comments) }
@@ -1,14 +1,16 @@
1
1
  require 'spec_helper'
2
2
 
3
- RSpec.describe "Associations" do
3
+ RSpec.describe 'Associations' do
4
4
  describe User do
5
- it { is_expected.to have_many(:articles).with_foreign_key(:author_id).ordered_by(:title) }
5
+ if Mongoid::Compatibility::Version.mongoid6_or_newer?
6
+ it { is_expected.to have_many(:articles).with_foreign_key(:author_id).ordered_by(:title) }
7
+ end
6
8
 
7
- it { is_expected.to have_one(:record).with_autobuild }
9
+ it { is_expected.to have_one(:record).as_inverse_of(:user).with_autobuild }
8
10
 
9
11
  it { is_expected.to have_many(:comments).with_dependent(:destroy).with_autosave }
10
12
 
11
- it { is_expected.to embed_one(:profile) }
13
+ it { is_expected.to embed_one(:profile).as_inverse_of(:user) }
12
14
 
13
15
  it { is_expected.to have_and_belong_to_many(:children).of_type(User) }
14
16
  end
@@ -19,8 +21,8 @@ RSpec.describe "Associations" do
19
21
 
20
22
  describe Article do
21
23
  it { is_expected.to belong_to(:author).of_type(User).as_inverse_of(:articles).with_index }
22
- it { is_expected.to embed_many(:comments).with_cascading_callbacks }
23
- it { is_expected.to embed_one(:permalink) }
24
+ it { is_expected.to embed_many(:comments).as_inverse_of(:article).with_cascading_callbacks }
25
+ it { is_expected.to embed_one(:permalink).as_inverse_of(:linkable) }
24
26
  end
25
27
 
26
28
  describe Comment do
@@ -37,6 +39,8 @@ RSpec.describe "Associations" do
37
39
  end
38
40
 
39
41
  describe Site do
40
- it { is_expected.to have_many(:users).as_inverse_of(:site).ordered_by(:email.desc).with_counter_cache }
42
+ if Mongoid::Compatibility::Version.mongoid6_or_newer?
43
+ it { is_expected.to have_many(:users).as_inverse_of(:site).ordered_by(:email.desc).with_counter_cache }
44
+ end
41
45
  end
42
46
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Mongoid::Matchers::BeDynamicDocument do
4
+ context 'when model does\'t include Mongoid::Document' do
5
+ subject do
6
+ Class.new
7
+ end
8
+
9
+ it { is_expected.not_to be_mongoid_document }
10
+ end
11
+
12
+ context 'when model doesn\'t include Mongoid::Document' do
13
+ subject do
14
+ Class.new do
15
+ include Mongoid::Document
16
+ end
17
+ end
18
+
19
+ it { is_expected.to be_mongoid_document }
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ if Mongoid::Compatibility::Version.mongoid4_or_newer?
3
+ RSpec.describe Mongoid::Matchers::BeMongoidDocument do
4
+ context 'when model does\'t include Mongoid::Attributes::Dynamic' do
5
+ subject do
6
+ Class.new do
7
+ include Mongoid::Document
8
+ end
9
+ end
10
+
11
+ it { is_expected.not_to be_dynamic_document }
12
+ end
13
+
14
+ context 'when model doesn\'t include Mongoid::Attributes::Dynamic' do
15
+ subject do
16
+ Class.new do
17
+ include Mongoid::Document
18
+ include Mongoid::Attributes::Dynamic
19
+ end
20
+ end
21
+
22
+ it { is_expected.to be_dynamic_document }
23
+ end
24
+ end
25
+ end