factory_girl 2.1.0 → 2.1.2

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 (43) hide show
  1. data/.travis.yml +3 -0
  2. data/Changelog +9 -0
  3. data/GETTING_STARTED.md +47 -16
  4. data/Gemfile.lock +10 -9
  5. data/gemfiles/2.1.gemfile.lock +2 -1
  6. data/gemfiles/2.3.gemfile.lock +2 -1
  7. data/gemfiles/3.0.gemfile.lock +2 -1
  8. data/gemfiles/3.1.gemfile.lock +2 -1
  9. data/lib/factory_girl.rb +6 -3
  10. data/lib/factory_girl/attribute/static.rb +8 -0
  11. data/lib/factory_girl/attribute_list.rb +20 -12
  12. data/lib/factory_girl/callback.rb +30 -0
  13. data/lib/factory_girl/declaration.rb +19 -0
  14. data/lib/factory_girl/declaration/association.rb +17 -0
  15. data/lib/factory_girl/declaration/dynamic.rb +16 -0
  16. data/lib/factory_girl/declaration/implicit.rb +23 -0
  17. data/lib/factory_girl/declaration/static.rb +16 -0
  18. data/lib/factory_girl/definition_proxy.rb +6 -6
  19. data/lib/factory_girl/factory.rb +63 -79
  20. data/lib/factory_girl/proxy.rb +7 -11
  21. data/lib/factory_girl/proxy/attributes_for.rb +1 -0
  22. data/lib/factory_girl/proxy/build.rb +1 -0
  23. data/lib/factory_girl/proxy/stub.rb +1 -0
  24. data/lib/factory_girl/syntax/default.rb +4 -2
  25. data/lib/factory_girl/syntax/vintage.rb +1 -1
  26. data/lib/factory_girl/trait.rb +12 -4
  27. data/lib/factory_girl/version.rb +1 -1
  28. data/spec/acceptance/callbacks_spec.rb +7 -1
  29. data/spec/acceptance/modify_inherited_spec.rb +52 -0
  30. data/spec/acceptance/syntax/vintage_spec.rb +19 -7
  31. data/spec/factory_girl/attribute_list_spec.rb +18 -45
  32. data/spec/factory_girl/callback_spec.rb +41 -0
  33. data/spec/factory_girl/{attribute → declaration}/implicit_spec.rb +16 -11
  34. data/spec/factory_girl/definition_proxy_spec.rb +16 -12
  35. data/spec/factory_girl/factory_spec.rb +43 -34
  36. data/spec/factory_girl/proxy/create_spec.rb +7 -9
  37. data/spec/factory_girl/proxy_spec.rb +26 -39
  38. data/spec/support/shared_examples/proxy.rb +1 -1
  39. metadata +137 -114
  40. data/lib/factory_girl/attribute/callback.rb +0 -14
  41. data/lib/factory_girl/attribute/implicit.rb +0 -39
  42. data/lib/factory_girl/attribute/trait.rb +0 -22
  43. data/spec/factory_girl/attribute/callback_spec.rb +0 -22
@@ -12,7 +12,8 @@ describe "callbacks" do
12
12
  end
13
13
 
14
14
  factory :user_with_inherited_callbacks, :parent => :user_with_callbacks do
15
- after_stub { |user| user.last_name = 'Double-Stubby' }
15
+ after_stub { |user| user.last_name = 'Double-Stubby' }
16
+ after_build { |user| user.first_name = 'Child-Buildy' }
16
17
  end
17
18
  end
18
19
  end
@@ -38,4 +39,9 @@ describe "callbacks" do
38
39
  user.first_name.should == 'Stubby'
39
40
  user.last_name.should == 'Double-Stubby'
40
41
  end
42
+
43
+ it "runs child callback after parent callback" do
44
+ user = FactoryGirl.build(:user_with_inherited_callbacks)
45
+ user.first_name.should == 'Child-Buildy'
46
+ end
41
47
  end
