mongoid-rspec-multi-db 1.4.4

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