factory_girl 1.3.3 → 2.0.0.beta1

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.
Files changed (53) hide show
  1. data/README.rdoc +68 -60
  2. data/features/support/test.db +0 -0
  3. data/lib/factory_girl.rb +6 -12
  4. data/lib/factory_girl/aliases.rb +2 -31
  5. data/lib/factory_girl/attribute.rb +1 -1
  6. data/lib/factory_girl/attribute/association.rb +1 -1
  7. data/lib/factory_girl/attribute/callback.rb +1 -1
  8. data/lib/factory_girl/attribute/dynamic.rb +3 -3
  9. data/lib/factory_girl/attribute/static.rb +1 -1
  10. data/lib/factory_girl/definition_proxy.rb +180 -0
  11. data/lib/factory_girl/deprecated.rb +18 -0
  12. data/lib/factory_girl/factory.rb +120 -355
  13. data/lib/factory_girl/find_definitions.rb +25 -0
  14. data/lib/factory_girl/proxy.rb +4 -6
  15. data/lib/factory_girl/proxy/attributes_for.rb +1 -1
  16. data/lib/factory_girl/proxy/build.rb +7 -5
  17. data/lib/factory_girl/proxy/create.rb +1 -1
  18. data/lib/factory_girl/proxy/stub.rb +11 -5
  19. data/lib/factory_girl/rails2.rb +1 -1
  20. data/lib/factory_girl/sequence.rb +5 -40
  21. data/lib/factory_girl/step_definitions.rb +7 -7
  22. data/lib/factory_girl/syntax.rb +7 -7
  23. data/lib/factory_girl/syntax/blueprint.rb +5 -4
  24. data/lib/factory_girl/syntax/default.rb +31 -0
  25. data/lib/factory_girl/syntax/generate.rb +13 -8
  26. data/lib/factory_girl/syntax/make.rb +8 -6
  27. data/lib/factory_girl/syntax/sham.rb +11 -8
  28. data/lib/factory_girl/syntax/vintage.rb +196 -0
  29. data/lib/factory_girl/version.rb +4 -0
  30. data/spec/acceptance/acceptance_spec.rb +43 -60
  31. data/spec/acceptance/syntax/blueprint_spec.rb +1 -5
  32. data/spec/acceptance/syntax/generate_spec.rb +1 -4
  33. data/spec/acceptance/syntax/make_spec.rb +1 -4
  34. data/spec/acceptance/syntax/sham_spec.rb +9 -7
  35. data/spec/acceptance/syntax/vintage_spec.rb +184 -0
  36. data/spec/factory_girl/aliases_spec.rb +5 -5
  37. data/spec/factory_girl/attribute/association_spec.rb +3 -3
  38. data/spec/factory_girl/attribute/callback_spec.rb +3 -3
  39. data/spec/factory_girl/attribute/dynamic_spec.rb +20 -9
  40. data/spec/factory_girl/attribute/static_spec.rb +5 -5
  41. data/spec/factory_girl/attribute_spec.rb +5 -5
  42. data/spec/factory_girl/definition_proxy_spec.rb +138 -0
  43. data/spec/factory_girl/deprecated_spec.rb +66 -0
  44. data/spec/factory_girl/factory_spec.rb +283 -566
  45. data/spec/factory_girl/find_definitions_spec.rb +89 -0
  46. data/spec/factory_girl/proxy/attributes_for_spec.rb +2 -2
  47. data/spec/factory_girl/proxy/build_spec.rb +17 -12
  48. data/spec/factory_girl/proxy/create_spec.rb +17 -12
  49. data/spec/factory_girl/proxy/stub_spec.rb +6 -5
  50. data/spec/factory_girl/proxy_spec.rb +2 -2
  51. data/spec/factory_girl/sequence_spec.rb +15 -38
  52. data/spec/spec_helper.rb +4 -0
  53. metadata +28 -11
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe "accessing an undefined method on Factory that is defined on FactoryGirl" do
4
+ let(:method_name) { :aliases }
5
+ let(:return_value) { 'value' }
6
+ let(:args) { [1, 2, 3] }
7
+
8
+ before do
9
+ stub($stderr).puts
10
+ stub(FactoryGirl, method_name).returns { return_value }
11
+
12
+ @result = Factory.send(method_name, *args)
13
+ end
14
+
15
+ it "prints a deprecation warning" do
16
+ $stderr.should have_received.puts(anything)
17
+ end
18
+
19
+ it "invokes that method on FactoryGirl" do
20
+ FactoryGirl.should have_received.method_missing(method_name, *args)
21
+ end
22
+
23
+ it "returns the value from the method on FactoryGirl" do
24
+ @result.should == return_value
25
+ end
26
+ end
27
+
28
+ describe "accessing an undefined method on Factory that is not defined on FactoryGirl" do
29
+ let(:method_name) { :magic_beans }
30
+
31
+ before do
32
+ stub($stderr).puts { raise "Don't print a deprecation warning" }
33
+
34
+ begin
35
+ Factory.send(method_name)
36
+ rescue Exception => @raised
37
+ end
38
+ end
39
+
40
+ it "raises a NoMethodError" do
41
+ @raised.should be_a(NoMethodError)
42
+ end
43
+ end
44
+
45
+ describe "accessing an undefined constant on Factory that is defined on FactoryGirl" do
46
+ before do
47
+ @result = Factory::VERSION
48
+ end
49
+
50
+ it "returns that constant on FactoryGirl" do
51
+ @result.should == FactoryGirl::VERSION
52
+ end
53
+ end
54
+
55
+ describe "accessing an undefined constant on Factory that is undefined on FactoryGirl" do
56
+ it "raises a NameError for Factory" do
57
+ begin
58
+ Factory::BOGUS
59
+ rescue Exception => exception
60
+ end
61
+
62
+ exception.should be_a(NameError)
63
+ exception.message.should include("Factory::BOGUS")
64
+ end
65
+ end
66
+
@@ -1,677 +1,394 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Factory do
4
- include DefinesConstants
5
-
3
+ describe FactoryGirl::Factory, "registering a factory" do
6
4
  before do
