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.
- data/README.rdoc +68 -60
- data/features/support/test.db +0 -0
- data/lib/factory_girl.rb +6 -12
- data/lib/factory_girl/aliases.rb +2 -31
- data/lib/factory_girl/attribute.rb +1 -1
- data/lib/factory_girl/attribute/association.rb +1 -1
- data/lib/factory_girl/attribute/callback.rb +1 -1
- data/lib/factory_girl/attribute/dynamic.rb +3 -3
- data/lib/factory_girl/attribute/static.rb +1 -1
- data/lib/factory_girl/definition_proxy.rb +180 -0
- data/lib/factory_girl/deprecated.rb +18 -0
- data/lib/factory_girl/factory.rb +120 -355
- data/lib/factory_girl/find_definitions.rb +25 -0
- data/lib/factory_girl/proxy.rb +4 -6
- data/lib/factory_girl/proxy/attributes_for.rb +1 -1
- data/lib/factory_girl/proxy/build.rb +7 -5
- data/lib/factory_girl/proxy/create.rb +1 -1
- data/lib/factory_girl/proxy/stub.rb +11 -5
- data/lib/factory_girl/rails2.rb +1 -1
- data/lib/factory_girl/sequence.rb +5 -40
- data/lib/factory_girl/step_definitions.rb +7 -7
- data/lib/factory_girl/syntax.rb +7 -7
- data/lib/factory_girl/syntax/blueprint.rb +5 -4
- data/lib/factory_girl/syntax/default.rb +31 -0
- data/lib/factory_girl/syntax/generate.rb +13 -8
- data/lib/factory_girl/syntax/make.rb +8 -6
- data/lib/factory_girl/syntax/sham.rb +11 -8
- data/lib/factory_girl/syntax/vintage.rb +196 -0
- data/lib/factory_girl/version.rb +4 -0
- data/spec/acceptance/acceptance_spec.rb +43 -60
- data/spec/acceptance/syntax/blueprint_spec.rb +1 -5
- data/spec/acceptance/syntax/generate_spec.rb +1 -4
- data/spec/acceptance/syntax/make_spec.rb +1 -4
- data/spec/acceptance/syntax/sham_spec.rb +9 -7
- data/spec/acceptance/syntax/vintage_spec.rb +184 -0
- data/spec/factory_girl/aliases_spec.rb +5 -5
- data/spec/factory_girl/attribute/association_spec.rb +3 -3
- data/spec/factory_girl/attribute/callback_spec.rb +3 -3
- data/spec/factory_girl/attribute/dynamic_spec.rb +20 -9
- data/spec/factory_girl/attribute/static_spec.rb +5 -5
- data/spec/factory_girl/attribute_spec.rb +5 -5
- data/spec/factory_girl/definition_proxy_spec.rb +138 -0
- data/spec/factory_girl/deprecated_spec.rb +66 -0
- data/spec/factory_girl/factory_spec.rb +283 -566
- data/spec/factory_girl/find_definitions_spec.rb +89 -0
- data/spec/factory_girl/proxy/attributes_for_spec.rb +2 -2
- data/spec/factory_girl/proxy/build_spec.rb +17 -12
- data/spec/factory_girl/proxy/create_spec.rb +17 -12
- data/spec/factory_girl/proxy/stub_spec.rb +6 -5
- data/spec/factory_girl/proxy_spec.rb +2 -2
- data/spec/factory_girl/sequence_spec.rb +15 -38
- data/spec/spec_helper.rb +4 -0
- 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
|
@@ -3,61 +3,60 @@ require 'acceptance/acceptance_helper'
|
|
3
3
|
|
4
4
|
describe "integration" do
|
5
5
|
before do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
19
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
20
|
+
factory Post, :default_strategy => :attributes_for do
|
21
|
+
name 'Test Post'
|
22
|
+
author
|
23
|
+
end
|
29
24
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
37
|
+
factory :guest, :parent => :user do
|
38
|
+
last_name 'Anonymous'
|
39
|
+
username 'GuestUser'
|
40
|
+
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
56
|
-
|
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(
|
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')
|