factory_girl 2.0.0.beta1 → 2.0.0.beta2

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 (63) hide show
  1. data/Appraisals +12 -0
  2. data/{CONTRIBUTION_GUIDELINES.rdoc → CONTRIBUTION_GUIDELINES.md} +3 -3
  3. data/GETTING_STARTED.md +246 -0
  4. data/Gemfile +12 -0
  5. data/Gemfile.lock +62 -0
  6. data/README.md +64 -0
  7. data/Rakefile +15 -30
  8. data/features/factory_girl_steps.feature +26 -0
  9. data/features/step_definitions/database_steps.rb +2 -0
  10. data/features/support/env.rb +0 -9
  11. data/features/support/factories.rb +15 -0
  12. data/features/support/test.db +0 -0
  13. data/lib/factory_girl.rb +2 -0
  14. data/lib/factory_girl/definition_proxy.rb +10 -43
  15. data/lib/factory_girl/factory.rb +48 -17
  16. data/lib/factory_girl/proxy.rb +3 -3
  17. data/lib/factory_girl/proxy/attributes_for.rb +1 -1
  18. data/lib/factory_girl/proxy/build.rb +3 -3
  19. data/lib/factory_girl/proxy/create.rb +6 -2
  20. data/lib/factory_girl/proxy/stub.rb +3 -3
  21. data/lib/factory_girl/registry.rb +59 -0
  22. data/lib/factory_girl/sequence.rb +23 -9
  23. data/lib/factory_girl/step_definitions.rb +16 -9
  24. data/lib/factory_girl/syntax/blueprint.rb +2 -2
  25. data/lib/factory_girl/syntax/default.rb +5 -3
  26. data/lib/factory_girl/syntax/generate.rb +6 -6
  27. data/lib/factory_girl/syntax/make.rb +2 -2
  28. data/lib/factory_girl/syntax/methods.rb +75 -0
  29. data/lib/factory_girl/syntax/sham.rb +2 -2
  30. data/lib/factory_girl/syntax/vintage.rb +16 -79
  31. data/lib/factory_girl/version.rb +1 -1
  32. data/spec/acceptance/acceptance_helper.rb +7 -12
  33. data/spec/acceptance/attribute_aliases_spec.rb +26 -0
  34. data/spec/acceptance/attributes_for_spec.rb +48 -0
  35. data/spec/acceptance/build_spec.rb +35 -0
  36. data/spec/acceptance/build_stubbed_spec.rb +79 -0
  37. data/spec/acceptance/callbacks_spec.rb +42 -0
  38. data/spec/acceptance/create_spec.rb +67 -0
  39. data/spec/acceptance/default_strategy_spec.rb +27 -0
  40. data/spec/acceptance/definition_spec.rb +28 -0
  41. data/spec/acceptance/parent_spec.rb +39 -0
  42. data/spec/acceptance/sequence_spec.rb +32 -0
  43. data/spec/acceptance/syntax/blueprint_spec.rb +7 -5
  44. data/spec/acceptance/syntax/generate_spec.rb +10 -4
  45. data/spec/acceptance/syntax/make_spec.rb +7 -4
  46. data/spec/acceptance/syntax/sham_spec.rb +15 -8
  47. data/spec/acceptance/syntax/vintage_spec.rb +57 -17
  48. data/spec/factory_girl/attribute/dynamic_spec.rb +1 -1
  49. data/spec/factory_girl/definition_proxy_spec.rb +13 -11
  50. data/spec/factory_girl/factory_spec.rb +29 -52
  51. data/spec/factory_girl/find_definitions_spec.rb +34 -23
  52. data/spec/factory_girl/proxy/attributes_for_spec.rb +6 -6
  53. data/spec/factory_girl/proxy/build_spec.rb +4 -4
  54. data/spec/factory_girl/proxy/create_spec.rb +11 -3
  55. data/spec/factory_girl/proxy/stub_spec.rb +6 -6
  56. data/spec/factory_girl/proxy_spec.rb +1 -1
  57. data/spec/factory_girl/registry_spec.rb +92 -0
  58. data/spec/factory_girl/sequence_spec.rb +65 -8
  59. data/spec/spec_helper.rb +75 -29
  60. metadata +66 -43
  61. data/README.rdoc +0 -282
  62. data/spec/acceptance/acceptance_spec.rb +0 -288
  63. data/spec/acceptance/models.rb +0 -48
