agibralter-factory_girl 1.2.1

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