lacomartincik-factory_girl 1.2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/CONTRIBUTION_GUIDELINES.rdoc +9 -0
  2. data/Changelog +29 -0
  3. data/LICENSE +19 -0
  4. data/README.rdoc +228 -0
  5. data/Rakefile +74 -0
  6. data/lib/factory_girl.rb +23 -0
  7. data/lib/factory_girl/aliases.rb +50 -0
  8. data/lib/factory_girl/attribute.rb +29 -0
  9. data/lib/factory_girl/attribute/association.rb +18 -0
  10. data/lib/factory_girl/attribute/dynamic.rb +20 -0
  11. data/lib/factory_girl/attribute/static.rb +17 -0
  12. data/lib/factory_girl/factory.rb +360 -0
  13. data/lib/factory_girl/proxy.rb +62 -0
  14. data/lib/factory_girl/proxy/attributes_for.rb +21 -0
  15. data/lib/factory_girl/proxy/build.rb +29 -0
  16. data/lib/factory_girl/proxy/create.rb +10 -0
  17. data/lib/factory_girl/proxy/stub.rb +49 -0
  18. data/lib/factory_girl/sequence.rb +63 -0
  19. data/lib/factory_girl/syntax.rb +12 -0
  20. data/lib/factory_girl/syntax/blueprint.rb +42 -0
  21. data/lib/factory_girl/syntax/generate.rb +68 -0
  22. data/lib/factory_girl/syntax/make.rb +39 -0
  23. data/lib/factory_girl/syntax/sham.rb +42 -0
  24. data/spec/factory_girl/aliases_spec.rb +29 -0
  25. data/spec/factory_girl/attribute/association_spec.rb +25 -0
  26. data/spec/factory_girl/attribute/dynamic_spec.rb +49 -0
  27. data/spec/factory_girl/attribute/static_spec.rb +29 -0
  28. data/spec/factory_girl/attribute_spec.rb +30 -0
  29. data/spec/factory_girl/factory_spec.rb +490 -0
  30. data/spec/factory_girl/proxy/attributes_for_spec.rb +52 -0
  31. data/spec/factory_girl/proxy/build_spec.rb +73 -0
  32. data/spec/factory_girl/proxy/create_spec.rb +83 -0
  33. data/spec/factory_girl/proxy/stub_spec.rb +69 -0
  34. data/spec/factory_girl/proxy_spec.rb +28 -0
  35. data/spec/factory_girl/sequence_spec.rb +66 -0
  36. data/spec/factory_girl/syntax/blueprint_spec.rb +34 -0
  37. data/spec/factory_girl/syntax/generate_spec.rb +57 -0
  38. data/spec/factory_girl/syntax/make_spec.rb +35 -0
  39. data/spec/factory_girl/syntax/sham_spec.rb +35 -0
  40. data/spec/integration_spec.rb +265 -0
  41. data/spec/models.rb +43 -0
  42. data/spec/spec_helper.rb +18 -0
  43. metadata +113 -0
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
+
3
+ describe Factory::Attribute::Static do
4
+ before do
5
+ @name = :first_name
6
+ @value = 'John'
7
+ @attr = Factory::Attribute::Static.new(@name, @value)
8
+ end
9
+
10
+ it "should have a name" do
11
+ @attr.name.should == @name
12
+ end
13
+
14
+ it "should set its static value on a proxy" do
15
+ @proxy = "proxy"
16
+ mock(@proxy).set(@name, @value)
17
+ @attr.add_to(@proxy)
18
+ end
19
+
20
+ it "should raise an error when defining an attribute writer" do
21
+ lambda {
22
+ Factory::Attribute::Static.new('test=', nil)
23
+ }.should raise_error(Factory::AttributeDefinitionError)
24
+ end
25
+
26
+ it "should convert names to symbols" do
27
+ Factory::Attribute::Static.new('name', nil).name.should == :name
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe Factory::Attribute do
4
+ before do
5
+ @name = :user
6
+ @attr = Factory::Attribute.new(@name)
7
+ end
8
+
9
+ it "should have a name" do
10
+ @attr.name.should == @name
11
+ end
12
+
13
+ it "should do nothing when being added to a proxy" do
14
+ @proxy = "proxy"
15
+ stub(@proxy).set
16
+ @attr.add_to(@proxy)
17
+ @proxy.should have_received.set.never
18
+ end
19
+
20
+ it "should raise an error when defining an attribute writer" do
21
+ error_message = %{factory_girl uses 'f.test value' syntax rather than 'f.test = value'}
22
+ lambda {
23
+ Factory::Attribute.new('test=')
24
+ }.should raise_error(Factory::AttributeDefinitionError, error_message)
25
+ end
26
+
27
+ it "should convert names to symbols" do
28
+ Factory::Attribute.new('name').name.should == :name
29
+ end
30
+ end
@@ -0,0 +1,490 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe Factory do
4
+ describe "defining a factory" do
5
+ before do
6
+ @name = :user
7
+ @factory = "factory"
8
+ stub(@factory).factory_name { @name }
9
+ @options = { :class => 'magic' }
10
+ stub(Factory).new { @factory }
11
+ end
12
+
13
+ it "should create a new factory using the specified name and options" do
14
+ mock(Factory).new(@name, @options) { @factory }
15
+ Factory.define(@name, @options) {|f| }
16
+ end
17
+
18
+ it "should pass the factory do the block" do
19
+ yielded = nil
20
+ Factory.define(@name) do |y|
21
+ yielded = y
22
+ end
23
+ yielded.should == @factory
24
+ end
25
+
26
+ it "should add the factory to the list of factories" do
27
+ Factory.define(@name) {|f| }
28
+ @factory.should == Factory.factories[@name]
29
+ end
30
+ end
31
+
32
+ describe "a factory" do
33
+ before do
34
+ @name = :user
35
+ @class = User
36
+ @factory = Factory.new(@name)
37
+ end
38
+
39
+ it "should have a factory name" do
40
+ @factory.factory_name.should == @name
41
+ end
42
+
43
+ it "should have a build class" do
44
+ @factory.build_class.should == @class
45
+ end
46
+
47
+ it "should have a default strategy" do
48
+ @factory.default_strategy.should == :create
49
+ end
50
+
51
+ it "should not allow the same attribute to be added twice" do
52
+ lambda {
53
+ 2.times { @factory.add_attribute :first_name }
54
+ }.should raise_error(Factory::AttributeDefinitionError)
55
+ end
56
+
57
+ it "should add a static attribute when an attribute is defined with a value" do
58
+ attribute = 'attribute'
59
+ stub(attribute).name { :name }
60
+ mock(Factory::Attribute::Static).new(:name, 'value') { attribute }
61
+ @factory.add_attribute(:name, 'value')
62
+ end
63
+
64
+ it "should add a dynamic attribute when an attribute is defined with a block" do
65
+ attribute = 'attribute'
66
+ stub(attribute).name { :name }
67
+ block = lambda {}
68
+ mock(Factory::Attribute::Dynamic).new(:name, block) { attribute }
69
+ @factory.add_attribute(:name, &block)
70
+ end
71
+
72
+ it "should raise for an attribute with a value and a block" do
73
+ lambda {
74
+ @factory.add_attribute(:name, 'value') {}
75
+ }.should raise_error(Factory::AttributeDefinitionError)
76
+ end
77
+
78
+ describe "adding an attribute using a in-line sequence" do
79
+ it "should create the sequence" do
80
+ mock(Factory::Sequence).new
81
+ @factory.sequence(:name) {}
82
+ end
83
+
84
+ it "should add a dynamic attribute" do
85
+ attribute = 'attribute'
86
+ stub(attribute).name { :name }
87
+ mock(Factory::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute }
88
+ @factory.sequence(:name) {}
89
+ @factory.attributes.should include(attribute)
90
+ end
91
+ end
92
+
93
+ describe "after adding an attribute" do
94
+ before do
95
+ @attribute = "attribute"
96
+ @proxy = "proxy"
97
+
98
+ stub(@attribute).name { :name }
99
+ stub(@attribute).add_to
100
+ stub(@proxy).set
101
+ stub(@proxy).result { 'result' }
102
+ stub(Factory::Attribute::Static).new { @attribute }
103
+ stub(Factory::Proxy::Build).new { @proxy }
104
+
105
+ @factory.add_attribute(:name, 'value')
106
+ end
107
+
108
+ it "should create the right proxy using the build class when running" do
109
+ mock(Factory::Proxy::Build).new(@factory.build_class) { @proxy }
110
+ @factory.run(Factory::Proxy::Build, {})
111
+ end
112
+
113
+ it "should add the attribute to the proxy when running" do
114
+ mock(@attribute).add_to(@proxy)
115
+ @factory.run(Factory::Proxy::Build, {})
116
+ end
117
+
118
+ it "should return the result from the proxy when running" do
119
+ mock(@proxy).result() { 'result' }
120
+ @factory.run(Factory::Proxy::Build, {}).should == 'result'
121
+ end
122
+ end
123
+
124
+ it "should add an association without a factory name or overrides" do
125
+ factory = Factory.new(:post)
126
+ name = :user
127
+ attr = 'attribute'
128
+ mock(Factory::Attribute::Association).new(name, name, {}) { attr }
129
+ factory.association(name)
130
+ factory.attributes.should include(attr)
131
+ end
132
+
133
+ it "should add an association with overrides" do
134
+ factory = Factory.new(:post)
135
+ name = :user
136
+ attr = 'attribute'
137
+ overrides = { :first_name => 'Ben' }
138
+ mock(Factory::Attribute::Association).new(name, name, overrides) { attr }
139
+ factory.association(name, overrides)
140
+ factory.attributes.should include(attr)
141
+ end
142
+
143
+ it "should add an association with a factory name" do
144
+ factory = Factory.new(:post)
145
+ attr = 'attribute'
146
+ mock(Factory::Attribute::Association).new(:author, :user, {}) { attr }
147
+ factory.association(:author, :factory => :user)
148
+ factory.attributes.should include(attr)
149
+ end
150
+
151
+ it "should add an association with a factory name and overrides" do
152
+ factory = Factory.new(:post)
153
+ attr = 'attribute'
154
+ mock(Factory::Attribute::Association).new(:author, :user, :first_name => 'Ben') { attr }
155
+ factory.association(:author, :factory => :user, :first_name => 'Ben')
156
+ factory.attributes.should include(attr)
157
+ end
158
+
159
+ it "should raise for a self referencing association" do
160
+ factory = Factory.new(:post)
161
+ lambda {
162
+ factory.association(:parent, :factory => :post)
163
+ }.should raise_error(Factory::AssociationDefinitionError)
164
+ end
165
+
166
+ it "should add an attribute using the method name when passed an undefined method" do
167
+ attribute = 'attribute'
168
+ stub(attribute).name { :name }
169
+ block = lambda {}
170
+ mock(Factory::Attribute::Static).new(:name, 'value') { attribute }
171
+ @factory.send(:name, 'value')
172
+ @factory.attributes.should include(attribute)
173
+ end
174
+
175
+ describe "when overriding generated attributes with a hash" do
176
+ before do
177
+ @attr = :name
178
+ @value = 'The price is right!'
179
+ @hash = { @attr => @value }
180
+ end
181
+
182
+ it "should return the overridden value in the generated attributes" do
183
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
184
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
185
+ result[@attr].should == @value
186
+ end
187
+
188
+ it "should not call a lazy attribute block for an overridden attribute" do
189
+ @factory.add_attribute(@attr) { flunk }
190
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
191
+ end
192
+
193
+ it "should override a symbol parameter with a string parameter" do
194
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
195
+ @hash = { @attr.to_s => @value }
196
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
197
+ result[@attr].should == @value
198
+ end
199
+ end
200
+
201
+ describe "overriding an attribute with an alias" do
202
+ before do
203
+ @factory.add_attribute(:test, 'original')
204
+ Factory.alias(/(.*)_alias/, '\1')
205
+ @result = @factory.run(Factory::Proxy::AttributesFor,
206
+ :test_alias => 'new')
207
+ end
208
+
209
+ it "should use the passed in value for the alias" do
210
+ @result[:test_alias].should == 'new'
211
+ end
212
+
213
+ it "should discard the predefined value for the attribute" do
214
+ @result[:test].should be_nil
215
+ end
216
+ end
217
+
218
+ it "should guess the build class from the factory name" do
219
+ @factory.build_class.should == User
220
+ end
221
+
222
+ describe "when defined with a custom class" do
223
+ before do
224
+ @class = User
225
+ @factory = Factory.new(:author, :class => @class)
226
+ end
227
+
228
+ it "should use the specified class as the build class" do
229
+ @factory.build_class.should == @class
230
+ end
231
+ end
232
+
233
+ describe "when defined with a class instead of a name" do
234
+ before do
235
+ @class = ArgumentError
236
+ @name = :argument_error
237
+ @factory = Factory.new(@class)
238
+ end
239
+
240
+ it "should guess the name from the class" do
241
+ @factory.factory_name.should == @name
242
+ end
243
+
244
+ it "should use the class as the build class" do
245
+ @factory.build_class.should == @class
246
+ end
247
+ end
248
+
249
+ describe "when defined with a custom class name" do
250
+ before do
251
+ @class = ArgumentError
252
+ @factory = Factory.new(:author, :class => :argument_error)
253
+ end
254
+
255
+ it "should use the specified class as the build class" do
256
+ @factory.build_class.should == @class
257
+ end
258
+ end
259
+ end
260
+
261
+ describe "a factory with a name ending in s" do
262
+ before do
263
+ @name = :business
264
+ @class = Business
265
+ @factory = Factory.new(@name)
266
+ end
267
+
268
+ it "should have a factory name" do
269
+ @factory.factory_name.should == @name
270
+ end
271
+
272
+ it "should have a build class" do
273
+ @factory.build_class.should == @class
274
+ end
275
+ end
276
+
277
+ describe "a factory with a string for a name" do
278
+ before do
279
+ @name = :user
280
+ @factory = Factory.new(@name.to_s) {}
281
+ end
282
+
283
+ it "should convert the string to a symbol" do
284
+ @factory.factory_name.should == @name
285
+ end
286
+ end
287
+
288
+ describe "a factory defined with a string name" do
289
+ before do
290
+ Factory.factories = {}
291
+ @name = :user
292
+ @factory = Factory.define(@name.to_s) {}
293
+ end
294
+
295
+ it "should store the factory using a symbol" do
296
+ Factory.factories[@name].should == @factory
297
+ end
298
+ end
299
+
300
+ describe "after defining a factory" do
301
+ before do
302
+ @name = :user
303
+ @factory = "factory"
304
+
305
+ Factory.factories[@name] = @factory
306
+ end
307
+
308
+ after { Factory.factories.clear }
309
+
310
+ it "should use Proxy::AttributesFor for Factory.attributes_for" do
311
+ mock(@factory).run(Factory::Proxy::AttributesFor, :attr => 'value') { 'result' }
312
+ Factory.attributes_for(@name, :attr => 'value').should == 'result'
313
+ end
314
+
315
+ it "should use Proxy::Build for Factory.build" do
316
+ mock(@factory).run(Factory::Proxy::Build, :attr => 'value') { 'result' }
317
+ Factory.build(@name, :attr => 'value').should == 'result'
318
+ end
319
+
320
+ it "should use Proxy::Create for Factory.create" do
321
+ mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
322
+ Factory.create(@name, :attr => 'value').should == 'result'
323
+ end
324
+
325
+ it "should use Proxy::Stub for Factory.stub" do
326
+ mock(@factory).run(Factory::Proxy::Stub, :attr => 'value') { 'result' }
327
+ Factory.stub(@name, :attr => 'value').should == 'result'
328
+ end
329
+
330
+ it "should use default strategy option as Factory.default_strategy" do
331
+ stub(@factory).default_strategy { :create }
332
+ mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
333
+ Factory.default_strategy(@name, :attr => 'value').should == 'result'
334
+ end
335
+
336
+ it "should use the default strategy for the global Factory method" do
337
+ stub(@factory).default_strategy { :create }
338
+ mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
339
+ Factory(@name, :attr => 'value').should == 'result'
340
+ end
341
+
342
+ [:build, :create, :attributes_for, :stub].each do |method|
343
+ it "should raise an ArgumentError on #{method} with a nonexistant factory" do
344
+ lambda { Factory.send(method, :bogus) }.should raise_error(ArgumentError)
345
+ end
346
+
347
+ it "should recognize either 'name' or :name for Factory.#{method}" do
348
+ stub(@factory).run
349
+ lambda { Factory.send(method, @name.to_s) }.should_not raise_error
350
+ lambda { Factory.send(method, @name.to_sym) }.should_not raise_error
351
+ end
352
+ end
353
+ end
354
+
355
+ describe 'defining a factory with a parent parameter' do
356
+ before do
357
+ @parent = Factory.define :object do |f|
358
+ f.name 'Name'
359
+ end
360
+ end
361
+
362
+ it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
363
+ lambda {
364
+ Factory.define(:child, :parent => :nonexsitent) {}
365
+ }.should raise_error(ArgumentError)
366
+ end
367
+
368
+ it "should create a new factory using the class of the parent" do
369
+ child = Factory.define(:child, :parent => :object) {}
370
+ child.build_class.should == @parent.build_class
371
+ end
372
+
373
+ it "should create a new factory while overriding the parent class" do
374
+ class Other; end
375
+
376
+ child = Factory.define(:child, :parent => :object, :class => Other) {}
377
+ child.build_class.should == Other
378
+ end
379
+
380
+ it "should create a new factory with attributes of the parent" do
381
+ child = Factory.define(:child, :parent => :object) {}
382
+ child.attributes.size.should == 1
383
+ child.attributes.first.name.should == :name
384
+ end
385
+
386
+ it "should allow to define additional attributes" do
387
+ child = Factory.define(:child, :parent => :object) do |f|
388
+ f.email 'person@somebody.com'
389
+ end
390
+ child.attributes.size.should == 2
391
+ end
392
+
393
+ it "should allow to override parent attributes" do
394
+ child = Factory.define(:child, :parent => :object) do |f|
395
+ f.name { 'Child Name' }
396
+ end
397
+ child.attributes.size.should == 1
398
+ child.attributes.first.should be_kind_of(Factory::Attribute::Dynamic)
399
+ end
400
+ end
401
+
402
+ describe 'defining a factory with a default strategy parameter' do
403
+ it "should raise an ArgumentError when trying to use a non-existent factory" do
404
+ lambda {
405
+ Factory.define(:object, :default_strategy => :nonexistent) {}
406
+ }.should raise_error(ArgumentError)
407
+ end
408
+
409
+ it "should create a new factory with a specified default strategy" do
410
+ factory = Factory.define(:object, :default_strategy => :stub) {}
411
+ factory.default_strategy.should == :stub
412
+ end
413
+ end
414
+
415
+ def self.in_directory_with_files(*files)
416
+ before do
417
+ @pwd = Dir.pwd
418
+ @tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
419
+ FileUtils.mkdir_p @tmp_dir
420
+ Dir.chdir(@tmp_dir)
421
+
422
+ files.each do |file|
423
+ FileUtils.mkdir_p File.dirname(file)
424
+ FileUtils.touch file
425
+ stub(Factory).require(file)
426
+ end
427
+ end
428
+
429
+ after do
430
+ Dir.chdir(@pwd)
431
+ FileUtils.rm_rf(@tmp_dir)
432
+ end
433
+ end
434
+
435
+ def require_definitions_from(file)
436
+ simple_matcher do |given, matcher|
437
+ has_received = have_received.require(file)
438
+ result = has_received.matches?(given)
439
+ matcher.description = "require definitions from #{file}"
440
+ matcher.failure_message = has_received.failure_message
441
+ result
442
+ end
443
+ end
444
+
445
+ share_examples_for "finds definitions" do
446
+ before do
447
+ stub(Factory).require
448
+ Factory.find_definitions
449
+ end
450
+ subject { Factory }
451
+ end
452
+
453
+ describe "with factories.rb" do
454
+ in_directory_with_files 'factories.rb'
455
+ it_should_behave_like "finds definitions"
456
+ it { should require_definitions_from('factories.rb') }
457
+ end
458
+
459
+ %w(spec test).each do |dir|
460
+ describe "with a factories file under #{dir}" do
461
+ in_directory_with_files File.join(dir, 'factories.rb')
462
+ it_should_behave_like "finds definitions"
463
+ it { should require_definitions_from("#{dir}/factories.rb") }
464
+ end
465
+
466
+ describe "with a factories file under #{dir}/factories" do
467
+ in_directory_with_files File.join(dir, 'factories', 'post_factory.rb')
468
+ it_should_behave_like "finds definitions"
469
+ it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
470
+ end
471
+
472
+ describe "with several factories files under #{dir}/factories" do
473
+ in_directory_with_files File.join(dir, 'factories', 'post_factory.rb'),
474
+ File.join(dir, 'factories', 'person_factory.rb')
475
+ it_should_behave_like "finds definitions"
476
+ it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
477
+ it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
478
+ end
479
+
480
+ describe "with nested and unnested factories files under #{dir}" do
481
+ in_directory_with_files File.join(dir, 'factories.rb'),
482
+ File.join(dir, 'factories', 'post_factory.rb'),
483
+ File.join(dir, 'factories', 'person_factory.rb')
484
+ it_should_behave_like "finds definitions"
485
+ it { should require_definitions_from("#{dir}/factories.rb") }
486
+ it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
487
+ it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
488
+ end
489
+ end
490
+ end