mongoid4-rspec 1.11.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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +6 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +21 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +20 -0
  9. data/README.md +207 -0
  10. data/Rakefile +17 -0
  11. data/lib/matchers/accept_nested_attributes.rb +67 -0
  12. data/lib/matchers/allow_mass_assignment.rb +101 -0
  13. data/lib/matchers/associations.rb +316 -0
  14. data/lib/matchers/collections.rb +9 -0
  15. data/lib/matchers/document.rb +163 -0
  16. data/lib/matchers/indexes.rb +84 -0
  17. data/lib/matchers/validations.rb +81 -0
  18. data/lib/matchers/validations/acceptance_of.rb +9 -0
  19. data/lib/matchers/validations/associated.rb +19 -0
  20. data/lib/matchers/validations/confirmation_of.rb +9 -0
  21. data/lib/matchers/validations/custom_validation_of.rb +47 -0
  22. data/lib/matchers/validations/exclusion_of.rb +49 -0
  23. data/lib/matchers/validations/format_of.rb +71 -0
  24. data/lib/matchers/validations/inclusion_of.rb +49 -0
  25. data/lib/matchers/validations/length_of.rb +147 -0
  26. data/lib/matchers/validations/numericality_of.rb +74 -0
  27. data/lib/matchers/validations/presence_of.rb +9 -0
  28. data/lib/matchers/validations/uniqueness_of.rb +82 -0
  29. data/lib/matchers/validations/with_message.rb +27 -0
  30. data/lib/mongoid-rspec.rb +33 -0
  31. data/lib/mongoid-rspec/version.rb +5 -0
  32. data/mongoid-rspec.gemspec +25 -0
  33. data/mongoid4-rspec.gemspec +25 -0
  34. data/spec/models/article.rb +29 -0
  35. data/spec/models/comment.rb +6 -0
  36. data/spec/models/log.rb +4 -0
  37. data/spec/models/movie_article.rb +8 -0
  38. data/spec/models/permalink.rb +5 -0
  39. data/spec/models/person.rb +10 -0
  40. data/spec/models/profile.rb +16 -0
  41. data/spec/models/record.rb +5 -0
  42. data/spec/models/site.rb +9 -0
  43. data/spec/models/user.rb +36 -0
  44. data/spec/spec_helper.rb +32 -0
  45. data/spec/unit/accept_nested_attributes_spec.rb +12 -0
  46. data/spec/unit/associations_spec.rb +42 -0
  47. data/spec/unit/collections_spec.rb +7 -0
  48. data/spec/unit/document_spec.rb +21 -0
  49. data/spec/unit/indexes_spec.rb +13 -0
  50. data/spec/unit/validations_spec.rb +52 -0
  51. data/spec/validators/ssn_validator.rb +16 -0
  52. metadata +137 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9f589db6ba254383c7742c6dc69fb25b7510125b