@@ -5,17 +5,19 @@ require 'factory_girl/syntax/blueprint'
5
5
 
6
6
  describe "a blueprint" do
7
7
  before do
8
+ define_model('User', :first_name => :string, :last_name => :string, :email => :string)
9
+
8
10
  Factory.sequence(:email) { |n| "somebody#{n}@example.com" }
9
11
  User.blueprint do
10
- first_name { 'Bill' }
11
- last_name { 'Nye' }
12
- email { Factory.next(:email) }
12
+ first_name { 'Bill' }
13
+ last_name { 'Nye' }
14
+ email { FactoryGirl.create(:email) }
13
15
  end
14
16
  end
15
17
 
16
18
  describe "after making an instance" do
17
19
  before do
18
- @instance = Factory(:user, :last_name => 'Rye')
20
+ @instance = FactoryGirl.create(:user, :last_name => 'Rye')
19
21
  end
20
22
 
21
23
  it "should use attributes from the blueprint" do
@@ -24,7 +26,7 @@ describe "a blueprint" do
24
26
 
25
27
  it "should evaluate attribute blocks for each instance" do
26
28
  @instance.email.should =~ /somebody\d+@example.com/
27
- Factory(:user).email.should_not == @instance.email
29
+ FactoryGirl.create(:user).email.should_not == @instance.email
28
30
  end
29
31
  end
30
32
  end
@@ -5,10 +5,16 @@ require 'factory_girl/syntax/generate'
5
5
 
6
6
  describe "a factory using generate syntax" do
7
7
  before do
8
- Factory.define :user do |factory|
9
- factory.first_name 'Bill'
10
- factory.last_name 'Nye'
11
- factory.email 'science@guys.net'
8
+ define_model('User', :first_name => :string, :last_name => :string, :email => :string) do
9
+ validates_presence_of :first_name
10
+ end
11
+
12
+ FactoryGirl.define do
13
+ factory :user do
14
+ first_name 'Bill'
15
+ last_name 'Nye'
16
+ email 'science@guys.net'
17
+ end
12
18
  end
13
19
  end
14
20
 
@@ -5,10 +5,13 @@ require 'factory_girl/syntax/make'
5
5
 
6
6
  describe "a factory using make syntax" do
7
7
  before do
8
- Factory.define :user do |factory|
9
- factory.first_name 'Bill'
10
- factory.last_name 'Nye'
11
- factory.email 'science@guys.net'
8
+ define_model('User', :first_name => :string, :last_name => :string)
9
+
10
+ FactoryGirl.define do
11
+ factory :user do
12
+ first_name 'Bill'
13
+ last_name 'Nye'
14
+ end
12
15
  end
13
16
  end
14
17
 
@@ -5,21 +5,28 @@ require 'factory_girl/syntax/sham'
5
5
 
6
6
  describe "a factory using sham syntax" do
7
7
  before do
8
+ define_model('User', :first_name => :string,
9
+ :last_name => :string,
10
+ :email => :string,
11
+ :username => :string)
12
+
8
13
  Sham.name { "Name" }
9
14
  Sham.email { "somebody#{rand(5)}@example.com" }
10
- Sham.user("FOO") { |c| "User-#{c}" }
15
+ Sham.username("FOO") { |c| "User-#{c}" }
11
16
 
12
- Factory.define :user do |factory|
13
- factory.first_name { Sham.name }
14
- factory.last_name { Sham.name }
15
- factory.email { Sham.email }
16
- factory.username { Sham.user }
17
+ FactoryGirl.define do
18
+ factory :user do
19
+ first_name { Sham.name }
20
+ last_name { Sham.name }
21
+ email { Sham.email }
22
+ username { Sham.username }
23
+ end
17
24
  end
18
25
  end
19
26
 
20
27
  describe "after making an instance" do
21
28
  before do
22
- @instance = Factory(:user, :last_name => 'Rye')
29
+ @instance = FactoryGirl.create(:user, :last_name => 'Rye')
23
30
  end
24
31
 
25
32
  it "should support a sham called 'name'" do
@@ -29,7 +36,7 @@ describe "a factory using sham syntax" do
29
36
  it "should support shams with starting values" do
30
37
  @instance.username.should == 'User-FOO'
