factory_girl 2.2.0 → 2.3.0

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 (58) hide show
  1. data/.autotest +1 -1
  2. data/CONTRIBUTION_GUIDELINES.md +1 -1
  3. data/Changelog +16 -3
  4. data/GETTING_STARTED.md +22 -2
  5. data/Gemfile.lock +1 -1
  6. data/Rakefile +11 -15
  7. data/gemfiles/2.1.gemfile.lock +1 -1
  8. data/gemfiles/2.3.gemfile.lock +1 -1
  9. data/gemfiles/3.0.gemfile.lock +1 -1
  10. data/gemfiles/3.1.gemfile.lock +1 -1
  11. data/lib/factory_girl.rb +8 -3
  12. data/lib/factory_girl/attribute.rb +8 -0
  13. data/lib/factory_girl/attribute/dynamic.rb +1 -5
  14. data/lib/factory_girl/attribute/sequence.rb +1 -5
  15. data/lib/factory_girl/attribute/static.rb +1 -5
  16. data/lib/factory_girl/attribute_list.rb +18 -44
  17. data/lib/factory_girl/callback.rb +5 -0
  18. data/lib/factory_girl/declaration.rb +3 -0
  19. data/lib/factory_girl/declaration/association.rb +8 -0
  20. data/lib/factory_girl/declaration/dynamic.rb +9 -0
  21. data/lib/factory_girl/declaration/implicit.rb +11 -2
  22. data/lib/factory_girl/declaration/static.rb +9 -0
  23. data/lib/factory_girl/declaration_list.rb +48 -0
  24. data/lib/factory_girl/definition.rb +62 -0
  25. data/lib/factory_girl/definition_proxy.rb +11 -11
  26. data/lib/factory_girl/factory.rb +100 -111
  27. data/lib/factory_girl/null_factory.rb +15 -0
  28. data/lib/factory_girl/proxy.rb +14 -9
  29. data/lib/factory_girl/proxy/attributes_for.rb +2 -3
  30. data/lib/factory_girl/proxy/build.rb +12 -20
  31. data/lib/factory_girl/proxy/create.rb +0 -6
  32. data/lib/factory_girl/proxy/stub.rb +4 -10
  33. data/lib/factory_girl/registry.rb +4 -3
  34. data/lib/factory_girl/step_definitions.rb +1 -1
  35. data/lib/factory_girl/syntax/default.rb +3 -4
  36. data/lib/factory_girl/syntax/methods.rb +38 -16
  37. data/lib/factory_girl/trait.rb +13 -21
  38. data/lib/factory_girl/version.rb +1 -1
  39. data/spec/acceptance/modify_factories_spec.rb +1 -1
  40. data/spec/acceptance/traits_spec.rb +87 -1
  41. data/spec/factory_girl/attribute/dynamic_spec.rb +1 -1
  42. data/spec/factory_girl/attribute_list_spec.rb +9 -58
  43. data/spec/factory_girl/declaration_list_spec.rb +71 -0
  44. data/spec/factory_girl/definition_proxy_spec.rb +135 -139
  45. data/spec/factory_girl/definition_spec.rb +81 -0
  46. data/spec/factory_girl/factory_spec.rb +42 -17
  47. data/spec/factory_girl/null_factory_spec.rb +12 -0
  48. data/spec/factory_girl/proxy/build_spec.rb +1 -24
  49. data/spec/factory_girl/proxy/create_spec.rb +14 -11
  50. data/spec/factory_girl/proxy_spec.rb +23 -40
  51. data/spec/factory_girl/registry_spec.rb +4 -3
  52. data/spec/spec_helper.rb +2 -0
  53. data/spec/support/matchers/callback.rb +9 -0
  54. data/spec/support/matchers/declaration.rb +71 -0
  55. data/spec/support/matchers/delegate.rb +44 -0
  56. data/spec/support/matchers/trait.rb +9 -0
  57. data/spec/support/shared_examples/proxy.rb +4 -5
  58. metadata +191 -115