@@ -0,0 +1,52 @@
1
+ require "spec_helper"
2
+
3
+ describe "modifying inherited factories with traits" do
4
+ before do
5
+ define_model('User', :gender => :string, :admin => :boolean, :age => :integer)
6
+ FactoryGirl.define do
7
+ factory :user do
8
+ trait(:female) { gender "Female" }
9
+ trait(:male) { gender "Male" }
10
+
11
+ trait(:young_admin) do
12
+ admin true
13
+ age 17
14
+ end
15
+
16
+ female
17
+ young_admin
18
+
19
+ factory :female_user do
20
+ gender "Female"
21
+ age 25
22
+ end
23
+
24
+ factory :male_user do
25
+ gender "Male"
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ it "returns the correct value for overridden attributes from traits" do
32
+ Factory.build(:male_user).gender.should == "Male"
33
+ end
34
+
35
+ it "returns the correct value for overridden attributes from traits defining multiple attributes" do
36
+ Factory.build(:female_user).gender.should == "Female"
37
+ Factory.build(:female_user).age.should == 25
38
+ Factory.build(:female_user).admin.should == true
39
+ end
40
+
41
+ it "allows modification of attributes created via traits" do
42
+ FactoryGirl.modify do
43
+ factory :male_user do
44
+ age 20
45
+ end
46
+ end
47
+
48
+ Factory.build(:male_user).gender.should == "Male"
49
+ Factory.build(:male_user).age.should == 20
50
+ Factory.build(:male_user).admin.should == true
51
+ end
52
+ end
@@ -46,13 +46,7 @@ describe "vintage syntax" do
46
46
  end
47
47
  end
48
48
 
49
- describe Factory, "given a parent factory" do
50
- before do
51
- @parent = FactoryGirl::Factory.new(:object)
52
- @parent.define_attribute(FactoryGirl::Attribute::Static.new(:name, 'value'))
53
- FactoryGirl.register_factory(@parent)
54
- end
55
-
49
+ describe Factory, "referencing a nonexistent factory as a parent" do
56
50
  it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
57
51
  lambda {
58
52
  Factory.define(:child, :parent => :nonexsitent) {}
@@ -220,3 +214,21 @@ describe "an attribute generated by an in-line sequence" do
220
214
  end
221
215
  end
222
216
 
217
+
218
+ describe "a factory with a parent" do
219
+ before do
220
+ define_model("User", :username => :string)
221
+
222
+ Factory.define(:user) do |factory|
223
+ factory.username "awesome_username"
224
+ end
225
+
226
+ Factory.define(:boring_user, :parent => :user) do |factory|
227
+ factory.username "boring_username"
228
+ end
229
+ end
230
+
231
+ it "supports defining parents" do
232
+ Factory.build(:boring_user).username.should == "boring_username"
233
+ end
234
+ end
@@ -47,7 +47,7 @@ end
47
47
 
48
48
  describe FactoryGirl::AttributeList, "#attribute_defined?" do
49
49
  let(:static_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "value") }
50
- let(:callback_attribute) { FactoryGirl::Attribute::Callback.new(:after_create, lambda { }) }
50
+ let(:callback_attribute) { FactoryGirl::Callback.new(:after_create, lambda { }) }
51
51
  let(:static_attribute_named_after_create) { FactoryGirl::Attribute::Static.new(:after_create, "funky!") }
52
52
 
53
53
  it "knows if an attribute has been defined" do
@@ -58,50 +58,17 @@ describe FactoryGirl::AttributeList, "#attribute_defined?" do
58
58
  subject.attribute_defined?(static_attribute.name).should == true
59
59
  subject.attribute_defined?(:undefined_attribute).should == false
60
60
  end
61
-
62
- it "doesn't reference callbacks" do
63
- subject.define_attribute(callback_attribute)
64
-
65
- subject.attribute_defined?(:after_create).should == false
66
-
67
- subject.define_attribute(static_attribute_named_after_create)
68
- subject.attribute_defined?(:after_create).should == true
69
- end
70
61
  end
