mongoid-rspec 1.5.3 → 2.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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +7 -2
  6. data/README.md +227 -152
  7. data/lib/matchers/accept_nested_attributes.rb +67 -0
  8. data/lib/matchers/allow_mass_assignment.rb +1 -0
  9. data/lib/matchers/associations.rb +127 -22
  10. data/lib/matchers/document.rb +31 -2
  11. data/lib/matchers/indexes.rb +48 -15
  12. data/lib/matchers/validations/acceptance_of.rb +2 -2
  13. data/lib/matchers/validations/associated.rb +5 -5
  14. data/lib/matchers/validations/confirmation_of.rb +2 -2
  15. data/lib/matchers/validations/custom_validation_of.rb +2 -19
  16. data/lib/matchers/validations/exclusion_of.rb +8 -1
  17. data/lib/matchers/validations/format_of.rb +21 -21
  18. data/lib/matchers/validations/inclusion_of.rb +13 -13
  19. data/lib/matchers/validations/length_of.rb +66 -19
  20. data/lib/matchers/validations/numericality_of.rb +10 -10
  21. data/lib/matchers/validations/presence_of.rb +2 -2
  22. data/lib/matchers/validations/uniqueness_of.rb +13 -30
  23. data/lib/matchers/validations/with_message.rb +27 -0
  24. data/lib/matchers/validations.rb +18 -3
  25. data/lib/mongoid-rspec/version.rb +1 -1
  26. data/lib/mongoid-rspec.rb +5 -1
  27. data/mongoid-rspec.gemspec +5 -5
  28. data/spec/models/article.rb +18 -12
  29. data/spec/models/comment.rb +2 -2
  30. data/spec/models/movie_article.rb +6 -5
  31. data/spec/models/permalink.rb +1 -1
  32. data/spec/models/person.rb +0 -3
  33. data/spec/models/profile.rb +9 -7
  34. data/spec/models/record.rb +1 -1
  35. data/spec/models/site.rb +2 -3
  36. data/spec/models/user.rb +14 -14
  37. data/spec/unit/accept_nested_attributes_spec.rb +12 -0
  38. data/spec/unit/associations_spec.rb +6 -6
  39. data/spec/unit/document_spec.rb +6 -6
  40. data/spec/unit/indexes_spec.rb +3 -2
  41. data/spec/unit/validations_spec.rb +7 -0
  42. data/spec/validators/ssn_validator.rb +3 -1
  43. metadata +43 -32
  44. data/.rvmrc +0 -1
  45. data/spec/unit/allow_mass_assignment_spec.rb +0 -14
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 22432282a4af9711e7ff58260bd7e9ccf7279a31
4
+ data.tar.gz: c183931632e9cdd7594ab6314678f3ca6f76f849
5
+ SHA512:
6
+ metadata.gz: 1b3752eba793b316c4d0ccc611c4b6d9e8b766ceb43617a92185899c90839e4e9067dabe7b9b274868e85434c2c209189bb2278cbd7e644c51c8c7ecfcb83470
7
+ data.tar.gz: 69ac5c4fe2ddf2626021c2776e311394fc8a709713f926e16bb4ca4c3e58906d1f9880510d594c5887c4645155a285c8237e44b91082da7e2b32a4745a5321d3
data/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
1
  *.gem
2
+ .rvmrc
2
3
  .bundle
3
4
  Gemfile.lock