@@ -0,0 +1,81 @@
1
+ require "spec_helper"
2
+
3
+ describe FactoryGirl::Definition do
4
+ it { should delegate(:declare_attribute).to(:declarations) }
5
+ it { should delegate(:attributes).to(:declarations).as(:attribute_list) }
6
+ end
7
+
8
+ describe FactoryGirl::Definition, "with a name" do
9
+ let(:name) { :"great name" }
10
+ subject { FactoryGirl::Definition.new(name) }
11
+
12
+ it "creates a new attribute list with the name passed" do
13
+ FactoryGirl::DeclarationList.stubs(:new)
14
+ subject
15
+ FactoryGirl::DeclarationList.should have_received(:new).with(name)
16
+ end
17
+ end
18
+
19
+ describe FactoryGirl::Definition, "#overridable" do
20
+ let(:list) { stub("declaration list", :overridable => true) }
21
+ before { FactoryGirl::DeclarationList.stubs(:new => list) }
22
+
23
+ it "sets the declaration list as overridable" do
24
+ subject.overridable.should == subject
25
+ list.should have_received(:overridable).once
26
+ end
27
+ end
28
+
29
+ describe FactoryGirl::Definition, "defining traits" do
30
+ let(:trait_1) { stub("trait") }
31
+ let(:trait_2) { stub("trait") }
32
+
33
+ it "maintains a list of traits" do
34
+ subject.define_trait(trait_1)
35
+ subject.define_trait(trait_2)
36
+ subject.defined_traits.should == [trait_1, trait_2]
37
+ end
38
+ end
39
+
40
+ describe FactoryGirl::Definition, "adding callbacks" do
41
+ let(:callback_1) { stub("callback") }
42
+ let(:callback_2) { stub("callback") }
43
+
44
+ it "maintains a list of callbacks" do
45
+ subject.add_callback(callback_1)
46
+ subject.add_callback(callback_2)
47
+ subject.callbacks.should == [callback_1, callback_2]
48
+ end
49
+ end
50
+
51
+ describe FactoryGirl::Definition, "#to_create" do
52
+ its(:to_create) { should be_nil }
53
+
54
+ it "returns the assigned value when given a block" do
55
+ block = proc { nil }
56
+ subject.to_create(&block)
57
+ subject.to_create.should == block
58
+ end
59
+ end
60
+
61
+ describe FactoryGirl::Definition, "#traits" do
62
+ let(:female_trait) { stub("female trait", :name => :female) }
63
+ let(:admin_trait) { stub("admin trait", :name => :admin) }
64
+
65
+ before do
66
+ subject.define_trait(female_trait)
67
+ FactoryGirl.stubs(:trait_by_name => admin_trait)
68
+ end
69
+
70
+ its(:traits) { should be_empty }
71
+
72
+ it "finds the correct traits after inheriting" do
73
+ subject.inherit_traits([:female])
74
+ subject.traits.should == [female_trait]
75
+ end
76
+
77
+ it "looks for the trait on FactoryGirl" do
78
+ subject.inherit_traits([:female, :admin])
79
+ subject.traits.should == [admin_trait, female_trait]
80
+ end
81
+ end
@@ -48,14 +48,6 @@ describe FactoryGirl::Factory do
48
48
  factory.associations.size.should == 3
49
49
  end
50
50
 
51
- it "raises for a self referencing association" do
52
- factory = FactoryGirl::Factory.new(:post)
53
- lambda {
54
- factory.declare_attribute(FactoryGirl::Declaration::Association.new(:parent, { :factory => :post }))
55
- factory.ensure_compiled
56
- }.should raise_error(FactoryGirl::AssociationDefinitionError)
57
- end
58
-
59
51
  describe "when overriding generated attributes with a hash" do
60
52
  before do
61
53
  @name = :name
@@ -71,9 +63,9 @@ describe FactoryGirl::Factory do
71
63
  end
72
64
 
73
65
  it "does not call a lazy attribute block for an overridden attribute" do
74
- declaration = FactoryGirl::Declaration::Dynamic.new(@name, lambda { flunk })
66
+ declaration = FactoryGirl::Declaration::Dynamic.new(@name, false, lambda { flunk })
75
67
  @factory.declare_attribute(declaration)
76
- result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
68
+ @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
77
69
  end
78
70
 
79
71
  it "overrides a symbol parameter with a string parameter" do
