factory_girl 2.0.0.beta1 → 2.0.0.beta2

Sign up to get free protection for your applications and to get access to all the features.
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