mongoid-minitest 0.0.1 → 0.0.2
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/.travis.yml +5 -0
- data/CHANGELOG.md +34 -21
- data/Guardfile +9 -4
- data/README.md +36 -9
- data/lib/matchers/associations/associations.rb +27 -15
- data/lib/matchers/document/be_stored_in.rb +23 -0
- data/lib/matchers/document/document.rb +50 -0
- data/lib/matchers/document/have_field.rb +18 -8
- data/lib/matchers/helpers.rb +4 -0
- data/lib/matchers/validations/exclusion_of.rb +3 -3
- data/lib/matchers/validations/format_of.rb +2 -2
- data/lib/matchers/validations/inclusion_of.rb +43 -0
- data/lib/matchers/validations/length_of.rb +25 -4
- data/lib/matchers/validations/uniqueness_of.rb +29 -8
- data/lib/matchers/validations/validations.rb +44 -14
- data/lib/minitest/matchers.rb +4 -4
- data/lib/mongoid-minitest.rb +3 -4
- data/lib/mongoid-minitest/version.rb +1 -1
- data/test/matchers/associations_test.rb +15 -6
- data/test/matchers/document_test.rb +11 -22
- data/test/matchers/validations_test.rb +25 -26
- data/test/models/models.rb +15 -1
- metadata +16 -16
- data/lib/matchers/document/be_document.rb +0 -20
- data/lib/matchers/document/be_paranoid.rb +0 -20
- data/lib/matchers/document/be_timestamped.rb +0 -20
- data/lib/matchers/document/be_versioned.rb +0 -20
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,30 +1,43 @@
|
|
1
|
-
###
|
1
|
+
### 0.0.2 - 04/13/2012
|
2
2
|
|
3
|
-
+ Added `
|
4
|
-
+ Added `
|
3
|
+
+ Added `have_one(association_name)` association matcher.
|
4
|
+
+ Added `in(range)` alias to `within` matcher.
|
5
|
+
+ Added `within(range)` chain matcher to `validate_length_of`.
|
6
|
+
+ Added `scoped_to(*scope)` chain matcher to `validate_uniqueness_of`
|
7
|
+
+ Added `with_message(custom_message)` chain matcher for validation matchers to test custom messages.
|
8
|
+
+ Added `DocumentModuleMatcher` class to simplify document matchers.
|
9
|
+
+ Added `be_stored_in(collection_name)` document matcher.
|
10
|
+
+ Added `to_allow(values)` chain matcher to `validate_inclusion_of`.
|
11
|
+
+ Added `validate_inclusion_of(field)` validation matcher.
|
12
|
+
+ Added `belong_to(association_name)` association matcher.
|
13
|
+
|
14
|
+
### 0.0.1 - 04/11/2012
|
15
|
+
|
16
|
+
+ Added `of_type(type)` chain matcher to association matcher.
|
17
|
+
+ Added `have_many(association_name)` association matcher.
|
5
18
|
+ Added `Mongoid::Matchers::Associations` module.
|
6
|
-
+ Added `to_not_allow` matcher to `
|
7
|
-
+ Added `validate_exclusion_of` matcher.
|
8
|
-
+ Added `to_not_allow` matcher to `
|
9
|
-
+ Added `to_allow` matcher to `
|
10
|
-
+ Added `validate_format_of` matcher.
|
11
|
-
+ Added `with_max` alias to `with_maximum` matcher.
|
12
|
-
+ Added `with_maximum` matcher to `
|
13
|
-
+ Added `with_min` alias to `with_minimum` matcher.
|
14
|
-
+ Added `with_minimum` matcher to `
|
15
|
-
+ Added `validate_length_of` matcher.
|
16
|
-
+ Added `case_sensitive` matcher to `
|
17
|
-
+ Added `validate_uniqueness_of` matcher.
|
18
|
-
+ Added `validate_presence_of` matcher.
|
19
|
-
+ Added `have_fields` matcher.
|
19
|
+
+ Added `to_not_allow(*values)` chain matcher to `validate_exclusion_of`.
|
20
|
+
+ Added `validate_exclusion_of(field)` validation matcher.
|
21
|
+
+ Added `to_not_allow(*values)` matcher to `validate_format_of`.
|
22
|
+
+ Added `to_allow(*values)` matcher to `validate_format_of`.
|
23
|
+
+ Added `validate_format_of(field)` validation matcher.
|
24
|
+
+ Added `with_max(value)` alias to `with_maximum` matcher.
|
25
|
+
+ Added `with_maximum(value)` chain matcher to `validate_length_of`
|
26
|
+
+ Added `with_min(value)` alias to `with_minimum` matcher.
|
27
|
+
+ Added `with_minimum(value)` matcher to `validate_length_of`.
|
28
|
+
+ Added `validate_length_of(field)` validation matcher.
|
29
|
+
+ Added `case_sensitive` chain matcher to `validate_uniqueness_of`.
|
30
|
+
+ Added `validate_uniqueness_of(field)` validation matcher.
|
31
|
+
+ Added `validate_presence_of(field)` validation matcher.
|
32
|
+
+ Added `have_fields(*fields)` document matcher.
|
20
33
|
+ Added `be_timestamped` document matcher.
|
21
34
|
+ Added `be_versioned` document matcher.
|
22
35
|
+ Added `be_paranoid` document matcher.
|
23
|
-
+ Added default failure messages based on description matcher.
|
24
36
|
+ Added `be_document` document matcher.
|
25
|
-
+ Added `with_default_value` matcher to `
|
26
|
-
+ Added `of_type` matcher to `
|
37
|
+
+ Added `with_default_value(default)` chain matcher to `have_field`.
|
38
|
+
+ Added `of_type(type)` chain matcher to `have_field`.
|
27
39
|
+ Added `must` and `wont` methods to `MiniTest::Spec`.
|
28
|
-
+ Added `have_field` matcher.
|
40
|
+
+ Added `have_field(field)` document matcher.
|
41
|
+
+ Added default failure messages based on description matcher.
|
29
42
|
+ Added `must` and `wont` expectations.
|
30
43
|
+ Added `assert_must` and `assert_wont` to `MiniTest::Assertions`.
|
data/Guardfile
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
guard 'minitest' do
|
2
2
|
watch(%r|^test/(.*)_test\.rb|)
|
3
|
-
watch(%r|^test/test_helper\.rb|)
|
4
|
-
watch(%r|^test/models/(.*)\.rb|)
|
5
|
-
watch(%r|^lib/
|
6
|
-
watch(%r|^lib/
|
3
|
+
watch(%r|^test/test_helper\.rb|) { "test" }
|
4
|
+
watch(%r|^test/models/(.*)\.rb|) { "test" }
|
5
|
+
watch(%r|^lib/minitest/matchers\.rb|) { "test" }
|
6
|
+
watch(%r|^lib/mongoid-minitest\.rb|) { "test" }
|
7
|
+
|
8
|
+
watch(%r|^lib/matchers/helpers\.rb|) { "test" }
|
9
|
+
watch(%r|^lib/matchers/document/(.*)\.rb|) { "test/matchers/document_test.rb" }
|
10
|
+
watch(%r|^lib/matchers/validations/(.*)\.rb|) { "test/matchers/validations_test.rb" }
|
11
|
+
watch(%r|^lib/matchers/associations/(.*)\.rb|) { "test/matchers/associations_test.rb" }
|
7
12
|
end
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
# mongoid-minitest
|
1
|
+
# mongoid-minitest [](http://travis-ci.org/frodsan/mongoid-minitest) [](https://gemnasium.com/frodsan/mongoid-minitest)
|
2
2
|
|
3
3
|
MiniTest matchers for Mongoid.
|
4
4
|
|
5
|
-
|
5
|
+
* Compatible with Ruby >=1.9.2.
|
6
|
+
* Tested on MiniTest 2.x
|
6
7
|
|
7
8
|
## Installation
|
8
9
|
|
@@ -76,10 +77,12 @@ See the following examples:
|
|
76
77
|
describe Mongoid::Matchers::Document do
|
77
78
|
subject { Person }
|
78
79
|
|
79
|
-
it { must be_document }
|
80
|
-
it { must be_paranoid }
|
81
|
-
it { must be_versioned }
|
82
|
-
it { must be_timestamped }
|
80
|
+
it { must be_document } # if model includes Mongoid::Document
|
81
|
+
it { must be_paranoid } # if model includes Mongoid::Paranoia
|
82
|
+
it { must be_versioned } # if model includes Mongoid::Versioning
|
83
|
+
it { must be_timestamped } # if model includes Mongoid::Timestamps
|
84
|
+
|
85
|
+
it { must be_stored_in(:people) } # checks the collection for model's document
|
83
86
|
|
84
87
|
it { must have_field(:name) }
|
85
88
|
it { must have_field(:name).of_type(String) }
|
@@ -92,7 +95,7 @@ See the following examples:
|
|
92
95
|
it { must have_fields(:name, :login).of_type(String).with_default_value("me") }
|
93
96
|
end
|
94
97
|
|
95
|
-
###
|
98
|
+
### Validation Matchers
|
96
99
|
|
97
100
|
describe Mongoid::Matchers::Validations do
|
98
101
|
subject { Person }
|
@@ -100,6 +103,10 @@ See the following examples:
|
|
100
103
|
it { must validate_presence_of(:name) }
|
101
104
|
|
102
105
|
it { must validate_uniqueness_of(:login).case_insensitive }
|
106
|
+
it { must validate_uniqueness_of(:login).scoped_to(:site) }
|
107
|
+
|
108
|
+
it { must validate_length_of(:login).in(5..12) }
|
109
|
+
it { must validate_length_of(:login).within(5..12) }
|
103
110
|
|
104
111
|
it { must validate_length_of(:password).with_min(8) }
|
105
112
|
it { must validate_length_of(:password).with_minimum(8) }
|
@@ -109,15 +116,35 @@ See the following examples:
|
|
109
116
|
it { must validate_format_of(:email).to_allow("foo@bar.com") }
|
110
117
|
it { must validate_format_of(:email).to_not_allow("foo_bar_com") }
|
111
118
|
|
119
|
+
it { must validate_inclusion_of(:role).to_allow("user", "admin") }
|
112
120
|
it { must validate_exclusion_of(:email).to_not_allow("foo@bar.com", "fizz@buzz.com") }
|
121
|
+
|
122
|
+
# Testing validators custom messages
|
123
|
+
it { must validate_presence_of(:role).with_message("no role") }
|
124
|
+
it { must validate_length_of(:password).with_min(8).with_message("len >= 8") }
|
113
125
|
end
|
114
126
|
|
115
127
|
### Association Matchers
|
116
128
|
|
117
129
|
describe Mongoid::Matchers::Associations do
|
118
|
-
|
130
|
+
describe Person do
|
131
|
+
subject { Person }
|
132
|
+
|
133
|
+
it { must have_one(:account).of_type(Account) }
|
134
|
+
it { must have_many(:pets).of_type(Pet) }
|
135
|
+
end
|
119
136
|
|
120
|
-
|
137
|
+
describe Pet do
|
138
|
+
subject { Pet }
|
139
|
+
|
140
|
+
it { must belong_to(:person).of_type(Person) }
|
141
|
+
end
|
142
|
+
|
143
|
+
describe Account do
|
144
|
+
subject { Account }
|
145
|
+
|
146
|
+
it { must belong_to(:person).of_type(Person) }
|
147
|
+
end
|
121
148
|
end
|
122
149
|
|
123
150
|
## Contributing
|
@@ -1,44 +1,44 @@
|
|
1
1
|
module Mongoid
|
2
2
|
module Matchers
|
3
3
|
module Associations
|
4
|
-
|
4
|
+
HAS_ONE = Mongoid::Relations::Referenced::One
|
5
|
+
HAS_MANY = Mongoid::Relations::Referenced::Many
|
6
|
+
BELONGS_TO = Mongoid::Relations::Referenced::In
|
5
7
|
|
6
8
|
class HaveAssociationMatcher
|
9
|
+
include Helpers
|
10
|
+
|
7
11
|
def initialize(name, type)
|
8
12
|
@association = {}
|
9
13
|
@association[:name] = name.to_s
|
10
14
|
@association[:type] = type
|
11
|
-
@
|
15
|
+
@description = "#{type_description} #{@association[:name].inspect}"
|
12
16
|
end
|
13
17
|
|
14
18
|
def of_type(klass)
|
15
19
|
@association[:class] = klass
|
16
|
-
@
|
20
|
+
@description << " of type #{@association[:class].inspect}"
|
17
21
|
self
|
18
22
|
end
|
19
23
|
|
20
|
-
def matches?(
|
21
|
-
@klass =
|
24
|
+
def matches?(subject)
|
25
|
+
@klass = class_of(subject)
|
22
26
|
@metadata = @klass.relations[@association[:name]]
|
23
27
|
@result = true
|
24
28
|
|
25
29
|
check_association_name
|
26
|
-
check_association_type
|
27
|
-
check_association_class if @
|
30
|
+
check_association_type
|
31
|
+
check_association_class if @association[:class]
|
28
32
|
|
29
33
|
@result
|
30
34
|
end
|
31
35
|
|
32
36
|
def failure_message
|
33
|
-
"
|
37
|
+
"#{@klass} to #{@description}, got #{@negative_message}"
|
34
38
|
end
|
35
39
|
|
36
40
|
def negative_failure_message
|
37
|
-
"
|
38
|
-
end
|
39
|
-
|
40
|
-
def description
|
41
|
-
@expectation_message
|
41
|
+
"#{@klass} to not #{@description}, got #{@positive_message}"
|
42
42
|
end
|
43
43
|
|
44
44
|
private
|
@@ -71,7 +71,7 @@ module Mongoid
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def check_association_class
|
74
|
-
if
|
74
|
+
if @association[:class] != @metadata.klass
|
75
75
|
@negative_message = "#{@positive_message} of type #{@metadata.klass}"
|
76
76
|
@result = false
|
77
77
|
else
|
@@ -82,17 +82,29 @@ module Mongoid
|
|
82
82
|
def type_description(type = nil, passive = true)
|
83
83
|
type ||= @association[:type]
|
84
84
|
case type.name
|
85
|
+
when HAS_ONE.name
|
86
|
+
(passive ? "reference" : "references") << " one"
|
85
87
|
when HAS_MANY.name
|
86
88
|
(passive ? "reference" : "references") << " many"
|
89
|
+
when BELONGS_TO.name
|
90
|
+
(passive ? "be referenced" : "referenced") << " in"
|
87
91
|
else
|
88
|
-
raise "Unknown association type
|
92
|
+
raise "Unknown association type #{type}"
|
89
93
|
end
|
90
94
|
end
|
91
95
|
end
|
92
96
|
|
97
|
+
def have_one(association_name)
|
98
|
+
HaveAssociationMatcher.new(association_name, HAS_ONE)
|
99
|
+
end
|
100
|
+
|
93
101
|
def have_many(association_name)
|
94
102
|
HaveAssociationMatcher.new(association_name, HAS_MANY)
|
95
103
|
end
|
104
|
+
|
105
|
+
def belong_to(association_name)
|
106
|
+
HaveAssociationMatcher.new(association_name, BELONGS_TO)
|
107
|
+
end
|
96
108
|
end
|
97
109
|
end
|
98
110
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
class BeStoredInMatcher
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
def initialize(collection_name)
|
7
|
+
@collection_name = collection_name.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
def matches?(subject)
|
11
|
+
class_of(subject).collection_name == @collection_name
|
12
|
+
end
|
13
|
+
|
14
|
+
def description
|
15
|
+
"be stored in #{@collection_name.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def be_stored_in(collection_name)
|
20
|
+
BeStoredInMatcher.new(collection_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Document
|
4
|
+
DOCUMENT = Mongoid::Document
|
5
|
+
PARANOIA = Mongoid::Paranoia
|
6
|
+
VERSIONING = Mongoid::Versioning
|
7
|
+
TIMESTAMPS = Mongoid::Timestamps
|
8
|
+
|
9
|
+
class DocumentModuleMatcher
|
10
|
+
include Helpers
|
11
|
+
|
12
|
+
def initialize(mod)
|
13
|
+
@mod = mod
|
14
|
+
end
|
15
|
+
|
16
|
+
def matches?(subject)
|
17
|
+
class_of(subject).included_modules.include?(@mod)
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
msg = case
|
22
|
+
when @mod == DOCUMENT then ""
|
23
|
+
when @mod == PARANOIA then "paranoid "
|
24
|
+
when @mod == VERSIONING then "versioned "
|
25
|
+
when @mod == TIMESTAMPS then "timestamped "
|
26
|
+
else raise "Unknow Mongoid module #{@mod}"
|
27
|
+
end
|
28
|
+
|
29
|
+
"be a #{msg}Mongoid document"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def be_document
|
34
|
+
DocumentModuleMatcher.new(DOCUMENT)
|
35
|
+
end
|
36
|
+
|
37
|
+
def be_paranoid
|
38
|
+
DocumentModuleMatcher.new(PARANOIA)
|
39
|
+
end
|
40
|
+
|
41
|
+
def be_versioned
|
42
|
+
DocumentModuleMatcher.new(VERSIONING)
|
43
|
+
end
|
44
|
+
|
45
|
+
def be_timestamped
|
46
|
+
DocumentModuleMatcher.new(TIMESTAMPS)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -2,7 +2,7 @@ module Mongoid
|
|
2
2
|
module Matchers
|
3
3
|
module Document
|
4
4
|
class HaveFieldMatcher
|
5
|
-
include
|
5
|
+
include Helpers
|
6
6
|
|
7
7
|
def initialize(*fields)
|
8
8
|
@fields = fields.collect(&:to_s)
|
@@ -18,8 +18,8 @@ module Mongoid
|
|
18
18
|
self
|
19
19
|
end
|
20
20
|
|
21
|
-
def matches?(
|
22
|
-
@klass =
|
21
|
+
def matches?(subject)
|
22
|
+
@klass = class_of(subject)
|
23
23
|
@errors = []
|
24
24
|
|
25
25
|
@fields.each do |field|
|
@@ -27,11 +27,11 @@ module Mongoid
|
|
27
27
|
error = ""
|
28
28
|
result_field = @klass.fields[field]
|
29
29
|
|
30
|
-
if
|
30
|
+
if check_type_with(result_field.type)
|
31
31
|
error << " of type #{result_field.type.inspect}"
|
32
32
|
end
|
33
33
|
|
34
|
-
if
|
34
|
+
if check_default_with(result_field.default)
|
35
35
|
error << " with default value of #{result_field.default.inspect}"
|
36
36
|
end
|
37
37
|
|
@@ -45,21 +45,31 @@ module Mongoid
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def failure_message
|
48
|
-
"
|
48
|
+
"#{@klass} to #{description}, got #{@errors.to_sentence}"
|
49
49
|
end
|
50
50
|
|
51
51
|
def negative_failure_message
|
52
|
-
msg =
|
52
|
+
msg = "#{@klass.inspect} to not #{description}, "
|
53
53
|
msg << "got #{@klass.inspect} to #{description}"
|
54
54
|
end
|
55
55
|
|
56
56
|
def description
|
57
|
-
desc =
|
57
|
+
desc = "have #{@fields.size > 1 ? 'fields' : 'field'} named"
|
58
58
|
desc << " #{to_sentence(@fields)}"
|
59
59
|
desc << " of type #{@type.inspect}" if @type
|
60
60
|
desc << " with default value of #{@default.inspect}" if !@default.nil?
|
61
61
|
desc
|
62
62
|
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def check_type_with(type)
|
67
|
+
@type && type != @type
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_default_with(default)
|
71
|
+
!@default.nil? && !default.nil? && default != @default
|
72
|
+
end
|
63
73
|
end
|
64
74
|
|
65
75
|
def have_field(*fields)
|
data/lib/matchers/helpers.rb
CHANGED
@@ -11,11 +11,11 @@ module Mongoid
|
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
14
|
-
def matches?(
|
15
|
-
return false unless result = super(
|
14
|
+
def matches?(subject)
|
15
|
+
return false unless result = super(subject)
|
16
16
|
|
17
17
|
if @not_allowed_values
|
18
|
-
allowed_values = @not_allowed_values - @validator.options[:in]
|
18
|
+
allowed_values = @not_allowed_values - @validator.options[:in].to_a
|
19
19
|
if allowed_values.empty?
|
20
20
|
@positive_message << " not allowing all values mentioned"
|
21
21
|
else
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Matchers
|
3
|
+
module Validations
|
4
|
+
class ValidateInclusionMatcher < HaveValidationMatcher
|
5
|
+
def initialize(field)
|
6
|
+
super(field, :inclusion)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_allow(*values)
|
10
|
+
@allowed_values = values.flatten
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def matches?(subject)
|
15
|
+
return false unless result = super(subject)
|
16
|
+
|
17
|
+
if @allowed_values
|
18
|
+
not_allowed_values = @allowed_values - @validator.options[:in].to_a
|
19
|
+
if not_allowed_values.empty?
|
20
|
+
@positive_message << " allowing all values mentioned"
|
21
|
+
else
|
22
|
+
@negative_message << " not allowing the following the values:"
|
23
|
+
@negative_message << " #{not_allowed_values.inspect}"
|
24
|
+
result = false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
result
|
29
|
+
end
|
30
|
+
|
31
|
+
def description
|
32
|
+
if @allowed_values
|
33
|
+
super << " allowing the values: #{to_sentence(@allowed_values)}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def validate_inclusion_of(field)
|
39
|
+
ValidateInclusionMatcher.new(field)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -18,11 +18,18 @@ module Mongoid
|
|
18
18
|
end
|
19
19
|
alias :with_max :with_maximum
|
20
20
|
|
21
|
-
def
|
22
|
-
|
21
|
+
def within(value)
|
22
|
+
@within = value
|
23
|
+
self
|
24
|
+
end
|
25
|
+
alias :in :within
|
26
|
+
|
27
|
+
def matches?(subject)
|
28
|
+
return false unless @result = super(subject)
|
23
29
|
|
24
30
|
check_minimum if @minimum
|
25
31
|
check_maximum if @maximum
|
32
|
+
check_range if @within
|
26
33
|
|
27
34
|
@result
|
28
35
|
end
|
@@ -31,6 +38,7 @@ module Mongoid
|
|
31
38
|
desc = []
|
32
39
|
desc << " with minimum #{@minimum}" if @minimum
|
33
40
|
desc << " with maximum #{@maximum}" if @maximum
|
41
|
+
desc << " within range #{@within}" if @within
|
34
42
|
super << desc.to_sentence
|
35
43
|
end
|
36
44
|
|
@@ -39,7 +47,7 @@ module Mongoid
|
|
39
47
|
def check_minimum
|
40
48
|
actual = @validator.options[:minimum]
|
41
49
|
if actual == @minimum
|
42
|
-
@positive_message << " with minimum of #{
|
50
|
+
@positive_message << " with minimum of #{actual}"
|
43
51
|
else
|
44
52
|
@negative_message << " with minimum of #{actual}"
|
45
53
|
@result = false
|
@@ -49,12 +57,25 @@ module Mongoid
|
|
49
57
|
def check_maximum
|
50
58
|
actual = @validator.options[:maximum]
|
51
59
|
if actual == @maximum
|
52
|
-
@positive_message << " with maximum of #{
|
60
|
+
@positive_message << " with maximum of #{actual}"
|
53
61
|
else
|
54
62
|
@negative_message << " with maximum of #{actual}"
|
55
63
|
@result = false
|
56
64
|
end
|
57
65
|
end
|
66
|
+
|
67
|
+
def check_range
|
68
|
+
min, max = [@within.min, @within.max]
|
69
|
+
actual_min = @validator.options[:minimum]
|
70
|
+
actual_max = @validator.options[:maximum]
|
71
|
+
|
72
|
+
if actual_min == min && actual_max == max
|
73
|
+
@positive_message << " with range #{@within}"
|
74
|
+
else
|
75
|
+
@negative_message << " with range #{actual_min..actual_max}"
|
76
|
+
@result = false
|
77
|
+
end
|
78
|
+
end
|
58
79
|
end
|
59
80
|
|
60
81
|
def validate_length_of(field)
|
@@ -11,14 +11,41 @@ module Mongoid
|
|
11
11
|
self
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def scoped_to(*scope)
|
15
|
+
@scope = [scope].flatten.map(&:to_s)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def matches?(subject)
|
20
|
+
return false unless @result = super(subject)
|
16
21
|
|
22
|
+
check_scope if @scope
|
17
23
|
check_case_sensivity if @case_insensitive
|
18
24
|
|
19
25
|
@result
|
20
26
|
end
|
21
27
|
|
28
|
+
def description
|
29
|
+
desc = []
|
30
|
+
desc << " scoped to #{to_sentence(@scope)}" if @scope
|
31
|
+
desc << " allowing case insensitive values" if @case_insensitive
|
32
|
+
super << desc.to_sentence
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def check_scope
|
38
|
+
actual_scope = [@validator.options[:scope]].flatten.map(&:to_s)
|
39
|
+
message = " scoped to #{to_sentence(actual_scope)}"
|
40
|
+
|
41
|
+
if actual_scope == @scope
|
42
|
+
@positive_message << message
|
43
|
+
else
|
44
|
+
@negative_message << message
|
45
|
+
@result = false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
22
49
|
def check_case_sensivity
|
23
50
|
if @validator.options[:case_sensitive] == false
|
24
51
|
@positive_message << " with case insensitive values"
|
@@ -27,12 +54,6 @@ module Mongoid
|
|
27
54
|
@result = false
|
28
55
|
end
|
29
56
|
end
|
30
|
-
|
31
|
-
def description
|
32
|
-
desc = []
|
33
|
-
desc << " allowing case insensitive values" if @case_insensitive
|
34
|
-
super << desc.to_sentence
|
35
|
-
end
|
36
57
|
end
|
37
58
|
|
38
59
|
def validate_uniqueness_of(field)
|
@@ -9,31 +9,61 @@ module Mongoid
|
|
9
9
|
@type = validation_type.to_s
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
@
|
14
|
-
|
12
|
+
def with_message(expected_message)
|
13
|
+
@expected_message = expected_message
|
14
|
+
self
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
def matches?(subject)
|
18
|
+
@klass = class_of(subject)
|
19
|
+
@validator = detect_validator
|
20
|
+
@result = true
|
21
|
+
|
22
|
+
check_validator
|
23
|
+
check_message if @expected_message
|
23
24
|
|
24
|
-
|
25
|
+
@result
|
25
26
|
end
|
26
27
|
|
27
28
|
def failure_message
|
28
|
-
"
|
29
|
+
"#{@klass} to #{description}; instead got #{@negative_message}"
|
29
30
|
end
|
30
31
|
|
31
32
|
def negative_failure_message
|
32
|
-
"
|
33
|
+
"#{@klass} to not #{description}; instead got #{@positive_message}"
|
33
34
|
end
|
34
35
|
|
35
36
|
def description
|
36
|
-
"validate #{@type.inspect} of #{@field.inspect}"
|
37
|
+
desc = "validate #{@type.inspect} of #{@field.inspect}"
|
38
|
+
desc << " with message: #{@expected_message.inspect}" if @expected_message
|
39
|
+
|
40
|
+
desc
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def check_validator
|
46
|
+
if @validator
|
47
|
+
@negative_message = "#{@type.inspect} validator on #{@field.inspect}"
|
48
|
+
@positive_message = "#{@type.inspect} validator on #{@field.inspect}"
|
49
|
+
else
|
50
|
+
@negative_message = "no #{@type.inspect} validator on #{@field.inspect}"
|
51
|
+
@result = false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def check_message
|
56
|
+
error_message = @validator.options[:message]
|
57
|
+
if @expected_message == error_message
|
58
|
+
@positive_message << " with message: #{error_message.inspect}"
|
59
|
+
else
|
60
|
+
@negative_message << " with message: #{error_message.inspect}"
|
61
|
+
@result = false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def detect_validator
|
66
|
+
@klass.validators_on(@field).detect { |v| v.kind.to_s == @type }
|
37
67
|
end
|
38
68
|
end
|
39
69
|
end
|
data/lib/minitest/matchers.rb
CHANGED
@@ -3,9 +3,9 @@ module MiniTest
|
|
3
3
|
def assert_must(subject, matcher, msg = nil)
|
4
4
|
msg = message(msg) do
|
5
5
|
if matcher.respond_to? :failure_message
|
6
|
-
matcher.failure_message
|
6
|
+
"Expected #{matcher.failure_message}".squeeze(" ")
|
7
7
|
else
|
8
|
-
"Expected #{subject.inspect} to #{matcher.description}"
|
8
|
+
"Expected #{subject.inspect} to #{matcher.description}".squeeze(" ")
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -15,9 +15,9 @@ module MiniTest
|
|
15
15
|
def assert_wont(subject, matcher, msg = nil)
|
16
16
|
msg = message(msg) do
|
17
17
|
if matcher.respond_to? :negative_failure_message
|
18
|
-
matcher.negative_failure_message
|
18
|
+
"Expected #{matcher.negative_failure_message}".squeeze(" ")
|
19
19
|
else
|
20
|
-
"Expected not to #{matcher.description}"
|
20
|
+
"Expected not to #{matcher.description}".squeeze(" ")
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
data/lib/mongoid-minitest.rb
CHANGED
@@ -4,16 +4,15 @@ require "minitest/spec"
|
|
4
4
|
|
5
5
|
require "minitest/matchers"
|
6
6
|
require "matchers/helpers"
|
7
|
+
require "matchers/document/document"
|
7
8
|
require "matchers/document/have_field"
|
8
|
-
require "matchers/document/
|
9
|
-
require "matchers/document/be_paranoid"
|
10
|
-
require "matchers/document/be_versioned"
|
11
|
-
require "matchers/document/be_timestamped"
|
9
|
+
require "matchers/document/be_stored_in"
|
12
10
|
require "matchers/validations/validations"
|
13
11
|
require "matchers/validations/presence_of"
|
14
12
|
require "matchers/validations/uniqueness_of"
|
15
13
|
require "matchers/validations/length_of"
|
16
14
|
require "matchers/validations/format_of"
|
15
|
+
require "matchers/validations/inclusion_of"
|
17
16
|
require "matchers/validations/exclusion_of"
|
18
17
|
require "matchers/associations/associations"
|
19
18
|
|
@@ -1,15 +1,24 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe "Associations" do
|
4
4
|
|
5
|
-
describe
|
5
|
+
describe Person do
|
6
6
|
subject { Person }
|
7
7
|
|
8
|
-
it { must have_many(:pets) }
|
9
|
-
it { wont have_many(:accounts) }
|
10
|
-
|
11
8
|
it { must have_many(:pets).of_type(Pet) }
|
12
|
-
it {
|
9
|
+
it { must have_one(:account).of_type(Account) }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Pet do
|
13
|
+
subject { Pet }
|
14
|
+
|
15
|
+
it { must belong_to(:person).of_type(Person) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe Account do
|
19
|
+
subject { Account }
|
20
|
+
|
21
|
+
it { must belong_to(:person).of_type(Person) }
|
13
22
|
end
|
14
23
|
|
15
24
|
end
|
@@ -1,28 +1,17 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
3
|
+
describe "Document" do
|
4
|
+
describe Person do
|
5
|
+
subject { Person }
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
it { must be_document }
|
8
|
+
it { must be_paranoid }
|
9
|
+
it { must be_versioned }
|
10
|
+
it { must be_timestamped }
|
10
11
|
|
11
|
-
|
12
|
-
it { wont have_field(:noexist) }
|
12
|
+
it { must be_stored_in(:people) }
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
it { must have_field(:name).with_default_value("me") }
|
18
|
-
it { wont have_field(:name).with_default_value("nodefault") }
|
19
|
-
it { must have_field(:name).of_type(String).with_default_value("me") }
|
20
|
-
it { wont have_field(:name).of_type(String).with_default_value("nodefault") }
|
21
|
-
|
22
|
-
it { must have_fields(:name, :login) }
|
23
|
-
it { wont have_fields(:noexist, :noexistagain) }
|
24
|
-
it { must have_fields(:name, :login).of_type(String) }
|
25
|
-
it { wont have_fields(:name, :login).of_type(Integer) }
|
26
|
-
it { must have_fields(:name, :login).with_default_value("me") }
|
27
|
-
it { must have_fields(:name, :login).of_type(String).with_default_value("me") }
|
14
|
+
it { must have_field(:name).of_type(String).with_default_value("me") }
|
15
|
+
it { must have_fields(:name, :login).of_type(String).with_default_value("me") }
|
16
|
+
end
|
28
17
|
end
|
@@ -1,29 +1,28 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
it { wont validate_exclusion_of(:email).to_not_allow("foo_bar.com") }
|
3
|
+
describe "Validations" do
|
4
|
+
describe Person do
|
5
|
+
subject { Person }
|
6
|
+
|
7
|
+
it { must validate_presence_of(:name) }
|
8
|
+
it { must validate_presence_of(:role).with_message("no role") }
|
9
|
+
|
10
|
+
it { must validate_uniqueness_of(:login).case_insensitive }
|
11
|
+
it { must validate_uniqueness_of(:login).scoped_to(:site) }
|
12
|
+
|
13
|
+
it { must validate_length_of(:login).in(5..12) }
|
14
|
+
it { must validate_length_of(:login).within(5..12) }
|
15
|
+
|
16
|
+
it { must validate_length_of(:password).with_min(8) }
|
17
|
+
it { must validate_length_of(:password).with_minimum(8) }
|
18
|
+
|
19
|
+
it { must validate_length_of(:password).with_max(16) }
|
20
|
+
it { must validate_length_of(:password).with_maximum(16) }
|
21
|
+
|
22
|
+
it { must validate_format_of(:email).to_allow("foo@bar.com") }
|
23
|
+
it { must validate_format_of(:email).to_not_allow("foo_bar_com") }
|
24
|
+
|
25
|
+
it { must validate_inclusion_of(:role).to_allow("user", "admin") }
|
26
|
+
it { must validate_exclusion_of(:email).to_not_allow("foo@bar.com", "fizz@buzz.com") }
|
27
|
+
end
|
29
28
|
end
|
data/test/models/models.rb
CHANGED
@@ -9,17 +9,31 @@ class Person
|
|
9
9
|
field :name, type: String, default: "me"
|
10
10
|
field :age, type: Integer
|
11
11
|
field :email, type: String
|
12
|
+
field :role, type: String
|
13
|
+
field :site, type: String
|
12
14
|
|
13
15
|
has_many :pets
|
16
|
+
has_one :account
|
14
17
|
|
15
18
|
validates_presence_of(:name)
|
19
|
+
validates_presence_of(:role, message: "no role")
|
16
20
|
validates_uniqueness_of(:email)
|
17
|
-
validates_uniqueness_of(:login, case_sensitive: false)
|
21
|
+
validates_uniqueness_of(:login, scope: :site, case_sensitive: false)
|
18
22
|
validates_length_of(:password, minimum: 8, maximum: 16)
|
23
|
+
validates_length_of(:login, in: 5..12)
|
19
24
|
validates_format_of(:email, with: /^([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})$/i)
|
25
|
+
validates_inclusion_of(:role, in: ["admin", "user"])
|
20
26
|
validates_exclusion_of(:email, in: ["foo@bar.com", "fizz@buzz.com"])
|
21
27
|
end
|
22
28
|
|
23
29
|
class Pet
|
24
30
|
include Mongoid::Document
|
31
|
+
|
32
|
+
belongs_to :person
|
33
|
+
end
|
34
|
+
|
35
|
+
class Account
|
36
|
+
include Mongoid::Document
|
37
|
+
|
38
|
+
belongs_to :person
|
25
39
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-minitest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
16
|
-
requirement: &
|
16
|
+
requirement: &70256836430000 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.12.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70256836430000
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: mongoid
|
27
|
-
requirement: &
|
27
|
+
requirement: &70256836423540 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 2.4.7
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70256836423540
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: bson_ext
|
38
|
-
requirement: &
|
38
|
+
requirement: &70256836425720 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.6.1
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70256836425720
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: guard-minitest
|
49
|
-
requirement: &
|
49
|
+
requirement: &70256836427820 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70256836427820
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rake
|
60
|
-
requirement: &
|
60
|
+
requirement: &70256836328980 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
@@ -65,7 +65,7 @@ dependencies:
|
|
65
65
|
version: 0.9.2
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70256836328980
|
69
69
|
description: Minitest matchers for Mongoid
|
70
70
|
email:
|
71
71
|
- lrodriguezsanc@gmail.com
|
@@ -75,6 +75,7 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- .gitignore
|
77
77
|
- .rbenv-version
|
78
|
+
- .travis.yml
|
78
79
|
- CHANGELOG.md
|
79
80
|
- Gemfile
|
80
81
|
- Guardfile
|
@@ -82,14 +83,13 @@ files:
|
|
82
83
|
- README.md
|
83
84
|
- Rakefile
|
84
85
|
- lib/matchers/associations/associations.rb
|
85
|
-
- lib/matchers/document/
|
86
|
-
- lib/matchers/document/
|
87
|
-
- lib/matchers/document/be_timestamped.rb
|
88
|
-
- lib/matchers/document/be_versioned.rb
|
86
|
+
- lib/matchers/document/be_stored_in.rb
|
87
|
+
- lib/matchers/document/document.rb
|
89
88
|
- lib/matchers/document/have_field.rb
|
90
89
|
- lib/matchers/helpers.rb
|
91
90
|
- lib/matchers/validations/exclusion_of.rb
|
92
91
|
- lib/matchers/validations/format_of.rb
|
92
|
+
- lib/matchers/validations/inclusion_of.rb
|
93
93
|
- lib/matchers/validations/length_of.rb
|
94
94
|
- lib/matchers/validations/presence_of.rb
|
95
95
|
- lib/matchers/validations/uniqueness_of.rb
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Matchers
|
3
|
-
module Document
|
4
|
-
class BeDocumentMatcher
|
5
|
-
def matches?(klass)
|
6
|
-
@klass = klass
|
7
|
-
@klass.included_modules.include?(Mongoid::Document)
|
8
|
-
end
|
9
|
-
|
10
|
-
def description
|
11
|
-
"be a Mongoid document"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def be_document
|
16
|
-
BeDocumentMatcher.new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Matchers
|
3
|
-
module Document
|
4
|
-
class BeParanoidMatcher
|
5
|
-
def matches?(klass)
|
6
|
-
@klass = klass
|
7
|
-
@klass.included_modules.include?(Mongoid::Paranoia)
|
8
|
-
end
|
9
|
-
|
10
|
-
def description
|
11
|
-
"be a paranoid Mongoid document"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def be_paranoid
|
16
|
-
BeParanoidMatcher.new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Matchers
|
3
|
-
module Document
|
4
|
-
class BeTimestamped
|
5
|
-
def matches?(klass)
|
6
|
-
@klass = klass
|
7
|
-
@klass.included_modules.include?(Mongoid::Timestamps)
|
8
|
-
end
|
9
|
-
|
10
|
-
def description
|
11
|
-
"be timestamped Mongoid document"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def be_timestamped
|
16
|
-
BeTimestamped.new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Mongoid
|
2
|
-
module Matchers
|
3
|
-
module Document
|
4
|
-
class BeVersionedMatcher
|
5
|
-
def matches?(klass)
|
6
|
-
@klass = klass
|
7
|
-
@klass.included_modules.include?(Mongoid::Versioning)
|
8
|
-
end
|
9
|
-
|
10
|
-
def description
|
11
|
-
"be a versioned Mongoid document"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def be_versioned
|
16
|
-
BeVersionedMatcher.new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|