7
- define_constant('User')
8
- define_constant('Admin', User)
9
- define_constant('Business')
10
- define_constant('Admin::Settings')
5
+ @name = :user
6
+ @factory = "factory"
7
+ stub(@factory).name { @name }
11
8
  end
12
9
 
13
- describe "defining a factory" do
14
- before do
15
- @name = :user
16
- @factory = "factory"
17
- stub(@factory).factory_name { @name }
18
- @options = { :class => 'magic' }
19
- stub(Factory).new { @factory }
20
- end
21
-
22
- after { Factory.factories.clear }
23
-
24
- it "should create a new factory using the specified name and options" do
25
- mock(Factory).new(@name, @options) { @factory }
26
- Factory.define(@name, @options) {|f| }
27
- end
28
-
29
- it "should pass the factory do the block" do
30
- yielded = nil
31
- Factory.define(@name) do |y|
32
- yielded = y
33
- end
34
- yielded.should == @factory
35
- end
36
-
37
- it "should add the factory to the list of factories" do
38
- Factory.define(@name) {|f| }
39
- @factory.should == Factory.factories[@name]
40
- end
41
-
42
- it "should allow a factory to be found by name" do
43
- Factory.define(@name) {|f| }
44
- Factory.factory_by_name(@name).should == @factory
45
- end
46
-
47
- it "should not allow a duplicate factory definition" do
48
- lambda {
49
- 2.times { Factory.define(@name) {|f| } }
50
- }.should raise_error(Factory::DuplicateDefinitionError)
51
- end
52
-
10
+ it "should add the factory to the list of factories" do
11
+ FactoryGirl.register_factory(@factory)
12
+ FactoryGirl.factory_by_name(@name).should == @factory
53
13
  end
54
14
 
55
- describe "a factory" do
56
- before do
57
- @name = :user
58
- @class = User
59
- @factory = Factory.new(@name)
60
- end
61
-
62
- it "should have a factory name" do
63
- @factory.factory_name.should == @name
64
- end
65
-
66
- it "should have a build class" do
67
- @factory.build_class.should == @class
68
- end
69
-
70
- it "should have a default strategy" do
71
- @factory.default_strategy.should == :create
72
- end
73
-
74
- it "should return static attribute when asked for a type" do
75
- result = @factory.type
76
- result.should be_kind_of(Array)
77
- result.first.should be_kind_of(Factory::Attribute::Static)
78
- result.first.name.should == :type
79
- end
80
-
81
- it "should define type as an attribute" do
82
- @factory.type { "it's a type" }
83
- attributes = @factory.attributes
84
- attributes.should be_kind_of(Array)
85
- attributes.size.should == 1
86
- attributes.first.name.should == :type
87
- end
88
-
89
- it "should return static attribute when asked for the id" do
90
- result = @factory.id
91
- result.should be_kind_of(Array)
92
- result.first.should be_kind_of(Factory::Attribute::Static)
93
- result.first.name.should == :id
94
- end
95
-
96
- it "should define id as an attribute" do
97
- @factory.id { "it's an id" }
98
- attributes = @factory.attributes
99
- attributes.should be_kind_of(Array)
100
- attributes.size.should == 1
101
- attributes.first.name.should == :id
102
- end
103
-
104
- it "should not allow the same attribute to be added twice" do
105
- lambda {
106
- 2.times { @factory.add_attribute :first_name }
107
- }.should raise_error(Factory::AttributeDefinitionError)
108
- end
15
+ it "should not allow a duplicate factory definition" do
16
+ lambda {
17
+ 2.times { FactoryGirl.register_factory(@factory) }
18
+ }.should raise_error(FactoryGirl::DuplicateDefinitionError)
19
+ end
20
+ end
109
21
 
110
- it "should add a static attribute when an attribute is defined with a value" do
111
- attribute = 'attribute'
112
- stub(attribute).name { :name }
113
- mock(Factory::Attribute::Static).new(:name, 'value') { attribute }
114
- @factory.add_attribute(:name, 'value')
115
- end
22
+ describe FactoryGirl::Factory do
23
+ include DefinesConstants
116
24
 
117
- it "should add a dynamic attribute when an attribute is defined with a block" do
118
- attribute = 'attribute'
119
- stub(attribute).name { :name }
120
- block = lambda {}
121
- mock(Factory::Attribute::Dynamic).new(:name, block) { attribute }
122
- @factory.add_attribute(:name, &block)
123
- end
25
+ before do
26
+ @name = :user
27
+ @class = define_constant('User')
28
+ @factory = FactoryGirl::Factory.new(@name)
29
+ end
124
30
 
