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,196 @@
1
+ module FactoryGirl
2
+ module Syntax
3
+ module Vintage
4
+ module Factory
5
+ # Defines a new factory that can be used by the build strategies (create and
6
+ # build) to build new objects.
7
+ #
8
+ # Arguments:
9
+ # * name: +Symbol+ or +String+
10
+ # A unique name used to identify this factory.
11
+ # * options: +Hash+
12
+ #
13
+ # Options:
14
+ # * class: +Symbol+, +Class+, or +String+
15
+ # The class that will be used when generating instances for this factory. If not specified, the class will be guessed from the factory name.
16
+ # * parent: +Symbol+
17
+ # The parent factory. If specified, the attributes from the parent
18
+ # factory will be copied to the current one with an ability to override
19
+ # them.
20
+ # * default_strategy: +Symbol+
21
+ # The strategy that will be used by the Factory shortcut method.
22
+ # Defaults to :create.
23
+ #
24
+ # Yields: +Factory+
25
+ # The newly created factory.
26
+ def self.define(name, options = {})
27
+ factory = FactoryGirl::Factory.new(name, options)
28
+ proxy = FactoryGirl::DefinitionProxy.new(factory)
29
+ yield(proxy)
30
+ if parent = options.delete(:parent)
31
+ factory.inherit_from(FactoryGirl.factory_by_name(parent))
32
+ end
33
+ FactoryGirl.register_factory(factory)
34
+ end
35
+
36
+ # Generates and returns a Hash of attributes from this factory. Attributes
37
+ # can be individually overridden by passing in a Hash of attribute => value
38
+ # pairs.
39
+ #
40
+ # Arguments:
41
+ # * name: +Symbol+ or +String+
42
+ # The name of the factory that should be used.
43
+ # * overrides: +Hash+
44
+ # Attributes to overwrite for this set.
45
+ #
46
+ # Returns: +Hash+
47
+ # A set of attributes that can be used to build an instance of the class
48
+ # this factory generates.
49
+ def self.attributes_for(name, overrides = {})
50
+ FactoryGirl.factory_by_name(name).run(Proxy::AttributesFor, overrides)
51
+ end
52
+
53
+ # Generates and returns an instance from this factory. Attributes can be
54
+ # individually overridden by passing in a Hash of attribute => value pairs.
55
+ #
56
+ # Arguments:
57
+ # * name: +Symbol+ or +String+
58
+ # The name of the factory that should be used.
59
+ # * overrides: +Hash+
60
+ # Attributes to overwrite for this instance.
61
+ #
62
+ # Returns: +Object+
63
+ # An instance of the class this factory generates, with generated attributes
64
+ # assigned.
65
+ def self.build(name, overrides = {})
66
+ FactoryGirl.factory_by_name(name).run(Proxy::Build, overrides)
67
+ end
68
+
69
+ # Generates, saves, and returns an instance from this factory. Attributes can
70
+ # be individually overridden by passing in a Hash of attribute => value
71
+ # pairs.
72
+ #
73
+ # Instances are saved using the +save!+ method, so ActiveRecord models will
74
+ # raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
75
+ #
76
+ # Arguments:
77
+ # * name: +Symbol+ or +String+
78
+ # The name of the factory that should be used.
79
+ # * overrides: +Hash+
80
+ # Attributes to overwrite for this instance.
81
+ #
82
+ # Returns: +Object+
83
+ # A saved instance of the class this factory generates, with generated
84
+ # attributes assigned.
85
+ def self.create(name, overrides = {})
86
+ FactoryGirl.factory_by_name(name).run(Proxy::Create, overrides)
87
+ end
88
+
89
+ # Generates and returns an object with all attributes from this factory
90
+ # stubbed out. Attributes can be individually overridden by passing in a Hash
91
+ # of attribute => value pairs.
92
+ #
93
+ # Arguments:
94
+ # * name: +Symbol+ or +String+
95
+ # The name of the factory that should be used.
96
+ # * overrides: +Hash+
97
+ # Attributes to overwrite for this instance.
98
+ #
99
+ # Returns: +Object+
100
+ # An object with generated attributes stubbed out.
101
+ def self.stub(name, overrides = {})
102
+ FactoryGirl.factory_by_name(name).run(Proxy::Stub, overrides)
103
+ end
104
+
105
+ # Executes the default strategy for the given factory. This is usually create,
106
+ # but it can be overridden for each factory.
107
+ #
108
+ # Arguments:
109
+ # * name: +Symbol+ or +String+
110
+ # The name of the factory that should be used.
111
+ # * overrides: +Hash+
112
+ # Attributes to overwrite for this instance.
113
+ #
114
+ # Returns: +Object+
115
+ # The result of the default strategy.
116
+ def self.default_strategy(name, overrides = {})
117
+ self.send(FactoryGirl.factory_by_name(name).default_strategy, name, overrides)
118
+ end
119
+
120
+ # Defines a new sequence that can be used to generate unique values in a specific format.
121
+ #
122
+ # Arguments:
123
+ # name: (Symbol)
124
+ # A unique name for this sequence. This name will be referenced when
125
+ # calling next to generate new values from this sequence.
126
+ # block: (Proc)
127
+ # The code to generate each value in the sequence. This block will be
128
+ # called with a unique number each time a value in the sequence is to be
129
+ # generated. The block should return the generated value for the
130
+ # sequence.
131
+ #
132
+ # Example:
133
+ #
134
+ # Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
135
+ def self.sequence(name, start_value = 1, &block)
136
+ FactoryGirl.sequences[name] = Sequence.new(start_value, &block)
137
+ end
138
+
139
+ # Generates and returns the next value in a sequence.
140
+ #
141
+ # Arguments:
142
+ # name: (Symbol)
143
+ # The name of the sequence that a value should be generated for.
144
+ #
145
+ # Returns:
146
+ # The next value in the sequence. (Object)
147
+ def self.next(sequence)
148
+ unless FactoryGirl.sequences.key?(sequence)
149
+ raise "No such sequence: #{sequence}"
150
+ end
151
+
152
+ FactoryGirl.sequences[sequence].next
153
+ end
154
+
155
+ # Defines a new alias for attributes.
156
+ #
157
+ # Arguments:
158
+ # * pattern: +Regexp+
159
+ # A pattern that will be matched against attributes when looking for
160
+ # aliases. Contents captured in the pattern can be used in the alias.
161
+ # * replace: +String+
162
+ # The alias that results from the matched pattern. Captured strings can
163
+ # be substituted like with +String#sub+.
164
+ #
165
+ # Example:
166
+ #
167
+ # Factory.alias /(.*)_confirmation/, '\1'
168
+ #
169
+ # factory_girl starts with aliases for foreign keys, so that a :user
170
+ # association can be overridden by a :user_id parameter:
171
+ #
172
+ # Factory.define :post do |p|
173
+ # p.association :user
174
+ # end
175
+ #
176
+ # # The user association will not be built in this example. The user_id
177
+ # # will be used instead.
178
+ # Factory(:post, :user_id => 1)
179
+ def self.alias(pattern, replace)
180
+ FactoryGirl.aliases << [pattern, replace]
181
+ end
182
+
183
+ end
184
+
185
+ # Shortcut for Factory.default_strategy.
186
+ #
187
+ # Example:
188
+ # Factory(:user, :name => 'Joe')
189
+ def Factory(name, attrs = {})
190
+ Factory.default_strategy(name, attrs)
191
+ end
192
+ end
193
+ end
194
+ end
195
+
196
+ include FactoryGirl::Syntax::Vintage
@@ -0,0 +1,4 @@
1
+ module FactoryGirl
2
+ VERSION = "2.0.0.beta1"
3
+ end
4
+
@@ -3,61 +3,60 @@ require 'acceptance/acceptance_helper'
3
3
 
