mongoid-rspec-multi-db 1.4.4

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2-head
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 1.8.7 # (current default)
3
+ - 1.9.2
4
+ - rbx
5
+ - rbx-2.0
6
+ - ree
7
+ - jruby
8
+ - ruby-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.
@@ -0,0 +1,117 @@
1
+ mongoid-rspec
2
+ =
3
+
4
+ RSpec matchers for Mongoid.
5
+
6
+ Association Matchers
7
+ -
8
+ describe User do
9
+ it { should reference_many(:articles).with_foreign_key(:author_id) }
10
+ it { should have_many(:articles).with_foreign_key(:author_id) }
11
+
12
+ it { should reference_one(:record) }
13
+ it { should have_one(:record) }
14
+
15
+ it { should reference_many :comments }
16
+ it { should have_many :comments }
17
+
18
+ #can also specify with_dependent to test if :dependent => :destroy/:destroy_all/:delete is set
19
+ it { should have_many(:comments).with_dependent(:destroy) }
20
+ #can verify autosave is set to true
21
+ it { should have_many(:comments).with_autosave }
22
+
23
+ it { should embed_one :profile }
24
+
25
+ it { should reference_and_be_referenced_in_many(:children).of_type(User) }
26
+ it { should have_and_belong_to_many(:children) }
27
+ end
28
+
29
+ describe Profile do
30
+ it { should be_embedded_in(:user).as_inverse_of(:profile) }
31
+ end
32
+
33
+ describe Article do
34
+ it { should be_referenced_in(:author).of_type(User).as_inverse_of(:articles) }
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 be_referenced_in(:user).as_inverse_of(:comments) }
43
+ end
44
+
45
+ describe Record do
46
+ it { should be_referenced_in(:user).as_inverse_of(:record) }
47
+ end
48
+
49
+ Validation Matchers
50
+ -
51
+ describe Site do
52
+ it { should validate_presence_of(:name) }
53
+ it { should validate_uniqueness_of(:name) }
54
+ end
55
+
56
+ describe User do
57
+ it { should validate_presence_of(:login) }
58
+ it { should validate_uniqueness_of(:login).scoped_to(:site) }
59
+ it { should validate_uniqueness_of(:email).case_insensitive.with_message("is already taken") }
60
+ it { should validate_format_of(:login).to_allow("valid_login").not_to_allow("invalid login") }
61
+ it { should validate_associated(:profile) }
62
+ it { should validate_inclusion_of(:role).to_allow("admin", "member") }
63
+ it { should validate_confirmation_of(:email) }
64
+ end
65
+
66
+ describe Article do
67
+ it { should validate_length_of(:title).within(8..16) }
68
+ end
69
+
70
+ describe Profile do
71
+ it { should validate_numericality_of(:age).greater_than(0) }
72
+ end
73
+
74
+ describe MovieArticle do
75
+ it { should validate_numericality_of(:rating).to_allow(:greater_than => 0).less_than_or_equal_to(5) }
76
+ it { should validate_numericality_of(:classification).to_allow(:even => true, :only_integer => true, :nil => false) }
77
+ end
78
+
79
+ Others
80
+ -
81
+ describe User do
82
+ it { should have_fields(:email, :login) }
83
+ it { should have_field(:active).of_type(Boolean).with_default_value_of(false) }
84
+ it { should have_fields(:birthdate, :registered_at).of_type(DateTime) }
85
+
86
+ it { should have_index_for(:last_name) }
87
+ it { should have_index_for(:email).with_options(:unique => true) }
88
+
89
+ # useful if you use factory_girl and have Factory(:user) defined for User
90
+ it { should save }
91
+
92
+ it { should be_timestamped_document } # if you're declaring `include Mongoid::Timestamps`
93
+ it { should be_versioned_document } # if you're declaring `include Mongoid::Versioning`
94
+ it { should be_paranoid_document } # if you're declaring `include Mongoid::Paranoia`
95
+ end
96
+
97
+ describe Log do
98
+ it { should be_stored_in :logs }
99
+ end
100
+
101
+ Use
102
+ -
103
+ add in Gemfile
104
+
105
+ gem 'mongoid-rspec'
106
+
107
+ drop in existing or dedicated support file in spec/support (spec/support/mongoid.rb)
108
+
109
+ RSpec.configure do |configuration|
110
+ configuration.include Mongoid::Matchers
111
+ end
112
+
113
+ Acknowledgement
114
+ -
115
+ Thanks to [Durran Jordan](https://github.com/durran) for providing the changes necessary to make
116
+ this compatible with mongoid 2.0.0.rc, and for other [contributors](https://github.com/evansagge/mongoid-rspec/contributors)
117
+ to this project.
@@ -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,215 @@
1
+ require 'mongoid/relations'
2
+
3
+ module Mongoid
4
+ module Matchers
5
+ module Associations
6
+
7
+ HAS_MANY = Mongoid::Relations::Referenced::Many
8
+ HAS_AND_BELONGS_TO_MANY = Mongoid::Relations::Referenced::ManyToMany
9
+ HAS_ONE = Mongoid::Relations::Referenced::One
10
+ BELONGS_TO = Mongoid::Relations::Referenced::In
11
+ EMBEDS_MANY = Mongoid::Relations::Embedded::Many
12
+ EMBEDS_ONE = Mongoid::Relations::Embedded::One
13
+ EMBEDDED_IN = Mongoid::Relations::Embedded::In
14
+
15
+
16
+ class HaveAssociationMatcher
17
+ def initialize(name, association_type)
18
+ @association = {}
19
+ @association[:name] = name.to_s
20
+ @association[:type] = association_type
21
+ # begin
22
+ # @association[:class] = name.to_s.classify.constantize
23
+ # rescue
24
+ # end
25
+ @expectation_message = "#{type_description} #{@association[:name].inspect}"
26
+ @expectation_message << " of type #{@association[:class].inspect}" unless @association[:class].nil?
27
+ end
28
+
29
+ def of_type(klass)
30
+ @association[:class] = klass
31
+ @expectation_message << " of type #{@association[:class].inspect}"
32
+ self
33
+ end
34
+
35
+ def as_inverse_of(association_inverse_name)
36
+ 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])
37
+ @association[:inverse_of] = association_inverse_name.to_s
38
+ @expectation_message << " which is an inverse of #{@association[:inverse_of].inspect}"
39
+ self
40
+ end
41
+
42
+ def with_dependent(method_name)
43
+ @association[:dependent] = method_name
44
+ @expectation_message << " which specifies dependent as #{@association[:dependent].to_s}"
45
+ self
46
+ end
47
+
48
+ def with_autosave
49
+ @association[:autosave] = true
50
+ @expectation_message << " which specifies autosave as #{@association[:autosave].to_s}"
51
+ self
52
+ end
53
+
54
+ def with_index
55
+ @association[:index] = true
56
+ @expectation_message << " which specifies index as #{@association[:index].to_s}"
57
+ self
58
+ end
59
+
60
+ def stored_as(store_as)
61
+ raise NotImplementedError, "`references_many #{@association[:name]} :stored_as => :array` has been removed in Mongoid 2.0.0.rc, use `references_and_referenced_in_many #{@association[:name]}` instead"
62
+ end
63
+
64
+ def with_foreign_key(foreign_key)
65
+ @association[:foreign_key] = foreign_key.to_s
66
+ @expectation_message << " using foreign key #{@association[:foreign_key].inspect}"
67
+ self
68
+ end
69
+
70
+ def matches?(actual)
71
+ @actual = actual.is_a?(Class) ? actual : actual.class
72
+ metadata = @actual.relations[@association[:name]]
73
+
74
+ if metadata.nil?
75
+ @negative_result_message = "no association named #{@association[:name]}"
76
+ return false
77
+ else
78
+ @positive_result_message = "association named #{@association[:name]}"
79
+ end
80
+
81
+ relation = metadata.relation
82
+ if relation != @association[:type]
83
+ @negative_result_message = "#{@actual.inspect} #{type_description(relation, false)} #{@association[:name]}"
84
+ return false
85
+ else
86
+ @positive_result_message = "#{@actual.inspect} #{type_description(relation, false)} #{@association[:name]}"
87
+ end
88
+
89
+ if !@association[:class].nil? and @association[:class] != metadata.klass
90
+ @negative_result_message = "#{@positive_result_message} of type #{metadata.klass.inspect}"
91
+ return false
92
+ else
93
+ @positive_result_message = "#{@positive_result_message}#{" of type #{metadata.klass.inspect}" if @association[:class]}"
94
+ end
95
+
96
+ if @association[:inverse_of]
97
+ if @association[:inverse_of].to_s != metadata.inverse_of.to_s
98
+ @negative_result_message = "#{@positive_result_message} which is an inverse of #{metadata.inverse_of}"
99
+ return false
100
+ else
101
+ @positive_result_message = "#{@positive_result_message} which is an inverse of #{metadata.inverse_of}"
102
+ end
103
+ end
104
+
105
+ if @association[:dependent]
106
+ if @association[:dependent].to_s != metadata.dependent.to_s
107
+ @negative_result_message = "#{@positive_result_message} which specified dependent as #{metadata.dependent}"
108
+ return false
109
+ else
110
+ @positive_result_message = "#{@positive_result_message} which specified dependent as #{metadata.dependent}"
111
+ end
112
+ end
113
+
114
+ if @association[:autosave]
115
+ if metadata.autosave != true
116
+ @negative_result_message = "#{@positive_result_message} which did not set autosave"
117
+ return false
118
+ else
119
+ @positive_result_message = "#{@positive_result_message} which set autosave"
120
+ end
121
+ end
122
+
123
+ if @association[:index]
124
+ if metadata.index != true
125
+ @negative_result_message = "#{@positive_result_message} which did not set index"
126
+ return false
127
+ else
128
+ @positive_result_message = "#{@positive_result_message} which set index"
129
+ end
130
+ end
131
+
132
+ if @association[:foreign_key]
133
+ if metadata.foreign_key != @association[:foreign_key]
134
+ @negative_result_message = "#{@positive_result_message} with foreign key #{metadata.foreign_key.inspect}"
135
+ return false
136
+ else
137
+ @positive_result_message = "#{@positive_result_message} with foreign key #{metadata.foreign_key.inspect}"
138
+ end
139
+ end
140
+
141
+ return true
142
+ end
143
+
144
+ def failure_message_for_should
145
+ "Expected #{@actual.inspect} to #{@expectation_message}, got #{@negative_result_message}"
146
+ end
147
+
148
+ def failure_message_for_should_not
149
+ "Expected #{@actual.inspect} to not #{@expectation_message}, got #{@positive_result_message}"
150
+ end
151
+
152
+ def description
153
+ @expectation_message
154
+ end
155
+
156
+ def type_description(type = nil, passive = true)
157
+ type ||= @association[:type]
158
+ case type.name
159
+ when EMBEDS_ONE.name
160
+ (passive ? 'embed' : 'embeds') << ' one'
161
+ when EMBEDS_MANY.name
162
+ (passive ? 'embed' : 'embeds') << ' many'
163
+ when EMBEDDED_IN.name
164
+ (passive ? 'be' : 'is') << ' embedded in'
165
+ when HAS_ONE.name
166
+ (passive ? 'reference' : 'references') << ' one'
167
+ when HAS_MANY.name
168
+ (passive ? 'reference' : 'references') << ' many'
169
+ when HAS_AND_BELONGS_TO_MANY.name
170
+ (passive ? 'reference' : 'references') << ' and referenced in many'
171
+ when BELONGS_TO.name
172
+ (passive ? 'be referenced in' : 'referenced in')
173
+ else
174
+ raise "Unknown association type '%s'" % type
175
+ end
176
+ end
177
+ end
178
+
179
+ def embed_one(association_name)
180
+ HaveAssociationMatcher.new(association_name, EMBEDS_ONE)
181
+ end
182
+
183
+ def embed_many(association_name)
184
+ HaveAssociationMatcher.new(association_name, EMBEDS_MANY)
185
+ end
186
+
187
+ def be_embedded_in(association_name)
188
+ HaveAssociationMatcher.new(association_name, EMBEDDED_IN)
189
+ end
190
+
191
+ def have_one_related(association_name)
192
+ HaveAssociationMatcher.new(association_name, HAS_ONE)
193
+ end
194
+ alias :reference_one :have_one_related
195
+ alias :have_one :have_one_related
196
+
197
+ def have_many_related(association_name)
198
+ HaveAssociationMatcher.new(association_name, HAS_MANY)
199
+ end
200
+ alias :reference_many :have_many_related
201
+ alias :have_many :have_many_related
202
+
203
+ def have_and_belong_to_many(association_name)
204
+ HaveAssociationMatcher.new(association_name, HAS_AND_BELONGS_TO_MANY)
205
+ end
206
+ alias :reference_and_be_referenced_in_many :have_and_belong_to_many
207
+
208
+ def belong_to_related(association_name)
209
+ HaveAssociationMatcher.new(association_name, BELONGS_TO)
210
+ end
211
+ alias :be_referenced_in :belong_to_related
212
+ alias :belong_to :belong_to_related
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,9 @@
1
+ RSpec::Matchers.define :be_stored_in do |collection_name|
2
+ match do |doc|
3
+ doc.collection_name == collection_name.to_s
4
+ end
5
+
6
+ description do
7
+ "be stored in #{collection_name.to_s}"
8
+ end
9
+ end
@@ -0,0 +1,111 @@
1
+ module Mongoid
2
+ module Matchers
3
+ class HaveFieldMatcher # :nodoc:
4
+ def initialize(*attrs)
5
+ @attributes = attrs.collect(&:to_s)
6
+ end
7
+
8
+ def of_type(type)
9
+ @type = type
10
+ self
11
+ end
12
+
13
+ def with_default_value_of(default)
14
+ @default = default
15
+ self
16
+ end
17
+
18
+ def matches?(klass)
19
+ @klass = klass.is_a?(Class) ? klass : klass.class
20
+ @errors = []
21
+ @attributes.each do |attr|
22
+ if @klass.fields.include?(attr)
23
+ error = ""
24
+ if @type and @klass.fields[attr].type != @type
25
+ error << " of type #{@klass.fields[attr].type}"
26
+ end
27
+
28
+ if !@default.nil? and !@klass.fields[attr].default.nil? and @klass.fields[attr].default != @default
29
+ error << " with default value of #{@klass.fields[attr].default}"
30
+ end
31
+
32
+ @errors.push("field #{attr.inspect}" << error) unless error.blank?
33
+ else
34
+ @errors.push "no field named #{attr.inspect}"
35
+ end
36
+ end
37
+ @errors.empty?
38
+ end
39
+
40
+ def failure_message_for_should
41
+ "Expected #{@klass.inspect} to #{description}, got #{@errors.to_sentence}"
42
+ end
43
+
44
+ def failure_message_for_should_not
45
+ "Expected #{@klass.inspect} to not #{description}, got #{@klass.inspect} to #{description}"
46
+ end
47
+
48
+ def description
49
+ desc = "have #{@attributes.size > 1 ? 'fields' : 'field'} named #{@attributes.collect(&:inspect).to_sentence}"
50
+ desc << " of type #{@type.inspect}" if @type
51
+ desc << " with default value of #{@default.inspect}" if !@default.nil?
52
+ desc
53
+ end
54
+ end
55
+
56
+ def have_field(*args)
57
+ HaveFieldMatcher.new(*args)
58
+ end
59
+ alias_method :have_fields, :have_field
60
+ end
61
+ end
62
+
63
+ RSpec::Matchers.define :have_instance_method do |name|
64
+ match do |klass|
65
+ klass.instance_methods.include?(name.to_sym)
66
+ end
67
+
68
+ description do
69
+ "have instance method #{name.to_s}"
70
+ end
71
+ end
72
+
73
+ RSpec::Matchers.define :be_mongoid_document do
74
+ match do |doc|
75
+ doc.class.included_modules.include?(Mongoid::Document)
76
+ end
77
+
78
+ description do
79
+ "be a Mongoid document"
80
+ end
81
+ end
82
+
83
+ RSpec::Matchers.define :be_versioned_document do
84
+ match do |doc|
85
+ doc.class.included_modules.include?(Mongoid::Versioning)
86
+ end
87
+
88
+ description do
89
+ "be a versioned Mongoid document"
90
+ end
91
+ end
92
+
93
+ RSpec::Matchers.define :be_timestamped_document do
94
+ match do |doc|
95
+ doc.class.included_modules.include?(Mongoid::Timestamps)
96
+ end
97
+
98
+ description do
99
+ "be a timestamped Mongoid document"
100
+ end
101
+ end
102
+
103
+ RSpec::Matchers.define :be_paranoid_document do
104
+ match do |doc|
105
+ doc.class.included_modules.include?(Mongoid::Paranoia)
106
+ end
107
+
108
+ description do
109
+ "be a paranoid Mongoid document"
110
+ end
111
+ end