remarkable_activerecord 3.0.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.
- data/CHANGELOG +47 -0
- data/LICENSE +20 -0
- data/README +2 -0
- data/lib/remarkable_activerecord/base.rb +238 -0
- data/lib/remarkable_activerecord/human_names.rb +37 -0
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +34 -0
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +94 -0
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +235 -0
- data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -0
- data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +57 -0
- data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -0
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +80 -0
- data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +51 -0
- data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +99 -0
- data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +45 -0
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +47 -0
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +47 -0
- data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +123 -0
- data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +184 -0
- data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -0
- data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +151 -0
- data/lib/remarkable_activerecord.rb +29 -0
- data/locale/en.yml +253 -0
- data/spec/allow_mass_assignment_of_matcher_spec.rb +57 -0
- data/spec/allow_values_for_matcher_spec.rb +56 -0
- data/spec/association_matcher_spec.rb +616 -0
- data/spec/have_column_matcher_spec.rb +73 -0
- data/spec/have_index_matcher_spec.rb +68 -0
- data/spec/have_readonly_attributes_matcher_spec.rb +47 -0
- data/spec/have_scope_matcher_spec.rb +69 -0
- data/spec/model_builder.rb +101 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/validate_acceptance_of_matcher_spec.rb +68 -0
- data/spec/validate_associated_matcher_spec.rb +122 -0
- data/spec/validate_confirmation_of_matcher_spec.rb +58 -0
- data/spec/validate_exclusion_of_matcher_spec.rb +88 -0
- data/spec/validate_inclusion_of_matcher_spec.rb +84 -0
- data/spec/validate_length_of_matcher_spec.rb +165 -0
- data/spec/validate_numericality_of_matcher_spec.rb +180 -0
- data/spec/validate_presence_of_matcher_spec.rb +52 -0
- data/spec/validate_uniqueness_of_matcher_spec.rb +150 -0
- metadata +112 -0
@@ -0,0 +1,616 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'association_matcher' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
describe 'belong_to' do
|
7
|
+
|
8
|
+
# Defines a model, create a validation and returns a raw matcher
|
9
|
+
def define_and_validate(options={})
|
10
|
+
columns = options.delete(:association_columns) || { :projects_count => :integer }
|
11
|
+
define_model :company, columns
|
12
|
+
|
13
|
+
columns = options.delete(:model_columns) || { :company_id => :integer, :company_type => :string }
|
14
|
+
@model = define_model :project, columns do
|
15
|
+
belongs_to :company, options
|
16
|
+
end
|
17
|
+
|
18
|
+
belong_to :company
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'messages' do
|
22
|
+
it 'should contain a description' do
|
23
|
+
matcher = define_and_validate
|
24
|
+
matcher.description.should == 'belong to company'
|
25
|
+
|
26
|
+
matcher.class_name('Company')
|
27
|
+
matcher.description.should == 'belong to company with class name "Company"'
|
28
|
+
|
29
|
+
matcher.foreign_key('company_id')
|
30
|
+
matcher.description.should == 'belong to company with class name "Company" and with foreign key "company_id"'
|
31
|
+
|
32
|
+
matcher = belong_to(:company).dependent(:destroy)
|
33
|
+
matcher.description.should == 'belong to company with dependent :destroy'
|
34
|
+
|
35
|
+
matcher.readonly
|
36
|
+
matcher.description.should == 'belong to company with dependent :destroy and with readonly records'
|
37
|
+
|
38
|
+
matcher.polymorphic
|
39
|
+
matcher.description.should == 'belong to company with dependent :destroy, with readonly records, ' <<
|
40
|
+
'and through a polymorphic interface'
|
41
|
+
|
42
|
+
matcher.counter_cache('projects_count')
|
43
|
+
matcher.description.should == 'belong to company with dependent :destroy, with readonly records, ' <<
|
44
|
+
'through a polymorphic interface, and with counter cache "projects_count"'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should set association_exists? message' do
|
48
|
+
define_and_validate
|
49
|
+
matcher = belong_to('whatever')
|
50
|
+
matcher.matches?(@model)
|
51
|
+
matcher.failure_message.should == 'Expected Project records belong to whatever, got no association'
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should set macro_matches? message' do
|
55
|
+
define_and_validate
|
56
|
+
matcher = have_one('company')
|
57
|
+
matcher.matches?(@model)
|
58
|
+
matcher.failure_message.should == 'Expected Project records have one company, got Project records belong to company'
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'should set foreign_key_exists? message' do
|
62
|
+
matcher = define_and_validate(:model_columns => {})
|
63
|
+
matcher.matches?(@model)
|
64
|
+
matcher.failure_message.should == 'Expected foreign key "company_id" to exist on "projects", but does not'
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should set polymorphic_exists? message' do
|
68
|
+
matcher = define_and_validate(:model_columns => { :company_id => :integer }, :polymorphic => true)
|
69
|
+
matcher.polymorphic.matches?(@model)
|
70
|
+
matcher.failure_message.should == 'Expected "projects" to have "company_type" as column, but does not'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'should set counter_cache_exists? message' do
|
74
|
+
matcher = define_and_validate(:association_columns => {}, :counter_cache => true)
|
75
|
+
matcher.counter_cache.matches?(@model)
|
76
|
+
matcher.failure_message.should == 'Expected "companies" to have "projects_count" as column, but does not'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'should set validate_matches? message' do
|
80
|
+
matcher = define_and_validate(:validate => false)
|
81
|
+
matcher.validate.matches?(@model)
|
82
|
+
matcher.failure_message.should == 'Expected company association with validate equals to true, got "false"'
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'should set readonly_matches? message' do
|
86
|
+
matcher = define_and_validate(:readonly => false)
|
87
|
+
matcher.readonly.matches?(@model)
|
88
|
+
matcher.failure_message.should == 'Expected company association with readonly equals to true, got "false"'
|
89
|
+
end
|
90
|
+
|
91
|
+
if RAILS_VERSION =~ /^2.3/
|
92
|
+
it 'should set autosave_matches? message' do
|
93
|
+
matcher = define_and_validate(:autosave => false)
|
94
|
+
matcher.autosave.matches?(@model)
|
95
|
+
matcher.failure_message.should == 'Expected company association with autosave equals to true, got "false"'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should set polymorphic_matches? message' do
|
100
|
+
matcher = define_and_validate(:polymorphic => false)
|
101
|
+
matcher.polymorphic.matches?(@model)
|
102
|
+
matcher.failure_message.should == 'Expected company association with polymorphic equals to true, got "false"'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should set counter_cache_matches? message' do
|
106
|
+
matcher = define_and_validate(:counter_cache => true)
|
107
|
+
matcher.counter_cache(false).matches?(@model)
|
108
|
+
matcher.failure_message.should == 'Expected company association with counter cache false, got "true"'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'matchers' do
|
113
|
+
describe 'without options' do
|
114
|
+
before(:each){ define_and_validate }
|
115
|
+
|
116
|
+
it { should belong_to(:company) }
|
117
|
+
it { should_not belong_to(:project) }
|
118
|
+
it { should_not have_one(:company) }
|
119
|
+
it { should_not have_many(:company) }
|
120
|
+
end
|
121
|
+
|
122
|
+
describe 'with class name option' do
|
123
|
+
it { should define_and_validate.class_name('Company') }
|
124
|
+
it { should define_and_validate(:class_name => 'SuperCompany').class_name('SuperCompany') }
|
125
|
+
|
126
|
+
it { should_not define_and_validate.class_name('SuperCompany') }
|
127
|
+
it { should_not define_and_validate(:class_name => 'Company').class_name('SuperCompany') }
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'with foreign_key option' do
|
131
|
+
it { should define_and_validate.foreign_key(:company_id) }
|
132
|
+
it { should_not define_and_validate.foreign_key(:association_id) }
|
133
|
+
|
134
|
+
# Checks whether fk exists or not
|
135
|
+
it { should define_and_validate(:foreign_key => :association_id,
|
136
|
+
:model_columns => { :association_id => :integer }).foreign_key(:association_id) }
|
137
|
+
|
138
|
+
it { should_not define_and_validate(:foreign_key => :association_id).foreign_key(:association_id) }
|
139
|
+
it { should_not define_and_validate(:model_columns => { :association_id => :integer }).foreign_key(:association_id) }
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'with dependent option' do
|
143
|
+
it { should define_and_validate(:dependent => :delete).dependent(:delete) }
|
144
|
+
it { should define_and_validate(:dependent => :destroy).dependent(:destroy) }
|
145
|
+
|
146
|
+
it { should_not define_and_validate(:dependent => :delete).dependent(:destroy) }
|
147
|
+
it { should_not define_and_validate(:dependent => :destroy).dependent(:delete) }
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'with counter_cache option' do
|
151
|
+
# Checks whether fk exists or not
|
152
|
+
it { should define_and_validate(:counter_cache => :association_count,
|
153
|
+
:association_columns => { :association_count => :integer }).counter_cache(:association_count) }
|
154
|
+
|
155
|
+
it { should_not define_and_validate(:counter_cache => :association_count).counter_cache(:association_count) }
|
156
|
+
it { should_not define_and_validate(:association_columns => { :association_count => :integer }).counter_cache(:association_count) }
|
157
|
+
end
|
158
|
+
|
159
|
+
create_optional_boolean_specs(:readonly, self)
|
160
|
+
create_optional_boolean_specs(:validate, self)
|
161
|
+
create_optional_boolean_specs(:autosave, self) if RAILS_VERSION =~ /^2.3/
|
162
|
+
create_optional_boolean_specs(:polymorphic, self)
|
163
|
+
create_optional_boolean_specs(:counter_cache, self)
|
164
|
+
end
|
165
|
+
|
166
|
+
describe 'macros' do
|
167
|
+
before(:each){ define_and_validate(:validate => true, :readonly => true) }
|
168
|
+
|
169
|
+
should_belong_to :company
|
170
|
+
should_belong_to :company, :readonly => true
|
171
|
+
should_belong_to :company, :validate => true
|
172
|
+
should_belong_to :company, :class_name => "Company"
|
173
|
+
should_belong_to :company, :foreign_key => :company_id
|
174
|
+
|
175
|
+
should_not_belong_to :project
|
176
|
+
should_not_have_one :company
|
177
|
+
should_not_have_many :companies
|
178
|
+
|
179
|
+
should_not_belong_to :company, :readonly => false
|
180
|
+
should_not_belong_to :company, :validate => false
|
181
|
+
should_not_belong_to :company, :class_name => "Anything"
|
182
|
+
should_not_belong_to :company, :foreign_key => :anything_id
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'have_and_belong_to_many' do
|
187
|
+
|
188
|
+
# Defines a model, create a validation and returns a raw matcher
|
189
|
+
def define_and_validate(options={})
|
190
|
+
define_model :label
|
191
|
+
|
192
|
+
columns = options.delete(:association_columns) || [ :label_id, :project_id ]
|
193
|
+
create_table(options.delete(:association_table) || :labels_projects) do |table|
|
194
|
+
columns.each { |name| table.column(name, :integer) }
|
195
|
+
end
|
196
|
+
|
197
|
+
@model = define_model :project, options.delete(:model_columns) || {} do
|
198
|
+
has_and_belongs_to_many :labels, options
|
199
|
+
end
|
200
|
+
|
201
|
+
have_and_belong_to_many :labels
|
202
|
+
end
|
203
|
+
|
204
|
+
describe 'messages' do
|
205
|
+
it 'should contain a description' do
|
206
|
+
matcher = define_and_validate
|
207
|
+
matcher.description.should == 'have and belong to many labels'
|
208
|
+
|
209
|
+
matcher.class_name('Label')
|
210
|
+
matcher.description.should == 'have and belong to many labels with class name "Label"'
|
211
|
+
|
212
|
+
matcher.foreign_key('label_id')
|
213
|
+
matcher.description.should == 'have and belong to many labels with class name "Label" and with foreign key "label_id"'
|
214
|
+
|
215
|
+
matcher = have_and_belong_to_many(:labels).autosave
|
216
|
+
matcher.description.should == 'have and belong to many labels autosaving associated records'
|
217
|
+
|
218
|
+
matcher.uniq
|
219
|
+
matcher.description.should == 'have and belong to many labels with unique records and autosaving associated records'
|
220
|
+
end
|
221
|
+
|
222
|
+
it 'should set association_exists? message' do
|
223
|
+
define_and_validate
|
224
|
+
matcher = have_and_belong_to_many('whatever')
|
225
|
+
matcher.matches?(@model)
|
226
|
+
matcher.failure_message.should == 'Expected Project records have and belong to many whatever, got no association'
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should set macro_matches? message' do
|
230
|
+
define_and_validate
|
231
|
+
matcher = have_many('labels')
|
232
|
+
matcher.matches?(@model)
|
233
|
+
matcher.failure_message.should == 'Expected Project records have many labels, got Project records have and belong to many labels'
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should set join_table_exists? message' do
|
237
|
+
matcher = define_and_validate(:association_table => 'another_name')
|
238
|
+
matcher.matches?(@model)
|
239
|
+
matcher.failure_message.should == 'Expected join table "labels_projects" to exist, but does not'
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'should set foreign_key_exists? message' do
|
243
|
+
matcher = define_and_validate(:association_columns => [])
|
244
|
+
matcher.matches?(@model)
|
245
|
+
matcher.failure_message.should == 'Expected foreign key "project_id" to exist on "labels_projects", but does not'
|
246
|
+
end
|
247
|
+
|
248
|
+
it 'should set validate_matches? message' do
|
249
|
+
matcher = define_and_validate(:validate => false)
|
250
|
+
matcher.validate.matches?(@model)
|
251
|
+
matcher.failure_message.should == 'Expected labels association with validate equals to true, got "false"'
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'should set readonly_matches? message' do
|
255
|
+
matcher = define_and_validate(:readonly => false)
|
256
|
+
matcher.readonly.matches?(@model)
|
257
|
+
matcher.failure_message.should == 'Expected labels association with readonly equals to true, got "false"'
|
258
|
+
end
|
259
|
+
|
260
|
+
if RAILS_VERSION =~ /^2.3/
|
261
|
+
it 'should set autosave_matches? message' do
|
262
|
+
matcher = define_and_validate(:autosave => false)
|
263
|
+
matcher.autosave.matches?(@model)
|
264
|
+
matcher.failure_message.should == 'Expected labels association with autosave equals to true, got "false"'
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
it 'should set uniq_matches? message' do
|
269
|
+
matcher = define_and_validate(:uniq => false)
|
270
|
+
matcher.uniq.matches?(@model)
|
271
|
+
matcher.failure_message.should == 'Expected labels association with uniq equals to true, got "false"'
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe 'matchers' do
|
276
|
+
describe 'without options' do
|
277
|
+
before(:each){ define_and_validate }
|
278
|
+
|
279
|
+
it { should have_and_belong_to_many(:labels) }
|
280
|
+
it { should_not belong_to(:label) }
|
281
|
+
it { should_not have_one(:label) }
|
282
|
+
it { should_not have_many(:labels) }
|
283
|
+
it { should_not have_and_belong_to_many(:companies) }
|
284
|
+
end
|
285
|
+
|
286
|
+
describe 'with class name option' do
|
287
|
+
it { should define_and_validate.class_name('Label') }
|
288
|
+
|
289
|
+
it { should define_and_validate(:class_name => 'SuperLabel',
|
290
|
+
:association_table => 'projects_super_labels').class_name('SuperLabel') }
|
291
|
+
|
292
|
+
it { should_not define_and_validate.class_name('SuperLabel') }
|
293
|
+
end
|
294
|
+
|
295
|
+
describe 'with foreign_key option' do
|
296
|
+
it { should define_and_validate.foreign_key(:project_id) }
|
297
|
+
it { should_not define_and_validate.foreign_key(:association_id) }
|
298
|
+
|
299
|
+
# Checks whether fk exists or not
|
300
|
+
it { should define_and_validate(:foreign_key => :association_id,
|
301
|
+
:association_columns => [ :association_id ]).foreign_key(:association_id) }
|
302
|
+
|
303
|
+
it { should_not define_and_validate(:foreign_key => :association_id).foreign_key(:association_id) }
|
304
|
+
it { should_not define_and_validate(:association_columns => [ :association_id ]).foreign_key(:association_id) }
|
305
|
+
end
|
306
|
+
|
307
|
+
describe 'with join table option' do
|
308
|
+
it { should define_and_validate.join_table('labels_projects') }
|
309
|
+
it { should define_and_validate(:join_table => 'my_table',
|
310
|
+
:association_table => 'my_table').join_table('my_table') }
|
311
|
+
|
312
|
+
it { should_not define_and_validate.join_table('projects_labels') }
|
313
|
+
|
314
|
+
it { should_not define_and_validate(:join_table => 'my_table',
|
315
|
+
:association_table => 'another_table').join_table('my_table') }
|
316
|
+
it { should_not define_and_validate(:join_table => 'another_table',
|
317
|
+
:association_table => 'my_table').join_table('my_table') }
|
318
|
+
it { should_not define_and_validate(:join_table => 'my_table',
|
319
|
+
:association_table => 'my_table').join_table('another_table') }
|
320
|
+
end
|
321
|
+
|
322
|
+
create_optional_boolean_specs(:uniq, self)
|
323
|
+
create_optional_boolean_specs(:readonly, self)
|
324
|
+
create_optional_boolean_specs(:validate, self)
|
325
|
+
create_optional_boolean_specs(:autosave, self) if RAILS_VERSION =~ /^2.3/
|
326
|
+
end
|
327
|
+
|
328
|
+
describe 'macros' do
|
329
|
+
before(:each){ define_and_validate(:validate => true, :readonly => true) }
|
330
|
+
|
331
|
+
should_have_and_belong_to_many :labels
|
332
|
+
should_have_and_belong_to_many :labels, :readonly => true
|
333
|
+
should_have_and_belong_to_many :labels, :validate => true
|
334
|
+
should_have_and_belong_to_many :labels, :class_name => "Label"
|
335
|
+
should_have_and_belong_to_many :labels, :foreign_key => :project_id
|
336
|
+
|
337
|
+
should_not_have_and_belong_to_many :companies
|
338
|
+
should_not_have_one :label
|
339
|
+
should_not_have_many :labels
|
340
|
+
|
341
|
+
should_not_have_and_belong_to_many :labels, :readonly => false
|
342
|
+
should_not_have_and_belong_to_many :labels, :validate => false
|
343
|
+
should_not_have_and_belong_to_many :labels, :class_name => "Anything"
|
344
|
+
should_not_have_and_belong_to_many :labels, :foreign_key => :anything_id
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe 'have_many' do
|
349
|
+
|
350
|
+
# Defines a model, create a validation and returns a raw matcher
|
351
|
+
def define_and_validate(options={})
|
352
|
+
columns = options.delete(:association_columns) || { :task_id => :integer, :project_id => :integer }
|
353
|
+
define_model :task, columns
|
354
|
+
|
355
|
+
define_model :project_task, columns do
|
356
|
+
belongs_to :task
|
357
|
+
belongs_to :project
|
358
|
+
end unless options.delete(:skip_through)
|
359
|
+
|
360
|
+
@model = define_model :project, options.delete(:model_columns) || {} do
|
361
|
+
has_many :tasks, options
|
362
|
+
has_many :project_tasks
|
363
|
+
end
|
364
|
+
|
365
|
+
have_many :tasks
|
366
|
+
end
|
367
|
+
|
368
|
+
describe 'messages' do
|
369
|
+
it 'should contain a description' do
|
370
|
+
matcher = define_and_validate
|
371
|
+
matcher.description.should == 'have many tasks'
|
372
|
+
|
373
|
+
matcher.class_name('Task')
|
374
|
+
matcher.description.should == 'have many tasks with class name "Task"'
|
375
|
+
|
376
|
+
matcher.foreign_key('task_id')
|
377
|
+
matcher.description.should == 'have many tasks with class name "Task" and with foreign key "task_id"'
|
378
|
+
|
379
|
+
matcher = have_many(:tasks).autosave
|
380
|
+
matcher.description.should == 'have many tasks autosaving associated records'
|
381
|
+
|
382
|
+
matcher.uniq
|
383
|
+
matcher.description.should == 'have many tasks with unique records and autosaving associated records'
|
384
|
+
end
|
385
|
+
|
386
|
+
it 'should set association_exists? message' do
|
387
|
+
define_and_validate
|
388
|
+
matcher = have_many('whatever')
|
389
|
+
matcher.matches?(@model)
|
390
|
+
matcher.failure_message.should == 'Expected Project records have many whatever, got no association'
|
391
|
+
end
|
392
|
+
|
393
|
+
it 'should set macro_matches? message' do
|
394
|
+
define_and_validate
|
395
|
+
matcher = have_and_belong_to_many('tasks')
|
396
|
+
matcher.matches?(@model)
|
397
|
+
matcher.failure_message.should == 'Expected Project records have and belong to many tasks, got Project records have many tasks'
|
398
|
+
end
|
399
|
+
|
400
|
+
it 'should set foreign_key_exists? message' do
|
401
|
+
matcher = define_and_validate(:association_columns => {})
|
402
|
+
matcher.matches?(@model)
|
403
|
+
matcher.failure_message.should == 'Expected foreign key "project_id" to exist on "tasks", but does not'
|
404
|
+
end
|
405
|
+
|
406
|
+
it 'should set through_exists? message' do
|
407
|
+
matcher = define_and_validate(:through => 'project_tasks')
|
408
|
+
matcher.through(:another).matches?(@model)
|
409
|
+
matcher.failure_message.should == 'Expected Project records have many tasks through :another, through association does not exist'
|
410
|
+
end
|
411
|
+
|
412
|
+
it 'should set join_table_exists? message' do
|
413
|
+
matcher = define_and_validate(:through => 'project_tasks', :skip_through => true)
|
414
|
+
matcher.through(:project_tasks).matches?(@model)
|
415
|
+
matcher.failure_message.should == 'Expected join table "project_tasks" to exist, but does not'
|
416
|
+
end
|
417
|
+
end
|
418
|
+
|
419
|
+
describe 'matchers' do
|
420
|
+
describe 'without options' do
|
421
|
+
before(:each){ define_and_validate }
|
422
|
+
|
423
|
+
it { should have_many(:tasks) }
|
424
|
+
it { should_not belong_to(:task) }
|
425
|
+
it { should_not have_one(:task) }
|
426
|
+
it { should_not have_and_belong_to_many(:tasks) }
|
427
|
+
end
|
428
|
+
|
429
|
+
describe 'with class name option' do
|
430
|
+
before(:each){ define_model :super_task, :project_id => :integer }
|
431
|
+
|
432
|
+
it { should define_and_validate.class_name('Task') }
|
433
|
+
it { should define_and_validate(:class_name => 'SuperTask').class_name('SuperTask') }
|
434
|
+
|
435
|
+
it { should_not define_and_validate.class_name('SuperTask') }
|
436
|
+
it { should_not define_and_validate(:class_name => 'SuperTask').class_name('Task') }
|
437
|
+
end
|
438
|
+
|
439
|
+
describe 'with foreign_key option' do
|
440
|
+
it { should define_and_validate.foreign_key(:project_id) }
|
441
|
+
it { should_not define_and_validate.foreign_key(:association_id) }
|
442
|
+
|
443
|
+
# Checks whether fk exists or not
|
444
|
+
it { should define_and_validate(:foreign_key => :association_id,
|
445
|
+
:association_columns => { :association_id => :integer }).foreign_key(:association_id) }
|
446
|
+
|
447
|
+
it { should_not define_and_validate(:foreign_key => :association_id).foreign_key(:association_id) }
|
448
|
+
it { should_not define_and_validate(:association_columns => { :association_id => :integer }).foreign_key(:association_id) }
|
449
|
+
end
|
450
|
+
|
451
|
+
describe 'with dependent option' do
|
452
|
+
it { should define_and_validate(:dependent => :delete_all).dependent(:delete_all) }
|
453
|
+
it { should define_and_validate(:dependent => :destroy).dependent(:destroy) }
|
454
|
+
|
455
|
+
it { should_not define_and_validate(:dependent => :delete_all).dependent(:destroy) }
|
456
|
+
it { should_not define_and_validate(:dependent => :destroy).dependent(:delete_all) }
|
457
|
+
end
|
458
|
+
|
459
|
+
describe 'with through option' do
|
460
|
+
it { should define_and_validate(:through => 'project_tasks') }
|
461
|
+
it { should define_and_validate(:through => 'project_tasks').through(:project_tasks) }
|
462
|
+
|
463
|
+
it { should_not define_and_validate(:through => 'project_tasks').through(:something) }
|
464
|
+
it { should_not define_and_validate(:through => 'project_tasks', :skip_through => true).through(:project_tasks) }
|
465
|
+
end
|
466
|
+
|
467
|
+
create_optional_boolean_specs(:uniq, self)
|
468
|
+
create_optional_boolean_specs(:readonly, self)
|
469
|
+
create_optional_boolean_specs(:validate, self)
|
470
|
+
create_optional_boolean_specs(:autosave, self) if RAILS_VERSION =~ /^2.3/
|
471
|
+
end
|
472
|
+
|
473
|
+
describe 'macros' do
|
474
|
+
before(:each){ define_and_validate(:through => 'project_tasks', :readonly => true, :validate => true) }
|
475
|
+
|
476
|
+
should_have_many :tasks
|
477
|
+
should_have_many :tasks, :readonly => true
|
478
|
+
should_have_many :tasks, :validate => true
|
479
|
+
should_have_many :tasks, :through => :project_tasks
|
480
|
+
|
481
|
+
should_not_have_many :tasks, :readonly => false
|
482
|
+
should_not_have_many :tasks, :validate => false
|
483
|
+
should_not_have_many :tasks, :through => :another_thing
|
484
|
+
end
|
485
|
+
end
|
486
|
+
|
487
|
+
describe 'have_one' do
|
488
|
+
|
489
|
+
# Defines a model, create a validation and returns a raw matcher
|
490
|
+
def define_and_validate(options={})
|
491
|
+
columns = options.delete(:association_columns) || { :manager_id => :integer, :project_id => :integer }
|
492
|
+
define_model :manager, columns
|
493
|
+
|
494
|
+
define_model :project_manager, columns do
|
495
|
+
belongs_to :manager
|
496
|
+
belongs_to :project
|
497
|
+
end unless options.delete(:skip_through)
|
498
|
+
|
499
|
+
@model = define_model :project, options.delete(:model_columns) || {} do
|
500
|
+
has_one :manager, options
|
501
|
+
has_many :project_managers
|
502
|
+
end
|
503
|
+
|
504
|
+
have_one :manager
|
505
|
+
end
|
506
|
+
|
507
|
+
describe 'messages' do
|
508
|
+
it 'should contain a description' do
|
509
|
+
matcher = define_and_validate
|
510
|
+
matcher.description.should == 'have one manager'
|
511
|
+
|
512
|
+
matcher.class_name('Manager')
|
513
|
+
matcher.description.should == 'have one manager with class name "Manager"'
|
514
|
+
|
515
|
+
matcher.foreign_key('manager_id')
|
516
|
+
matcher.description.should == 'have one manager with class name "Manager" and with foreign key "manager_id"'
|
517
|
+
end
|
518
|
+
|
519
|
+
it 'should set association_exists? message' do
|
520
|
+
define_and_validate
|
521
|
+
matcher = have_one('whatever')
|
522
|
+
matcher.matches?(@model)
|
523
|
+
matcher.failure_message.should == 'Expected Project records have one whatever, got no association'
|
524
|
+
end
|
525
|
+
|
526
|
+
it 'should set macro_matches? message' do
|
527
|
+
define_and_validate
|
528
|
+
matcher = belong_to('manager')
|
529
|
+
matcher.matches?(@model)
|
530
|
+
matcher.failure_message.should == 'Expected Project records belong to manager, got Project records have one manager'
|
531
|
+
end
|
532
|
+
|
533
|
+
it 'should set foreign_key_exists? message' do
|
534
|
+
matcher = define_and_validate(:association_columns => {})
|
535
|
+
matcher.matches?(@model)
|
536
|
+
matcher.failure_message.should == 'Expected foreign key "project_id" to exist on "managers", but does not'
|
537
|
+
end
|
538
|
+
|
539
|
+
it 'should set through_exists? message' do
|
540
|
+
matcher = define_and_validate(:through => 'project_managers')
|
541
|
+
matcher.through(:another).matches?(@model)
|
542
|
+
matcher.failure_message.should == 'Expected Project records have one manager through :another, through association does not exist'
|
543
|
+
end
|
544
|
+
|
545
|
+
it 'should set join_table_exists? message' do
|
546
|
+
matcher = define_and_validate(:through => 'project_managers', :skip_through => true)
|
547
|
+
matcher.through(:project_managers).matches?(@model)
|
548
|
+
matcher.failure_message.should == 'Expected join table "project_managers" to exist, but does not'
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
describe 'matchers' do
|
553
|
+
describe 'without options' do
|
554
|
+
before(:each){ define_and_validate }
|
555
|
+
|
556
|
+
it { should have_one(:manager) }
|
557
|
+
it { should_not belong_to(:manager) }
|
558
|
+
it { should_not have_many(:managers) }
|
559
|
+
it { should_not have_and_belong_to_many(:managers) }
|
560
|
+
end
|
561
|
+
|
562
|
+
describe 'with class name option' do
|
563
|
+
before(:each){ define_model :super_manager, :project_id => :integer }
|
564
|
+
|
565
|
+
it { should define_and_validate.class_name('Manager') }
|
566
|
+
it { should define_and_validate(:class_name => 'SuperManager').class_name('SuperManager') }
|
567
|
+
|
568
|
+
it { should_not define_and_validate.class_name('SuperManager') }
|
569
|
+
it { should_not define_and_validate(:class_name => 'SuperManager').class_name('Manager') }
|
570
|
+
end
|
571
|
+
|
572
|
+
describe 'with foreign_key option' do
|
573
|
+
it { should define_and_validate.foreign_key(:project_id) }
|
574
|
+
it { should_not define_and_validate.foreign_key(:association_id) }
|
575
|
+
|
576
|
+
# Checks whether fk exists or not
|
577
|
+
it { should define_and_validate(:foreign_key => :association_id,
|
578
|
+
:association_columns => { :association_id => :integer }).foreign_key(:association_id) }
|
579
|
+
|
580
|
+
it { should_not define_and_validate(:foreign_key => :association_id).foreign_key(:association_id) }
|
581
|
+
it { should_not define_and_validate(:association_columns => { :association_id => :integer }).foreign_key(:association_id) }
|
582
|
+
end
|
583
|
+
|
584
|
+
describe 'with dependent option' do
|
585
|
+
it { should define_and_validate(:dependent => :delete).dependent(:delete) }
|
586
|
+
it { should define_and_validate(:dependent => :destroy).dependent(:destroy) }
|
587
|
+
|
588
|
+
it { should_not define_and_validate(:dependent => :delete).dependent(:destroy) }
|
589
|
+
it { should_not define_and_validate(:dependent => :destroy).dependent(:delete) }
|
590
|
+
end
|
591
|
+
|
592
|
+
describe 'with through option' do
|
593
|
+
it { should define_and_validate(:through => 'project_managers') }
|
594
|
+
it { should define_and_validate(:through => 'project_managers').through(:project_managers) }
|
595
|
+
|
596
|
+
it { should_not define_and_validate(:through => 'project_managers').through(:something) }
|
597
|
+
it { should_not define_and_validate(:through => 'project_managers', :skip_through => true).through(:project_managers) }
|
598
|
+
end
|
599
|
+
|
600
|
+
create_optional_boolean_specs(:validate, self)
|
601
|
+
create_optional_boolean_specs(:autosave, self) if RAILS_VERSION =~ /^2.3/
|
602
|
+
end
|
603
|
+
|
604
|
+
describe 'macros' do
|
605
|
+
before(:each){ define_and_validate(:through => 'project_managers', :validate => true) }
|
606
|
+
|
607
|
+
should_have_one :manager
|
608
|
+
should_have_one :manager, :validate => true
|
609
|
+
should_have_one :manager, :through => :project_managers
|
610
|
+
|
611
|
+
should_not_have_one :manager, :validate => false
|
612
|
+
should_not_have_one :manager, :through => :another_thing
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe 'have_column_matcher' do
|
4
|
+
include ModelBuilder
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@model = define_model :product, :table => lambda {|table|
|
8
|
+
table.string :name, :null => true
|
9
|
+
table.string :email, :limit => '255', :default => 'jose.valim@gmail.com'
|
10
|
+
table.decimal :price, :precision => 10, :scale => 2
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'messages' do
|
15
|
+
|
16
|
+
it 'should contain a description' do
|
17
|
+
@matcher = have_column(:name, :email)
|
18
|
+
@matcher.description.should == 'have column(s) named name and email'
|
19
|
+
|
20
|
+
@matcher.type(:string)
|
21
|
+
@matcher.description.should == 'have column(s) named name and email with type :string'
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should set column_exists? message' do
|
25
|
+
@matcher = have_column(:password)
|
26
|
+
@matcher.matches?(@model)
|
27
|
+
@matcher.failure_message.should == 'Expected Product to have column named password'
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should set options_match? message' do
|
31
|
+
@matcher = have_column(:name, :type => :integer)
|
32
|
+
@matcher.matches?(@model)
|
33
|
+
@matcher.failure_message.should == 'Expected Product to have column name with options {:type=>"integer"}, got {:type=>"string"}'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'matchers' do
|
38
|
+
it { should have_column(:name) }
|
39
|
+
it { should have_columns(:name, :email) }
|
40
|
+
it { should have_columns(:name, :email, :price) }
|
41
|
+
|
42
|
+
it { should have_column(:name).null }
|
43
|
+
it { should have_column(:email).limit(255) }
|
44
|
+
it { should have_column(:email).default('jose.valim@gmail.com') }
|
45
|
+
it { should have_column(:price).precision(10) }
|
46
|
+
it { should have_column(:price).precision(10).scale(2) }
|
47
|
+
|
48
|
+
it { should_not have_column(:name).null(false) }
|
49
|
+
it { should_not have_column(:email).limit(400) }
|
50
|
+
it { should_not have_column(:email).default('') }
|
51
|
+
it { should_not have_column(:price).precision(1) }
|
52
|
+
it { should_not have_column(:price).precision(10).scale(5) }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'macros' do
|
56
|
+
should_have_column :name
|
57
|
+
should_have_columns :name, :email
|
58
|
+
should_have_columns :name, :email, :price
|
59
|
+
|
60
|
+
should_have_column :name, :null => true
|
61
|
+
should_have_column :email, :limit => 255
|
62
|
+
should_have_column :email, :default => 'jose.valim@gmail.com'
|
63
|
+
should_have_column :price, :precision => 10
|
64
|
+
should_have_column :price, :precision => 10, :scale => 2
|
65
|
+
|
66
|
+
should_not_have_column :name, :null => false
|
67
|
+
should_not_have_column :email, :limit => 400
|
68
|
+
should_not_have_column :email, :default => ''
|
69
|
+
should_not_have_column :price, :precision => 1
|
70
|
+
should_not_have_column :price, :precision => 10, :scale => 5
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|