remockable 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.travis.yml +2 -3
- data/CHANGELOG.md +6 -0
- data/README.markdown +18 -4
- data/lib/remockable/active_model/allow_values_for.rb +14 -13
- data/lib/remockable/active_model/helpers.rb +7 -6
- data/lib/remockable/active_model/validate_acceptance_of.rb +9 -11
- data/lib/remockable/active_model/validate_confirmation_of.rb +9 -11
- data/lib/remockable/active_model/validate_exclusion_of.rb +9 -11
- data/lib/remockable/active_model/validate_format_of.rb +9 -11
- data/lib/remockable/active_model/validate_inclusion_of.rb +9 -11
- data/lib/remockable/active_model/validate_length_of.rb +32 -19
- data/lib/remockable/active_model/validate_numericality_of.rb +23 -12
- data/lib/remockable/active_model/validate_presence_of.rb +9 -11
- data/lib/remockable/active_record/accept_nested_attributes_for.rb +10 -13
- data/lib/remockable/active_record/belong_to.rb +21 -13
- data/lib/remockable/active_record/have_and_belong_to_many.rb +16 -13
- data/lib/remockable/active_record/have_column.rb +14 -11
- data/lib/remockable/active_record/have_default_scope.rb +38 -20
- data/lib/remockable/active_record/have_index.rb +12 -13
- data/lib/remockable/active_record/have_many.rb +22 -13
- data/lib/remockable/active_record/have_one.rb +21 -13
- data/lib/remockable/active_record/have_scope.rb +40 -25
- data/lib/remockable/active_record/helpers.rb +3 -0
- data/lib/remockable/active_record/validate_associated.rb +9 -11
- data/lib/remockable/active_record/validate_uniqueness_of.rb +19 -11
- data/lib/remockable/helpers.rb +58 -6
- data/lib/remockable/version.rb +1 -1
- data/remockable.gemspec +3 -3
- data/spec/active_model/allow_values_for_spec.rb +19 -13
- data/spec/active_model/validate_acceptance_of_spec.rb +0 -2
- data/spec/active_model/validate_confirmation_of_spec.rb +0 -2
- data/spec/active_model/validate_exclusion_of_spec.rb +7 -9
- data/spec/active_model/validate_format_of_spec.rb +9 -11
- data/spec/active_model/validate_inclusion_of_spec.rb +7 -9
- data/spec/active_model/validate_length_of_spec.rb +16 -18
- data/spec/active_model/validate_numericality_of_spec.rb +14 -16
- data/spec/active_model/validate_presence_of_spec.rb +0 -2
- data/spec/active_record/accept_nested_attributes_for_spec.rb +22 -18
- data/spec/active_record/belong_to_spec.rb +26 -26
- data/spec/active_record/have_and_belong_to_many_spec.rb +22 -20
- data/spec/active_record/have_column_spec.rb +32 -35
- data/spec/active_record/have_default_scope_spec.rb +54 -55
- data/spec/active_record/have_index_spec.rb +24 -27
- data/spec/active_record/have_many_spec.rb +10 -11
- data/spec/active_record/have_one_spec.rb +26 -25
- data/spec/active_record/have_scope_spec.rb +75 -75
- data/spec/active_record/validate_associated_spec.rb +11 -11
- data/spec/active_record/validate_uniqueness_of_spec.rb +11 -13
- data/spec/spec_helper.rb +2 -4
- data/spec/support/active_record_example_group.rb +3 -4
- data/spec/support/class_builder.rb +15 -11
- data/spec/support/shared/a_validation_matcher.rb +25 -25
- data/spec/support/shared/an_active_record_matcher.rb +14 -12
- metadata +60 -84
@@ -1,228 +1,228 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
describe :have_scope do
|
4
2
|
let(:options) { :one }
|
5
3
|
|
6
4
|
it_behaves_like 'an Active Record matcher' do
|
7
5
|
let(:model) { build_class(:User, ActiveRecord::Base) }
|
8
6
|
|
7
|
+
subject(:instance) { model.new }
|
8
|
+
|
9
9
|
before do
|
10
|
-
create_table
|
10
|
+
create_table :users do |table|
|
11
|
+
table.string :one
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
|
-
subject { model.new }
|
14
|
-
|
15
15
|
context 'description' do
|
16
16
|
let(:matcher) { send(matcher_name, *options) }
|
17
17
|
|
18
18
|
it 'has a custom description' do
|
19
|
-
name = matcher.
|
20
|
-
with = " with #{matcher.
|
19
|
+
name = matcher.attribute
|
20
|
+
with = " with #{matcher.options}" if matcher.options.any?
|
21
21
|
|
22
|
-
matcher.description.
|
22
|
+
expect(matcher.description).to eq "have scope #{name}#{with}"
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
context 'with a scope name' do
|
27
27
|
it 'matches if the scope exists' do
|
28
|
-
model.instance_eval { scope
|
29
|
-
model.
|
28
|
+
model.instance_eval { scope :no_one, -> { where one: nil } }
|
29
|
+
expect(model).to have_scope :no_one
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'does not match if the scope does not exist' do
|
33
|
-
model.
|
33
|
+
expect(model).to_not have_scope :no_one
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
context 'with an eager_load value' do
|
38
38
|
it 'matches if the scope exists and the query matches' do
|
39
|
-
model.instance_eval { scope
|
40
|
-
model.
|
39
|
+
model.instance_eval { scope :loaded, -> { eager_load :order } }
|
40
|
+
expect(model).to have_scope(:loaded).eager_load(:order)
|
41
41
|
end
|
42
42
|
|
43
43
|
it 'does not match if the query does not match' do
|
44
|
-
model.instance_eval { scope
|
45
|
-
model.
|
44
|
+
model.instance_eval { scope :loaded, -> { eager_load :order } }
|
45
|
+
expect(model).to_not have_scope(:loaded).eager_load(:from)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
context 'with a from value' do
|
50
50
|
it 'matches if the scope exists and the query matches' do
|
51
|
-
model.instance_eval { scope
|
52
|
-
model.
|
51
|
+
model.instance_eval { scope :used, -> { from 'users' } }
|
52
|
+
expect(model).to have_scope(:used).from('users')
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'does not match if the query does not match' do
|
56
|
-
model.instance_eval { scope
|
57
|
-
model.
|
56
|
+
model.instance_eval { scope :used, -> { from 'users' } }
|
57
|
+
expect(model).to_not have_scope(:used).from('friends')
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
61
|
context 'with a group value' do
|
62
62
|
it 'matches if the scope exists and the query matches' do
|
63
|
-
model.instance_eval { scope
|
64
|
-
model.
|
63
|
+
model.instance_eval { scope :grouped, -> { group 'one' } }
|
64
|
+
expect(model).to have_scope(:grouped).group('one')
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'does not match if the query does not match' do
|
68
|
-
model.instance_eval { scope
|
69
|
-
model.
|
68
|
+
model.instance_eval { scope :grouped, -> { group 'one' } }
|
69
|
+
expect(model).to_not have_scope(:grouped).group('two')
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
73
|
context 'with a having value' do
|
74
74
|
it 'matches if the scope exists and the query matches' do
|
75
|
-
model.instance_eval { scope
|
76
|
-
model.
|
75
|
+
model.instance_eval { scope :had, -> { having 'COUNT(*) > 1' } }
|
76
|
+
expect(model).to have_scope(:had).having('COUNT(*) > 1')
|
77
77
|
end
|
78
78
|
|
79
79
|
it 'does not match if the query does not match' do
|
80
|
-
model.instance_eval { scope
|
81
|
-
model.
|
80
|
+
model.instance_eval { scope :had, -> { having 'COUNT(*) > 1' } }
|
81
|
+
expect(model).to_not have_scope(:had).having('COUNT(*) > 2')
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'with an includes value' do
|
86
86
|
it 'matches if the scope exists and the query matches' do
|
87
|
-
model.instance_eval { scope
|
88
|
-
model.
|
87
|
+
model.instance_eval { scope :joined, -> { includes :company } }
|
88
|
+
expect(model).to have_scope(:joined).includes(:company)
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'does not match if the query does not match' do
|
92
|
-
model.instance_eval { scope
|
93
|
-
model.
|
92
|
+
model.instance_eval { scope :joined, -> { includes :company } }
|
93
|
+
expect(model).to_not have_scope(:joined).includes(:address)
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
97
|
context 'with a joins value' do
|
98
98
|
it 'matches if the scope exists and the query matches' do
|
99
|
-
model.instance_eval { scope
|
100
|
-
model.
|
99
|
+
model.instance_eval { scope :joined, -> { joins 'INNER JOIN friends' } }
|
100
|
+
expect(model).to have_scope(:joined).joins('INNER JOIN friends')
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'does not match if the query does not match' do
|
104
|
-
model.instance_eval { scope
|
105
|
-
model.
|
104
|
+
model.instance_eval { scope :joined, -> { joins 'INNER JOIN friends' } }
|
105
|
+
expect(model).to_not have_scope(:joined).joins('INNER JOIN enemies')
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
context 'with a limit value' do
|
110
110
|
it 'matches if the scope exists and the query matches' do
|
111
|
-
model.instance_eval { scope
|
112
|
-
model.
|
111
|
+
model.instance_eval { scope :limited, -> { limit 10 } }
|
112
|
+
expect(model).to have_scope(:limited).limit(10)
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'does not match if the query does not match' do
|
116
|
-
model.instance_eval { scope
|
117
|
-
model.
|
116
|
+
model.instance_eval { scope :limited, -> { limit 10 } }
|
117
|
+
expect(model).to_not have_scope(:limited).limit(15)
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
121
121
|
context 'with a lock value' do
|
122
122
|
it 'matches if the scope exists and the query matches' do
|
123
|
-
model.instance_eval { scope
|
124
|
-
model.
|
123
|
+
model.instance_eval { scope :locked, -> { lock true } }
|
124
|
+
expect(model).to have_scope(:locked).lock(true)
|
125
125
|
end
|
126
126
|
|
127
127
|
it 'does not match if the query does not match' do
|
128
|
-
model.instance_eval { scope
|
129
|
-
model.
|
128
|
+
model.instance_eval { scope :locked, -> { lock true } }
|
129
|
+
expect(model).to_not have_scope(:locked).lock(false)
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
133
|
context 'with an offset value' do
|
134
134
|
it 'matches if the scope exists and the query matches' do
|
135
|
-
model.instance_eval { scope
|
136
|
-
model.
|
135
|
+
model.instance_eval { scope :shifted, -> { offset 10 } }
|
136
|
+
expect(model).to have_scope(:shifted).offset(10)
|
137
137
|
end
|
138
138
|
|
139
139
|
it 'does not match if the query does not match' do
|
140
|
-
model.instance_eval { scope
|
141
|
-
model.
|
140
|
+
model.instance_eval { scope :shifted, -> { offset 10 } }
|
141
|
+
expect(model).to_not have_scope(:shifted).offset(15)
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
145
|
context 'with an order value' do
|
146
146
|
it 'matches if the scope exists and the query matches' do
|
147
|
-
model.instance_eval { scope
|
148
|
-
model.
|
147
|
+
model.instance_eval { scope :ordered, -> { order 'one' } }
|
148
|
+
expect(model).to have_scope(:ordered).order('one')
|
149
149
|
end
|
150
150
|
|
151
151
|
it 'does not match if the query does not match' do
|
152
|
-
model.instance_eval { scope
|
153
|
-
model.
|
152
|
+
model.instance_eval { scope :ordered, -> { order 'one' } }
|
153
|
+
expect(model).to_not have_scope(:ordered).order('id')
|
154
154
|
end
|
155
155
|
end
|
156
156
|
|
157
157
|
context 'with a preload value' do
|
158
158
|
it 'matches if the scope exists and the query matches' do
|
159
|
-
model.instance_eval { scope
|
160
|
-
model.
|
159
|
+
model.instance_eval { scope :preloaded, -> { preload :company } }
|
160
|
+
expect(model).to have_scope(:preloaded).preload(:company)
|
161
161
|
end
|
162
162
|
|
163
163
|
it 'does not match if the query does not match' do
|
164
|
-
model.instance_eval { scope
|
165
|
-
model.
|
164
|
+
model.instance_eval { scope :preloaded, -> { preload :company } }
|
165
|
+
expect(model).to_not have_scope(:preloaded).preload(:address)
|
166
166
|
end
|
167
167
|
end
|
168
168
|
|
169
169
|
context 'with a readonly value' do
|
170
170
|
it 'matches if the scope exists and the query matches' do
|
171
|
-
model.instance_eval { scope
|
172
|
-
model.
|
171
|
+
model.instance_eval { scope :prepared, -> { readonly false } }
|
172
|
+
expect(model).to have_scope(:prepared).readonly(false)
|
173
173
|
end
|
174
174
|
|
175
175
|
it 'does not match if the query does not match' do
|
176
|
-
model.instance_eval { scope
|
177
|
-
model.
|
176
|
+
model.instance_eval { scope :prepared, -> { readonly false } }
|
177
|
+
expect(model).to_not have_scope(:prepared).readonly(true)
|
178
178
|
end
|
179
179
|
end
|
180
180
|
|
181
181
|
context 'with a reorder value' do
|
182
182
|
it 'matches if the scope exists and the query matches' do
|
183
|
-
model.instance_eval { scope
|
184
|
-
model.
|
183
|
+
model.instance_eval { scope :reordered, -> { reorder 'one' } }
|
184
|
+
expect(model).to have_scope(:reordered).reorder('one')
|
185
185
|
end
|
186
186
|
|
187
187
|
it 'does not match if the query does not match' do
|
188
|
-
model.instance_eval { scope
|
189
|
-
model.
|
188
|
+
model.instance_eval { scope :reordered, -> { reorder 'one' } }
|
189
|
+
expect(model).to_not have_scope(:reordered).reorder('id')
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
193
|
context 'with a select value' do
|
194
194
|
it 'matches if the scope exists and the query matches' do
|
195
|
-
model.instance_eval { scope
|
196
|
-
model.
|
195
|
+
model.instance_eval { scope :ones, -> { select 'one' } }
|
196
|
+
expect(model).to have_scope(:ones).select('one')
|
197
197
|
end
|
198
198
|
|
199
199
|
it 'does not match if the query does not match' do
|
200
|
-
model.instance_eval { scope
|
201
|
-
model.
|
200
|
+
model.instance_eval { scope :ones, -> { select 'one' } }
|
201
|
+
expect(model).to_not have_scope(:ones).select('id')
|
202
202
|
end
|
203
203
|
end
|
204
204
|
|
205
205
|
context 'with a where value' do
|
206
206
|
it 'matches if the scope exists and the query matches' do
|
207
|
-
model.instance_eval { scope
|
208
|
-
model.
|
207
|
+
model.instance_eval { scope :no_one, -> { where one: nil } }
|
208
|
+
expect(model).to have_scope(:no_one).where(one: nil)
|
209
209
|
end
|
210
210
|
|
211
211
|
it 'does not match if the query does not match' do
|
212
|
-
model.instance_eval { scope
|
213
|
-
model.
|
212
|
+
model.instance_eval { scope :no_one, -> { where one: nil } }
|
213
|
+
expect(model).to_not have_scope(:no_one).where(one: 1)
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
217
|
context 'with option :with' do
|
218
218
|
it 'matches if the query matches for the given value' do
|
219
|
-
model.instance_eval { scope
|
220
|
-
model.
|
219
|
+
model.instance_eval { scope :which_one, ->(one) { where one: one } }
|
220
|
+
expect(model).to have_scope(:which_one, with: 1).where(one: 1)
|
221
221
|
end
|
222
222
|
|
223
223
|
it 'does not match if the query does not match for the given value' do
|
224
|
-
model.instance_eval { scope
|
225
|
-
model.
|
224
|
+
model.instance_eval { scope :which_one, ->(one) { where one: one } }
|
225
|
+
expect(model).to_not have_scope(:which_one, with: 2).where(one: 1)
|
226
226
|
end
|
227
227
|
end
|
228
228
|
end
|
@@ -1,27 +1,27 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
describe :validate_associated do
|
4
2
|
let(:validator_name) { :associated }
|
5
3
|
let(:attribute) { :company }
|
6
|
-
let(:default_options) { { :
|
4
|
+
let(:default_options) { { on: :create } }
|
7
5
|
|
8
6
|
before do
|
9
|
-
create_table
|
7
|
+
create_table :users do |table|
|
8
|
+
table.string :company_id
|
9
|
+
end
|
10
10
|
end
|
11
11
|
|
12
12
|
it_behaves_like 'a validation matcher' do
|
13
|
-
let(:model)
|
14
|
-
build_class
|
13
|
+
let(:model) {
|
14
|
+
build_class :User, ActiveRecord::Base do
|
15
15
|
include ActiveRecord::Validations
|
16
16
|
|
17
17
|
belongs_to :company
|
18
18
|
end
|
19
|
-
|
19
|
+
}
|
20
20
|
|
21
|
-
with_option
|
22
|
-
with_option
|
21
|
+
with_option :message, 'is not unique!', 'invalid'
|
22
|
+
with_option :on, :create, :update
|
23
23
|
|
24
|
-
with_conditional_option
|
25
|
-
with_conditional_option
|
24
|
+
with_conditional_option :if
|
25
|
+
with_conditional_option :unless
|
26
26
|
end
|
27
27
|
end
|
@@ -1,23 +1,21 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
1
|
describe :validate_uniqueness_of do
|
4
2
|
let(:validator_name) { :uniqueness }
|
5
|
-
let(:default_options) { { :
|
3
|
+
let(:default_options) { { scope: :two } }
|
6
4
|
|
7
5
|
it_behaves_like 'a validation matcher' do
|
8
|
-
let(:model)
|
9
|
-
build_class
|
6
|
+
let(:model) {
|
7
|
+
build_class :User do
|
10
8
|
include ActiveRecord::Validations
|
11
9
|
end
|
12
|
-
|
10
|
+
}
|
13
11
|
|
14
|
-
with_option
|
15
|
-
with_option
|
16
|
-
with_option
|
17
|
-
with_option
|
18
|
-
with_option
|
12
|
+
with_option :allow_blank, true, false
|
13
|
+
with_option :allow_nil, true, false
|
14
|
+
with_option :case_sensitive, true, false
|
15
|
+
with_option :message, 'is not unique!', 'invalid'
|
16
|
+
with_option :scope, :two, :three
|
19
17
|
|
20
|
-
with_conditional_option
|
21
|
-
with_conditional_option
|
18
|
+
with_conditional_option :if
|
19
|
+
with_conditional_option :unless
|
22
20
|
end
|
23
21
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
require 'active_model'
|
2
2
|
require 'active_record'
|
3
3
|
|
4
|
-
$:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
|
5
4
|
require 'remockable'
|
6
5
|
|
7
|
-
#
|
8
|
-
# in ./support/ and its subdirectories.
|
6
|
+
# Require supporting files with custom matchers and macros, etc.
|
9
7
|
Dir[File.expand_path('../support/**/*.rb', __FILE__)].each do |file|
|
10
8
|
require(file)
|
11
9
|
end
|
12
10
|
|
13
11
|
RSpec.configure do |config|
|
14
12
|
config.mock_with :rspec
|
15
|
-
config.filter_run :
|
13
|
+
config.filter_run focus: true
|
16
14
|
config.run_all_when_everything_filtered = true
|
17
15
|
end
|
@@ -6,14 +6,13 @@ module ActiveRecordExampleGroup
|
|
6
6
|
|
7
7
|
before do
|
8
8
|
ActiveRecord::Base.establish_connection(
|
9
|
-
:
|
10
|
-
:
|
9
|
+
adapter: 'sqlite3',
|
10
|
+
database: ':memory:'
|
11
11
|
)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
RSpec.configure do |config|
|
16
|
-
config.include self,
|
17
|
-
:example_group => { :file_path => /spec\/active_record/ }
|
16
|
+
config.include self, file_path: /spec\/active_record/
|
18
17
|
end
|
19
18
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
class_builder = Module.new do
|
2
2
|
def build_class(name, superclass=Object, &block)
|
3
3
|
Class.new(superclass) do
|
4
4
|
class_eval <<-EVAL
|
@@ -7,33 +7,37 @@ module ClassBuilder
|
|
7
7
|
end
|
8
8
|
EVAL
|
9
9
|
|
10
|
-
class_eval
|
10
|
+
class_eval &block if block_given?
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
def create_table(table_name, options={}, &block)
|
15
15
|
begin
|
16
|
-
drop_table
|
17
|
-
ActiveRecord::Base.connection.create_table
|
18
|
-
|
16
|
+
drop_table table_name
|
17
|
+
ActiveRecord::Base.connection.create_table table_name, options, &block
|
18
|
+
created_tables << table_name
|
19
19
|
rescue
|
20
|
-
drop_table
|
21
|
-
raise
|
20
|
+
drop_table table_name
|
21
|
+
raise
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
def created_tables
|
26
|
+
@created_tables ||= []
|
27
|
+
end
|
28
|
+
|
25
29
|
def drop_table(table_name)
|
26
|
-
ActiveRecord::Base.connection.execute
|
30
|
+
ActiveRecord::Base.connection.execute "DROP TABLE IF EXISTS #{table_name}"
|
27
31
|
end
|
28
32
|
|
29
33
|
def drop_created_tables
|
30
|
-
|
31
|
-
|
34
|
+
created_tables.each do |table_name|
|
35
|
+
drop_table table_name
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
36
40
|
RSpec.configure do |config|
|
37
|
-
config.include
|
41
|
+
config.include class_builder
|
38
42
|
config.after { drop_created_tables }
|
39
43
|
end
|
@@ -3,25 +3,25 @@ shared_examples_for 'a validation matcher' do
|
|
3
3
|
let(:options) { default_options }
|
4
4
|
let(:matcher_name) { self.class.parent.parent.description }
|
5
5
|
|
6
|
-
let(:model)
|
7
|
-
build_class
|
6
|
+
let(:model) {
|
7
|
+
build_class :User do
|
8
8
|
include ActiveModel::Validations
|
9
9
|
end
|
10
|
-
|
10
|
+
}
|
11
|
+
|
12
|
+
subject(:instance) { model.new }
|
11
13
|
|
12
14
|
before do
|
13
|
-
model.validates
|
15
|
+
model.validates attribute, validator_name => options
|
14
16
|
end
|
15
17
|
|
16
|
-
subject { model.new }
|
17
|
-
|
18
18
|
def self.with_option(option_name, positive, negative, exclusive=false)
|
19
19
|
context "with option #{option_name.inspect}" do
|
20
|
-
let(:options)
|
20
|
+
let(:options) {
|
21
21
|
option = { option_name => positive }
|
22
22
|
merge_with_default = !exclusive && default_options.is_a?(Hash)
|
23
23
|
merge_with_default ? default_options.merge(option) : option
|
24
|
-
|
24
|
+
}
|
25
25
|
|
26
26
|
it 'matches if the options match' do
|
27
27
|
should send(matcher_name, attribute, option_name => positive)
|
@@ -34,7 +34,7 @@ shared_examples_for 'a validation matcher' do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def self.with_option!(option_name, positive, negative)
|
37
|
-
with_option
|
37
|
+
with_option option_name, positive, negative, true
|
38
38
|
end
|
39
39
|
|
40
40
|
def self.with_conditional_option(option_name)
|
@@ -54,7 +54,7 @@ shared_examples_for 'a validation matcher' do
|
|
54
54
|
end
|
55
55
|
|
56
56
|
context "with option #{option_name.inspect} with a procedure" do
|
57
|
-
let(:procedure) {
|
57
|
+
let(:procedure) { ->(record) { record.skip_validations } }
|
58
58
|
|
59
59
|
let(:options) {
|
60
60
|
option = { option_name => procedure }
|
@@ -62,12 +62,12 @@ shared_examples_for 'a validation matcher' do
|
|
62
62
|
}
|
63
63
|
|
64
64
|
it 'matches if the options match' do
|
65
|
-
|
65
|
+
allow(instance).to receive(:skip_validations).and_return(true)
|
66
66
|
should send(matcher_name, attribute, option_name => true)
|
67
67
|
end
|
68
68
|
|
69
69
|
it 'does not match if the options do not match' do
|
70
|
-
|
70
|
+
allow(instance).to receive(:skip_validations).and_return(false)
|
71
71
|
should_not send(matcher_name, attribute, option_name => true)
|
72
72
|
end
|
73
73
|
end
|
@@ -76,9 +76,8 @@ shared_examples_for 'a validation matcher' do
|
|
76
76
|
def self.with_unsupported_option(option_name, value=nil)
|
77
77
|
context "with unsupported option #{option_name.inspect}" do
|
78
78
|
it 'raises an error' do
|
79
|
-
expect {
|
80
|
-
|
81
|
-
}.to raise_error(ArgumentError, /unsupported.*:#{option_name}/i)
|
79
|
+
expect { should send(matcher_name, option_name => value) }
|
80
|
+
.to raise_error ArgumentError, /unsupported.*:#{option_name}/i
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|
@@ -88,25 +87,27 @@ shared_examples_for 'a validation matcher' do
|
|
88
87
|
|
89
88
|
it 'has a custom description' do
|
90
89
|
name = matcher.instance_variable_get(:@name).to_s.gsub(/_/, ' ')
|
91
|
-
with = " with #{matcher.
|
90
|
+
with = " with #{matcher.options}" if matcher.options.any?
|
92
91
|
|
93
|
-
matcher.description.
|
92
|
+
expect(matcher.description).to eq "#{name} #{attribute}#{with}"
|
94
93
|
end
|
95
94
|
end
|
96
95
|
|
97
96
|
context 'failure messages' do
|
98
97
|
let(:matcher) { send(matcher_name, attribute) }
|
99
98
|
|
100
|
-
before
|
99
|
+
before do
|
100
|
+
matcher.matches?(instance)
|
101
|
+
end
|
101
102
|
|
102
103
|
it 'has a custom failure message' do
|
103
|
-
matcher.
|
104
|
-
"Expected #{
|
104
|
+
expect(matcher.failure_message)
|
105
|
+
.to eq "Expected #{instance.class.name} to #{matcher.description}"
|
105
106
|
end
|
106
107
|
|
107
108
|
it 'has a custom negative failure message' do
|
108
|
-
matcher.
|
109
|
-
"Did not expect #{
|
109
|
+
expect(matcher.failure_message_when_negated)
|
110
|
+
.to eq "Did not expect #{instance.class.name} to #{matcher.description}"
|
110
111
|
end
|
111
112
|
end
|
112
113
|
|
@@ -122,9 +123,8 @@ shared_examples_for 'a validation matcher' do
|
|
122
123
|
|
123
124
|
context 'with an unknown option' do
|
124
125
|
it 'raises an error' do
|
125
|
-
expect {
|
126
|
-
|
127
|
-
}.to raise_error(ArgumentError, /unknown.*:xxx/i)
|
126
|
+
expect { should send(matcher_name, xxx: true) }
|
127
|
+
.to raise_error ArgumentError, /unknown.*:xxx/i
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
@@ -5,7 +5,9 @@ shared_examples_for 'an Active Record matcher' do
|
|
5
5
|
context "with option #{option_name.inspect}" do
|
6
6
|
let(:options) { [:company, context.merge(option_name => positive)] }
|
7
7
|
|
8
|
-
before
|
8
|
+
before do
|
9
|
+
model.send macro, *options
|
10
|
+
end
|
9
11
|
|
10
12
|
it 'matches if the options match' do
|
11
13
|
should send(matcher_name, :company, option_name => positive)
|
@@ -20,9 +22,8 @@ shared_examples_for 'an Active Record matcher' do
|
|
20
22
|
def self.with_unsupported_option(option_name, value=nil)
|
21
23
|
context "with unsupported option #{option_name.inspect}" do
|
22
24
|
it 'raises an error' do
|
23
|
-
expect {
|
24
|
-
|
25
|
-
}.to raise_error(ArgumentError, /unsupported.*:#{option_name}/i)
|
25
|
+
expect { should send(matcher_name, :company, option_name => value) }
|
26
|
+
.to raise_error ArgumentError, /unsupported.*:#{option_name}/i
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -30,24 +31,25 @@ shared_examples_for 'an Active Record matcher' do
|
|
30
31
|
context 'failure messages' do
|
31
32
|
let(:matcher) { send(matcher_name, *options) }
|
32
33
|
|
33
|
-
before
|
34
|
+
before do
|
35
|
+
matcher.matches? subject
|
36
|
+
end
|
34
37
|
|
35
38
|
it 'has a custom failure message' do
|
36
|
-
matcher.
|
37
|
-
"Expected #{subject.class.name} to #{matcher.description}"
|
39
|
+
expect(matcher.failure_message)
|
40
|
+
.to eq "Expected #{subject.class.name} to #{matcher.description}"
|
38
41
|
end
|
39
42
|
|
40
43
|
it 'has a custom negative failure message' do
|
41
|
-
matcher.
|
42
|
-
"Did not expect #{subject.class.name} to #{matcher.description}"
|
44
|
+
expect(matcher.failure_message_when_negated)
|
45
|
+
.to eq "Did not expect #{subject.class.name} to #{matcher.description}"
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
46
49
|
context 'with an unknown option' do
|
47
50
|
it 'raises an error' do
|
48
|
-
expect {
|
49
|
-
|
50
|
-
}.to raise_error(ArgumentError, /unknown.*:xxx/i)
|
51
|
+
expect { should send(matcher_name, xxx: true) }
|
52
|
+
.to raise_error ArgumentError, /unknown.*:xxx/i
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|