4
4
  describe "integration" do
5
5
  before do
6
- Factory.define :user, :class => 'user' do |f|
7
- f.first_name 'Jimi'
8
- f.last_name 'Hendrix'
9
- f.admin false
10
- f.email {|a| "#{a.first_name}.#{a.last_name}@example.com".downcase }
11
- end
6
+ FactoryGirl.define do
7
+ sequence :email do |n|
8
+ "somebody#{n}@example.com"
9
+ end
12
10
 
13
- Factory.define Post, :default_strategy => :attributes_for do |f|
14
- f.name 'Test Post'
15
- f.association :author, :factory => :user
16
- end
11
+ factory :user, :class => 'user' do
12
+ first_name 'Jimi'
13
+ last_name 'Hendrix'
14
+ admin false
15
+ email { "#{first_name}.#{last_name}@example.com".downcase }
17
16
 
18
- Factory.define :admin, :class => User do |f|
19
- f.first_name 'Ben'
20
- f.last_name 'Stein'
21
- f.admin true
22
- f.sequence(:username) { |n| "username#{n}" }
23
- f.email { Factory.next(:email) }
24
- end
17
+ aliased_as :author
18
+ end
25
19
 
26
- Factory.define :sequence_abuser, :class => User do |f|
27
- f.first_name { Factory.sequence(:email) }
28
- end
20
+ factory Post, :default_strategy => :attributes_for do
21
+ name 'Test Post'
22
+ author
23
+ end
29
24
 