125
- it "should raise for an attribute with a value and a block" do
126
- lambda {
127
- @factory.add_attribute(:name, 'value') {}
128
- }.should raise_error(Factory::AttributeDefinitionError)
129
- end
31
+ it "should have a factory name" do
32
+ @factory.name.should == @name
33
+ end
130
34
 
131
- describe "adding an attribute using a in-line sequence" do
132
- it "should create the sequence" do
133
- mock(Factory::Sequence).new
134
- @factory.sequence(:name) {}
135
- end
136
-
137
- it "should add a dynamic attribute" do
138
- attribute = 'attribute'
139
- stub(attribute).name { :name }
140
- mock(Factory::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute }
141
- @factory.sequence(:name) {}
142
- @factory.attributes.should include(attribute)
143
- end
144
- end
35
+ it "responds to factory_name" do
36
+ @factory.factory_name.should == @name
37
+ end
145
38
 
146
- describe "adding a callback" do
147
- it "should add a callback attribute when the after_build attribute is defined" do
148
- mock(Factory::Attribute::Callback).new(:after_build, is_a(Proc)) { 'after_build callback' }
149
- @factory.after_build {}
150
- @factory.attributes.should include('after_build callback')
151
- end
152
-
153
- it "should add a callback attribute when the after_create attribute is defined" do
154
- mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
155
- @factory.after_create {}
156
- @factory.attributes.should include('after_create callback')
157
- end
158
-
159
- it "should add a callback attribute when the after_stub attribute is defined" do
160
- mock(Factory::Attribute::Callback).new(:after_stub, is_a(Proc)) { 'after_stub callback' }
161
- @factory.after_stub {}
162
- @factory.attributes.should include('after_stub callback')
163
- end
164
-
165
- it "should add a callback attribute when defining a callback" do
166
- mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
167
- @factory.callback(:after_create) {}
168
- @factory.attributes.should include('after_create callback')
169
- end
170
-
171
- it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do
172
- lambda{
173
- @factory.callback(:invalid_callback_name) {}
174
- }.should raise_error(Factory::InvalidCallbackNameError)
175
- end
176
- end
39
+ it "should have a build class" do
40
+ @factory.build_class.should == @class
41
+ end
177
42
 
178
- describe "after adding an attribute" do
179
- before do
180
- @attribute = "attribute"
181
- @proxy = "proxy"
182
-
183
- stub(@attribute).name { :name }
184
- stub(@attribute).add_to
185
- stub(@proxy).set
186
- stub(@proxy).result { 'result' }
187
- stub(Factory::Attribute::Static).new { @attribute }
188
- stub(Factory::Proxy::Build).new { @proxy }
189
-
190
- @factory.add_attribute(:name, 'value')
191
- end
192
-
193
- it "should create the right proxy using the build class when running" do
194
- mock(Factory::Proxy::Build).new(@factory.build_class) { @proxy }
195
- @factory.run(Factory::Proxy::Build, {})
196
- end
197
-
198
- it "should add the attribute to the proxy when running" do
199
- mock(@attribute).add_to(@proxy)
200
- @factory.run(Factory::Proxy::Build, {})
201
- end
202
-
203
- it "should return the result from the proxy when running" do
204
- mock(@proxy).result() { 'result' }
205
- @factory.run(Factory::Proxy::Build, {}).should == 'result'
206
- end
207
- end
43
+ it "should have a default strategy" do
44
+ @factory.default_strategy.should == :create
45
+ end
208
46
 
209
- it "should add an association without a factory name or overrides" do
210
- factory = Factory.new(:post)
211
- name = :user
212
- attr = 'attribute'
213
- mock(Factory::Attribute::Association).new(name, name, {}) { attr }
214
- factory.association(name)
215
- factory.attributes.should include(attr)
216
- end
47
+ it "should not allow the same attribute to be added twice" do
48
+ lambda {
49
+ 2.times { @factory.define_attribute FactoryGirl::Attribute::Static.new(:name, 'value') }
50
+ }.should raise_error(FactoryGirl::AttributeDefinitionError)
51
+ end
217
52
 