71
62
 
72
63
  describe FactoryGirl::AttributeList, "#add_callback" do
73
64
  let(:proxy_class) { mock("klass") }
74
65
  let(:proxy) { FactoryGirl::Proxy.new(proxy_class) }
75
- let(:valid_callback_names) { [:after_create, :after_build, :after_stub] }
76
- let(:invalid_callback_names) { [:before_create, :before_build, :bogus] }
77
66
 
78
67
  it "allows for defining adding a callback" do
79
- subject.add_callback(:after_create) { "Called after_create" }
80
-
81
- subject.first.name.should == :after_create
82
-
83
- subject.first.add_to(proxy)
84
- proxy.callbacks[:after_create].first.call.should == "Called after_create"
85
- end
86
-
87
- it "returns the callback" do
88
- subject.add_callback(:after_create) { "Called after_create" }.should be_a(FactoryGirl::Attribute::Callback)
89
- end
90
-
91
- it "allows valid callback names to be assigned" do
92
- valid_callback_names.each do |callback_name|
93
- expect do
94
- subject.add_callback(callback_name) { "great name!" }
95
- end.to_not raise_error(FactoryGirl::InvalidCallbackNameError)
96
- end
97
- end
68
+ subject.add_callback(FactoryGirl::Callback.new(:after_create, lambda { "Called after_create" }))
98
69
 
99
- it "raises if an invalid callback name is assigned" do
100
- invalid_callback_names.each do |callback_name|
101
- expect do
102
- subject.add_callback(callback_name) { "great name!" }
103
- end.to raise_error(FactoryGirl::InvalidCallbackNameError, "#{callback_name} is not a valid callback name. Valid callback names are [:after_build, :after_create, :after_stub]")
104
- end
70
+ subject.callbacks.first.name.should == :after_create
71
+ subject.callbacks.first.run(nil, nil).should == "Called after_create"
105
72
  end
106
73
  end
107
74
 
@@ -111,22 +78,28 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
111
78
  let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, lambda {|model| "#{model.full_name}@example.com" }) }
112
79
  let(:login_attribute) { FactoryGirl::Attribute::Dynamic.new(:login, lambda {|model| "username-#{model.full_name}" }) }
113
80
 
81
+ def list(*attributes)
82
+ FactoryGirl::AttributeList.new.tap do |list|
83
+ attributes.each { |attribute| list.define_attribute(attribute) }
84
+ end
85
+ end
86
+
114
87
  it "prepends applied attributes" do
115
88
  subject.define_attribute(full_name_attribute)
116
- subject.apply_attributes([city_attribute])
89
+ subject.apply_attributes(list(city_attribute))
117
90
  subject.to_a.should == [city_attribute, full_name_attribute]
118
91
  end
119
92
 
120
93
  it "moves non-static attributes to the end of the list" do
121
94
  subject.define_attribute(full_name_attribute)
122
- subject.apply_attributes([city_attribute, email_attribute])
95
+ subject.apply_attributes(list(city_attribute, email_attribute))
123
96
  subject.to_a.should == [city_attribute, full_name_attribute, email_attribute]
124
97
  end
125
98
 
126
99
  it "maintains order of non-static attributes" do
127
100
  subject.define_attribute(full_name_attribute)
128
101
  subject.define_attribute(login_attribute)
129
- subject.apply_attributes([city_attribute, email_attribute])
102
+ subject.apply_attributes(list(city_attribute, email_attribute))
130
103
  subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute]
131
104
  end
132
105
 
@@ -134,7 +107,7 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
134
107
  subject.define_attribute(full_name_attribute)
135
108
  attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin")
136
109
 
137
- subject.apply_attributes([attribute_with_same_name])
110
+ subject.apply_attributes(list(attribute_with_same_name))
138
111
  subject.to_a.should == [full_name_attribute]