@@ -108,13 +100,13 @@ describe FactoryGirl::Factory do
108
100
 
109
101
  it "creates a new factory using the class of the parent" do
110
102
  child = FactoryGirl::Factory.new(:child, :parent => @factory.name)
111
- child.ensure_compiled
103
+ child.compile
112
104
  child.build_class.should == @factory.build_class
113
105
  end
114
106
 
115
107
  it "creates a new factory while overriding the parent class" do
116
108
  child = FactoryGirl::Factory.new(:child, :class => String, :parent => @factory.name)
117
- child.ensure_compiled
109
+ child.compile
118
110
  child.build_class.should == String
119
111
  end
120
112
  end
@@ -197,8 +189,8 @@ describe FactoryGirl::Factory do
197
189
  FactoryGirl.register_factory(factory_with_stub_strategy)
198
190
  end
199
191
 
200
- it "raises an ArgumentError when trying to use a non-existent strategy" do
201
- expect { factory_with_non_existent_strategy }.to raise_error(ArgumentError)
192
+ it "raises when trying to use a non-existent strategy" do
193
+ expect { factory_with_non_existent_strategy }.to raise_error
202
194
  end
203
195
 
204
196
  it "creates a new factory with a specified default strategy" do
@@ -207,7 +199,7 @@ describe FactoryGirl::Factory do
207
199
 
208
200
  describe "defining a child factory without setting default strategy" do
209
201
  subject { FactoryGirl::Factory.new(:other_object, :parent => factory_with_stub_strategy.name) }
210
- before { subject.ensure_compiled }
202
+ before { subject.compile }
211
203
 
212
204
  it "inherits default strategy from its parent" do
213
205
  subject.default_strategy.should == :stub
@@ -216,7 +208,7 @@ describe FactoryGirl::Factory do
216
208
 
217
209
  describe "defining a child factory with a default strategy" do
218
210
  subject { FactoryGirl::Factory.new(:other_object, :default_strategy => :build, :parent => factory_with_stub_strategy.name) }
219
- before { subject.ensure_compiled }
211
+ before { subject.compile }
220
212
 
221
213
  it "overrides the default strategy from parent" do
222
214
  subject.default_strategy.should == :build
@@ -237,6 +229,12 @@ describe FactoryGirl::Factory, "human names" do
237
229
  its(:human_names) { should == ["happy user"] }
238
230
  end
239
231
 
232
+ context "factory name with big letters" do
233
+ subject { FactoryGirl::Factory.new(:LoL) }
234
+ its(:names) { should == [:LoL] }
235
+ its(:human_names) { should == ["lol"] }
236
+ end
237
+
240
238
  context "factory name with aliases" do
241
239
  subject { FactoryGirl::Factory.new(:happy_user, :aliases => [:gleeful_user, :person]) }
242
240
  its(:names) { should == [:happy_user, :gleeful_user, :person] }
@@ -263,7 +261,7 @@ describe FactoryGirl::Factory, "running a factory" do
263
261
 
264
262
  it "creates the right proxy using the build class when running" do
265
263
  subject.run(FactoryGirl::Proxy::Build, {})
266
- FactoryGirl::Proxy::Build.should have_received(:new).with(subject.build_class)
264
+ FactoryGirl::Proxy::Build.should have_received(:new).with(subject.build_class, [])
267
265
  end
268
266
 
269
267
  it "adds the attribute to the proxy when running" do
@@ -280,4 +278,31 @@ describe FactoryGirl::Factory, "running a factory" do
280
278
  subject.run(FactoryGirl::Proxy::Build, { :name => "John Doe" })
281
279
  proxy.should have_received(:set).once
282
280
  end