218
- it "should return associations" do
219
- factory = Factory.new(:post)
220
- factory.association(:author)
221
- factory.association(:editor)
222
- factory.associations.each do |association|
223
- association.should be_a(Factory::Attribute::Association)
224
- end
225
- factory.associations.size.should == 2
226
- end
53
+ it "should add a callback attribute when defining a callback" do
54
+ mock(FactoryGirl::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
55
+ @factory.add_callback(:after_create) {}
56
+ @factory.attributes.should include('after_create callback')
57
+ end
227
58
 
228
- it "should add an association with overrides" do
229
- factory = Factory.new(:post)
230
- name = :user
231
- attr = 'attribute'
232
- overrides = { :first_name => 'Ben' }
233
- mock(Factory::Attribute::Association).new(name, name, overrides) { attr }
234
- factory.association(name, overrides)
235
- factory.attributes.should include(attr)
236
- end
59
+ it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do
60
+ lambda{
61
+ @factory.add_callback(:invalid_callback_name) {}
62
+ }.should raise_error(FactoryGirl::InvalidCallbackNameError)
63
+ end
237
64
 
238
- it "should add an association with a factory name" do
239
- factory = Factory.new(:post)
240
- attr = 'attribute'
241
- mock(Factory::Attribute::Association).new(:author, :user, {}) { attr }
242
- factory.association(:author, :factory => :user)
243
- factory.attributes.should include(attr)
244
- end
65
+ describe "after adding an attribute" do
66
+ before do
67
+ @attribute = "attribute"
68
+ @proxy = "proxy"
245
69
 
246
- it "should add an association with a factory name and overrides" do
247
- factory = Factory.new(:post)
248
- attr = 'attribute'
249
- mock(Factory::Attribute::Association).new(:author, :user, :first_name => 'Ben') { attr }
250
- factory.association(:author, :factory => :user, :first_name => 'Ben')
251
- factory.attributes.should include(attr)
252
- end
70
+ stub(@attribute).name { :name }
71
+ stub(@attribute).add_to
72
+ stub(@proxy).set
73
+ stub(@proxy).result { 'result' }
74
+ stub(FactoryGirl::Attribute::Static).new { @attribute }
75
+ stub(FactoryGirl::Proxy::Build).new { @proxy }
253
76
 
254
- it "should raise for a self referencing association" do
255
- factory = Factory.new(:post)
256
- lambda {
257
- factory.association(:parent, :factory => :post)
258
- }.should raise_error(Factory::AssociationDefinitionError)
77
+ @factory.define_attribute(@attribute)
259
78
  end
260
79
 
261
- it "should add an attribute using the method name when passed an undefined method" do
262
- attribute = 'attribute'
263
- stub(attribute).name { :name }
264
- block = lambda {}
265
- mock(Factory::Attribute::Static).new(:name, 'value') { attribute }
266
- @factory.send(:name, 'value')
267
- @factory.attributes.should include(attribute)
80
+ it "should create the right proxy using the build class when running" do
81
+ mock(FactoryGirl::Proxy::Build).new(@factory.build_class) { @proxy }
82
+ @factory.run(FactoryGirl::Proxy::Build, {})
268
83
  end
269
84
 
270
- it "should allow human_name as a static attribute name" do
271
- attribute = 'attribute'
272
- stub(attribute).name { :name }
273
- mock(Factory::Attribute::Static).new(:human_name, 'value') { attribute}
274
- @factory.human_name 'value'
85
+ it "should add the attribute to the proxy when running" do
86
+ mock(@attribute).add_to(@proxy)
87
+ @factory.run(FactoryGirl::Proxy::Build, {})
275
88
  end
276
89
 
277
- it "should allow human_name as a dynamic attribute name" do
278
- attribute = 'attribute'
279
- stub(attribute).name { :name }
280
- block = lambda {}
281
- mock(Factory::Attribute::Dynamic).new(:human_name, block) { attribute }
282
- @factory.human_name(&block)
90
+ it "should return the result from the proxy when running" do
91
+ mock(@proxy).result() { 'result' }
92
+ @factory.run(FactoryGirl::Proxy::Build, {}).should == 'result'
283
93
  end
94
+ end
284
95
 
285
- describe "when overriding generated attributes with a hash" do
286
- before do
287
- @attr = :name
288
- @value = 'The price is right!'
289
- @hash = { @attr => @value }
290
- end
291
-
292
- it "should return the overridden value in the generated attributes" do
293
- @factory.add_attribute(@attr, 'The price is wrong, Bob!')
294
- result = @factory.run(Factory::Proxy::AttributesFor, @hash)
295
- result[@attr].should == @value
296
- end
297
-
298
- it "should not call a lazy attribute block for an overridden attribute" do
299
- @factory.add_attribute(@attr) { flunk }
300
- result = @factory.run(Factory::Proxy::AttributesFor, @hash)
301
- end
302
-
303
- it "should override a symbol parameter with a string parameter" do
304
- @factory.add_attribute(@attr, 'The price is wrong, Bob!')
305
- @hash = { @attr.to_s => @value }
306
- result = @factory.run(Factory::Proxy::AttributesFor, @hash)
307
- result[@attr].should == @value
308
- end
96
+ it "should return associations" do
97
+ factory = FactoryGirl::Factory.new(:post)
98
+ factory.define_attribute(FactoryGirl::Attribute::Association.new(:author, :author, {}))
99
+ factory.define_attribute(FactoryGirl::Attribute::Association.new(:editor, :editor, {}))
100
+ factory.associations.each do |association|
101
+ association.should be_a(FactoryGirl::Attribute::Association)
309
102
  end
103
+ factory.associations.size.should == 2
104
+ end
310
105
 
311
- describe "overriding an attribute with an alias" do
312
- before do
313
- @factory.add_attribute(:test, 'original')
314
- Factory.alias(/(.*)_alias/, '\1')
315
- @result = @factory.run(Factory::Proxy::AttributesFor,
316
- :test_alias => 'new')
317
- end
318
-
319
- it "should use the passed in value for the alias" do
320
- @result[:test_alias].should == 'new'
321
- end
322
-
323
- it "should discard the predefined value for the attribute" do
324
- @result[:test].should be_nil
325
- end
326
- end
106
+ it "should raise for a self referencing association" do
107
+ factory = FactoryGirl::Factory.new(:post)
108
+ lambda {
109
+ factory.define_attribute(FactoryGirl::Attribute::Association.new(:parent, :post, {}))
110
+ }.should raise_error(FactoryGirl::AssociationDefinitionError)
111
+ end
327
112
 
328
- it "should guess the build class from the factory name" do
329
- @factory.build_class.should == User
113
+ describe "when overriding generated attributes with a hash" do
114
+ before do
115
+ @name = :name
116
+ @value = 'The price is right!'
117
+ @hash = { @name => @value }
330
118
  end
331
119
 
332
- describe "when defined with a custom class" do
333
- before do
334
- @class = User
335
- @factory = Factory.new(:author, :class => @class)
336
- end
337
-
338
- it "should use the specified class as the build class" do
339
- @factory.build_class.should == @class
340
- end
120
+ it "should return the overridden value in the generated attributes" do
121
+ attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
122
+ @factory.define_attribute(attr)
123
+ result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
124
+ result[@name].should == @value
341
125
  end
342
126
 
343
- describe "when defined with a class instead of a name" do
344
- before do
345
- @class = ArgumentError
346
- @name = :argument_error
347
- @factory = Factory.new(@class)
348
- end
349
-
350
- it "should guess the name from the class" do
351
- @factory.factory_name.should == @name
352
- end
353
-
354
- it "should use the class as the build class" do
355
- @factory.build_class.should == @class
356
- end
127
+ it "should not call a lazy attribute block for an overridden attribute" do
128
+ attr = FactoryGirl::Attribute::Dynamic.new(@name, lambda { flunk })
129
+ @factory.define_attribute(attr)
130
+ result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
357
131
  end
358
132
 
359
- describe "when defined with a custom class name" do
360
- before do
361
- @class = ArgumentError
362
- @factory = Factory.new(:author, :class => :argument_error)
363
- end
364
-
365
- it "should use the specified class as the build class" do
366
- @factory.build_class.should == @class
367
- end
133
+ it "should override a symbol parameter with a string parameter" do
134
+ attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
135
+ @factory.define_attribute(attr)
136
+ @hash = { @name.to_s => @value }
137
+ result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
138
+ result[@name].should == @value
368
139
  end
369
140
  end
370
141
 
371
- describe "a factory with a name ending in s" do
142
+ describe "overriding an attribute with an alias" do
372
143
  before do
373
- @name = :business
374
- @class = Business
375
- @factory = Factory.new(@name)
144
+ @factory.define_attribute(FactoryGirl::Attribute::Static.new(:test, 'original'))
145
+ Factory.alias(/(.*)_alias/, '\1')
146
+ @result = @factory.run(FactoryGirl::Proxy::AttributesFor,
147
+ :test_alias => 'new')
376
148
  end
377
149
 
378
- it "should have a factory name" do
379
- @factory.factory_name.should == @name
150
+ it "should use the passed in value for the alias" do
151
+ @result[:test_alias].should == 'new'
380
152
  end
381
153
 
382
- it "should have a build class" do
383
- @factory.build_class.should == @class
154
+ it "should discard the predefined value for the attribute" do
155
+ @result[:test].should be_nil
384
156
  end
385
157
  end
386
158
 
387
- describe "a factory with a string for a name" do
388
- before do
389
- @name = :user
390
- @factory = Factory.new(@name.to_s) {}
391
- end
392
-
393
- it "should convert the string to a symbol" do
394
- @factory.factory_name.should == @name
395
- end
159
+ it "should guess the build class from the factory name" do
160
+ @factory.build_class.should == User
396
161
  end
397
162
 
398
- describe "a factory defined with a string name" do
399
- before do
400
- Factory.factories = {}
401
- @name = :user
402
- @factory = Factory.define(@name.to_s) {}
403
- end
404
-
405
- it "should store the factory using a symbol" do
406
- Factory.factories[@name].should == @factory
407
- end
163
+ it "should create a new factory using the class of the parent" do
164
+ child = FactoryGirl::Factory.new(:child)
165
+ child.inherit_from(@factory)
166
+ child.build_class.should == @factory.build_class
408
167
  end
409
168
 
410
- describe "a factory for namespaced class" do
411
- before do
412
- Factory.factories = {}
413
- @name = :settings
414
- @class = Admin::Settings
415
- end
416
-
417
- it "should build namespaced class passed by string" do
418
- factory = Factory.define(@name.to_s, :class => @class.name) {}
419
- factory.build_class.should == @class
420
- end
421
-
422
- it "should build Admin::Settings class from Admin::Settings string" do
423
- factory = Factory.define(@name.to_s, :class => 'admin/settings') {}
424
- factory.build_class.should == @class
425
- end
169
+ it "should create a new factory while overriding the parent class" do
170
+ child = FactoryGirl::Factory.new(:child, :class => String)
171
+ child.inherit_from(@factory)
172
+ child.build_class.should == String
426
173
  end
427
174
 
428
- describe "after defining a factory" do
175
+ describe "given a parent with attributes" do
429
176
  before do
430
- @name = :user
431
- @factory = "factory"
432
-
433
- Factory.factories[@name] = @factory
434
- end
435
-
436
- after { Factory.factories.clear }
437
-
438
- it "should use Proxy::AttributesFor for Factory.attributes_for" do
439
- mock(@factory).run(Factory::Proxy::AttributesFor, :attr => 'value') { 'result' }
440
- Factory.attributes_for(@name, :attr => 'value').should == 'result'
441
- end
442
-
443
- it "should use Proxy::Build for Factory.build" do
444
- mock(@factory).run(Factory::Proxy::Build, :attr => 'value') { 'result' }
445
- Factory.build(@name, :attr => 'value').should == 'result'
177
+ @parent_attr = :name
178
+ @factory.define_attribute(FactoryGirl::Attribute::Static.new(@parent_attr, 'value'))
446
179
  end
447
180
 
448
- it "should use Proxy::Create for Factory.create" do
449
- mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
450
- Factory.create(@name, :attr => 'value').should == 'result'
181
+ it "should create a new factory with attributes of the parent" do
182
+ child = FactoryGirl::Factory.new(:child)
183
+ child.inherit_from(@factory)
184
+ child.attributes.size.should == 1
185
+ child.attributes.first.name.should == @parent_attr
451
186
  end
452
187
 
453
- it "should use Proxy::Stub for Factory.stub" do
454
- mock(@factory).run(Factory::Proxy::Stub, :attr => 'value') { 'result' }
455
- Factory.stub(@name, :attr => 'value').should == 'result'
188
+ it "should allow a child to define additional attributes" do
189
+ child = FactoryGirl::Factory.new(:child)
190
+ child.define_attribute(FactoryGirl::Attribute::Static.new(:email, 'value'))
191
+ child.inherit_from(@factory)
192
+ child.attributes.size.should == 2
456
193
  end
457
194
 
458
- it "should use default strategy option as Factory.default_strategy" do
459
- stub(@factory).default_strategy { :create }
460
- mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
461
- Factory.default_strategy(@name, :attr => 'value').should == 'result'
195
+ it "should allow to override parent attributes" do
196
+ child = FactoryGirl::Factory.new(:child)
197
+ @child_attr = FactoryGirl::Attribute::Static.new(@parent_attr, 'value')
198
+ child.define_attribute(@child_attr)
199
+ child.inherit_from(@factory)
200
+ child.attributes.size.should == 1
201
+ child.attributes.first.should == @child_attr
462
202
  end
463
203
 
464
- it "should use the default strategy for the global Factory method" do
465
- stub(@factory).default_strategy { :create }
466
- mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
467
- Factory(@name, :attr => 'value').should == 'result'
468
- end
204
+ it "should allow to use parent attributes in defining additional attributes" do
205
+ User.class_eval { attr_accessor :name, :email }
469
206
 
470
- [:build, :create, :attributes_for, :stub].each do |method|
471
- it "should raise an ArgumentError on #{method} with a nonexistant factory" do
472
- lambda { Factory.send(method, :bogus) }.should raise_error(ArgumentError)
473
- end
207
+ child = FactoryGirl::Factory.new(:child)
208
+ @child_attr = FactoryGirl::Attribute::Dynamic.new(:email, lambda {|u| "#{u.name}@example.com"})
209
+ child.define_attribute(@child_attr)
210
+ child.inherit_from(@factory)
211
+ child.attributes.size.should == 2
474
212
 
475
- it "should recognize either 'name' or :name for Factory.#{method}" do
476
- stub(@factory).run
477
- lambda { Factory.send(method, @name.to_s) }.should_not raise_error
478
- lambda { Factory.send(method, @name.to_sym) }.should_not raise_error
479
- end
213
+ result = child.run(FactoryGirl::Proxy::Build, {})
214
+ result.email.should == 'value@example.com'
480
215
  end
481
216
  end
482
217
 
483
- describe 'defining a factory with a parent parameter' do
484
- before do
485
- @parent = Factory.define :object do |f|
486
- f.name 'Name'
487
- end
488
- end
218
+ it "inherit all callbacks" do
219
+ @factory.add_callback(:after_stub) { |object| object.name = 'Stubby' }
220
+ child = FactoryGirl::Factory.new(:child)
221
+ child.inherit_from(@factory)
222
+ child.attributes.last.should be_kind_of(FactoryGirl::Attribute::Callback)
223
+ end
224
+ end
489
225
 
490
- after { Factory.factories.clear }
226
+ describe FactoryGirl::Factory, "when defined with a custom class" do
227
+ before do
228
+ @class = Float
229
+ @factory = FactoryGirl::Factory.new(:author, :class => @class)
230
+ end
491
231
 
492
- it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
493
- lambda {
494
- Factory.define(:child, :parent => :nonexsitent) {}
495
- }.should raise_error(ArgumentError)
496
- end
232
+ it "should use the specified class as the build class" do
233
+ @factory.build_class.should == @class
234
+ end
235
+ end
497
236
 
498
- it "should create a new factory using the class of the parent" do
499
- child = Factory.define(:child, :parent => :object) {}
500
- child.build_class.should == @parent.build_class
501
- end
237
+ describe FactoryGirl::Factory, "when defined with a class instead of a name" do
238
+ before do
239
+ @class = ArgumentError
240
+ @name = :argument_error
241
+ @factory = FactoryGirl::Factory.new(@class)
242
+ end
502
243
 
503
- it "should create a new factory while overriding the parent class" do
504
- class Other; end
244
+ it "should guess the name from the class" do
245
+ @factory.name.should == @name
246
+ end
505
247
 
506
- child = Factory.define(:child, :parent => :object, :class => Other) {}
507
- child.build_class.should == Other
508
- end
248
+ it "should use the class as the build class" do
249
+ @factory.build_class.should == @class
250
+ end
251
+ end
509
252
 
510
- it "should create a new factory with attributes of the parent" do
511
- child = Factory.define(:child, :parent => :object) {}
512
- child.attributes.size.should == 1
513
- child.attributes.first.name.should == :name
514
- end
253
+ describe FactoryGirl::Factory, "when defined with a custom class name" do
254
+ before do
255
+ @class = ArgumentError
256
+ @factory = FactoryGirl::Factory.new(:author, :class => :argument_error)
257
+ end
515
258
 
516
- it "should allow to define additional attributes" do
517
- child = Factory.define(:child, :parent => :object) do |f|
518
- f.email 'person@somebody.com'
519
- end
520
- child.attributes.size.should == 2
521
- end
259
+ it "should use the specified class as the build class" do
260
+ @factory.build_class.should == @class
261
+ end
262
+ end
522
263
 
523
- it "should allow to override parent attributes" do
524
- child = Factory.define(:child, :parent => :object) do |f|
525
- f.name { 'Child Name' }
526
- end
527
- child.attributes.size.should == 1
528
- child.attributes.first.should be_kind_of(Factory::Attribute::Dynamic)
529
- end
264
+ describe FactoryGirl::Factory, "with a name ending in s" do
265
+ include DefinesConstants
530
266
 
531
- it "should allow to use parent attributes in defining additional attributes" do
532
- User.class_eval { attr_accessor :name, :email }
267
+ before do
268
+ define_constant('Business')
269
+ @name = :business
270
+ @class = Business
271
+ @factory = FactoryGirl::Factory.new(@name)
272
+ end
533
273
 
534
- parent = Factory.define(:parent, :class => User) do |f|
535
- f.name 'value'
536
- end
274
+ it "should have a factory name" do
275
+ @factory.name.should == @name
276
+ end
537
277
 
538
- child = Factory.new(:child)
539
- child.add_attribute(:email) {|u| "#{u.name}@example.com" }
540
- child.inherit_from(parent)
541
- child.attributes.size.should == 2
278
+ it "should have a build class" do
279
+ @factory.build_class.should == @class
280
+ end
281
+ end
542
282
 
543
- result = child.run(Factory::Proxy::Build, {})
544
- result.email.should == 'value@example.com'
545
- end
283
+ describe FactoryGirl::Factory, "with a string for a name" do
284
+ before do
285
+ @name = :string
286
+ @factory = FactoryGirl::Factory.new(@name.to_s) {}
287
+ end
546
288
 
547
- it "inherit all callbacks" do
548
- Factory.define(:child, :parent => :object) do |f|
549
- f.after_stub {|o| o.name = 'Stubby' }
550
- end
289
+ it "should convert the string to a symbol" do
290
+ @factory.name.should == @name
291
+ end
292
+ end
551
293
 
552
- grandchild = Factory.define(:grandchild, :parent => :child) do |f|
553
- f.after_stub {|o| o.name = "#{o.name} McStubby" }
554
- end
294
+ describe FactoryGirl::Factory, "registered with a string name" do
295
+ before do
296
+ @name = :string
297
+ @factory = FactoryGirl::Factory.new(@name)
298
+ FactoryGirl.register_factory(@factory)
299
+ end
555
300
 
556
- grandchild.attributes.size.should == 3
557
- grandchild.attributes[1].should be_kind_of(Factory::Attribute::Callback)
558
- grandchild.attributes[2].should be_kind_of(Factory::Attribute::Callback)
559
- end
301
+ it "should store the factory using a symbol" do
302
+ FactoryGirl.factories[@name].should == @factory
560
303
  end
304
+ end
561
305
 
562
- describe 'defining a factory with a default strategy parameter' do
563
- it "should raise an ArgumentError when trying to use a non-existent factory" do
564
- lambda {
565
- Factory.define(:object, :default_strategy => :nonexistent) {}
566
- }.should raise_error(ArgumentError)
567
- end
306
+ describe FactoryGirl::Factory, "registered with a custom name" do
307
+ before do
308
+ @actual_name = :string
309
+ @custom_name = :words
310
+ @factory = FactoryGirl::Factory.new(@actual_name)
568
311
 
569
- it "should create a new factory with a specified default strategy" do
570
- factory = Factory.define(:object, :default_strategy => :stub) {}
571
- factory.default_strategy.should == :stub
572
- end
312
+ FactoryGirl.register_factory(@factory, :as => @custom_name)
313
+ end
573
314
 
574
- describe 'defining a child factory without setting default strategy' do
575
- before do
576
- @child = Factory.define(:child_object, :parent => :object) {}
577
- end
315
+ it "finds the factory using the custom name" do
316
+ FactoryGirl.factory_by_name(@custom_name).should == @factory
317
+ end
318
+ end
578
319
 
579
- it "should inherit default strategy from its parent" do
580
- @child.default_strategy.should == :stub
581
- end
582
- end
320
+ describe FactoryGirl::Factory, "for namespaced class" do
321
+ include DefinesConstants
583
322
 
584
- describe 'defining a child factory with a default strategy' do
585
- before do
586
- @child2 = Factory.define(:child_object2, :parent => :object, :default_strategy => :build) {}
587
- end
323
+ before do
324
+ define_constant('Admin')
325
+ define_constant('Admin::Settings')
588
326
 
589
- it "should not inherit default strategy from parent" do
590
- @child2.default_strategy.should == :build
591
- end
592
- end
327
+ @name = :settings
328
+ @class = Admin::Settings
593
329
  end
594
330
 
595
- def self.in_directory_with_files(*files)
596
- before do
597
- @pwd = Dir.pwd
598
- @tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
599
- FileUtils.mkdir_p @tmp_dir
600
- Dir.chdir(@tmp_dir)
601
-
602
- files.each do |file|
603
- FileUtils.mkdir_p File.dirname(file)
604
- FileUtils.touch file
605
- stub(Factory).require
606
- end
607
- end
331
+ it "should build namespaced class passed by string" do
332
+ factory = FactoryGirl::Factory.new(@name.to_s, :class => @class.name)
333
+ factory.build_class.should == @class
334
+ end
608
335
 
609
- after do
610
- Dir.chdir(@pwd)
611
- FileUtils.rm_rf(@tmp_dir)
612
- end
336
+ it "should build Admin::Settings class from Admin::Settings string" do
337
+ factory = FactoryGirl::Factory.new(@name.to_s, :class => 'admin/settings')
338
+ factory.build_class.should == @class
613
339
  end
340
+ end
614
341
 
615
- def require_definitions_from(file)
616
- simple_matcher do |given, matcher|
617
- full_path = File.expand_path(file)
618
- has_received = have_received.method_missing(:require, full_path)
619
- result = has_received.matches?(given)
620
- matcher.description = "require definitions from #{file}"
621
- matcher.failure_message = has_received.failure_message
622
- result
623
- end
342
+ describe FactoryGirl::Factory do
343
+ include DefinesConstants
344
+
345
+ before do
346
+ define_constant('User')
347
+ define_constant('Admin', User)
624
348
  end
625
349
 
626
- share_examples_for "finds definitions" do
627
- before do
628
- stub(Factory).require
629
- Factory.find_definitions
630
- end
631
- subject { Factory }
350
+ it "should raise an ArgumentError when trying to use a non-existent strategy" do
351
+ lambda {
352
+ FactoryGirl::Factory.new(:object, :default_strategy => :nonexistent) {}
353
+ }.should raise_error(ArgumentError)
632
354
  end
633
355
 
634
- describe "with factories.rb" do
635
- in_directory_with_files 'factories.rb'
636
- it_should_behave_like "finds definitions"
637
- it { should require_definitions_from('factories.rb') }
356
+ it "should create a new factory with a specified default strategy" do
357
+ factory = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
358
+ factory.default_strategy.should == :stub
638
359
  end
639
360
 
640
- %w(spec test).each do |dir|
641
- describe "with a factories file under #{dir}" do
642
- in_directory_with_files File.join(dir, 'factories.rb')
643
- it_should_behave_like "finds definitions"
644
- it { should require_definitions_from("#{dir}/factories.rb") }
361
+ describe 'defining a child factory without setting default strategy' do
362
+ before do
363
+ @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
364
+ @child = FactoryGirl::Factory.new(:child_object)
365
+ @child.inherit_from(@parent)
645
366
  end
646
367
 
647
- describe "with a factories file under #{dir}/factories" do
648
- in_directory_with_files File.join(dir, 'factories', 'post_factory.rb')
649
- it_should_behave_like "finds definitions"
650
- it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
368
+ it "should inherit default strategy from its parent" do
369
+ @child.default_strategy.should == :stub
651
370
  end
371
+ end
652
372
 
653
- describe "with several factories files under #{dir}/factories" do
654
- in_directory_with_files File.join(dir, 'factories', 'post_factory.rb'),
655
- File.join(dir, 'factories', 'person_factory.rb')
656
- it_should_behave_like "finds definitions"
657
- it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
658
- it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
373
+ describe 'defining a child factory with a default strategy' do
374
+ before do
375
+ @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
376
+ @child = FactoryGirl::Factory.new(:child_object2, :default_strategy => :build)
377
+ @child.inherit_from(@parent)
659
378
  end
660
379
 
661
- describe "with nested and unnested factories files under #{dir}" do
662
- in_directory_with_files File.join(dir, 'factories.rb'),
663
- File.join(dir, 'factories', 'post_factory.rb'),
664
- File.join(dir, 'factories', 'person_factory.rb')
665
- it_should_behave_like "finds definitions"
666
- it { should require_definitions_from("#{dir}/factories.rb") }
667
- it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
668
- it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
380
+ it "should override the default strategy from parent" do
381
+ @child.default_strategy.should == :build
669
382
  end
670
383
  end
671
384
 
672
- it "should return the factory name without underscores for the human name" do
673
- factory = Factory.new(:name_with_underscores)
674
- factory.human_name.should == 'name with underscores'
675
- end
385
+ end
386
+
387
+ describe FactoryGirl::Factory, "with an underscore in the name" do
388
+ subject { FactoryGirl::Factory.new("happy_users") }
676
389
 
390
+ it "has a human name" do
391
+ subject.human_name.should == 'happy users'
392
+ end
677
393
  end
394
+