31
38
  end
32
-
39
+
33
40
  it "should use the sham for the email" do
34
41
  @instance.email.should =~ /somebody\d@example.com/
35
42
  end
@@ -1,13 +1,17 @@
1
1
  require 'spec_helper'
2
2
  require 'acceptance/acceptance_helper'
3
3
 
4
- describe "default syntax" do
4
+ describe "vintage syntax" do
5
5
  before do
6
+ define_model('User', :first_name => :string,
7
+ :last_name => :string,
8
+ :email => :string)
9
+
6
10
  Factory.sequence(:email) { |n| "somebody#{n}@example.com" }
7
11
  Factory.define :user do |factory|
8
12
  factory.first_name { 'Bill' }
9
13
  factory.last_name { 'Nye' }
10
- factory.email { Factory.next(:email) }
14
+ factory.email { Factory(:email) }
11
15
  end
12
16
  end
13
17
 
@@ -31,13 +35,23 @@ describe "default syntax" do
31
35
  Factory.define(:object, :default_strategy => :nonexistent) {}
32
36
  }.should raise_error(ArgumentError)
33
37
  end
38
+
39
+ it "should raise Factory::SequenceAbuseError" do
40
+ Factory.define :sequence_abuser, :class => User do |factory|
41
+ factory.first_name { Factory.sequence(:name) }
42
+ end
43
+
44
+ lambda {
45
+ Factory(:sequence_abuser)
46
+ }.should raise_error(FactoryGirl::SequenceAbuseError)
47
+ end
34
48
  end
35
49
 
36
50
  describe Factory, "given a parent factory" do
37
51
  before do
38
52
  @parent = FactoryGirl::Factory.new(:object)
39
53
  @parent.define_attribute(FactoryGirl::Attribute::Static.new(:name, 'value'))
40
- FactoryGirl.register_factory(@parent)
54
+ FactoryGirl.register(@parent)
41
55
  end
42
56
 
43
57
  it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
@@ -52,7 +66,7 @@ describe "defining a factory" do
52
66
  @name = :user
53
67
  @factory = "factory"
54
68
  @proxy = "proxy"
55
- stub(@factory).name { @name }
69
+ stub(@factory).names { [@name] }
56
70
  @options = { :class => 'magic' }
57
71
  stub(FactoryGirl::Factory).new { @factory }
58
72
  stub(FactoryGirl::DefinitionProxy).new { @proxy }
@@ -73,21 +87,16 @@ describe "defining a factory" do
73
87
 
74
88
  it "should add the factory to the list of factories" do
75
89
  Factory.define(@name) {|f| }
76
- @factory.should == FactoryGirl.factories[@name]
77
- end
78
-
79
- it "should allow a factory to be found by name" do
80
- Factory.define(@name) {|f| }
81
- FactoryGirl.factory_by_name(@name).should == @factory
90
+ @factory.should == FactoryGirl.find(@name)
82
91
  end
83
92
  end
84
93
 
85
94
  describe "after defining a factory" do
86
95
  before do
87
96
  @name = :user
88
- @factory = "factory"
97
+ @factory = FactoryGirl::Factory.new(@name)
89
98
 
90
- FactoryGirl.factories[@name] = @factory
99
+ FactoryGirl.register(@factory)
91
100
  end
92
101
 
93
102
  it "should use Proxy::AttributesFor for Factory.attributes_for" do
@@ -137,33 +146,33 @@ end
137
146
 
138
147
  describe "defining a sequence" do
139
148
  before do
140
- @sequence = "sequence"
141
149
  @name = :count
150
+ @sequence = FactoryGirl::Sequence.new(@name) {}
142
151
  stub(FactoryGirl::Sequence).new { @sequence }
143
152
  end
144
153
 
145
154
  it "should create a new sequence" do
146
- mock(FactoryGirl::Sequence).new(1) { @sequence }
155
+ mock(FactoryGirl::Sequence).new(@name, 1) { @sequence }
147
156
  Factory.sequence(@name)
148
157
  end
149
158
 
150
159
  it "should use the supplied block as the sequence generator" do
151
- stub(FactoryGirl::Sequence).new.yields(1)
160
+ stub(FactoryGirl::Sequence).new { @sequence }.yields(1)
152
161
  yielded = false
153
162
  Factory.sequence(@name) {|n| yielded = true }
