vitalish-factory_girl 1.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/CONTRIBUTION_GUIDELINES.rdoc +9 -0
  2. data/Changelog +29 -0
  3. data/LICENSE +19 -0
  4. data/README.rdoc +282 -0
  5. data/Rakefile +66 -0
  6. data/lib/factory_girl.rb +24 -0
  7. data/lib/factory_girl/aliases.rb +21 -0
  8. data/lib/factory_girl/attribute.rb +29 -0
  9. data/lib/factory_girl/attribute/association.rb +20 -0
  10. data/lib/factory_girl/attribute/callback.rb +16 -0
  11. data/lib/factory_girl/attribute/dynamic.rb +20 -0
  12. data/lib/factory_girl/attribute/static.rb +17 -0
  13. data/lib/factory_girl/factory.rb +215 -0
  14. data/lib/factory_girl/proxy.rb +77 -0
  15. data/lib/factory_girl/proxy/attributes_for.rb +21 -0
  16. data/lib/factory_girl/proxy/build.rb +32 -0
  17. data/lib/factory_girl/proxy/create.rb +12 -0
  18. data/lib/factory_girl/proxy/stub.rb +64 -0
  19. data/lib/factory_girl/sequence.rb +28 -0
  20. data/lib/factory_girl/step_definitions.rb +60 -0
  21. data/lib/factory_girl/syntax.rb +12 -0
  22. data/lib/factory_girl/syntax/blueprint.rb +42 -0
  23. data/lib/factory_girl/syntax/generate.rb +73 -0
  24. data/lib/factory_girl/syntax/make.rb +41 -0
  25. data/lib/factory_girl/syntax/sham.rb +45 -0
  26. data/spec/factory_girl/aliases_spec.rb +33 -0
  27. data/spec/factory_girl/attribute/association_spec.rb +29 -0
  28. data/spec/factory_girl/attribute/callback_spec.rb +23 -0
  29. data/spec/factory_girl/attribute/dynamic_spec.rb +60 -0
  30. data/spec/factory_girl/attribute/static_spec.rb +29 -0
  31. data/spec/factory_girl/attribute_spec.rb +30 -0
  32. data/spec/factory_girl/factory_spec.rb +411 -0
  33. data/spec/factory_girl/proxy/attributes_for_spec.rb +52 -0
  34. data/spec/factory_girl/proxy/build_spec.rb +86 -0
  35. data/spec/factory_girl/proxy/create_spec.rb +99 -0
  36. data/spec/factory_girl/proxy/stub_spec.rb +80 -0
  37. data/spec/factory_girl/proxy_spec.rb +84 -0
  38. data/spec/factory_girl/sequence_spec.rb +43 -0
  39. data/spec/spec_helper.rb +93 -0
  40. metadata +119 -0
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe FactoryGirl::Attribute::Callback do
4
+ before do
5
+ @name = :after_create
6
+ @block = proc{ 'block' }
7
+ @attr = FactoryGirl::Attribute::Callback.new(@name, @block)
8
+ end
9
+
10
+ it "should have a name" do
11
+ @attr.name.should == @name
12
+ end
13
+
14
+ it "should set its callback on a proxy" do
15
+ @proxy = "proxy"
16
+ mock(@proxy).add_callback(@name, @block)
17
+ @attr.add_to(@proxy)
18
+ end
19
+
20
+ it "should convert names to symbols" do
21
+ FactoryGirl::Attribute::Callback.new('name', nil).name.should == :name
22
+ end
23
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe FactoryGirl::Attribute::Dynamic do
4
+ before do
5
+ @name = :first_name
6
+ @block = lambda { 'value' }
7
+ @attr = FactoryGirl::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 = FactoryGirl::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 "evaluates the block with in the context of the proxy without an argument" do
31
+ result = 'other attribute value'
32
+ @block = lambda { other_attribute }
33
+ @attr = FactoryGirl::Attribute::Dynamic.new(:user, @block)
34
+ @proxy = "proxy"
35
+ stub(@proxy).set
36
+ stub(@proxy).other_attribute { result }
37
+ @attr.add_to(@proxy)
38
+ @proxy.should have_received.set(:user, result)
39
+ end
40
+
41
+ it "should raise an error when defining an attribute writer" do
42
+ lambda {
43
+ FactoryGirl::Attribute::Dynamic.new('test=', nil)
44
+ }.should raise_error(FactoryGirl::AttributeDefinitionError)
45
+ end
46
+
47
+ it "should raise an error when returning a sequence" do
48
+ stub(Factory).sequence { FactoryGirl::Sequence.new }
49
+ block = lambda { Factory.sequence(:email) }
50
+ attr = FactoryGirl::Attribute::Dynamic.new(:email, block)
51
+ proxy = stub!.set.subject
52
+ lambda {
53
+ attr.add_to(proxy)
54
+ }.should raise_error(FactoryGirl::SequenceAbuseError)
55
+ end
56
+
57
+ it "should convert names to symbols" do
58
+ FactoryGirl::Attribute::Dynamic.new('name', nil).name.should == :name
59
+ end
60
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe FactoryGirl::Attribute::Static do
4
+ before do
5
+ @name = :first_name
6
+ @value = 'John'
7
+ @attr = FactoryGirl::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
+ FactoryGirl::Attribute::Static.new('test=', nil)
23
+ }.should raise_error(FactoryGirl::AttributeDefinitionError)
24
+ end
25
+
26
+ it "should convert names to symbols" do
27
+ FactoryGirl::Attribute::Static.new('name', nil).name.should == :name
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+
3
+ describe FactoryGirl::Attribute do
4
+ before do
5
+ @name = :user
6
+ @attr = FactoryGirl::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
+ FactoryGirl::Attribute.new('test=')
24
+ }.should raise_error(FactoryGirl::AttributeDefinitionError, error_message)
25
+ end
26
+
27
+ it "should convert names to symbols" do
28
+ FactoryGirl::Attribute.new('name').name.should == :name
29
+ end
30
+ end
@@ -0,0 +1,411 @@
1
+ require 'spec_helper'
2
+
3
+ describe FactoryGirl::Factory, "registering a factory" do
4
+ before do
5
+ @name = :user
6
+ @factory = "factory"
7
+ @aliases = [:one, :two]
8
+ stub(@factory).name { @name }
9
+ stub(@factory).aliases { @aliases }
10
+ end
11
+
12
+ it "should add the factory to the list of factories" do
13
+ FactoryGirl.register_factory(@factory)
14
+ FactoryGirl.factory_by_name(@name).should == @factory
15
+ end
16
+
17
+ it "should not allow a duplicate factory definition" do
18
+ lambda {
19
+ 2.times { FactoryGirl.register_factory(@factory) }
20
+ }.should raise_error(FactoryGirl::DuplicateDefinitionError)
21
+ end
22
+
23
+ it "registers aliases" do
24
+ FactoryGirl.register_factory(@factory)
25
+ @aliases.each do |name|
26
+ FactoryGirl.factory_by_name(name).should == @factory
27
+ end
28
+ end
29
+ end
30
+
31
+ describe FactoryGirl::Factory do
32
+ include DefinesConstants
33
+
34
+ before do
35
+ @name = :user
36
+ @class = define_class('User')
37
+ @factory = FactoryGirl::Factory.new(@name)
38
+ end
39
+
40
+ it "should have a factory name" do
41
+ @factory.name.should == @name
42
+ end
43
+
44
+ it "responds to factory_name" do
45
+ @factory.factory_name.should == @name
46
+ end
47
+
48
+ it "should have a build class" do
49
+ @factory.build_class.should == @class
50
+ end
51
+
52
+ it "should have a default strategy" do
53
+ @factory.default_strategy.should == :create
54
+ end
55
+
56
+ it "should not allow the same attribute to be added twice" do
57
+ lambda {
58
+ 2.times { @factory.define_attribute FactoryGirl::Attribute::Static.new(:name, 'value') }
59
+ }.should raise_error(FactoryGirl::AttributeDefinitionError)
60
+ end
61
+
62
+ it "should add a callback attribute when defining a callback" do
63
+ mock(FactoryGirl::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
64
+ @factory.add_callback(:after_create) {}
65
+ @factory.attributes.should include('after_create callback')
66
+ end
67
+
68
+ it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do
69
+ lambda{
70
+ @factory.add_callback(:invalid_callback_name) {}
71
+ }.should raise_error(FactoryGirl::InvalidCallbackNameError)
72
+ end
73
+
74
+ describe "after adding an attribute" do
75
+ before do
76
+ @attribute = "attribute"
77
+ @proxy = "proxy"
78
+
79
+ stub(@attribute).name { :name }
80
+ stub(@attribute).add_to
81
+ stub(@proxy).set
82
+ stub(@proxy).result { 'result' }
83
+ stub(FactoryGirl::Attribute::Static).new { @attribute }
84
+ stub(FactoryGirl::Proxy::Build).new { @proxy }
85
+
86
+ @factory.define_attribute(@attribute)
87
+ end
88
+
89
+ it "should create the right proxy using the build class when running" do
90
+ mock(FactoryGirl::Proxy::Build).new(@factory.build_class) { @proxy }
91
+ @factory.run(FactoryGirl::Proxy::Build, {})
92
+ end
93
+
94
+ it "should add the attribute to the proxy when running" do
95
+ mock(@attribute).add_to(@proxy)
96
+ @factory.run(FactoryGirl::Proxy::Build, {})
97
+ end
98
+
99
+ it "should return the result from the proxy when running" do
100
+ mock(@proxy).result() { 'result' }
101
+ @factory.run(FactoryGirl::Proxy::Build, {}).should == 'result'
102
+ end
103
+ end
104
+
105
+ it "should return associations" do
106
+ factory = FactoryGirl::Factory.new(:post)
107
+ factory.define_attribute(FactoryGirl::Attribute::Association.new(:author, :author, {}))
108
+ factory.define_attribute(FactoryGirl::Attribute::Association.new(:editor, :editor, {}))
109
+ factory.associations.each do |association|
110
+ association.should be_a(FactoryGirl::Attribute::Association)
111
+ end
112
+ factory.associations.size.should == 2
113
+ end
114
+
115
+ it "should raise for a self referencing association" do
116
+ factory = FactoryGirl::Factory.new(:post)
117
+ lambda {
118
+ factory.define_attribute(FactoryGirl::Attribute::Association.new(:parent, :post, {}))
119
+ }.should raise_error(FactoryGirl::AssociationDefinitionError)
120
+ end
121
+
122
+ describe "when overriding generated attributes with a hash" do
123
+ before do
124
+ @name = :name
125
+ @value = 'The price is right!'
126
+ @hash = { @name => @value }
127
+ end
128
+
129
+ it "should return the overridden value in the generated attributes" do
130
+ attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
131
+ @factory.define_attribute(attr)
132
+ result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
133
+ result[@name].should == @value
134
+ end
135
+
136
+ it "should not call a lazy attribute block for an overridden attribute" do
137
+ attr = FactoryGirl::Attribute::Dynamic.new(@name, lambda { flunk })
138
+ @factory.define_attribute(attr)
139
+ result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
140
+ end
141
+
142
+ it "should override a symbol parameter with a string parameter" do
143
+ attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
144
+ @factory.define_attribute(attr)
145
+ @hash = { @name.to_s => @value }
146
+ result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
147
+ result[@name].should == @value
148
+ end
149
+ end
150
+
151
+ describe "overriding an attribute with an alias" do
152
+ before do
153
+ @factory.define_attribute(FactoryGirl::Attribute::Static.new(:test, 'original'))
154
+ Factory.alias(/(.*)_alias/, '\1')
155
+ @result = @factory.run(FactoryGirl::Proxy::AttributesFor,
156
+ :test_alias => 'new')
157
+ end
158
+
159
+ it "should use the passed in value for the alias" do
160
+ @result[:test_alias].should == 'new'
161
+ end
162
+
163
+ it "should discard the predefined value for the attribute" do
164
+ @result[:test].should be_nil
165
+ end
166
+ end
167
+
168
+ it "should guess the build class from the factory name" do
169
+ @factory.build_class.should == User
170
+ end
171
+
172
+ it "should create a new factory using the class of the parent" do
173
+ child = FactoryGirl::Factory.new(:child)
174
+ child.inherit_from(@factory)
175
+ child.build_class.should == @factory.build_class
176
+ end
177
+
178
+ it "should create a new factory while overriding the parent class" do
179
+ child = FactoryGirl::Factory.new(:child, :class => String)
180
+ child.inherit_from(@factory)
181
+ child.build_class.should == String
182
+ end
183
+
184
+ describe "given a parent with attributes" do
185
+ before do
186
+ @parent_attr = :name
187
+ @factory.define_attribute(FactoryGirl::Attribute::Static.new(@parent_attr, 'value'))
188
+ end
189
+
190
+ it "should create a new factory with attributes of the parent" do
191
+ child = FactoryGirl::Factory.new(:child)
192
+ child.inherit_from(@factory)
193
+ child.attributes.size.should == 1
194
+ child.attributes.first.name.should == @parent_attr
195
+ end
196
+
197
+ it "should allow a child to define additional attributes" do
198
+ child = FactoryGirl::Factory.new(:child)
199
+ child.define_attribute(FactoryGirl::Attribute::Static.new(:email, 'value'))
200
+ child.inherit_from(@factory)
201
+ child.attributes.size.should == 2
202
+ end
203
+
204
+ it "should allow to override parent attributes" do
205
+ child = FactoryGirl::Factory.new(:child)
206
+ @child_attr = FactoryGirl::Attribute::Static.new(@parent_attr, 'value')
207
+ child.define_attribute(@child_attr)
208
+ child.inherit_from(@factory)
209
+ child.attributes.size.should == 1
210
+ child.attributes.first.should == @child_attr
211
+ end
212
+
213
+ it "should allow to use parent attributes in defining additional attributes" do
214
+ User.class_eval { attr_accessor :name, :email }
215
+
216
+ child = FactoryGirl::Factory.new(:child)
217
+ @child_attr = FactoryGirl::Attribute::Dynamic.new(:email, lambda {|u| "#{u.name}@example.com"})
218
+ child.define_attribute(@child_attr)
219
+ child.inherit_from(@factory)
220
+ child.attributes.size.should == 2
221
+
222
+ result = child.run(FactoryGirl::Proxy::Build, {})
223
+ result.email.should == 'value@example.com'
224
+ end
225
+ end
226
+
227
+ it "inherit all callbacks" do
228
+ @factory.add_callback(:after_stub) { |object| object.name = 'Stubby' }
229
+ child = FactoryGirl::Factory.new(:child)
230
+ child.inherit_from(@factory)
231
+ child.attributes.last.should be_kind_of(FactoryGirl::Attribute::Callback)
232
+ end
233
+ end
234
+
235
+ describe FactoryGirl::Factory, "when defined with a custom class" do
236
+ before do
237
+ @class = Float
238
+ @factory = FactoryGirl::Factory.new(:author, :class => @class)
239
+ end
240
+
241
+ it "should use the specified class as the build class" do
242
+ @factory.build_class.should == @class
243
+ end
244
+ end
245
+
246
+ describe FactoryGirl::Factory, "when defined with a class instead of a name" do
247
+ before do
248
+ @class = ArgumentError
249
+ @name = :argument_error
250
+ @factory = FactoryGirl::Factory.new(@class)
251
+ end
252
+
253
+ it "should guess the name from the class" do
254
+ @factory.name.should == @name
255
+ end
256
+
257
+ it "should use the class as the build class" do
258
+ @factory.build_class.should == @class
259
+ end
260
+ end
261
+
262
+ describe FactoryGirl::Factory, "when defined with a custom class name" do
263
+ before do
264
+ @class = ArgumentError
265
+ @factory = FactoryGirl::Factory.new(:author, :class => :argument_error)
266
+ end
267
+
268
+ it "should use the specified class as the build class" do
269
+ @factory.build_class.should == @class
270
+ end
271
+ end
272
+
273
+ describe FactoryGirl::Factory, "with a name ending in s" do
274
+ include DefinesConstants
275
+
276
+ before do
277
+ define_class('Business')
278
+ @name = :business
279
+ @class = Business
280
+ @factory = FactoryGirl::Factory.new(@name)
281
+ end
282
+
283
+ it "should have a factory name" do
284
+ @factory.name.should == @name
285
+ end
286
+
287
+ it "should have a build class" do
288
+ @factory.build_class.should == @class
289
+ end
290
+ end
291
+
292
+ describe FactoryGirl::Factory, "with a string for a name" do
293
+ before do
294
+ @name = :string
295
+ @factory = FactoryGirl::Factory.new(@name.to_s) {}
296
+ end
297
+
298
+ it "should convert the string to a symbol" do
299
+ @factory.name.should == @name
300
+ end
301
+ end
302
+
303
+ describe FactoryGirl::Factory, "registered with a string name" do
304
+ before do
305
+ @name = :string
306
+ @factory = FactoryGirl::Factory.new(@name)
307
+ FactoryGirl.register_factory(@factory)
308
+ end
309
+
310
+ it "should store the factory using a symbol" do
311
+ FactoryGirl.factories[@name].should == @factory
312
+ end
313
+ end
314
+
315
+ describe FactoryGirl::Factory, "registered with a custom name" do
316
+ before do
317
+ @actual_name = :string
318
+ @custom_name = :words
319
+ @factory = FactoryGirl::Factory.new(@actual_name)
320
+
321
+ FactoryGirl.register_factory(@factory, :as => @custom_name)
322
+ end
323
+
324
+ it "finds the factory using the custom name" do
325
+ FactoryGirl.factory_by_name(@custom_name).should == @factory
326
+ end
327
+ end
328
+
329
+ describe FactoryGirl::Factory, "for namespaced class" do
330
+ include DefinesConstants
331
+
332
+ before do
333
+ define_class('Admin')
334
+ define_class('Admin::Settings')
335
+
336
+ @name = :settings
337
+ @class = Admin::Settings
338
+ end
339
+
340
+ it "should build namespaced class passed by string" do
341
+ factory = FactoryGirl::Factory.new(@name.to_s, :class => @class.name)
342
+ factory.build_class.should == @class
343
+ end
344
+
345
+ it "should build Admin::Settings class from Admin::Settings string" do
346
+ factory = FactoryGirl::Factory.new(@name.to_s, :class => 'admin/settings')
347
+ factory.build_class.should == @class
348
+ end
349
+ end
350
+
351
+ describe FactoryGirl::Factory do
352
+ include DefinesConstants
353
+
354
+ before do
355
+ define_class('User')
356
+ define_class('Admin', User)
357
+ end
358
+
359
+ it "should raise an ArgumentError when trying to use a non-existent strategy" do
360
+ lambda {
361
+ FactoryGirl::Factory.new(:object, :default_strategy => :nonexistent) {}
362
+ }.should raise_error(ArgumentError)
363
+ end
364
+
365
+ it "should create a new factory with a specified default strategy" do
366
+ factory = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
367
+ factory.default_strategy.should == :stub
368
+ end
369
+
370
+ describe 'defining a child factory without setting default strategy' do
371
+ before do
372
+ @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
373
+ @child = FactoryGirl::Factory.new(:child_object)
374
+ @child.inherit_from(@parent)
375
+ end
376
+
377
+ it "should inherit default strategy from its parent" do
378
+ @child.default_strategy.should == :stub
379
+ end
380
+ end
381
+
382
+ describe 'defining a child factory with a default strategy' do
383
+ before do
384
+ @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
385
+ @child = FactoryGirl::Factory.new(:child_object2, :default_strategy => :build)
386
+ @child.inherit_from(@parent)
387
+ end
388
+
389
+ it "should override the default strategy from parent" do
390
+ @child.default_strategy.should == :build
391
+ end
392
+ end
393
+
394
+ end
395
+
396
+ describe FactoryGirl::Factory, "with an underscore in the name" do
397
+ subject { FactoryGirl::Factory.new("happy_users") }
398
+
399
+ it "has a human name" do
400
+ subject.human_name.should == 'happy users'
401
+ end
402
+ end
403
+
404
+
405
+ describe FactoryGirl::Factory, "with aliases" do
406
+ it "registers the aliases" do
407
+ aliased_name = :guest
408
+ factory = FactoryGirl::Factory.new("user", :aliases => [aliased_name])
409
+ factory.aliases.should == [aliased_name]
410
+ end
411
+ end