281
+
282
+ it "calls the block and returns the result" do
283
+ block_run = nil
284
+ block = lambda {|result| block_run = "changed" }
285
+ subject.run(FactoryGirl::Proxy::Build, { }, &block)
286
+ block_run.should == "changed"
287
+ end
288
+ end
289
+
290
+ describe FactoryGirl::Factory, "#with_traits" do
291
+ subject { FactoryGirl::Factory.new(:user) }
292
+ let(:admin_trait) { FactoryGirl::Trait.new(:admin) }
293
+ let(:female_trait) { FactoryGirl::Trait.new(:female) }
294
+
295
+ before do
296
+ FactoryGirl.register_trait(admin_trait)
297
+ FactoryGirl.register_trait(female_trait)
298
+ end
299
+
300
+ it "returns a factory with the correct traits" do
301
+ subject.with_traits([:admin, :female]).traits.should =~ [admin_trait, female_trait]
302
+ end
303
+
304
+ it "doesn't modify the original factory's traits" do
305
+ subject.with_traits([:admin, :female])
306
+ subject.traits.should be_empty
307
+ end
283
308
  end
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ describe FactoryGirl::NullFactory do
4
+ it { should delegate(:defined_traits).to(:definition) }
5
+ it { should delegate(:callbacks).to(:definition) }
6
+ it { should delegate(:attributes).to(:definition) }
7
+
8
+ its(:compile) { should be_nil }
9
+ its(:default_strategy) { should be_nil }
10
+ its(:class_name) { should be_nil }
11
+ its(:attributes) { should be_an_instance_of(FactoryGirl::AttributeList) }
12
+ end
@@ -9,28 +9,5 @@ describe FactoryGirl::Proxy::Build do
9
9
  it_should_behave_like "proxy with association support", FactoryGirl::Proxy::Create
10
10
  it_should_behave_like "proxy with standard getters and setters", :attribute_name, "attribute value!"
11
11
  it_should_behave_like "proxy with callbacks", :after_build
12
- it_should_behave_like "proxy with :method => :build",
13
- FactoryGirl::Proxy::Build
14
-
15
- describe "specifying method" do
16
- it "defaults to create" do
17
- subject.send(:get_method, nil).should == FactoryGirl::Proxy::Create
18
- end
19
-
20
- it "can specify create explicitly" do
21
- subject.send(:get_method, :create).should ==
22
- FactoryGirl::Proxy::Create
23
- end
24
-
25
- it "can specify build explicitly" do
26
- subject.send(:get_method, :build).should ==
27
- FactoryGirl::Proxy::Build
28
- end
29
-
30
- it "complains if method is unrecognized" do
31
- lambda { subject.send(:get_method, :froboznicate) }.
32
- should raise_error("unrecognized method froboznicate")
33
- end
34
- end
35
-
12
+ it_should_behave_like "proxy with :method => :build", FactoryGirl::Proxy::Build
36
13
  end
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe FactoryGirl::Proxy::Create do
4
-
5
4
  let(:instance) { stub("created-instance", :save! => true) }
6
5
  let(:proxy_class) { stub("class", :new => instance) }
7
6
 
@@ -24,17 +23,21 @@ describe FactoryGirl::Proxy::Create do
24
23
  instance.should have_received(:save!).never
25
24
  end
26
25
 
27
- context "callback execution order" do
28
- it "runs after_build callbacks before after_create callbacks" do
29
- ran = []
30
- after_create = FactoryGirl::Callback.new(:after_create, lambda { ran << :after_create })
31
- after_build = FactoryGirl::Callback.new(:after_build, lambda { ran << :after_build })
32
- subject.add_callback(after_create)
33
- subject.add_callback(after_build)
26
+ end
27
+
28
+ describe FactoryGirl::Proxy::Create, "when running callbacks" do
29
+ let(:instance) { stub("created-instance", :save! => true) }
30
+ let(:proxy_class) { stub("class", :new => instance) }
31
+ let!(:callback_result) { [] }
34
32
 
35
- subject.result(nil)
33
+ let(:after_create_one) { FactoryGirl::Callback.new(:after_create, lambda { callback_result << :after_create_one }) }
34
+ let(:after_create_two) { FactoryGirl::Callback.new(:after_create, lambda { callback_result << :after_create_two }) }
35
+ let(:after_build_one) { FactoryGirl::Callback.new(:after_build, lambda { callback_result << :after_build_one }) }
36
36
 
37
- ran.should == [:after_build, :after_create]
38
- end
37
+ subject { FactoryGirl::Proxy::Create.new(proxy_class, [after_create_one, after_create_two, after_build_one]) }
38
+
39
+ it "runs callbacks in the correct order" do
40
+ subject.result(nil)
41
+ callback_result.should == [:after_build_one, :after_create_one, :after_create_two]
39
42
  end
