factory_girl 1.3.3 → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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
+