154
163
  (yielded).should be
155
164
  end
156
165
 
157
166
  it "should use the supplied start_value as the sequence start_value" do
158
- mock(FactoryGirl::Sequence).new("A") { @sequence }
167
+ mock(FactoryGirl::Sequence).new(@name, "A") { @sequence }
159
168
  Factory.sequence(@name, "A")
160
169
  end
161
170
  end
162
171
 
163
172
  describe "after defining a sequence" do
164
173
  before do
165
- @sequence = "sequence"
166
174
  @name = :test
175
+ @sequence = FactoryGirl::Sequence.new(@name) {}
167
176
  @value = '1 2 5'
168
177
 
169
178
  stub(@sequence).next { @value }
@@ -182,3 +191,34 @@ describe "after defining a sequence" do
182
191
  Factory.next(@name).should == @value
183
192
  end
184
193
  end
194
+
195
+ describe "an attribute generated by an in-line sequence" do
196
+ before do
197
+ define_model('User', :username => :string)
198
+
199
+ Factory.define :user do |factory|
200
+ factory.sequence(:username) { |n| "username#{n}" }
201
+ end
202
+
203
+ @username = Factory.attributes_for(:user)[:username]
204
+ end
205
+
206
+ it "should match the correct format" do
207
+ @username.should =~ /^username\d+$/
208
+ end
209
+
210
+ describe "after the attribute has already been generated once" do
211
+ before do
212
+ @another_username = Factory.attributes_for(:user)[:username]
213
+ end
214
+
215
+ it "should match the correct format" do
216
+ @username.should =~ /^username\d+$/
217
+ end
218
+
219
+ it "should not be the same as the first generated value" do
220
+ @another_username.should_not == @username
221
+ end
222
+ end
223
+ end
224
+
@@ -45,7 +45,7 @@ describe FactoryGirl::Attribute::Dynamic do
45
45
  end
46
46
 
47
47
  it "should raise an error when returning a sequence" do
48
- stub(Factory).sequence { FactoryGirl::Sequence.new }
48
+ stub(Factory).sequence { FactoryGirl::Sequence.new(:email) }
49
49
  block = lambda { Factory.sequence(:email) }
50
50
  attr = FactoryGirl::Attribute::Dynamic.new(:email, block)
51
51
  proxy = stub!.set.subject
@@ -39,12 +39,12 @@ describe FactoryGirl::DefinitionProxy do
39
39
 
40
40
  describe "adding an attribute using a in-line sequence" do
41
41
  it "should create the sequence" do
42
- mock(FactoryGirl::Sequence).new(1)
42
+ mock(FactoryGirl::Sequence).new(:name, 1)
43
43
  subject.sequence(:name) {}
44
44
  end
45
45
 
46
46
  it "should create the sequence with a custom default value" do
47
- mock(FactoryGirl::Sequence).new("A")
47
+ mock(FactoryGirl::Sequence).new(:name, "A")
48
48
  subject.sequence(:name, "A") {}
49
49
  end
50
50
 
@@ -113,6 +113,7 @@ describe FactoryGirl::DefinitionProxy do
113
113
 
114
114
  it "adds an association when passed an undefined method without arguments or a block" do
115
115
  name = :user
116
+ FactoryGirl.register(FactoryGirl::Factory.new(name))
116
117
  attr = 'attribute'
117
118
  stub(attr).name { name }
118
119
  mock(FactoryGirl::Attribute::Association).new(name, name, {}) { attr }
@@ -122,17 +123,18 @@ describe FactoryGirl::DefinitionProxy do
122
123
 
123
124
  it "adds a sequence when passed an undefined method without arguments or a block" do
124
125
  name = :airport
125
- proxy = 'proxy'
126
- FactoryGirl.sequences[name] = FactoryGirl::Sequence.new { |value| "expected" }
126
+ FactoryGirl.register(FactoryGirl::Sequence.new(name))
127
+ attr = 'attribute'
128
+ stub(attr).name { name }
129
+ mock(FactoryGirl::Attribute::Association).new(name, name, {}) { attr }
127
130
  subject.send(name)
128
- stub(proxy).set
129
- factory.attributes.last.add_to(proxy)
130
- proxy.should have_received.set(name, 'expected')
131
+ factory.attributes.should include(attr)
131
132
  end