139
112
  end
140
113
 
@@ -143,20 +116,20 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
143
116
 
144
117
  it "prepends applied attributes" do
145
118
  subject.define_attribute(full_name_attribute)
146
- subject.apply_attributes([city_attribute])
119
+ subject.apply_attributes(list(city_attribute))
147
120
  subject.to_a.should == [city_attribute, full_name_attribute]
148
121
  end
149
122
 
150
123
  it "moves non-static attributes to the end of the list" do
151
124
  subject.define_attribute(full_name_attribute)
152
- subject.apply_attributes([city_attribute, email_attribute])
125
+ subject.apply_attributes(list(city_attribute, email_attribute))
153
126
  subject.to_a.should == [city_attribute, full_name_attribute, email_attribute]
154
127
  end
155
128
 
156
129
  it "maintains order of non-static attributes" do
157
130
  subject.define_attribute(full_name_attribute)
158
131
  subject.define_attribute(login_attribute)
159
- subject.apply_attributes([city_attribute, email_attribute])
132
+ subject.apply_attributes(list(city_attribute, email_attribute))
160
133
  subject.to_a.should == [city_attribute, full_name_attribute, email_attribute, login_attribute]
161
134
  end
162
135
 
@@ -164,7 +137,7 @@ describe FactoryGirl::AttributeList, "#apply_attributes" do
164
137
  subject.define_attribute(full_name_attribute)
165
138
  attribute_with_same_name = FactoryGirl::Attribute::Static.new(:full_name, "Benjamin Franklin")
166
139
 
167
- subject.apply_attributes([attribute_with_same_name])
140
+ subject.apply_attributes(list(attribute_with_same_name))
168
141
  subject.to_a.should == [attribute_with_same_name]
169
142
  end
170
143
  end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+
3
+ describe FactoryGirl::Callback do
4
+ it "has a name" do
5
+ FactoryGirl::Callback.new(:after_create, lambda {}).name.should == :after_create
6
+ end
7
+
8
+ it "converts strings to symbols" do
9
+ FactoryGirl::Callback.new("after_create", lambda {}).name.should == :after_create
10
+ end
11
+
12
+ it "runs its block with no parameters" do
13
+ ran_with = nil
14
+ FactoryGirl::Callback.new(:after_create, lambda { ran_with = [] }).run(:one, :two)
15
+ ran_with.should == []
16
+ end
17
+
18
+ it "runs its block with one parameter" do
19
+ ran_with = nil
20
+ FactoryGirl::Callback.new(:after_create, lambda { |one| ran_with = [one] }).run(:one, :two)
21
+ ran_with.should == [:one]
22
+ end
23
+
24
+ it "runs its block with two parameters" do
25
+ ran_with = nil
26
+ FactoryGirl::Callback.new(:after_create, lambda { |one, two| ran_with = [one, two] }).run(:one, :two)
27
+ ran_with.should == [:one, :two]
28
+ end
29
+
30
+ it "allows valid callback names to be assigned" do
31
+ FactoryGirl::Callback::VALID_NAMES.each do |callback_name|
32
+ expect { FactoryGirl::Callback.new(callback_name, lambda {}) }.
33
+ to_not raise_error(FactoryGirl::InvalidCallbackNameError)
34
+ end
35
+ end
36
+
37
+ it "raises if an invalid callback name is assigned" do
38
+ expect { FactoryGirl::Callback.new(:magic_fairies, lambda {}) }.
39
+ to raise_error(FactoryGirl::InvalidCallbackNameError, /magic_fairies is not a valid callback name/)
40
+ end
41
+ end
@@ -1,24 +1,27 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe FactoryGirl::Attribute::Implicit do
4
- let(:name) { :author }
5
- let(:proxy) { stub("proxy") }
6
- subject { FactoryGirl::Attribute::Implicit.new(name) }
7
-
8
- its(:name) { should == name }
3
+ describe FactoryGirl::Declaration::Implicit do
4
+ let(:name) { :author }
5
+ let(:proxy) { stub("proxy") }
6
+ subject { FactoryGirl::Declaration::Implicit.new(name) }
7
+ let(:attribute) { subject.to_attributes.first }
9
8
 
