factory_girl 2.1.0 → 2.1.2

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