40
43
  end
@@ -21,51 +21,34 @@ describe FactoryGirl::Proxy do
21
21
  it "raises an error when asking for the result" do
22
22
  expect { subject.result(nil) }.to raise_error(NotImplementedError)
23
23
  end
24
+ end
25
+
26
+ describe FactoryGirl::Proxy, "when running callbacks" do
27
+ let!(:callback_result) { [] }
28
+
29
+ let(:after_create_one) { FactoryGirl::Callback.new(:after_create, lambda { callback_result << :after_create_one }) }
30
+ let(:after_create_two) { FactoryGirl::Callback.new(:after_create, lambda { callback_result << :after_create_two }) }
31
+ let(:after_build_one) { FactoryGirl::Callback.new(:after_build, lambda { callback_result << :after_build_one }) }
24
32
 
25
- describe "when adding callbacks" do
26
- it "adds a callback" do
27
- callback = FactoryGirl::Callback.new(:after_create, lambda {})
28
- subject.add_callback(callback)
29
- subject.callbacks[:after_create].should == [callback]
30
- end
33
+ subject { FactoryGirl::Proxy.new(Class.new, [after_create_one, after_create_two, after_build_one]) }
31
34
 
32
- it "adds multiple callbacks of the same name" do
33
- one = FactoryGirl::Callback.new(:after_create, lambda {})
34
- two = FactoryGirl::Callback.new(:after_create, lambda {})
35
- subject.add_callback(one)
36
- subject.add_callback(two)
37
- subject.callbacks[:after_create].should == [one, two]
38
- end
35
+ it "runs callbacks in the correct order" do
36
+ subject.run_callbacks(:after_create)
37
+ callback_result.should == [:after_create_one, :after_create_two]
38
+ end
39
39
 
40
- it "adds multiple callbacks with different names" do
41
- after_create = FactoryGirl::Callback.new(:after_create, lambda {})
42
- after_build = FactoryGirl::Callback.new(:after_build, lambda {})
43
- subject.add_callback(after_create)
44
- subject.add_callback(after_build)
45
- subject.callbacks[:after_create].should == [after_create]
46
- subject.callbacks[:after_build].should == [after_build]
47
- end
40
+ it "runs the correct callbacks based on name" do
41
+ subject.run_callbacks(:after_build)
42
+ callback_result.should == [:after_build_one]
48
43
  end
44
+ end
49
45
 
50
- describe "when running callbacks" do
51
- it "runs all callbacks with a given name" do
52
- ran = []
53
- one = FactoryGirl::Callback.new(:after_create, lambda { ran << :one })
54
- two = FactoryGirl::Callback.new(:after_create, lambda { ran << :two })
55
- subject.add_callback(one)
56
- subject.add_callback(two)
57
- subject.run_callbacks(:after_create)
58
- ran.should == [:one, :two]
59
- end
46
+ describe FactoryGirl::Proxy, ".ensure_strategy_exists!" do
47
+ it "raises when passed a nonexistent strategy" do
48
+ expect { FactoryGirl::Proxy.ensure_strategy_exists!(:nonexistent) }.to raise_error(ArgumentError, "Unknown strategy: nonexistent")
49
+ end
60
50
 
61
- it "only runs callbacks with a given name" do
62
- ran = []
63
- after_create = FactoryGirl::Callback.new(:after_create, lambda { ran << :after_create })
64
- after_build = FactoryGirl::Callback.new(:after_build, lambda { ran << :after_build })
65
- subject.add_callback(after_create)
66
- subject.add_callback(after_build)
67
- subject.run_callbacks(:after_create)
68
- ran.should == [:after_create]
69
- end
51
+ it "doesn't raise when passed a valid strategy" do
52
+ expect { FactoryGirl::Proxy.ensure_strategy_exists!(:create) }.to_not raise_error
70
53
  end
71
54
  end
@@ -6,8 +6,9 @@ describe FactoryGirl::Registry do
6
6
  let(:factory) { FactoryGirl::Factory.new(:object) }