4
5
  pkg/*
6
+
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ mongoid-rspec
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.0
data/.travis.yml CHANGED
@@ -1,5 +1,10 @@
1
+ services: mongodb
1
2
  language: ruby
2
3
  rvm:
3
- - 1.9.2
4
4
  - 1.9.3
5
- - ruby-head
5
+ - 2.1.3
6
+ - 2.2.0
7
+ - jruby-19mode
8
+
9
+ gemfile:
10
+ - Gemfile
data/README.md CHANGED
@@ -1,153 +1,228 @@
1
- mongoid-rspec
2
- =
3
-
4
- http://rubygems.org/gems/mongoid-rspec
5
-
6
- RSpec matchers for Mongoid 3.x.
7
-
8
- For Mongoid 2.x, use [mongoid-rspec 1.4.5](http://rubygems.org/gems/mongoid-rspec/versions/1.4.5)
9
-
10
- Association Matchers
11
- -
12
- describe User do
13
- it { should have_many(:articles).with_foreign_key(:author_id) }
14
-
15
- it { should have_one(:record) }
16
-
17
- it { should have_many :comments }
18
-
19
- #can also specify with_dependent to test if :dependent => :destroy/:destroy_all/:delete is set
20
- it { should have_many(:comments).with_dependent(:destroy) }
21
- #can verify autosave is set to true
22
- it { should have_many(:comments).with_autosave }
23
-
24
- it { should embed_one :profile }
25
-
26
- it { should have_and_belong_to_many(:children) }
27
- it { should have_and_belong_to_many(:children).of_type(User) }
28
- end
29
-
30
- describe Profile do
31
- it { should be_embedded_in(:user).as_inverse_of(:profile) }
32
- end
33
-
34
- describe Article do
35
- it { should belong_to(:author).of_type(User).as_inverse_of(:articles) }
36
- it { should belong_to(:author).of_type(User).as_inverse_of(:articles).with_index }
37
- it { should embed_many(:comments) }
38
- end
39
-
40
- describe Comment do
41
- it { should be_embedded_in(:article).as_inverse_of(:comments) }
42
- it { should belong_to(:user).as_inverse_of(:comments) }
43
- end
44
-
45
- describe Record do
46
- it { should belong_to(:user).as_inverse_of(:record) }
47
- end
48
-
49
- Mass Assignment Matcher
50
- -
51
- describe User do
52
- it { should allow_mass_assignment_of(:login) }
53
- it { should allow_mass_assignment_of(:email) }
54
- it { should allow_mass_assignment_of(:age) }
55
- it { should allow_mass_assignment_of(:password) }
56
- it { should allow_mass_assignment_of(:password) }
57
- it { should allow_mass_assignment_of(:role).as(:admin) }
58
-
59
- it { should_not allow_mass_assignment_of(:role) }
60
- end
61
-
62
- Validation Matchers
63
- -
64
- describe Site do
65
- it { should validate_presence_of(:name) }
66
- it { should validate_uniqueness_of(:name) }
67
- end
68
-
69
- describe User do
70
- it { should validate_presence_of(:login) }
71
- it { should validate_uniqueness_of(:login).scoped_to(:site) }
72
- it { should validate_uniqueness_of(:email).case_insensitive.with_message("is already taken") }
73
- it { should validate_format_of(:login).to_allow("valid_login").not_to_allow("invalid login") }
74
- it { should validate_associated(:profile) }
75
- it { should validate_exclusion_of(:login).to_not_allow("super", "index", "edit") }
76
- it { should validate_inclusion_of(:role).to_allow("admin", "member") }
77
- it { should validate_confirmation_of(:email) }
78
- it { should validate_presence_of(:age).on(:create, :update) }
79
- it { should validate_numericality_of(:age).on(:create, :update) }
80
- it { should validate_inclusion_of(:age).to_allow(23..42).on([:create, :update]) }
81
- it { should validate_presence_of(:password).on(:create) }
82
- it { should validate_presence_of(:provider_uid).on(:create) }
83
- it { should validate_inclusion_of(:locale).to_allow([:en, :ru]) }
84
- end
85
-
86
- describe Article do
87
- it { should validate_length_of(:title).within(8..16) }
88
- end
89
-
90
- describe Profile do
91
- it { should validate_numericality_of(:age).greater_than(0) }
92
- end
93
-
94
- describe MovieArticle do
95
- it { should validate_numericality_of(:rating).to_allow(:greater_than => 0).less_than_or_equal_to(5) }
96
- it { should validate_numericality_of(:classification).to_allow(:even => true, :only_integer => true, :nil => false) }
97
- end
98
-
99
- describe Person do
100
- # in order to be able to use the custom_validate matcher, the custom validator class (in this case SsnValidator)
101
- # should redefine the kind method to return :custom, i.e. "def self.kind() :custom end"
102
- it { should custom_validate(:ssn).with_validator(SsnValidator) }
103
- end
104
-
105
- Index Matcher
106
- -
107
- describe Article do
108
- it { should have_index_for(published: 1) }
109
- it { should have_index_for(title: 1).with_options(unique: true, background: true) }
110
- end
111
-
112
- describe Profile do
113
- it { should have_index_for(first_name: 1, last_name: 1) }
114
- end
115
-
116
- Others
117
- -
118
- describe User do
119
- it { should have_fields(:email, :login) }
120
- it { should have_field(:active).of_type(Boolean).with_default_value_of(false) }
121
- it { should have_fields(:birthdate, :registered_at).of_type(DateTime) }
122
-
123
- it { should be_timestamped_document } # if you're declaring `include
124
- Mongoid::Timestamps` or any of `include Mongoid::Timestamps::Created` and `Mongoid::Timestamps::Updated`
125
- it { should be_timestamped_document.with(:created) }
126
- it { should_not be_timestamped_document.with(:updated) }
127
-
128
- it { should be_versioned_document } # if you're declaring `include Mongoid::Versioning`
129
- it { should be_paranoid_document } # if you're declaring `include Mongoid::Paranoia`
130
- it { should be_multiparameted_document } # if you're declaring `include Mongoid::MultiParameterAttributes`
131
- end
132
-
133
- describe Log do
134
- it { should be_stored_in :logs }
135
- end
136
-
137
- Use
138
- -
139
- add in Gemfile
140
-
141
- gem 'mongoid-rspec'
142
-
143
- drop in existing or dedicated support file in spec/support (spec/support/mongoid.rb)
144
-
145
- RSpec.configure do |configuration|
146
- configuration.include Mongoid::Matchers
147
- end
148
-
149
- Acknowledgement
150
- -
151
- Thanks to [Durran Jordan](https://github.com/durran) for providing the changes necessary to make
152
- this compatible with mongoid 2.0.0.rc, and for other [contributors](https://github.com/evansagge/mongoid-rspec/contributors)
1
+ # mongoid-rspec
2
+
3
+ [![Build Status][travis_badge]][travis]
4
+ [![Gem Version][rubygems_badge]][rubygems]
5
+ [![Code Climate][codeclimate_badge]][codeclimate]
6
+
7
+ mongoid-rspec provides a collection of RSpec-compatible matchers that help to test mongoid documents.
8
+
9
+ ## Installation
10
+
11
+ ### With Mongoid 4.x
12
+
13
+ Use mongoid-rspec [2.0.0.rc1][mongo4]
14
+
15
+ gem 'mongoid-rspec', '~> 2.0.0.rc1'
16
+
17
+ ### With Mongoid 3.x
18
+
19
+ Use mongoid-rspec [1.11.0][mongo3].
20
+
21
+ gem 'mongoid-rspec', '~> 1.11.0'
22
+
23
+ ### With Mongoid 2.x
24
+
25
+ Use mongoid-rspec [1.4.5][mongo2]
26
+
27
+ gem 'mongoid-rspec', '1.4.5'
28
+
29
+ ### Configuring
30
+
31
+ Drop in existing or dedicated support file in spec/support.
32
+ i.e: `spec/support/mongoid.rb`
33
+
34
+ ```ruby
35
+ RSpec.configure do |config|
36
+ config.include Mongoid::Matchers, type: :model
37
+ end
38
+ ```
39
+
40
+ ## Matchers
41
+
42
+ ### Association Matchers
43
+
44
+ ```ruby
45
+ describe User do
46
+ it { should have_many(:articles).with_foreign_key(:author_id).ordered_by(:title) }
47
+
48
+ it { should have_one(:record) }
49
+ #can verify autobuild is set to true
50
+ it { should have_one(:record).with_autobuild }
51
+
52
+ it { should have_many :comments }
53
+
54
+ #can also specify with_dependent to test if :dependent => :destroy/:destroy_all/:delete is set
55
+ it { should have_many(:comments).with_dependent(:destroy) }
56
+ #can verify autosave is set to true
57
+ it { should have_many(:comments).with_autosave }
58
+
59
+ it { should embed_one :profile }
60
+
61
+ it { should have_and_belong_to_many(:children) }
62
+ it { should have_and_belong_to_many(:children).of_type(User) }
63
+ end
64
+
65
+ describe Profile do
66
+ it { should be_embedded_in(:user).as_inverse_of(:profile) }
67
+ end
68
+
69
+ describe Article do
70
+ it { should belong_to(:author).of_type(User).as_inverse_of(:articles) }
71
+ it { should belong_to(:author).of_type(User).as_inverse_of(:articles).with_index }
72
+ it { should embed_many(:comments) }
73
+ end
74
+
75
+ describe Comment do
76
+ it { should be_embedded_in(:article).as_inverse_of(:comments) }
77
+ it { should belong_to(:user).as_inverse_of(:comments) }
78
+ end
79
+
80
+ describe Record do
81
+ it { should belong_to(:user).as_inverse_of(:record) }
82
+ end
83
+
84
+ describe Site do
85
+ it { should have_many(:users).as_inverse_of(:site).ordered_by(:email.asc) }
86
+ end
87
+ ```
88
+
89
+ ### Mass Assignment Matcher
90
+
91
+ ```ruby
92
+ describe User do
93
+ it { should allow_mass_assignment_of(:login) }
94
+ it { should allow_mass_assignment_of(:email) }
95
+ it { should allow_mass_assignment_of(:age) }
96
+ it { should allow_mass_assignment_of(:password) }
97
+ it { should allow_mass_assignment_of(:password) }
98
+ it { should allow_mass_assignment_of(:role).as(:admin) }
99
+
100
+ it { should_not allow_mass_assignment_of(:role) }
101
+ end
102
+ ```
103
+
104
+ ### Validation Matchers
105
+
106
+ ```ruby
107
+ describe Site do
108
+ it { should validate_presence_of(:name) }
109
+ it { should validate_uniqueness_of(:name) }
110
+ end
111
+
112
+ describe User do
113
+ it { should validate_presence_of(:login) }
114
+ it { should validate_uniqueness_of(:login).scoped_to(:site) }
115
+ it { should validate_uniqueness_of(:email).case_insensitive.with_message("is already taken") }
116
+ it { should validate_format_of(:login).to_allow("valid_login").not_to_allow("invalid login") }
117
+ it { should validate_associated(:profile) }
118
+ it { should validate_exclusion_of(:login).to_not_allow("super", "index", "edit") }
119
+ it { should validate_inclusion_of(:role).to_allow("admin", "member") }
120
+ it { should validate_confirmation_of(:email) }
121
+ it { should validate_presence_of(:age).on(:create, :update) }
122
+ it { should validate_numericality_of(:age).on(:create, :update) }
123
+ it { should validate_inclusion_of(:age).to_allow(23..42).on([:create, :update]) }
124
+ it { should validate_presence_of(:password).on(:create) }
125
+ it { should validate_presence_of(:provider_uid).on(:create) }
126
+ it { should validate_inclusion_of(:locale).to_allow([:en, :ru]) }
127
+ end
128
+
129
+ describe Article do
130
+ it { should validate_length_of(:title).within(8..16) }
131
+ end
132
+
133
+ describe Profile do
134
+ it { should validate_numericality_of(:age).greater_than(0) }
135
+ end
136
+
137
+ describe MovieArticle do
138
+ it { should validate_numericality_of(:rating).to_allow(:greater_than => 0).less_than_or_equal_to(5) }
139
+ it { should validate_numericality_of(:classification).to_allow(:even => true, :only_integer => true, :nil => false) }
140
+ end
141
+
142
+ describe Person do
143
+ # in order to be able to use the custom_validate matcher, the custom validator class (in this case SsnValidator)
144
+ # should redefine the kind method to return :custom, i.e. "def self.kind() :custom end"
145
+ it { should custom_validate(:ssn).with_validator(SsnValidator) }
146
+ end
147
+ ```
148
+
149
+ ### Accepts Nested Attributes Matcher
150
+
151
+ ```ruby
152
+ describe User do
153
+ it { should accept_nested_attributes_for(:articles) }
154
+ it { should accept_nested_attributes_for(:comments) }
155
+ end
156
+
157
+ describe Article do
158
+ it { should accept_nested_attributes_for(:permalink) }
159
+ end
160
+ ```
161
+
162
+ ### Index Matcher
163
+
164
+ ```ruby
165
+ describe Article do
166
+ it { should have_index_for(published: 1) }
167
+ it { should have_index_for(title: 1).with_options(unique: true, background: true) }
168
+ end
169
+
170
+ describe Profile do
171
+ it { should have_index_for(first_name: 1, last_name: 1) }
172
+ end
173
+ ```
174
+
175
+ ### Others
176
+
177
+ ```ruby
178
+ describe User do
179
+ it { should have_fields(:email, :login) }
180
+ it { should have_field(:s).with_alias(:status) }
181
+ it { should have_fields(:birthdate, :registered_at).of_type(DateTime) }
182
+
183
+ # if you're declaring 'include Mongoid::Timestamps'
184
+ # or any of 'include Mongoid::Timestamps::Created' and 'Mongoid::Timestamps::Updated'
185
+ it { should be_timestamped_document }
186
+ it { should be_timestamped_document.with(:created) }
187
+ it { should_not be_timestamped_document.with(:updated) }
188
+
189
+ it { should be_versioned_document } # if you're declaring `include Mongoid::Versioning`
190
+ it { should be_paranoid_document } # if you're declaring `include Mongoid::Paranoia`
191
+ it { should be_multiparameted_document } # if you're declaring `include Mongoid::MultiParameterAttributes`
192
+ end
193
+
194
+ describe Log do
195
+ it { should be_stored_in :logs }
196
+ end
197
+
198
+ describe Article do
199
+ it { should have_field(:published).of_type(Boolean).with_default_value_of(false) }
200
+ it { should have_field(:allow_comments).of_type(Boolean).with_default_value_of(true) }
201
+ it { should_not have_field(:allow_comments).of_type(Boolean).with_default_value_of(false) }
202
+ it { should_not have_field(:number_of_comments).of_type(Integer).with_default_value_of(1) }
203
+ end
204
+ ```
205
+
206
+ ## Known issues
207
+
208
+ accept_nested_attributes_for matcher must test options [issue 91](https://github.com/mongoid-rspec/mongoid-rspec/issues/91).
209
+
210
+ ## Acknowledgement
211
+
212
+ Thanks to [Durran Jordan][durran] for providing the changes necessary to make
213
+ this compatible with mongoid 2.0.0.rc, and for other [contributors](https://github.com/mongoid-rspec/mongoid-rspec/contributors)
153
214
  to this project.
215
+
216
+ [durran]: https://github.com/durran
217
+ [mongo2]: http://rubygems.org/gems/mongoid-rspec/versions/1.4.5
218
+ [mongo3]: http://rubygems.org/gems/mongoid-rspec/versions/1.11.0
219
+ [mongo4]: http://rubygems.org/gems/mongoid-rspec/versions/2.0.0.rc1
220
+
221
+ [travis_badge]: http://img.shields.io/travis/mongoid-rspec/mongoid-rspec.svg?style=flat
222
+ [travis]: https://travis-ci.org/mongoid-rspec/mongoid-rspec
223
+
224
+ [rubygems_badge]: http://img.shields.io/gem/v/mongoid-rspec.svg?style=flat
225
+ [rubygems]: http://rubygems.org/gems/mongoid-rspec
226
+
227
+ [codeclimate_badge]: http://img.shields.io/codeclimate/github/mongoid-rspec/mongoid-rspec.svg?style=flat
228
+ [codeclimate]: https://codeclimate.com/github/mongoid-rspec/mongoid-rspec
@@ -0,0 +1,67 @@
1
+ module Mongoid
2
+ module Matchers # :nodoc:
3
+
4
+ # Ensures that the model can accept nested attributes for the specified
5
+ # association.
6
+ #
7
+ # Example:
8
+ # it { should accept_nested_attributes_for(:articles) }
9
+ #
10
+ def accept_nested_attributes_for(attribute)
11
+ AcceptNestedAttributesForMatcher.new(attribute)
12
+ end
13
+
14
+ class AcceptNestedAttributesForMatcher
15
+
16
+ def initialize(attribute)
17
+ @attribute = attribute.to_s
18
+ @options = {}
19
+ end
20
+
21
+ def matches?(subject)
22
+ @subject = subject
23
+ match?
24
+ end
25
+
26
+ def failure_message
27
+ "Expected #{expectation} (#{@problem})"
28
+ end
29
+
30
+ def negative_failure_message
31
+ "Did not expect #{expectation}"
32
+ end
33
+
34
+ alias :failure_message_when_negated :negative_failure_message
35
+
36
+ def description
37
+ description = "accepts_nested_attributes_for :#{@attribute}"
38
+ end
39
+
40
+ protected
41
+ def match?
42
+ exists?
43
+ end
44
+
45
+ def exists?
46
+ if config
47
+ true
48
+ else
49
+ @problem = 'is not declared'
50
+ false
51
+ end
52
+ end
53
+
54
+ def config
55
+ model_class.nested_attributes["#{@attribute}_attributes"]
56
+ end
57
+
58
+ def model_class
59
+ @subject.class
60
+ end
61
+
62
+ def expectation
63
+ "#{model_class.name} to accept nested attributes for #{@attribute}"
64
+ end
65
+ end
66
+ end
67
+ end
@@ -3,6 +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
7
 
7
8
  def initialize(attribute)
8
9
  @attribute = attribute.to_s