10
9
  context "with a known factory" do
11
10
  before do
12
11
  FactoryGirl.factories.stubs(:registered? => true)
13
12
  end
14
13
 
15
- it { should be_association }
14
+ it "generates an association" do
15
+ attribute.should be_association
16
+ end
16
17
 
17
- its(:factory) { should == name }
18
+ it "generates an association with the correct factory" do
19
+ attribute.factory.should == name
20
+ end
18
21
 
19
22
  it "associates the factory" do
20
23
  proxy.stubs(:associate)
21
- subject.add_to(proxy)
24
+ attribute.add_to(proxy)
22
25
  proxy.should have_received(:associate).with(name, name, {})
23
26
  end
24
27
  end
@@ -27,11 +30,13 @@ describe FactoryGirl::Attribute::Implicit do
27
30
  let(:sequence) { FactoryGirl::Sequence.new(name, 1) { "magic" } }
28
31
  before { FactoryGirl.register_sequence(sequence) }
29
32
 
30
- it { should_not be_association }
33
+ it "doesn't generate an association" do
34
+ attribute.should_not be_association
35
+ end
31
36
 
32
37
  it "generates the sequence" do
33
38
  proxy.stubs(:set)
34
- subject.add_to(proxy)
39
+ attribute.add_to(proxy)
35
40
  proxy.should have_received(:set).with(name, "magic")
36
41
  end
37
42
  end
@@ -4,14 +4,18 @@ describe FactoryGirl::DefinitionProxy do
4
4
  let(:factory) { FactoryGirl::Factory.new(:object) }
5
5
  subject { FactoryGirl::DefinitionProxy.new(factory) }
6
6
 
7
+ def attributes
8
+ factory.attributes
9
+ end
10
+
7
11
  it "should add a static attribute for type" do
8
12
  subject.type 'value'
9
- factory.attributes.last.should be_kind_of(FactoryGirl::Attribute::Static)
13
+ attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
10
14
  end
11
15
 
12
16
  it "should add a static attribute for id" do
13
17
  subject.id 'value'
14
- factory.attributes.last.should be_kind_of(FactoryGirl::Attribute::Static)
18
+ attributes.to_a.last.should be_kind_of(FactoryGirl::Attribute::Static)
15
19
  end
16
20
 
17
21
  it "should add a static attribute when an attribute is defined with a value" do
@@ -19,6 +23,7 @@ describe FactoryGirl::DefinitionProxy do
19
23
  FactoryGirl::Attribute::Static.stubs(:new => attribute)
20
24
  factory.stubs(:define_attribute)
21
25
  subject.add_attribute(:name, 'value')
26
+ factory.compile
22
27
  factory.should have_received(:define_attribute).with(attribute)
23
28
  FactoryGirl::Attribute::Static.should have_received(:new).with(:name, "value")
24
29
  end
@@ -29,6 +34,7 @@ describe FactoryGirl::DefinitionProxy do
29
34
  FactoryGirl::Attribute::Dynamic.stubs(:new => attribute)
30
35
  factory.stubs(:define_attribute)
31
36
  subject.add_attribute(:name, &block)
37
+ factory.compile
32
38
  FactoryGirl::Attribute::Dynamic.should have_received(:new).with(:name, block)
33
39
  factory.should have_received(:define_attribute).with(attribute)
34
40
  end
@@ -41,7 +47,7 @@ describe FactoryGirl::DefinitionProxy do
41
47
 
42
48
  it "should add an attribute with a built-in private method" do
43
49
  subject.instance_eval { sleep(0.1) }
