snowblink-factory_girl 1.1.5

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.
@@ -0,0 +1,58 @@
1
+ class Factory
2
+
3
+ class Sequence
4
+
5
+ def initialize (&proc) #:nodoc:
6
+ @proc = proc
7
+ @value = 0
8
+ end
9
+
10
+ # Returns the next value for this sequence
11
+ def next
12
+ @value += 1
13
+ @proc.call(@value)
14
+ end
15
+
16
+ end
17
+
18
+ class << self
19
+ attr_accessor :sequences #:nodoc:
20
+ end
21
+ self.sequences = {}
22
+
23
+ # Defines a new sequence that can be used to generate unique values in a specific format.
24
+ #
25
+ # Arguments:
26
+ # name: (Symbol)
27
+ # A unique name for this sequence. This name will be referenced when
28
+ # calling next to generate new values from this sequence.
29
+ # block: (Proc)
30
+ # The code to generate each value in the sequence. This block will be
31
+ # called with a unique number each time a value in the sequence is to be
32
+ # generated. The block should return the generated value for the
33
+ # sequence.
34
+ #
35
+ # Example:
36
+ #
37
+ # Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
38
+ def self.sequence (name, &block)
39
+ self.sequences[name] = Sequence.new(&block)
40
+ end
41
+
42
+ # Generates and returns the next value in a sequence.
43
+ #
44
+ # Arguments:
45
+ # name: (Symbol)
46
+ # The name of the sequence that a value should be generated for.
47
+ #
48
+ # Returns:
49
+ # The next value in the sequence. (Object)
50
+ def self.next (sequence)
51
+ unless self.sequences.key?(sequence)
52
+ raise "No such sequence: #{sequence}"
53
+ end
54
+
55
+ self.sequences[sequence].next
56
+ end
57
+
58
+ end
@@ -0,0 +1,29 @@
1
+ require(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class AliasesTest < Test::Unit::TestCase
4
+
5
+ should "include an attribute as an alias for itself by default" do
6
+ assert Factory.aliases_for(:test).include?(:test)
7
+ end
8
+
9
+ should "include the root of a foreign key as an alias by default" do
10
+ assert Factory.aliases_for(:test_id).include?(:test)
11
+ end
12
+
13
+ should "include an attribute's foreign key as an alias by default" do
14
+ assert Factory.aliases_for(:test).include?(:test_id)
15
+ end
16
+
17
+ context "after adding an alias" do
18
+
19
+ setup do
20
+ Factory.alias(/(.*)_suffix/, '\1')
21
+ end
22
+
23
+ should "return the alias in the aliases list" do
24
+ assert Factory.aliases_for(:test_suffix).include?(:test)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,32 @@
1
+ require(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class AttributeTest < Test::Unit::TestCase
4
+
5
+ context "an attribute" do
6
+ setup do
7
+ @name = :user
8
+ @attr = Factory::Attribute.new(@name)
9
+ end
10
+
11
+ should "have a name" do
12
+ assert_equal @name, @attr.name
13
+ end
14
+
15
+ should "do nothing when being added to a proxy" do
16
+ @proxy = mock('proxy')
17
+ @proxy.expects(:set).never
18
+ @attr.add_to(@proxy)
19
+ end
20
+ end
21
+
22
+ should "raise an error when defining an attribute writer" do
23
+ assert_raise Factory::AttributeDefinitionError do
24
+ Factory::Attribute.new('test=')
25
+ end
26
+ end
27
+
28
+ should "convert names to symbols" do
29
+ assert_equal :name, Factory::Attribute.new('name').name
30
+ end
31
+
32
+ end
@@ -0,0 +1,410 @@
1
+ require(File.join(File.dirname(__FILE__), 'test_helper'))
2
+
3
+ class FactoryTest < Test::Unit::TestCase
4
+
5
+ context "defining a factory" do
6
+ setup do
7
+ @name = :user
8
+ @factory = mock('factory')
9
+ @factory.stubs(:factory_name).returns(@name)
10
+ @options = { :class => 'magic' }
11
+ Factory.stubs(:new).returns(@factory)
12
+ end
13
+
14
+ should "create a new factory using the specified name and options" do
15
+ Factory.expects(:new).with(@name, @options).returns(@factory)
16
+ Factory.define(@name, @options) {|f| }
17
+ end
18
+
19
+ should "pass the factory do the block" do
20
+ yielded = nil
21
+ Factory.define(@name) do |y|
22
+ yielded = y
23
+ end
24
+ assert_equal @factory, yielded
25
+ end
26
+
27
+ should "add the factory to the list of factories" do
28
+ Factory.define(@name) {|f| }
29
+ assert_equal Factory.factories[@name],
30
+ @factory,
31
+ "Factories: #{Factory.factories.inspect}"
32
+ end
33
+ end
34
+
35
+ context "a factory" do
36
+ setup do
37
+ @name = :user
38
+ @class = User
39
+ @factory = Factory.new(@name)
40
+ end
41
+
42
+ should "have a factory name" do
43
+ assert_equal @name, @factory.factory_name
44
+ end
45
+
46
+ should "have a build class" do
47
+ assert_equal @class, @factory.build_class
48
+ end
49
+
50
+ should "not allow the same attribute to be added twice" do
51
+ assert_raise(Factory::AttributeDefinitionError) do
52
+ 2.times { @factory.add_attribute :first_name }
53
+ end
54
+ end
55
+
56
+ should "add a static attribute when an attribute is defined with a value" do
57
+ attribute = mock('attribute', :name => :name)
58
+ Factory::Attribute::Static.
59
+ expects(:new).
60
+ with(:name, 'value').
61
+ returns(attribute)
62
+ @factory.add_attribute(:name, 'value')
63
+ end
64
+
65
+ should "add a dynamic attribute when an attribute is defined with a block" do
66
+ attribute = mock('attribute', :name => :name)
67
+ block = lambda {}
68
+ Factory::Attribute::Dynamic.
69
+ expects(:new).
70
+ with(:name, block).
71
+ returns(attribute)
72
+ @factory.add_attribute(:name, &block)
73
+ end
74
+
75
+ should "raise for an attribute with a value and a block" do
76
+ assert_raise(Factory::AttributeDefinitionError) do
77
+ @factory.add_attribute(:name, 'value') {}
78
+ end
79
+ end
80
+
81
+ context "after adding an attribute" do
82
+ setup do
83
+ @attribute = mock('attribute')
84
+ @proxy = mock('proxy')
85
+
86
+ @attribute. stubs(:name). returns(:name)
87
+ @attribute. stubs(:add_to)
88
+ @proxy. stubs(:set)
89
+ @proxy. stubs(:result).returns('result')
90
+ Factory::Attribute::Static.stubs(:new). returns(@attribute)
91
+ Factory::Proxy::Build. stubs(:new). returns(@proxy)
92
+
93
+ @factory.add_attribute(:name, 'value')
94
+ end
95
+
96
+ should "create the right proxy using the build class when running" do
97
+ Factory::Proxy::Build.
98
+ expects(:new).
99
+ with(@factory.build_class).
100
+ returns(@proxy)
101
+ @factory.run(Factory::Proxy::Build, {})
102
+ end
103
+
104
+ should "add the attribute to the proxy when running" do
105
+ @attribute.expects(:add_to).with(@proxy)
106
+ @factory.run(Factory::Proxy::Build, {})
107
+ end
108
+
109
+ should "return the result from the proxy when running" do
110
+ @proxy.expects(:result).with().returns('result')
111
+ assert_equal 'result',
112
+ @factory.run(Factory::Proxy::Build, {})
113
+ end
114
+ end
115
+
116
+ should "add an association without a factory name or overrides" do
117
+ factory = Factory.new(:post)
118
+ name = :user
119
+ attr = 'attribute'
120
+ Factory::Attribute::Association.
121
+ expects(:new).
122
+ with(name, name, {}).
123
+ returns(attr)
124
+ factory.association(name)
125
+ assert factory.attributes.include?(attr)
126
+ end
127
+
128
+ should "add an association with overrides" do
129
+ factory = Factory.new(:post)
130
+ name = :user
131
+ attr = 'attribute'
132
+ overrides = { :first_name => 'Ben' }
133
+ Factory::Attribute::Association.
134
+ expects(:new).
135
+ with(name, name, overrides).
136
+ returns(attr)
137
+ factory.association(name, overrides)
138
+ assert factory.attributes.include?(attr)
139
+ end
140
+
141
+ should "add an association with a factory name" do
142
+ factory = Factory.new(:post)
143
+ attr = 'attribute'
144
+ Factory::Attribute::Association.
145
+ expects(:new).
146
+ with(:author, :user, {}).
147
+ returns(attr)
148
+ factory.association(:author, :factory => :user)
149
+ assert factory.attributes.include?(attr)
150
+ end
151
+
152
+ should "add an association with a factory name and overrides" do
153
+ factory = Factory.new(:post)
154
+ attr = 'attribute'
155
+ Factory::Attribute::Association.
156
+ expects(:new).
157
+ with(:author, :user, :first_name => 'Ben').
158
+ returns(attr)
159
+ factory.association(:author, :factory => :user, :first_name => 'Ben')
160
+ assert factory.attributes.include?(attr)
161
+ end
162
+
163
+ should "add an attribute using the method name when passed an undefined method" do
164
+ attr = mock('attribute', :name => :name)
165
+ block = lambda {}
166
+ Factory::Attribute::Static.
167
+ expects(:new).
168
+ with(:name, 'value').
169
+ returns(attr)
170
+ @factory.send(:name, 'value')
171
+ assert @factory.attributes.include?(attr)
172
+ end
173
+
174
+ context "when overriding generated attributes with a hash" do
175
+ setup do
176
+ @attr = :name
177
+ @value = 'The price is right!'
178
+ @hash = { @attr => @value }
179
+ end
180
+
181
+ should "return the overridden value in the generated attributes" do
182
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
183
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
184
+ assert_equal @value, result[@attr]
185
+ end
186
+
187
+ should "not call a lazy attribute block for an overridden attribute" do
188
+ @factory.add_attribute(@attr) { flunk }
189
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
190
+ end
191
+
192
+ should "override a symbol parameter with a string parameter" do
193
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
194
+ @hash = { @attr.to_s => @value }
195
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
196
+ assert_equal @value, result[@attr]
197
+ end
198
+ end
199
+
200
+ context "overriding an attribute with an alias" do
201
+ setup do
202
+ @factory.add_attribute(:test, 'original')
203
+ Factory.alias(/(.*)_alias/, '\1')
204
+ @result = @factory.run(Factory::Proxy::AttributesFor,
205
+ :test_alias => 'new')
206
+ end
207
+
208
+ should "use the passed in value for the alias" do
209
+ assert_equal 'new', @result[:test_alias]
210
+ end
211
+
212
+ should "discard the predefined value for the attribute" do
213
+ assert_nil @result[:test]
214
+ end
215
+ end
216
+
217
+ should "guess the build class from the factory name" do
218
+ assert_equal User, @factory.build_class
219
+ end
220
+
221
+ context "when defined with a custom class" do
222
+ setup do
223
+ @class = User
224
+ @factory = Factory.new(:author, :class => @class)
225
+ end
226
+
227
+ should "use the specified class as the build class" do
228
+ assert_equal @class, @factory.build_class
229
+ end
230
+ end
231
+
232
+ context "when defined with a class instead of a name" do
233
+ setup do
234
+ @class = ArgumentError
235
+ @name = :argument_error
236
+ @factory = Factory.new(@class)
237
+ end
238
+
239
+ should "guess the name from the class" do
240
+ assert_equal @name, @factory.factory_name
241
+ end
242
+
243
+ should "use the class as the build class" do
244
+ assert_equal @class, @factory.build_class
245
+ end
246
+ end
247
+
248
+ context "when defined with a custom class name" do
249
+ setup do
250
+ @class = ArgumentError
251
+ @factory = Factory.new(:author, :class => :argument_error)
252
+ end
253
+
254
+ should "use the specified class as the build class" do
255
+ assert_equal @class, @factory.build_class
256
+ end
257
+ end
258
+ end
259
+
260
+ context "a factory with a name ending in s" do
261
+ setup do
262
+ @name = :business
263
+ @class = Business
264
+ @factory = Factory.new(@name)
265
+ end
266
+
267
+ should "have a factory name" do
268
+ assert_equal @name, @factory.factory_name
269
+ end
270
+
271
+ should "have a build class" do
272
+ assert_equal @class, @factory.build_class
273
+ end
274
+ end
275
+
276
+ context "a factory with a string for a name" do
277
+ setup do
278
+ @name = :user
279
+ @factory = Factory.new(@name.to_s) {}
280
+ end
281
+
282
+ should "convert the string to a symbol" do
283
+ assert_equal @name, @factory.factory_name
284
+ end
285
+ end
286
+
287
+ context "a factory defined with a string name" do
288
+ setup do
289
+ Factory.factories = {}
290
+ @name = :user
291
+ @factory = Factory.define(@name.to_s) {}
292
+ end
293
+
294
+ should "store the factory using a symbol" do
295
+ assert_equal @factory, Factory.factories[@name]
296
+ end
297
+ end
298
+
299
+ context "after defining a factory" do
300
+ setup do
301
+ @name = :user
302
+ @factory = mock('factory')
303
+
304
+ Factory.factories[@name] = @factory
305
+ end
306
+
307
+ teardown { Factory.factories.clear }
308
+
309
+ should "use Proxy::AttributesFor for Factory.attributes_for" do
310
+ @factory.
311
+ expects(:run).
312
+ with(Factory::Proxy::AttributesFor, :attr => 'value').
313
+ returns('result')
314
+ assert_equal 'result', Factory.attributes_for(@name, :attr => 'value')
315
+ end
316
+
317
+ should "use Proxy::Build for Factory.build" do
318
+ @factory.
319
+ expects(:run).
320
+ with(Factory::Proxy::Build, :attr => 'value').
321
+ returns('result')
322
+ assert_equal 'result', Factory.build(@name, :attr => 'value')
323
+ end
324
+
325
+ should "use Proxy::Create for Factory.create" do
326
+ @factory.
327
+ expects(:run).
328
+ with(Factory::Proxy::Create, :attr => 'value').
329
+ returns('result')
330
+ assert_equal 'result', Factory.create(@name, :attr => 'value')
331
+ end
332
+
333
+ should "use Proxy::Create for the global Factory method" do
334
+ @factory.
335
+ expects(:run).
336
+ with(Factory::Proxy::Create, :attr => 'value').
337
+ returns('result')
338
+ assert_equal 'result', Factory(@name, :attr => 'value')
339
+ end
340
+
341
+ [:build, :create, :attributes_for].each do |method|
342
+ should "raise an ArgumentError on #{method} with a nonexistant factory" do
343
+ assert_raise(ArgumentError) { Factory.send(method, :bogus) }
344
+ end
345
+
346
+ should "recognize either 'name' or :name for Factory.#{method}" do
347
+ @factory.stubs(:run)
348
+ assert_nothing_raised { Factory.send(method, @name.to_s) }
349
+ assert_nothing_raised { Factory.send(method, @name.to_sym) }
350
+ end
351
+ end
352
+ end
353
+
354
+ def self.context_in_directory_with_files(*files)
355
+ context "in a directory with #{files.to_sentence}" do
356
+ setup do
357
+ @pwd = Dir.pwd
358
+ @tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
359
+ FileUtils.mkdir_p @tmp_dir
360
+ Dir.chdir(@tmp_dir)
361
+
362
+ files.each do |file|
363
+ FileUtils.mkdir_p File.dirname(file)
364
+ FileUtils.touch file
365
+ Factory.stubs(:require).with(file)
366
+ end
367
+ end
368
+
369
+ teardown do
370
+ Dir.chdir(@pwd)
371
+ FileUtils.rm_rf(@tmp_dir)
372
+ end
373
+
374
+ yield
375
+ end
376
+ end
377
+
378
+ def self.should_require_definitions_from(file)
379
+ should "load definitions from #{file}" do
380
+ Factory.expects(:require).with(file)
381
+ Factory.find_definitions
382
+ end
383
+ end
384
+
385
+ context_in_directory_with_files 'factories.rb' do
386
+ should_require_definitions_from 'factories.rb'
387
+ end
388
+
389
+ %w(spec test).each do |dir|
390
+ context_in_directory_with_files File.join(dir, 'factories.rb') do
391
+ should_require_definitions_from "#{dir}/factories.rb"
392
+ end
393
+
394
+ context_in_directory_with_files File.join(dir, 'factories', 'post_factory.rb') do
395
+ should_require_definitions_from "#{dir}/factories/post_factory.rb"
396
+ end
397
+
398
+ context_in_directory_with_files File.join(dir, 'factories', 'post_factory.rb'), File.join(dir, 'factories', 'person_factory.rb') do
399
+ should_require_definitions_from "#{dir}/factories/post_factory.rb"
400
+ should_require_definitions_from "#{dir}/factories/person_factory.rb"
401
+ end
402
+
403
+ context_in_directory_with_files File.join(dir, 'factories.rb'), File.join(dir, 'factories', 'post_factory.rb'), File.join(dir, 'factories', 'person_factory.rb') do
404
+ should_require_definitions_from "#{dir}/factories.rb"
405
+ should_require_definitions_from "#{dir}/factories/post_factory.rb"
406
+ should_require_definitions_from "#{dir}/factories/person_factory.rb"
407
+ end
408
+ end
409
+
410
+ end