7
7
  let(:other_factory) { FactoryGirl::Factory.new(:string) }
8
8
  let(:factory_with_aliases) { FactoryGirl::Factory.new(:string, :aliases => aliases) }
9
+ let(:registry_name) { "Factory" }
9
10
 
10
- subject { FactoryGirl::Registry.new }
11
+ subject { FactoryGirl::Registry.new(registry_name) }
11
12
 
12
13
  it { should be_kind_of(Enumerable) }
13
14
 
@@ -17,7 +18,7 @@ describe FactoryGirl::Registry do
17
18
  end
18
19
 
19
20
  it "raises when finding an unregistered factory" do
20
- expect { subject.find(:bogus) }.to raise_error(ArgumentError)
21
+ expect { subject.find(:bogus) }.to raise_error(ArgumentError, "Factory not registered: bogus")
21
22
  end
22
23
 
23
24
  it "adds and returns a factory" do
@@ -62,7 +63,7 @@ describe FactoryGirl::Registry do
62
63
 
63
64
  it "doesn't allow a duplicate name" do
64
65
  expect { 2.times { subject.add(factory) } }.
65
- to raise_error(FactoryGirl::DuplicateDefinitionError)
66
+ to raise_error(FactoryGirl::DuplicateDefinitionError, "Factory already registered: object")
66
67
  end
67
68
 
68
69
  it "registers aliases" do
data/spec/spec_helper.rb CHANGED
@@ -15,6 +15,8 @@ Dir["spec/support/**/*.rb"].each { |f| require File.expand_path(f) }
15
15
  RSpec.configure do |config|
16
16
  config.mock_framework = :mocha
17
17
 
18
+ config.include DeclarationMatchers
19
+
18
20
  config.after do
19
21
  FactoryGirl.factories.clear
20
22
  FactoryGirl.sequences.clear
@@ -0,0 +1,9 @@
1
+ RSpec::Matchers.define :have_callback do |callback_name|
2
+ match do |instance|
3
+ instance.callbacks.include?(FactoryGirl::Callback.new(callback_name, @block))
4
+ end
5
+
6
+ chain :with_block do |block|
7
+ @block = block
8
+ end
9
+ end
@@ -0,0 +1,71 @@
1
+ module DeclarationMatchers
2
+ def have_static_declaration(name)
3
+ DeclarationMatcher.new(:static).named(name)
4
+ end
5
+
6
+ def have_dynamic_declaration(name)
7
+ DeclarationMatcher.new(:dynamic).named(name)
8
+ end
9
+
10
+ def have_association_declaration(name)
11
+ DeclarationMatcher.new(:association).named(name)
12
+ end
13
+
14
+ def have_implicit_declaration(name)
15
+ DeclarationMatcher.new(:implicit).named(name)
16
+ end
17
+
18
+ class DeclarationMatcher
19
+ def initialize(declaration_type)
20
+ @declaration_type = declaration_type
21
+ end
22
+
23
+ def matches?(subject)
24
+ subject.declarations.include?(expected_declaration)
25
+ end
26
+
27
+ def named(name)
28
+ @name = name
29
+ self
30
+ end
31
+
32
+ def ignored
33
+ @ignored = true
34
+ self
35
+ end
36
+
37
+ def with_value(value)
38
+ @value = value
39
+ self
40
+ end
41
+
42
+ def with_factory(factory)
43
+ @factory = factory
44
+ self
45
+ end
46
+
47
+ def with_options(options)
48
+ @options = options
49
+ self
50
+ end
51
+
52
+ private
53
+
54
+ def expected_declaration
55
+ case @declaration_type
56
+ when :static then FactoryGirl::Declaration::Static.new(@name, @value, ignored?)
57
+ when :dynamic then FactoryGirl::Declaration::Dynamic.new(@name, ignored?, @value)
58
+ when :implicit then FactoryGirl::Declaration::Implicit.new(@name, @factory, ignored?)
59
+ when :association then FactoryGirl::Declaration::Association.new(@name, options)
60
+ end
61
+ end
62
+
63
+ def ignored?
64
+ !!@ignored
65
+ end
66
+
67
+ def options
68
+ @options || {}
69
+ end
70
+ end
71
+ end