44
- factory.attributes.map { |attribute| attribute.name }.should == [:sleep]
50
+ attributes.map { |attribute| attribute.name }.should == [:sleep]
45
51
  end
46
52
 
47
53
  describe "child factories" do
@@ -67,15 +73,6 @@ describe FactoryGirl::DefinitionProxy do
67
73
  FactoryGirl::Sequence.should have_received(:new).with(:name, "A")
68
74
  end
69
75
  end
70
-
71
- it "adds an implicit attribute when passed an undefined method without arguments or a block" do
72
- factory.stubs(:define_attribute)
73
- attribute = stub('attribute', :name => :name)
74
- FactoryGirl::Attribute::Implicit.stubs(:new => attribute)
75
- subject.send(:name)
76
- FactoryGirl::Attribute::Implicit.should have_received(:new).with(:name, factory)
77
- factory.should have_received(:define_attribute).with(attribute)
78
- end
79
76
  end
80
77
 
81
78
  describe FactoryGirl::DefinitionProxy, "with a factory mock" do
@@ -126,12 +123,14 @@ describe FactoryGirl::DefinitionProxy, "adding attributes" do
126
123
 
127
124
  it "creates a dynamic attribute" do
128
125
  subject.add_attribute(attribute_name, &block)
126
+ factory.compile
129
127
  FactoryGirl::Attribute::Dynamic.should have_received(:new).with(attribute_name, block)
130
128
  factory.should have_received(:define_attribute).with(attribute)
131
129
  end
132
130
 
133
131
  it "creates a dynamic attribute without the method being defined" do
134
132
  subject.send(attribute_name, &block)
133
+ factory.compile
135
134
  FactoryGirl::Attribute::Dynamic.should have_received(:new).with(attribute_name, block)
136
135
  factory.should have_received(:define_attribute).with(attribute)
137
136
  end
@@ -142,12 +141,14 @@ describe FactoryGirl::DefinitionProxy, "adding attributes" do
142
141
 
143
142
  it "creates a static attribute" do
144
143
  subject.add_attribute(attribute_name, attribute_value)
144
+ factory.compile
145
145
  FactoryGirl::Attribute::Static.should have_received(:new).with(attribute_name, attribute_value)
146
146
  factory.should have_received(:define_attribute).with(attribute)
147
147
  end
148
148
 
149
149
  it "creates a static attribute without the method being defined" do
150
150
  subject.send(attribute_name, attribute_value)
151
+ factory.compile
151
152
  FactoryGirl::Attribute::Static.should have_received(:new).with(attribute_name, attribute_value)
152
153
  factory.should have_received(:define_attribute).with(attribute)
153
154
  end
@@ -179,6 +180,7 @@ describe FactoryGirl::DefinitionProxy, "#association" do
179
180
 
180
181
  it "defines an association attribute with the factory name" do
181
182
  subject.association(association_name, options)
183
+ factory.compile
182
184
 
183
185
  factory.should have_received(:define_attribute).with(attribute)
184
186
  FactoryGirl::Attribute::Association.should have_received(:new).with(association_name, factory_name, :name => "John Doe")
@@ -186,6 +188,7 @@ describe FactoryGirl::DefinitionProxy, "#association" do
186
188
 
187
189
  it "defines an association attribute when the association is called implicitly" do
188
190
  subject.send(association_name, options)
191
+ factory.compile
189
192
 
190
193
  factory.should have_received(:define_attribute).with(attribute)
191
194
  FactoryGirl::Attribute::Association.should have_received(:new).with(association_name, factory_name, :name => "John Doe")
@@ -197,6 +200,7 @@ describe FactoryGirl::DefinitionProxy, "#association" do
197
200
 
198
201
  it "defines an association attribute with the association name" do
199
202
  subject.association(association_name, options)
203
+ factory.compile
200
204
 
201
205
  factory.should have_received(:define_attribute).with(attribute)
202
206
  FactoryGirl::Attribute::Association.should have_received(:new).with(association_name, association_name, options)