30
- Factory.define :guest, :parent => :user do |f|
31
- f.last_name 'Anonymous'
32
- f.username 'GuestUser'
33
- end
25
+ factory :admin, :class => User do
26
+ first_name 'Ben'
27
+ last_name 'Stein'
28
+ admin true
29
+ sequence(:username) { |n| "username#{n}" }
30
+ email
31
+ end
34
32
 
35
- Factory.define :user_with_callbacks, :parent => :user do |f|
36
- f.after_stub {|u| u.first_name = 'Stubby' }
37
- f.after_build {|u| u.first_name = 'Buildy' }
38
- f.after_create {|u| u.last_name = 'Createy' }
39
- end
33
+ factory :sequence_abuser, :class => User do
34
+ first_name { Factory.sequence(:email) }
35
+ end
40
36
 
41
- Factory.define :user_with_inherited_callbacks, :parent => :user_with_callbacks do |f|
42
- f.callback(:after_stub) {|u| u.last_name = 'Double-Stubby' }
43
- end
37
+ factory :guest, :parent => :user do
38
+ last_name 'Anonymous'
39
+ username 'GuestUser'
40
+ end
44
41
 
45
- Factory.define :business do |f|
46
- f.name 'Supplier of Awesome'
47
- f.association :owner, :factory => :user
48
- end
42
+ factory :user_with_callbacks, :parent => :user do
43
+ after_stub {|u| u.first_name = 'Stubby' }
44
+ after_build {|u| u.first_name = 'Buildy' }
45
+ after_create {|u| u.last_name = 'Createy' }
46
+ end
49
47
 
50
- Factory.sequence :email do |n|
51
- "somebody#{n}@example.com"
52
- end
53
- end
48
+ factory :user_with_inherited_callbacks, :parent => :user_with_callbacks do
49
+ after_stub {|u| u.last_name = 'Double-Stubby' }
50
+ end
54
51
 
55
- after do
56
- Factory.factories.clear
52
+ factory :business do
53
+ name 'Supplier of Awesome'
54
+ association :owner, :factory => :user
55
+ end
56
+ end
57
57
  end
58
58
 
59
59
  describe "a generated attributes hash" do
60
-
61
60
  before do
62
61
  @attrs = Factory.attributes_for(:user, :first_name => 'Bill')
63
62
  end
@@ -79,11 +78,9 @@ describe "integration" do
79
78
  it "should not assign associations" do
80
79
  Factory.attributes_for(:post)[:author].should be_nil
81
80
  end
82
-
83
81
  end
84
82
 
85
83
  describe "a built instance" do
86
-
87
84
  before do
88
85
  @instance = Factory.build(:post)
89
86
  end
@@ -103,11 +100,9 @@ describe "integration" do
103
100
  it "should not assign both an association and its foreign key" do
104
101
  Factory.build(:post, :author_id => 1).author_id.should == 1
105
102
  end
106
-
107
103
  end
108
104
 
109
105
  describe "a created instance" do
110
-
111
106
  before do
112
107
  @instance = Factory.create('post')
113
108
  end
@@ -123,11 +118,9 @@ describe "integration" do
123
118
  it "should save associations" do
