mongoid-rspec 1.0.3
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.
- data/.bundle/config +2 -0
- data/.document +5 -0
- data/.gitignore +21 -0
- data/.rvmrc +1 -0
- data/Gemfile +11 -0
- data/LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/lib/matchers/associations.rb +126 -0
- data/lib/matchers/document.rb +102 -0
- data/lib/matchers/validations/associated.rb +19 -0
- data/lib/matchers/validations/format_of.rb +71 -0
- data/lib/matchers/validations/inclusion_of.rb +42 -0
- data/lib/matchers/validations/numericality_of.rb +9 -0
- data/lib/matchers/validations/presence_of.rb +9 -0
- data/lib/matchers/validations/uniqueness_of.rb +52 -0
- data/lib/matchers/validations.rb +41 -0
- data/lib/mongoid-rspec.rb +18 -0
- data/mongoid-rspec.gemspec +84 -0
- data/spec/models/article.rb +13 -0
- data/spec/models/comment.rb +6 -0
- data/spec/models/profile.rb +11 -0
- data/spec/models/user.rb +21 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/unit/associations_spec.rb +31 -0
- data/spec/unit/document_spec.rb +11 -0
- data/spec/unit/validations_spec.rb +15 -0
- metadata +141 -0
data/.bundle/config
ADDED
data/.document
ADDED
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm 1.9.2-head
|
data/Gemfile
ADDED
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.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "mongoid-rspec"
|
8
|
+
gem.summary = %Q{RSpec matchers for Mongoid}
|
9
|
+
gem.description = %Q{RSpec matches for Mongoid models, including association and validation matchers}
|
10
|
+
gem.email = "evansagge@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/evansagge/mongoid-rspec"
|
12
|
+
gem.authors = ["Evan Sagge"]
|
13
|
+
gem.add_dependency "mongoid", "2.0.0.beta4"
|
14
|
+
gem.add_dependency "bson_ext", "0.20.1"
|
15
|
+
gem.add_dependency "rspec-rails", ">= 2.0.0.beta.7"
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rspec/core'
|
24
|
+
require 'rspec/core/rake_task'
|
25
|
+
|
26
|
+
task :default => :spec
|
27
|
+
|
28
|
+
Rspec::Core::RakeTask.new(:spec) do |spec|
|
29
|
+
spec.pattern = "./spec/**/*_spec.rb"
|
30
|
+
end
|
31
|
+
|
32
|
+
Rspec::Core::RakeTask.new(:rcov) do |spec|
|
33
|
+
spec.pattern = "./spec/**/*_spec.rb"
|
34
|
+
spec.rcov = true
|
35
|
+
end
|
36
|
+
|
37
|
+
task :spec => :check_dependencies
|
38
|
+
|
39
|
+
require 'rake/rdoctask'
|
40
|
+
Rake::RDocTask.new do |rdoc|
|
41
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
42
|
+
|
43
|
+
rdoc.rdoc_dir = 'rdoc'
|
44
|
+
rdoc.title = "mongoid-rspec #{version}"
|
45
|
+
rdoc.rdoc_files.include('README*')
|
46
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
47
|
+
end
|
48
|
+
|
49
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.3
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Associations
|
4
|
+
class HaveAssociationMatcher
|
5
|
+
def initialize(name, association_type)
|
6
|
+
@association = {}
|
7
|
+
@association[:name] = name.to_s
|
8
|
+
@association[:type] = association_type
|
9
|
+
begin
|
10
|
+
@association[:class] = name.to_s.classify.constantize
|
11
|
+
rescue
|
12
|
+
end
|
13
|
+
@expectation_message = "#{type_description} #{@association[:name].inspect}"
|
14
|
+
@expectation_message << " of type #{@association[:class].inspect}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def of_type(klass)
|
18
|
+
@association[:class] = klass
|
19
|
+
@expectation_message << " of type #{@association[:class].inspect}"
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def as_inverse_of(association_inverse_name)
|
24
|
+
raise "#{@association[:type].inspect} does not respond to :inverse_of" unless [Mongoid::Associations::BelongsToRelated, Mongoid::Associations::EmbeddedIn].include?(@association[:type])
|
25
|
+
@association[:inverse_of] = association_inverse_name.to_s
|
26
|
+
@expectation_message << " which is an inverse of #{@association[:inverse_of].inspect}"
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def matches?(actual)
|
31
|
+
@actual = actual.is_a?(Class) ? actual : actual.class
|
32
|
+
association = @actual.associations[@association[:name]]
|
33
|
+
|
34
|
+
|
35
|
+
if association.nil?
|
36
|
+
@negative_result_message = "no association named #{@association[:name]}"
|
37
|
+
return false
|
38
|
+
else
|
39
|
+
@positive_result_message = "association named #{@association[:name]}"
|
40
|
+
end
|
41
|
+
|
42
|
+
if association.association != @association[:type]
|
43
|
+
@negative_result_message = "#{@actual.inspect} #{type_description(association.association, false)} #{@association[:name]}"
|
44
|
+
return false
|
45
|
+
else
|
46
|
+
@positive_result_message = "#{@actual.inspect} #{type_description(association.association, false)} #{@association[:name]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
if @association[:class] != association.klass
|
50
|
+
@negative_result_message = "#{@positive_result_message} of type #{association.klass.inspect}"
|
51
|
+
return false
|
52
|
+
else
|
53
|
+
@positive_result_message = "#{@positive_result_message} of type #{association.klass.inspect}"
|
54
|
+
end
|
55
|
+
|
56
|
+
if @association[:inverse_of]
|
57
|
+
if @association[:inverse_of].to_s != association.inverse_of.to_s
|
58
|
+
@negative_result_message = "#{@positive_result_message} which is an inverse of #{association.inverse_of}"
|
59
|
+
return false
|
60
|
+
else
|
61
|
+
@positive_result_message = "#{@positive_result_message} which is an inverse of #{association.inverse_of}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
true
|
66
|
+
end
|
67
|
+
|
68
|
+
def failure_message_for_should
|
69
|
+
"Expected #{@actual.inspect} to #{@expectation_message}, got #{@negative_result_message}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def failure_message_for_should_not
|
73
|
+
"Expected #{@actual.inspect} to not #{@expectation_message}, got #{@positive_result_message}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def description
|
77
|
+
@expectation_message
|
78
|
+
end
|
79
|
+
|
80
|
+
def type_description(type = nil, passive = true)
|
81
|
+
type ||= @association[:type]
|
82
|
+
case type.name
|
83
|
+
when "Mongoid::Associations::EmbedsOne"
|
84
|
+
(passive ? 'embed' : 'embeds') << ' one'
|
85
|
+
when "Mongoid::Associations::EmbedsMany"
|
86
|
+
(passive ? 'embed' : 'embeds') << ' many'
|
87
|
+
when "Mongoid::Associations::EmbeddedIn"
|
88
|
+
(passive ? 'be' : 'is') << ' embedded in'
|
89
|
+
when "Mongoid::Associations::HasOneRelated"
|
90
|
+
(passive ? 'have' : 'has') << ' one related'
|
91
|
+
when "Mongoid::Associations::HasManyRelated"
|
92
|
+
(passive ? 'have' : 'has') << ' many related'
|
93
|
+
when "Mongoid::Associations::BelongsToRelated"
|
94
|
+
(passive ? 'belong' : 'belongs') << ' to related'
|
95
|
+
else
|
96
|
+
raise "Unknown association type"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def embed_one(association_name)
|
102
|
+
HaveAssociationMatcher.new(association_name, Mongoid::Associations::EmbedsOne)
|
103
|
+
end
|
104
|
+
|
105
|
+
def embed_many(association_name)
|
106
|
+
HaveAssociationMatcher.new(association_name, Mongoid::Associations::EmbedsMany)
|
107
|
+
end
|
108
|
+
|
109
|
+
def be_embedded_in(association_name)
|
110
|
+
HaveAssociationMatcher.new(association_name, Mongoid::Associations::EmbeddedIn)
|
111
|
+
end
|
112
|
+
|
113
|
+
def have_one_related(association_name)
|
114
|
+
HaveAssociationMatcher.new(association_name, Mongoid::Associations::HasOneRelated)
|
115
|
+
end
|
116
|
+
|
117
|
+
def have_many_related(association_name)
|
118
|
+
HaveAssociationMatcher.new(association_name, Mongoid::Associations::HasManyRelated)
|
119
|
+
end
|
120
|
+
|
121
|
+
def belong_to_related(association_name)
|
122
|
+
HaveAssociationMatcher.new(association_name, Mongoid::Associations::BelongsToRelated)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,102 @@
|
|
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 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
|
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
|
+
|
61
|
+
class SaveMatcher
|
62
|
+
def initialize(attributes = {})
|
63
|
+
@attributes = attributes
|
64
|
+
end
|
65
|
+
|
66
|
+
def matches?(actual)
|
67
|
+
@actual = actual.is_a?(Class) ?
|
68
|
+
( defined?(::Factory) ? ::Factory.build(actual.name.underscore, @attributes) : actual.new(@attributes)) :
|
69
|
+
actual
|
70
|
+
@actual.valid? and @actual.save
|
71
|
+
end
|
72
|
+
|
73
|
+
def failure_message_for_should
|
74
|
+
"Expected #{@actual.inspect} to save properly, got #{@actual.errors.full_messages.to_sentence}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def failure_message_for_should_not
|
78
|
+
"Expected #{@actual.inspect} to not save, got saved instead"
|
79
|
+
end
|
80
|
+
|
81
|
+
def description
|
82
|
+
"save properly"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def save(attributes = {})
|
87
|
+
SaveMatcher.new(attributes)
|
88
|
+
end
|
89
|
+
alias_method :save_properly, :save
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
Rspec::Matchers.define :have_instance_method do |name|
|
95
|
+
match do |klass|
|
96
|
+
klass.instance_methods.include?(name.to_sym)
|
97
|
+
end
|
98
|
+
|
99
|
+
description do
|
100
|
+
"have instance method #{name.to_s}"
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Validations
|
4
|
+
class ValidateAssociatedMatcher < HaveValidationMatcher
|
5
|
+
def initialize(name)
|
6
|
+
super(name, :associated)
|
7
|
+
end
|
8
|
+
|
9
|
+
def description
|
10
|
+
"validate associated #{@field.inspect}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def validate_associated(association_name)
|
15
|
+
ValidateAssociatedMatcher.new(association_name)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Validations
|
4
|
+
class ValidateFormatOfMatcher < HaveValidationMatcher
|
5
|
+
def initialize(field)
|
6
|
+
super(field, :format)
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_format(format)
|
10
|
+
@format = format
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_allow(valid_value)
|
15
|
+
@valid_value = valid_value
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def not_to_allow(invalid_value)
|
20
|
+
@invalid_value = invalid_value
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def matches?(actual)
|
25
|
+
return false unless result = super(actual)
|
26
|
+
|
27
|
+
if @format
|
28
|
+
if @validator.options[:with] == @format
|
29
|
+
@positive_result_message = @positive_result_message << " with format #{@validator.options[:format].inspect}"
|
30
|
+
else
|
31
|
+
@negative_result_message = @negative_result_message << " with format #{@validator.options[:format].inspect}"
|
32
|
+
result = false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if @valid_value
|
37
|
+
if @validator.options[:with] =~ @valid_value
|
38
|
+
@positive_result_message = @positive_result_message << " with #{@valid_value.inspect} as a valid value"
|
39
|
+
else
|
40
|
+
@negative_result_message = @negative_result_message << " with #{@valid_value.inspect} as an invalid value"
|
41
|
+
result = false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if @invalid_value
|
46
|
+
if !(@invalid_value =~ @validator.options[:with])
|
47
|
+
@positive_result_message = @positive_result_message << " with #{@invalid_value.inspect} as an invalid value"
|
48
|
+
else
|
49
|
+
@negative_result_message = @negative_result_message << " with #{@invalid_value.inspect} as a valid value"
|
50
|
+
result = false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
def description
|
58
|
+
options_desc = []
|
59
|
+
options_desc << " with format #{@format.inspect}" if @format
|
60
|
+
options_desc << " allowing the value #{@valid_value.inspect}" if @valid_value
|
61
|
+
options_desc << " not allowing the value #{@invalid_value.inspect}" if @invalid_value
|
62
|
+
super << options_desc.to_sentence
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_format_of(field)
|
67
|
+
ValidateFormatOfMatcher.new(field)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Validations
|
4
|
+
class ValidateInclusionOfMatcher < HaveValidationMatcher
|
5
|
+
def initialize(name)
|
6
|
+
super(name, :inclusion)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_allow(*values)
|
10
|
+
@allowed_values = [values].flatten
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def matches?(actual)
|
15
|
+
return false unless result = super(actual)
|
16
|
+
|
17
|
+
if @allowed_values
|
18
|
+
not_allowed_values = @allowed_values - @validator.options[:in]
|
19
|
+
if not_allowed_values.empty?
|
20
|
+
@positive_result_message = @positive_result_message << " allowing all values mentioned"
|
21
|
+
else
|
22
|
+
@negative_result_message = @negative_result_message << " not allowing the following the ff. values: #{not_allowed_values.inspect}"
|
23
|
+
result = false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
result
|
28
|
+
end
|
29
|
+
|
30
|
+
def description
|
31
|
+
options_desc = []
|
32
|
+
options_desc << " allowing the ff. values: #{@allowed_values}" if @allowed_values
|
33
|
+
super << options_desc.to_sentence
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def validate_inclusion_of(field)
|
38
|
+
ValidateInclusionOfMatcher.new(field)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Validations
|
4
|
+
class ValidateUniquenessOfMatcher < HaveValidationMatcher
|
5
|
+
def initialize(field)
|
6
|
+
super(field, :uniqueness)
|
7
|
+
end
|
8
|
+
|
9
|
+
def scoped_to(*scope)
|
10
|
+
@scope = [scope].flatten
|
11
|
+
self
|
12
|
+
end
|
13
|
+
alias_method :scoped_on, :scoped_to
|
14
|
+
|
15
|
+
def allow_blank?(allow_blank)
|
16
|
+
@allow_blank = allow_blank
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(actual)
|
20
|
+
return false unless result = super(actual)
|
21
|
+
|
22
|
+
if [@validator.options[:scope]].flatten == @scope
|
23
|
+
@positive_result_message = @positive_result_message << "scope to #{@validator.options[:scope]}"
|
24
|
+
else
|
25
|
+
@negative_result_message = @negative_result_message << "scope to #{@validator.options[:scope]}"
|
26
|
+
result = false
|
27
|
+
end if @scope
|
28
|
+
|
29
|
+
if @validator.options[:allow_blank] == @allow_blank
|
30
|
+
@positive_result_message = @positive_result_message << " with blank values allowed"
|
31
|
+
else
|
32
|
+
@negative_result_message = @negative_result_message << " with no blank values allowed"
|
33
|
+
result = false
|
34
|
+
end if @allow_blank
|
35
|
+
|
36
|
+
result
|
37
|
+
end
|
38
|
+
|
39
|
+
def description
|
40
|
+
options_desc = []
|
41
|
+
options_desc << " scoped to #{@scope.inspect}" if @scope
|
42
|
+
options_desc << " allowing blank values" if @allow_blank
|
43
|
+
super << options_desc.to_sentence
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def validate_uniqueness_of(field)
|
48
|
+
ValidateUniquenessOfMatcher.new(field)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Validations
|
4
|
+
|
5
|
+
class HaveValidationMatcher
|
6
|
+
|
7
|
+
def initialize(field, validation_type)
|
8
|
+
@field = field.to_s
|
9
|
+
@type = validation_type.to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches?(actual)
|
13
|
+
@klass = actual.is_a?(Class) ? actual : actual.class
|
14
|
+
|
15
|
+
@validator = @klass.validators_on(@field).detect{|v| v.kind.to_s == @type }
|
16
|
+
|
17
|
+
if @validator
|
18
|
+
@negative_result_message = @positive_result_message = "#{@type.inspect} validator on #{@field.inspect}"
|
19
|
+
else
|
20
|
+
@negative_result_message = "no #{@type.inspect} validator on #{@field.inspect}"
|
21
|
+
return false
|
22
|
+
end
|
23
|
+
|
24
|
+
true
|
25
|
+
end
|
26
|
+
|
27
|
+
def failure_message_for_should
|
28
|
+
"Expected #{@klass.inspect} to #{description}, got #{@negative_result_message}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def failure_message_for_should_not
|
32
|
+
"Expected #{@klass.inspect} to not #{description}, got #{@positive_result_message}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def description
|
36
|
+
"validate #{@type} of #{@field.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'matchers/document'
|
4
|
+
require 'matchers/associations'
|
5
|
+
require 'matchers/validations'
|
6
|
+
require 'matchers/validations/associated'
|
7
|
+
require 'matchers/validations/format_of'
|
8
|
+
require 'matchers/validations/inclusion_of'
|
9
|
+
require 'matchers/validations/numericality_of'
|
10
|
+
require 'matchers/validations/presence_of'
|
11
|
+
require 'matchers/validations/uniqueness_of'
|
12
|
+
|
13
|
+
module Mongoid
|
14
|
+
module Matchers
|
15
|
+
include Mongoid::Matchers::Associations
|
16
|
+
include Mongoid::Matchers::Validations
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{mongoid-rspec}
|
8
|
+
s.version = "1.0.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Evan Sagge"]
|
12
|
+
s.date = %q{2010-05-09}
|
13
|
+
s.description = %q{RSpec matches for Mongoid models, including association and validation matchers}
|
14
|
+
s.email = %q{evansagge@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".bundle/config",
|
21
|
+
".document",
|
22
|
+
".gitignore",
|
23
|
+
".rvmrc",
|
24
|
+
"Gemfile",
|
25
|
+
"LICENSE",
|
26
|
+
"README.rdoc",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"lib/matchers/associations.rb",
|
30
|
+
"lib/matchers/document.rb",
|
31
|
+
"lib/matchers/validations.rb",
|
32
|
+
"lib/matchers/validations/associated.rb",
|
33
|
+
"lib/matchers/validations/format_of.rb",
|
34
|
+
"lib/matchers/validations/inclusion_of.rb",
|
35
|
+
"lib/matchers/validations/numericality_of.rb",
|
36
|
+
"lib/matchers/validations/presence_of.rb",
|
37
|
+
"lib/matchers/validations/uniqueness_of.rb",
|
38
|
+
"lib/mongoid-rspec.rb",
|
39
|
+
"mongoid-rspec.gemspec",
|
40
|
+
"spec/models/article.rb",
|
41
|
+
"spec/models/comment.rb",
|
42
|
+
"spec/models/profile.rb",
|
43
|
+
"spec/models/user.rb",
|
44
|
+
"spec/spec_helper.rb",
|
45
|
+
"spec/unit/associations_spec.rb",
|
46
|
+
"spec/unit/document_spec.rb",
|
47
|
+
"spec/unit/validations_spec.rb"
|
48
|
+
]
|
49
|
+
s.homepage = %q{http://github.com/evansagge/mongoid-rspec}
|
50
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
51
|
+
s.require_paths = ["lib"]
|
52
|
+
s.rubygems_version = %q{1.3.6}
|
53
|
+
s.summary = %q{RSpec matchers for Mongoid}
|
54
|
+
s.test_files = [
|
55
|
+
"spec/models/article.rb",
|
56
|
+
"spec/models/comment.rb",
|
57
|
+
"spec/models/profile.rb",
|
58
|
+
"spec/models/user.rb",
|
59
|
+
"spec/spec_helper.rb",
|
60
|
+
"spec/unit/associations_spec.rb",
|
61
|
+
"spec/unit/document_spec.rb",
|
62
|
+
"spec/unit/validations_spec.rb"
|
63
|
+
]
|
64
|
+
|
65
|
+
if s.respond_to? :specification_version then
|
66
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
67
|
+
s.specification_version = 3
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
70
|
+
s.add_runtime_dependency(%q<mongoid>, ["= 2.0.0.beta4"])
|
71
|
+
s.add_runtime_dependency(%q<bson_ext>, ["= 0.20.1"])
|
72
|
+
s.add_runtime_dependency(%q<rspec-rails>, [">= 2.0.0.beta.7"])
|
73
|
+
else
|
74
|
+
s.add_dependency(%q<mongoid>, ["= 2.0.0.beta4"])
|
75
|
+
s.add_dependency(%q<bson_ext>, ["= 0.20.1"])
|
76
|
+
s.add_dependency(%q<rspec-rails>, [">= 2.0.0.beta.7"])
|
77
|
+
end
|
78
|
+
else
|
79
|
+
s.add_dependency(%q<mongoid>, ["= 2.0.0.beta4"])
|
80
|
+
s.add_dependency(%q<bson_ext>, ["= 0.20.1"])
|
81
|
+
s.add_dependency(%q<rspec-rails>, [">= 2.0.0.beta.7"])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Article
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :title
|
5
|
+
field :content
|
6
|
+
field :published, :type => Boolean, :default => false
|
7
|
+
|
8
|
+
embeds_many :comments
|
9
|
+
belongs_to_related :user, :inverse_of => :articles
|
10
|
+
|
11
|
+
validates :title, :presence => true
|
12
|
+
end
|
13
|
+
|
data/spec/models/user.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class User
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :login
|
5
|
+
field :email
|
6
|
+
field :role
|
7
|
+
|
8
|
+
has_many_related :articles
|
9
|
+
has_many_related :comments
|
10
|
+
|
11
|
+
embeds_one :profile
|
12
|
+
|
13
|
+
validates :login, :presence => true, :uniqueness => true, :format => { :with => /^[\w\-]+$/ }
|
14
|
+
validates :email, :presence => true, :uniqueness => true
|
15
|
+
validates :role, :presence => true, :inclusion => { :in => ["admin", "moderator", "member"]}
|
16
|
+
validates :profile, :presence => true, :associated => true
|
17
|
+
|
18
|
+
def admin?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,32 @@
|
|
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")
|
4
|
+
$LOAD_PATH.unshift(MODELS)
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require "bundler"
|
8
|
+
Bundler.setup
|
9
|
+
|
10
|
+
require 'rspec'
|
11
|
+
require 'rspec/core'
|
12
|
+
require 'rspec/expectations'
|
13
|
+
require 'mongoid'
|
14
|
+
|
15
|
+
Mongoid.configure do |config|
|
16
|
+
name = "mongoid-rspec-test"
|
17
|
+
host = "localhost"
|
18
|
+
config.master = Mongo::Connection.new.db(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
Dir[ File.join(MODELS, "*.rb") ].sort.each { |file| require File.basename(file) }
|
22
|
+
|
23
|
+
require 'mongoid-rspec'
|
24
|
+
|
25
|
+
Rspec.configure do |config|
|
26
|
+
config.include Rspec::Matchers
|
27
|
+
config.include Mongoid::Matchers
|
28
|
+
config.mock_with :rspec
|
29
|
+
config.after :all do
|
30
|
+
Mongoid.master.collections.each(&:drop)
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Associations" do
|
4
|
+
describe User do
|
5
|
+
subject { User }
|
6
|
+
|
7
|
+
it { should have_many_related :articles }
|
8
|
+
it { should have_many_related :comments }
|
9
|
+
it { should embed_one :profile }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Profile do
|
13
|
+
subject { Profile }
|
14
|
+
|
15
|
+
it { should be_embedded_in(:user).as_inverse_of(:profile) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Article do
|
19
|
+
subject { Article }
|
20
|
+
|
21
|
+
it { should belong_to_related(:user).as_inverse_of(:articles) }
|
22
|
+
it { should embed_many(:comments) }
|
23
|
+
end
|
24
|
+
|
25
|
+
describe Comment do
|
26
|
+
subject { Comment }
|
27
|
+
|
28
|
+
it { should be_embedded_in(:article).as_inverse_of(:comments) }
|
29
|
+
it { should belong_to_related(:user).as_inverse_of(:comments) }
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Validations" do
|
4
|
+
describe User do
|
5
|
+
it { should validate_presence_of(:login) }
|
6
|
+
it { should validate_uniqueness_of(:login) }
|
7
|
+
it { should validate_format_of(:login).to_allow("valid_login").not_to_allow("invalid login") }
|
8
|
+
it { should validate_associated(:profile) }
|
9
|
+
it { should validate_inclusion_of(:role).to_allow("admin", "member") }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Profile do
|
13
|
+
it { should validate_numericality_of(:age) }
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mongoid-rspec
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
version: 1.0.3
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Evan Sagge
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-05-09 00:00:00 +08:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: mongoid
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 0
|
30
|
+
- 0
|
31
|
+
- beta4
|
32
|
+
version: 2.0.0.beta4
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: bson_ext
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - "="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
- 20
|
45
|
+
- 1
|
46
|
+
version: 0.20.1
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec-rails
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 2
|
58
|
+
- 0
|
59
|
+
- 0
|
60
|
+
- beta
|
61
|
+
- 7
|
62
|
+
version: 2.0.0.beta.7
|
63
|
+
type: :runtime
|
64
|
+
version_requirements: *id003
|
65
|
+
description: RSpec matches for Mongoid models, including association and validation matchers
|
66
|
+
email: evansagge@gmail.com
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- LICENSE
|
73
|
+
- README.rdoc
|
74
|
+
files:
|
75
|
+
- .bundle/config
|
76
|
+
- .document
|
77
|
+
- .gitignore
|
78
|
+
- .rvmrc
|
79
|
+
- Gemfile
|
80
|
+
- LICENSE
|
81
|
+
- README.rdoc
|
82
|
+
- Rakefile
|
83
|
+
- VERSION
|
84
|
+
- lib/matchers/associations.rb
|
85
|
+
- lib/matchers/document.rb
|
86
|
+
- lib/matchers/validations.rb
|
87
|
+
- lib/matchers/validations/associated.rb
|
88
|
+
- lib/matchers/validations/format_of.rb
|
89
|
+
- lib/matchers/validations/inclusion_of.rb
|
90
|
+
- lib/matchers/validations/numericality_of.rb
|
91
|
+
- lib/matchers/validations/presence_of.rb
|
92
|
+
- lib/matchers/validations/uniqueness_of.rb
|
93
|
+
- lib/mongoid-rspec.rb
|
94
|
+
- mongoid-rspec.gemspec
|
95
|
+
- spec/models/article.rb
|
96
|
+
- spec/models/comment.rb
|
97
|
+
- spec/models/profile.rb
|
98
|
+
- spec/models/user.rb
|
99
|
+
- spec/spec_helper.rb
|
100
|
+
- spec/unit/associations_spec.rb
|
101
|
+
- spec/unit/document_spec.rb
|
102
|
+
- spec/unit/validations_spec.rb
|
103
|
+
has_rdoc: true
|
104
|
+
homepage: http://github.com/evansagge/mongoid-rspec
|
105
|
+
licenses: []
|
106
|
+
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options:
|
109
|
+
- --charset=UTF-8
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
version: "0"
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
segments:
|
124
|
+
- 0
|
125
|
+
version: "0"
|
126
|
+
requirements: []
|
127
|
+
|
128
|
+
rubyforge_project:
|
129
|
+
rubygems_version: 1.3.6
|
130
|
+
signing_key:
|
131
|
+
specification_version: 3
|
132
|
+
summary: RSpec matchers for Mongoid
|
133
|
+
test_files:
|
134
|
+
- spec/models/article.rb
|
135
|
+
- spec/models/comment.rb
|
136
|
+
- spec/models/profile.rb
|
137
|
+
- spec/models/user.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/unit/associations_spec.rb
|
140
|
+
- spec/unit/document_spec.rb
|
141
|
+
- spec/unit/validations_spec.rb
|