4
+ data.tar.gz: c3284bbc53114213362de1c1f32aa9805759d4e0
5
+ SHA512:
6
+ metadata.gz: 31236abdc6e62d1809b4b18f2bcb938e1e2e17d1be0bb4fd97f66dd60cd61cc1769c821e33144cd66d7677839c31868c0f961790d15ac6ac3972a0d31c9dd65d
7
+ data.tar.gz: 9e79da7c63b0fbf2c7b6e910b3708e900bc113d02e96155390a4201a6ad877d2d4d1f6551313b41bd42ded08954ebcacba3d39c7928bb04acee876970e0b5704
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .rvmrc
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
6
+
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ mongoid-rspec
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.1.0
data/.travis.yml ADDED
@@ -0,0 +1,21 @@
1
+ services: mongodb
2
+ language: ruby
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+ - ruby-head
8
+ - jruby-19mode
9
+ - jruby-head
10
+ - rbx-2.1.1
11
+ - rbx-head
12
+ - rbx-19mode
13
+
14
+ gemfile:
15
+ - Gemfile
16
+
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: ruby-head
20
+ - rvm: jruby-head
21
+ - rvm: rbx-head
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in mongoid-rspec.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Evan Sagge
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,207 @@
1
+ mongoid4-rspec
2
+ =
3
+
4
+ This is a fork of the mongoid-rspec gem that you can find at [http://github.com/evansagge/mongoid-rspec](http://github.com/evansagge/mongoid-rspec)
5
+
6
+ [![Build Status](https://secure.travis-ci.org/evansagge/mongoid-rspec.png?branch=master)](https://travis-ci.org/evansagge/mongoid-rspec)
7
+
8
+ http://rubygems.org/gems/mongoid4-rspec
9
+
10
+ RSpec matchers for Mongoid 4.x.
11
+
12
+ For Mongoid 3.x, use [mongoid-rspec](http://rubygems.org/gems/mongoid-rspec)
13
+
14
+ Installation
15
+ -
16
+ Add to your Gemfile
17
+
18
+ gem 'mongoid4-rspec'
19
+
20
+ Drop in existing or dedicated support file in spec/support (spec/support/mongoid.rb)
21
+
22
+ ```ruby
23
+ RSpec.configure do |config|
24
+ config.include Mongoid::Matchers, type: :model
25
+ end
26
+ ```
27
+
28
+ Association Matchers
29
+ -
30
+
31
+ ```ruby
32
+ describe User do
33
+ it { should have_many(:articles).with_foreign_key(:author_id).ordered_by(:title) }
34
+
35
+ it { should have_one(:record) }
36
+ #can verify autobuild is set to true
37
+ it { should have_one(:record).with_autobuild }
38
+
39
+ it { should have_many :comments }
40
+
41
+ #can also specify with_dependent to test if :dependent => :destroy/:destroy_all/:delete is set
42
+ it { should have_many(:comments).with_dependent(:destroy) }
43
+ #can verify autosave is set to true
44
+ it { should have_many(:comments).with_autosave }
45
+
46
+ it { should embed_one :profile }
47
+
48
+ it { should have_and_belong_to_many(:children) }
49
+ it { should have_and_belong_to_many(:children).of_type(User) }
50
+ end
51
+
52
+ describe Profile do
53
+ it { should be_embedded_in(:user).as_inverse_of(:profile) }
54
+ end
55
+
56
+ describe Article do
57
+ it { should belong_to(:author).of_type(User).as_inverse_of(:articles) }
58
+ it { should belong_to(:author).of_type(User).as_inverse_of(:articles).with_index }
59
+ it { should embed_many(:comments) }
60
+ end
61
+
62
+ describe Comment do
63
+ it { should be_embedded_in(:article).as_inverse_of(:comments) }
64
+ it { should belong_to(:user).as_inverse_of(:comments) }
65
+ end
66
+
67
+ describe Record do
68
+ it { should belong_to(:user).as_inverse_of(:record) }
69
+ end
70
+
71
+ describe Site do
72
+ it { should have_many(:users).as_inverse_of(:site).ordered_by(:email.asc) }
73
+ end
74
+ ```
75
+
76
+ Mass Assignment Matcher
77
+ -
78
+
79
+ ```ruby
80
+ describe User do
81
+ it { should allow_mass_assignment_of(:login) }
82
+ it { should allow_mass_assignment_of(:email) }
83
+ it { should allow_mass_assignment_of(:age) }
84
+ it { should allow_mass_assignment_of(:password) }
85
+ it { should allow_mass_assignment_of(:password) }
86
+ it { should allow_mass_assignment_of(:role).as(:admin) }
87
+
88
+ it { should_not allow_mass_assignment_of(:role) }
89
+ end
90
+ ```
91
+
92
+ Validation Matchers
93
+ -
94
+
95
+ ```ruby
96
+ describe Site do
97
+ it { should validate_presence_of(:name) }
98
+ it { should validate_uniqueness_of(:name) }
99
+ end
100
+
101
+ describe User do
102
+ it { should validate_presence_of(:login) }
103
+ it { should validate_uniqueness_of(:login).scoped_to(:site) }
104
+ it { should validate_uniqueness_of(:email).case_insensitive.with_message("is already taken") }
105
+ it { should validate_format_of(:login).to_allow("valid_login").not_to_allow("invalid login") }
106
+ it { should validate_associated(:profile) }
107
+ it { should validate_exclusion_of(:login).to_not_allow("super", "index", "edit") }
108
+ it { should validate_inclusion_of(:role).to_allow("admin", "member") }
109
+ it { should validate_confirmation_of(:email) }
110
+ it { should validate_presence_of(:age).on(:create, :update) }
111
+ it { should validate_numericality_of(:age).on(:create, :update) }
112
+ it { should validate_inclusion_of(:age).to_allow(23..42).on([:create, :update]) }
113
+ it { should validate_presence_of(:password).on(:create) }
114
+ it { should validate_presence_of(:provider_uid).on(:create) }
115
+ it { should validate_inclusion_of(:locale).to_allow([:en, :ru]) }
116
+ end
117
+
118
+ describe Article do
119
+ it { should validate_length_of(:title).within(8..16) }
120
+ end
121
+
122
+ describe Profile do
123
+ it { should validate_numericality_of(:age).greater_than(0) }
124
+ end
125
+
126
+ describe MovieArticle do
127
+ it { should validate_numericality_of(:rating).to_allow(:greater_than => 0).less_than_or_equal_to(5) }
128
+ it { should validate_numericality_of(:classification).to_allow(:even => true, :only_integer => true, :nil => false) }
129
+ end
130
+
131
+ describe Person do
132
+ # in order to be able to use the custom_validate matcher, the custom validator class (in this case SsnValidator)
133
+ # should redefine the kind method to return :custom, i.e. "def self.kind() :custom end"
134
+ it { should custom_validate(:ssn).with_validator(SsnValidator) }
135
+ end
136
+ ```
137
+
138
+ Accepts Nested Attributes Matcher
139
+ -
140
+
141
+ ```ruby
142
+ describe User do
143
+ it { should accept_nested_attributes_for(:articles) }
144
+ it { should accept_nested_attributes_for(:comments) }
145
+ end
146
+
147
+ describe Article do
148
+ it { should accept_nested_attributes_for(:permalink) }
149
+ end
150
+ ```
151
+
152
+ Index Matcher
153
+ -
154
+
155
+ ```ruby
156
+ describe Article do
157
+ it { should have_index_for(published: 1) }
158
+ it { should have_index_for(title: 1).with_options(unique: true, background: true) }
159
+ end
160
+
161
+ describe Profile do
162
+ it { should have_index_for(first_name: 1, last_name: 1) }
163
+ end
164
+ ```
165
+
166
+ Others
167
+ -
168
+
169
+ ```ruby
170
+ describe User do
171
+ it { should have_fields(:email, :login) }
172
+ it { should have_field(:s).with_alias(:status) }
173
+ it { should have_fields(:birthdate, :registered_at).of_type(DateTime) }
174
+
175
+ # if you're declaring 'include Mongoid::Timestamps'
176
+ # or any of 'include Mongoid::Timestamps::Created' and 'Mongoid::Timestamps::Updated'
177
+ it { should be_timestamped_document }
178
+ it { should be_timestamped_document.with(:created) }
179
+ it { should_not be_timestamped_document.with(:updated) }
180
+
181
+ it { should be_versioned_document } # if you're declaring `include Mongoid::Versioning`
182
+ it { should be_paranoid_document } # if you're declaring `include Mongoid::Paranoia`
183
+ it { should be_multiparameted_document } # if you're declaring `include Mongoid::MultiParameterAttributes`
184
+ end
185
+
186
+ describe Log do
187
+ it { should be_stored_in :logs }
188
+ end
189
+
190
+ describe Article do
191
+ it { should have_field(:published).of_type(Boolean).with_default_value_of(false) }
192
+ it { should have_field(:allow_comments).of_type(Boolean).with_default_value_of(true) }
193
+ it { should_not have_field(:allow_comments).of_type(Boolean).with_default_value_of(false) }
194
+ it { should_not have_field(:number_of_comments).of_type(Integer).with_default_value_of(1) }
195
+ end
196
+ ```
197
+
198
+ Known issues
199
+ -
200
+
201
+ accept_nested_attributes_for matcher must test options [issue 91](https://github.com/evansagge/mongoid-rspec/issues/91).
202
+
203
+ Acknowledgement
204
+ -
205
+ Thanks to [Durran Jordan](https://github.com/durran) for providing the changes necessary to make
206
+ this compatible with mongoid 2.0.0.rc, and for other [contributors](https://github.com/evansagge/mongoid-rspec/contributors)
207
+ to this project.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+
8
+ task :default => :spec
9
+
10
+ RSpec::Core::RakeTask.new(:spec) do |spec|
11
+ spec.pattern = "./spec/**/*_spec.rb"
12
+ end
13
+
14
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
15
+ spec.pattern = "./spec/**/*_spec.rb"
16
+ spec.rcov = true
17
+ end
@@ -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
@@ -0,0 +1,101 @@
1
+ # this code is totally extracted from shoulda-matchers gem.
2
+ module Mongoid
3
+ module Matchers
4
+ class AllowMassAssignmentOfMatcher # :nodoc:
5
+ attr_reader :failure_message, :negative_failure_message
6
+
7
+ def initialize(attribute)
8
+ @attribute = attribute.to_s
9
+ @options = {}
10
+ end
11
+
12
+ def as(role)
13
+ if active_model_less_than_3_1?
14
+ raise "You can specify role only in Rails 3.1 or greater"
15
+ end
16
+ @options[:role] = role
17
+ self
18
+ end
19
+
20
+ def matches?(klass)
21
+ @klass = klass
22
+ if attr_mass_assignable?
23
+ if whitelisting?
24
+ @negative_failure_message = "#{@attribute} was made accessible"
25
+ else
26
+ if protected_attributes.empty?
27
+ @negative_failure_message = "no attributes were protected"
28
+ else
29
+ @negative_failure_message = "#{class_name} is protecting " <<
30
+ "#{protected_attributes.to_a.to_sentence}, " <<
31
+ "but not #{@attribute}."
32
+ end
33
+ end
34
+ true
35
+ else
36
+ if whitelisting?
37
+ @failure_message = "Expected #{@attribute} to be accessible"
38
+ else
39
+ @failure_message = "Did not expect #{@attribute} to be protected"
40
+ end
41
+ false
42
+ end
43
+ end
44
+
45
+ def description
46
+ "allow mass assignment of #{@attribute}"
47
+ end
48
+
49
+ private
50
+
51
+ def role
52
+ @options[:role] || :default
53
+ end
54
+
55
+ def protected_attributes
56
+ @protected_attributes ||= (@klass.class.protected_attributes || [])
57
+ end
58
+
59
+ def accessible_attributes
60
+ @accessible_attributes ||= (@klass.class.accessible_attributes || [])
61
+ end
62
+
63
+ def whitelisting?
64
+ authorizer.kind_of?(::ActiveModel::MassAssignmentSecurity::WhiteList)
65
+ end
66
+
67
+ def attr_mass_assignable?
68
+ !authorizer.deny?(@attribute)
69
+ end
70
+
71
+ def authorizer
72
+ if active_model_less_than_3_1?
73
+ @klass.class.active_authorizer
74
+ else
75
+ @klass.class.active_authorizer[role]
76
+ end
77
+ end
78
+
79
+ def class_name
80
+ @klass.class.name
81
+ end
82
+
83
+ def active_model_less_than_3_1?
84
+ ::ActiveModel::VERSION::STRING.to_f < 3.1
85
+ end
86
+ end
87
+
88
+ # Ensures that the attribute can be set on mass update.
89
+ #
90
+ # it { should_not allow_mass_assignment_of(:password) }
91
+ # it { should allow_mass_assignment_of(:first_name) }
92
+ #
93
+ # In Rails 3.1 you can check role as well:
94
+ #
95
+ # it { should allow_mass_assignment_of(:first_name).as(:admin) }
96
+ #
97
+ def allow_mass_assignment_of(value)
98
+ AllowMassAssignmentOfMatcher.new(value)
99
+ end
100
+ end
101
+ end