124
119
  @instance.author.should_not be_new_record
125
120
  end
126
-
127
121
  end
128
122
 
129
123
  describe "a generated stub instance" do
130
-
131
124
  before do
132
125
  @stub = Factory.stub(:user, :first_name => 'Bill')
133
126
  end
@@ -174,7 +167,6 @@ describe "integration" do
174
167
  end
175
168
 
176
169
  describe "an instance generated by a factory with a custom class name" do
177
-
178
170
  before do
179
171
  @instance = Factory.create(:admin)
180
172
  end
@@ -186,7 +178,6 @@ describe "integration" do
186
178
  it "should use the correct factory definition" do
187
179
  @instance.should be_admin
188
180
  end
189
-
190
181
  end
191
182
 
192
183
  describe "an instance generated by a factory that inherits from another factory" do
@@ -212,7 +203,6 @@ describe "integration" do
212
203
  end
213
204
 
214
205
  describe "an attribute generated by a sequence" do
215
-
216
206
  before do
217
207
  @email = Factory.attributes_for(:admin)[:email]
218
208
  end
@@ -222,7 +212,6 @@ describe "integration" do
222
212
  end
223
213
 
224
214
  describe "after the attribute has already been generated once" do
225
-
226
215
  before do
227
216
  @another_email = Factory.attributes_for(:admin)[:email]
228
217
  end
@@ -234,13 +223,10 @@ describe "integration" do
234
223
  it "should not be the same as the first generated value" do
235
224
  @another_email.should_not == @email
236
225
  end
237
-
238
226
  end
239
-
240
227
  end
241
228
 
242
229
  describe "an attribute generated by an in-line sequence" do
243
-
244
230
  before do
245
231
  @username = Factory.attributes_for(:admin)[:username]
246
232
  end
@@ -250,7 +236,6 @@ describe "integration" do
250
236
  end
251
237
 
252
238
  describe "after the attribute has already been generated once" do
253
-
254
239
  before do
255
240
  @another_username = Factory.attributes_for(:admin)[:username]
256
241
  end
@@ -262,9 +247,7 @@ describe "integration" do
262
247
  it "should not be the same as the first generated value" do
263
248
  @another_username.should_not == @username
264
249
  end
265
-
266
250
  end
267
-
268
251
  end
269
252
 
270
253
  describe "a factory with a default strategy specified" do
@@ -276,7 +259,7 @@ describe "integration" do
276
259
  it "should raise Factory::SequenceAbuseError" do
277
260
  lambda {
278
261
  Factory(:sequence_abuser)
279
- }.should raise_error(Factory::SequenceAbuseError)
262
+ }.should raise_error(FactoryGirl::SequenceAbuseError)
280
263
  end
281
264
 
282
265
  describe "an instance with callbacks" do
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'acceptance/acceptance_helper'
2
3
 
3
4
  require 'factory_girl/syntax/blueprint'
4
5
 
@@ -12,11 +13,6 @@ describe "a blueprint" do
12
13
  end
13
14
  end
14
15
 
15
- after do
16
- Factory.factories.clear
17
- Factory.sequences.clear
18
- end
19
-
20
16
  describe "after making an instance" do
21
17
  before do
22
18
  @instance = Factory(:user, :last_name => 'Rye')
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'acceptance/acceptance_helper'
2
3
 
3
4
  require 'factory_girl/syntax/generate'
4
5
 
@@ -11,10 +12,6 @@ describe "a factory using generate syntax" do
11
12
  end
12
13
  end
13
14
 
14
- after do
15
- Factory.factories.clear
16
- end
17
-
18
15
  it "should not raise an error when generating an invalid instance" do
19
16
  lambda { User.generate(:first_name => nil) }.should_not raise_error
20
17
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'acceptance/acceptance_helper'
2
3
 
3
4
  require 'factory_girl/syntax/make'
4
5
 
@@ -11,10 +12,6 @@ describe "a factory using make syntax" do
11
12
  end
12
13
  end
13
14
 
14
- after do
15
- Factory.factories.clear
16
- end
17
-
18
15
  describe "after making an instance" do
19
16
  before do
20
17
  @instance = User.make(:last_name => 'Rye')