132
133
 
133
- it "registers its factory for an alias" do
134
- aliased_name = :guest
135
- mock(FactoryGirl).register_factory(factory, :as => aliased_name)
136
- subject.aliased_as aliased_name
134
+ it "delegates to_create" do
135
+ result = 'expected'
136
+ mock(factory).to_create { result }
137
+
138
+ subject.to_create.should == result
137
139
  end
138
140
  end
@@ -1,30 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe FactoryGirl::Factory, "registering a factory" do
4
- before do
5
- @name = :user
6
- @factory = "factory"
7
- stub(@factory).name { @name }
8
- end
9
-
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
13
- end
14
-
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
21
-
22
3
  describe FactoryGirl::Factory do
23
4
  include DefinesConstants
24
5
 
25
6
  before do
26
7
  @name = :user
27
- @class = define_constant('User')
8
+ @class = define_class('User')
28
9
  @factory = FactoryGirl::Factory.new(@name)
29
10
  end
30
11
 
@@ -88,11 +69,24 @@ describe FactoryGirl::Factory do
88
69
  end
89
70
 
90
71
  it "should return the result from the proxy when running" do
91
- mock(@proxy).result() { 'result' }
72
+ mock(@proxy).result(nil) { 'result' }
92
73
  @factory.run(FactoryGirl::Proxy::Build, {}).should == 'result'
93
74
  end
94
75
  end
95
76
 
77
+ it "passes a custom creation block" do
78
+ proxy = 'proxy'
79
+ stub(FactoryGirl::Proxy::Build).new { proxy }
80
+ stub(proxy).result {}
81
+ block = lambda {}
82
+ factory = FactoryGirl::Factory.new(:object)
83
+ factory.to_create(&block)
84
+
85
+ factory.run(FactoryGirl::Proxy::Build, {})
86
+
87
+ proxy.should have_received.result(block)
88
+ end
89
+
96
90
  it "should return associations" do
97
91
  factory = FactoryGirl::Factory.new(:post)
98
92
  factory.define_attribute(FactoryGirl::Attribute::Association.new(:author, :author, {}))
@@ -265,7 +259,7 @@ describe FactoryGirl::Factory, "with a name ending in s" do
265
259
  include DefinesConstants
266
260
 
267
261
  before do
268
- define_constant('Business')
262
+ define_class('Business')
269
263
  @name = :business
270
264
  @class = Business
271
265
  @factory = FactoryGirl::Factory.new(@name)
@@ -291,38 +285,12 @@ describe FactoryGirl::Factory, "with a string for a name" do
291
285
  end
292
286
  end
293
287
 
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
300
-
301
- it "should store the factory using a symbol" do
302
- FactoryGirl.factories[@name].should == @factory
303
- end
304
- end
305
-
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)
311
-
312
- FactoryGirl.register_factory(@factory, :as => @custom_name)
313
- end
314
-
315
- it "finds the factory using the custom name" do
316
- FactoryGirl.factory_by_name(@custom_name).should == @factory
317
- end
318
- end
319
-
320
288
  describe FactoryGirl::Factory, "for namespaced class" do
321
289
  include DefinesConstants
322
290
 
323
291
  before do
324
- define_constant('Admin')
325
- define_constant('Admin::Settings')
292
+ define_class('Admin')
293
+ define_class('Admin::Settings')
326
294
 
327
295
  @name = :settings
328
296
  @class = Admin::Settings
@@ -343,8 +311,8 @@ describe FactoryGirl::Factory do
343
311
  include DefinesConstants
344
312
 
345
313
  before do
346
- define_constant('User')
347
- define_constant('Admin', User)
314
+ define_class('User')
315
+ define_class('Admin', User)
348
316
  end
349
317
 
350
318
  it "should raise an ArgumentError when trying to use a non-existent strategy" do
@@ -392,3 +360,12 @@ describe FactoryGirl::Factory, "with an underscore in the name" do
392
360
  end
393
361
  end
394
362
 
363
+
364
+ describe FactoryGirl::Factory, "with aliases" do
365
+ it "registers the aliases" do
366
+ name = :user
367
+ aliased_name = :guest
368
+ factory = FactoryGirl::Factory.new(:user, :aliases => [aliased_name])
369
+ factory.names.should =~ [name, aliased_name]
370
+ end
371
+ end