factory_girl 3.1.1 → 3.2.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 (59) hide show
  1. data/.simplecov +4 -0
  2. data/GETTING_STARTED.md +147 -3
  3. data/Gemfile.lock +1 -1
  4. data/NEWS +8 -0
  5. data/features/support/env.rb +0 -1
  6. data/gemfiles/3.0.gemfile.lock +1 -1
  7. data/gemfiles/3.1.gemfile.lock +1 -1
  8. data/gemfiles/3.2.gemfile.lock +1 -1
  9. data/lib/factory_girl.rb +50 -7
  10. data/lib/factory_girl/attribute.rb +1 -1
  11. data/lib/factory_girl/attribute/association.rb +1 -1
  12. data/lib/factory_girl/attribute/dynamic.rb +1 -1
  13. data/lib/factory_girl/attribute/sequence.rb +1 -1
  14. data/lib/factory_girl/attribute/static.rb +1 -1
  15. data/lib/factory_girl/attribute_assigner.rb +12 -3
  16. data/lib/factory_girl/callback.rb +4 -1
  17. data/lib/factory_girl/{callback_runner.rb → callbacks_observer.rb} +1 -1
  18. data/lib/factory_girl/definition.rb +1 -1
  19. data/lib/factory_girl/definition_proxy.rb +4 -0
  20. data/lib/factory_girl/disallows_duplicates_registry.rb +17 -0
  21. data/lib/factory_girl/evaluator.rb +14 -11
  22. data/lib/factory_girl/factory.rb +5 -5
  23. data/lib/factory_girl/null_object.rb +14 -2
  24. data/lib/factory_girl/registry.rb +15 -23
  25. data/lib/factory_girl/reload.rb +2 -0
  26. data/lib/factory_girl/strategy_calculator.rb +1 -5
  27. data/lib/factory_girl/syntax.rb +1 -0
  28. data/lib/factory_girl/syntax/blueprint.rb +1 -0
  29. data/lib/factory_girl/syntax/generate.rb +6 -3
  30. data/lib/factory_girl/syntax/make.rb +4 -2
  31. data/lib/factory_girl/syntax/methods.rb +0 -81
  32. data/lib/factory_girl/syntax/sham.rb +1 -0
  33. data/lib/factory_girl/syntax/vintage.rb +0 -2
  34. data/lib/factory_girl/syntax_runner.rb +5 -0
  35. data/lib/factory_girl/version.rb +1 -1
  36. data/spec/acceptance/activesupport_instrumentation_spec.rb +49 -0
  37. data/spec/acceptance/build_stubbed_spec.rb +6 -6
  38. data/spec/acceptance/initialize_with_spec.rb +26 -0
  39. data/spec/acceptance/modify_factories_spec.rb +2 -2
  40. data/spec/acceptance/register_strategies_spec.rb +120 -0
  41. data/spec/acceptance/skip_create_spec.rb +19 -0
  42. data/spec/acceptance/syntax/blueprint_spec.rb +2 -0
  43. data/spec/acceptance/syntax/generate_spec.rb +2 -0
  44. data/spec/acceptance/syntax/make_spec.rb +2 -0
  45. data/spec/acceptance/syntax/vintage_spec.rb +2 -2
  46. data/spec/acceptance/syntax_methods_within_dynamic_attributes_spec.rb +41 -0
  47. data/spec/factory_girl/attribute/dynamic_spec.rb +6 -6
  48. data/spec/factory_girl/attribute_list_spec.rb +4 -4
  49. data/spec/factory_girl/callback_spec.rb +7 -7
  50. data/spec/factory_girl/definition_proxy_spec.rb +6 -6
  51. data/spec/factory_girl/disallows_duplicates_registry_spec.rb +44 -0
  52. data/spec/factory_girl/evaluator_class_definer_spec.rb +5 -5
  53. data/spec/factory_girl/factory_spec.rb +3 -3
  54. data/spec/factory_girl/null_object_spec.rb +18 -4
  55. data/spec/factory_girl/registry_spec.rb +30 -72
  56. data/spec/factory_girl/sequence_spec.rb +3 -2
  57. data/spec/factory_girl/strategy_calculator_spec.rb +1 -1
  58. data/spec/spec_helper.rb +0 -1
  59. metadata +41 -28
@@ -52,27 +52,27 @@ describe "a generated stub instance" do
52
52
  end
53
53
 
54
54
  it "disables connection" do
55
- lambda { subject.connection }.should raise_error(RuntimeError)
55
+ expect { subject.connection }.to raise_error(RuntimeError)
56
56
  end
57
57
 
58
58
  it "disables update_attribute" do
59
- lambda { subject.update_attribute(:title, "value") }.should raise_error(RuntimeError)
59
+ expect { subject.update_attribute(:title, "value") }.to raise_error(RuntimeError)
60
60
  end
61
61
 
62
62
  it "disables reload" do
63
- lambda { subject.reload }.should raise_error(RuntimeError)
63
+ expect { subject.reload }.to raise_error(RuntimeError)
64
64
  end
65
65
 
66
66
  it "disables destroy" do
67
- lambda { subject.destroy }.should raise_error(RuntimeError)
67
+ expect { subject.destroy }.to raise_error(RuntimeError)
68
68
  end
69
69
 
70
70
  it "disables save" do
71
- lambda { subject.save }.should raise_error(RuntimeError)
71
+ expect { subject.save }.to raise_error(RuntimeError)
72
72
  end
73
73
 
74
74
  it "disables increment" do
75
- lambda { subject.increment!(:age) }.should raise_error(RuntimeError)
75
+ expect { subject.increment!(:age) }.to raise_error(RuntimeError)
76
76
  end
77
77
  end
78
78
 
@@ -145,3 +145,29 @@ describe "initialize_with parent and child factories" do
145
145
  FactoryGirl.build(:super_awesome).name.should == "Super"
146
146
  end
147
147
  end
148
+
149
+ describe "initialize_with implicit constructor" do
150
+ before do
151
+ define_class("Awesome") do
152
+ attr_reader :name
153
+
154
+ def initialize(name)
155
+ @name = name
156
+ end
157
+ end
158
+
159
+ FactoryGirl.define do
160
+ factory :awesome do
161
+ ignore do
162
+ name "Great"
163
+ end
164
+
165
+ initialize_with { new(name) }
166
+ end
167
+ end
168
+ end
169
+
170
+ it "instantiates the correct object" do
171
+ FactoryGirl.build(:awesome, name: "Awesome name").name.should == "Awesome name"
172
+ end
173
+ end
@@ -175,10 +175,10 @@ describe "modifying factories" do
175
175
  end
176
176
 
177
177
  it "raises an exception if the factory was not defined before" do
178
- lambda {
178
+ expect {
179
179
  FactoryGirl.modify do
180
180
  factory :unknown_factory
181
181
  end
182
- }.should raise_error(ArgumentError)
182
+ }.to raise_error(ArgumentError)
183
183
  end
184
184
  end
@@ -0,0 +1,120 @@
1
+ require "spec_helper"
2
+
3
+ shared_context "registering custom strategies" do
4
+ before do
5
+ define_class("NamedObject") do
6
+ attr_accessor :name
7
+ end
8
+ end
9
+
10
+ let(:custom_strategy) do
11
+ Class.new do
12
+ def result(evaluation)
13
+ evaluation.object.tap do |instance|
14
+ instance.name = "Custom strategy"
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "register custom strategies" do
22
+ include_context "registering custom strategies"
23
+
24
+ before do
25
+ FactoryGirl.define do
26
+ factory :named_object do
27
+ name "Great"
28
+ end
29
+ end
30
+ end
31
+
32
+ it "allows overriding default strategies" do
33
+ FactoryGirl.build(:named_object).name.should == "Great"
34
+ FactoryGirl.register_strategy(:build, custom_strategy)
35
+ FactoryGirl.build(:named_object).name.should == "Custom strategy"
36
+ end
37
+
38
+ it "allows adding additional strategies" do
39
+ FactoryGirl.register_strategy(:insert, custom_strategy)
40
+
41
+ FactoryGirl.build(:named_object).name.should == "Great"
42
+ FactoryGirl.insert(:named_object).name.should == "Custom strategy"
43
+ end
44
+ end
45
+
46
+ describe "including FactoryGirl::Syntax::Methods when custom strategies have been declared" do
47
+ include FactoryGirl::Syntax::Methods
48
+
49
+ include_context "registering custom strategies"
50
+
51
+ before do
52
+ FactoryGirl.define do
53
+ factory :named_object do
54
+ name "Great"
55
+ end
56
+ end
57
+ end
58
+
59
+ it "allows adding additional strategies" do
60
+ FactoryGirl.register_strategy(:insert, custom_strategy)
61
+
62
+ insert(:named_object).name.should == "Custom strategy"
63
+ end
64
+ end
65
+
66
+ describe "associations without overriding :strategy" do
67
+ include_context "registering custom strategies"
68
+
69
+ before do
70
+ define_model("Post", user_id: :integer) do
71
+ belongs_to :user
72
+ end
73
+
74
+ define_model("User", name: :string)
75
+
76
+ FactoryGirl.define do
77
+ factory :post do
78
+ user
79
+ end
80
+
81
+ factory :user do
82
+ name "John Doe"
83
+ end
84
+ end
85
+ end
86
+
87
+ it "uses the overridden create strategy to create the association" do
88
+ FactoryGirl.register_strategy(:create, custom_strategy)
89
+ post = FactoryGirl.build(:post)
90
+ post.user.name.should == "Custom strategy"
91
+ end
92
+ end
93
+
94
+ describe "associations overriding :strategy" do
95
+ include_context "registering custom strategies"
96
+
97
+ before do
98
+ define_model("Post", user_id: :integer) do
99
+ belongs_to :user
100
+ end
101
+
102
+ define_model("User", name: :string)
103
+
104
+ FactoryGirl.define do
105
+ factory :post do
106
+ association :user, strategy: :insert
107
+ end
108
+
109
+ factory :user do
110
+ name "John Doe"
111
+ end
112
+ end
113
+ end
114
+
115
+ it "uses the overridden create strategy to create the association" do
116
+ FactoryGirl.register_strategy(:insert, custom_strategy)
117
+ post = FactoryGirl.build(:post)
118
+ post.user.name.should == "Custom strategy"
119
+ end
120
+ end
@@ -0,0 +1,19 @@
1
+ require "spec_helper"
2
+
3
+ describe "skipping the default create" do
4
+ before do
5
+ define_model("User", email: :string)
6
+
7
+ FactoryGirl.define do
8
+ factory :user do
9
+ skip_create
10
+
11
+ email "john@example.com"
12
+ end
13
+ end
14
+ end
15
+
16
+ it "doesn't execute anything when creating the instance" do
17
+ FactoryGirl.create(:user).should_not be_persisted
18
+ end
19
+ end
@@ -4,6 +4,8 @@ require 'factory_girl/syntax/blueprint'
4
4
 
5
5
  describe "a blueprint" do
6
6
  before do
7
+ ActiveSupport::Deprecation.silenced = true
8
+
7
9
  define_model('User', first_name: :string, last_name: :string, email: :string)
8
10
 
9
11
  FactoryGirl.define do
@@ -4,6 +4,8 @@ require 'factory_girl/syntax/generate'
4
4
 
5
5
  describe "a factory using generate syntax" do
6
6
  before do
7
+ ActiveSupport::Deprecation.silenced = true
8
+
7
9
  define_model('User', first_name: :string, last_name: :string, email: :string) do
8
10
  validates_presence_of :first_name
9
11
  end
@@ -4,6 +4,8 @@ require 'factory_girl/syntax/make'
4
4
 
5
5
  describe "a factory using make syntax" do
6
6
  before do
7
+ ActiveSupport::Deprecation.silenced = true
8
+
7
9
  define_model('User', first_name: :string, last_name: :string)
8
10
 
9
11
  FactoryGirl.define do
@@ -120,8 +120,8 @@ describe "after defining a factory" do
120
120
 
121
121
  it "recognizes either 'name' or :name for Factory.#{method}" do
122
122
  @factory.stubs(:run)
123
- lambda { Factory.send(method, @name.to_s) }.should_not raise_error
124
- lambda { Factory.send(method, @name.to_sym) }.should_not raise_error
123
+ expect { Factory.send(method, @name.to_s) }.to_not raise_error
124
+ expect { Factory.send(method, @name.to_sym) }.to_not raise_error
125
125
  end
126
126
  end
127
127
  end
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ describe "syntax methods within dynamic attributes" do
4
+ before do
5
+ define_model("Post", title: :string, user_id: :integer) do
6
+ belongs_to :user
7
+
8
+ def generate
9
+ "generate result"
10
+ end
11
+ end
12
+ define_model("User", email: :string)
13
+
14
+ FactoryGirl.define do
15
+ sequence(:email_address) {|n| "person-#{n}@example.com" }
16
+
17
+ factory :user do
18
+ email { generate(:email_address) }
19
+ end
20
+
21
+ factory :post do
22
+ title { generate }
23
+ user { build(:user) }
24
+ end
25
+ end
26
+ end
27
+
28
+ it "can access syntax methods from dynamic attributes" do
29
+ FactoryGirl.build(:user).email.should == "person-1@example.com"
30
+ FactoryGirl.attributes_for(:user)[:email].should == "person-2@example.com"
31
+ end
32
+
33
+ it "can access syntax methods from dynamic attributes" do
34
+ FactoryGirl.build(:post).user.should be_instance_of(User)
35
+ end
36
+
37
+ it "can access methods already existing on the class" do
38
+ FactoryGirl.build(:post).title.should == "generate result"
39
+ FactoryGirl.attributes_for(:post)[:title].should be_nil
40
+ end
41
+ end
@@ -2,14 +2,14 @@ require 'spec_helper'
2
2
 
3
3
  describe FactoryGirl::Attribute::Dynamic do
4
4
  let(:name) { :first_name }
5
- let(:block) { lambda { } }
5
+ let(:block) { -> { } }
6
6
 
7
7
  subject { FactoryGirl::Attribute::Dynamic.new(name, false, block) }
8
8
 
9
9
  its(:name) { should == name }
10
10
 
11
11
  context "with a block returning a static value" do
12
- let(:block) { lambda { "value" } }
12
+ let(:block) { -> { "value" } }
13
13
 
14
14
  it "returns the value when executing the proc" do
15
15
  subject.to_proc.call.should == "value"
@@ -17,7 +17,7 @@ describe FactoryGirl::Attribute::Dynamic do
17
17
  end
18
18
 
19
19
  context "with a block returning its block-level variable" do
20
- let(:block) { lambda {|thing| thing } }
20
+ let(:block) { ->(thing) { thing } }
21
21
 
22
22
  it "returns self when executing the proc" do
23
23
  subject.to_proc.call.should == subject
@@ -25,7 +25,7 @@ describe FactoryGirl::Attribute::Dynamic do
25
25
  end
26
26
 
27
27
  context "with a block referencing an attribute on the attribute" do
28
- let(:block) { lambda { attribute_defined_on_attribute } }
28
+ let(:block) { -> { attribute_defined_on_attribute } }
29
29
  let(:result) { "other attribute value" }
30
30
 
31
31
  before do
@@ -38,7 +38,7 @@ describe FactoryGirl::Attribute::Dynamic do
38
38
  end
39
39
 
40
40
  context "with a block returning a sequence" do
41
- let(:block) { lambda { FactoryGirl.register_sequence(FactoryGirl::Sequence.new(:email, 1) {|n| "foo#{n}" }) } }
41
+ let(:block) { -> { FactoryGirl.register_sequence(FactoryGirl::Sequence.new(:email, 1) {|n| "foo#{n}" }) } }
42
42
 
43
43
  it "raises a sequence abuse error" do
44
44
  expect { subject.to_proc.call }.to raise_error(FactoryGirl::SequenceAbuseError)
@@ -47,6 +47,6 @@ describe FactoryGirl::Attribute::Dynamic do
47
47
  end
48
48
 
49
49
  describe FactoryGirl::Attribute::Dynamic, "with a string name" do
50
- subject { FactoryGirl::Attribute::Dynamic.new("name", false, lambda { } ) }
50
+ subject { FactoryGirl::Attribute::Dynamic.new("name", false, -> { } ) }
51
51
  its(:name) { should == :name }
52
52
  end
@@ -2,7 +2,7 @@ require "spec_helper"
2
2
 
3
3
  describe FactoryGirl::AttributeList, "#define_attribute" do
4
4
  let(:static_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "value", false) }
5
- let(:dynamic_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, lambda {|u| "#{u.full_name}@example.com" }) }
5
+ let(:dynamic_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, ->(u) { "#{u.full_name}@example.com" }) }
6
6
 
7
7
  it "maintains a list of attributes" do
8
8
  subject.define_attribute(static_attribute)
@@ -42,8 +42,8 @@ end
42
42
  describe FactoryGirl::AttributeList, "#apply_attributes" do
43
43
  let(:full_name_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "John Adams", false) }
44
44
  let(:city_attribute) { FactoryGirl::Attribute::Static.new(:city, "Boston", false) }
45
- let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, lambda {|model| "#{model.full_name}@example.com" }) }
46
- let(:login_attribute) { FactoryGirl::Attribute::Dynamic.new(:login, false, lambda {|model| "username-#{model.full_name}" }) }
45
+ let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, ->(model) { "#{model.full_name}@example.com" }) }
46
+ let(:login_attribute) { FactoryGirl::Attribute::Dynamic.new(:login, false, ->(model) { "username-#{model.full_name}" }) }
47
47
 
48
48
  def list(*attributes)
49
49
  FactoryGirl::AttributeList.new.tap do |list|
@@ -61,7 +61,7 @@ end
61
61
 
62
62
  describe FactoryGirl::AttributeList, "#associations" do
63
63
  let(:full_name_attribute) { FactoryGirl::Attribute::Static.new(:full_name, "value", false) }
64
- let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, lambda {|u| "#{u.full_name}@example.com" }) }
64
+ let(:email_attribute) { FactoryGirl::Attribute::Dynamic.new(:email, false, ->(u) { "#{u.full_name}@example.com" }) }
65
65
  let(:author_attribute) { FactoryGirl::Attribute::Association.new(:author, :user, {}) }
66
66
  let(:profile_attribute) { FactoryGirl::Attribute::Association.new(:profile, :profile, {}) }
67
67
 
@@ -2,40 +2,40 @@ require 'spec_helper'
2
2
 
3
3
  describe FactoryGirl::Callback do
4
4
  it "has a name" do
5
- FactoryGirl::Callback.new(:after_create, lambda {}).name.should == :after_create
5
+ FactoryGirl::Callback.new(:after_create, -> {}).name.should == :after_create
6
6
  end
7
7
 
8
8
  it "converts strings to symbols" do
9
- FactoryGirl::Callback.new("after_create", lambda {}).name.should == :after_create
9
+ FactoryGirl::Callback.new("after_create", -> {}).name.should == :after_create
10
10
  end
11
11
 
12
12
  it "runs its block with no parameters" do
13
13
  ran_with = nil
14
- FactoryGirl::Callback.new(:after_create, lambda { ran_with = [] }).run(:one, :two)
14
+ FactoryGirl::Callback.new(:after_create, -> { ran_with = [] }).run(:one, :two)
15
15
  ran_with.should == []
16
16
  end
17
17
 
18
18
  it "runs its block with one parameter" do
19
19
  ran_with = nil
20
- FactoryGirl::Callback.new(:after_create, lambda { |one| ran_with = [one] }).run(:one, :two)
20
+ FactoryGirl::Callback.new(:after_create, ->(one) { ran_with = [one] }).run(:one, :two)
21
21
  ran_with.should == [:one]
22
22
  end
23
23
 
24
24
  it "runs its block with two parameters" do
25
25
  ran_with = nil
26
- FactoryGirl::Callback.new(:after_create, lambda { |one, two| ran_with = [one, two] }).run(:one, :two)
26
+ FactoryGirl::Callback.new(:after_create, ->(one, two) { ran_with = [one, two] }).run(:one, :two)
27
27
  ran_with.should == [:one, :two]
28
28
  end
29
29
 
30
30
  it "allows valid callback names to be assigned" do
31
31
  FactoryGirl.callback_names.each do |callback_name|
32
- expect { FactoryGirl::Callback.new(callback_name, lambda {}) }.
32
+ expect { FactoryGirl::Callback.new(callback_name, -> {}) }.
33
33
  to_not raise_error(FactoryGirl::InvalidCallbackNameError)
34
34
  end
35
35
  end
36
36
 
37
37
  it "raises if an invalid callback name is assigned" do
38
- expect { FactoryGirl::Callback.new(:magic_fairies, lambda {}) }.
38
+ expect { FactoryGirl::Callback.new(:magic_fairies, -> {}) }.
39
39
  to raise_error(FactoryGirl::InvalidCallbackNameError, /magic_fairies is not a valid callback name/)
40
40
  end
41
41
  end
@@ -16,7 +16,7 @@ describe FactoryGirl::DefinitionProxy, "#add_attribute" do
16
16
  end
17
17
 
18
18
  it "declares a dynamic attribute on the factory" do
19
- attribute_value = lambda { "dynamic attribute" }
19
+ attribute_value = -> { "dynamic attribute" }
20
20
  proxy.add_attribute(:attribute_name, &attribute_value)
21
21
  subject.should have_dynamic_declaration(:attribute_name).with_value(attribute_value)
22
22
  end
@@ -38,7 +38,7 @@ describe FactoryGirl::DefinitionProxy, "#add_attribute when the proxy ignores at
38
38
  end
39
39
 
40
40
  it "declares a dynamic attribute on the factory" do
41
- attribute_value = lambda { "dynamic attribute" }
41
+ attribute_value = -> { "dynamic attribute" }
42
42
  proxy.add_attribute(:attribute_name, &attribute_value)
43
43
  subject.should have_dynamic_declaration(:attribute_name).ignored.with_value(attribute_value)
44
44
  end
@@ -77,7 +77,7 @@ describe FactoryGirl::DefinitionProxy, "#method_missing" do
77
77
  end
78
78
 
79
79
  it "declares a dynamic attribute" do
80
- attribute_value = lambda { "dynamic attribute" }
80
+ attribute_value = -> { "dynamic attribute" }
81
81
  proxy.attribute_name &attribute_value
82
82
  subject.should have_dynamic_declaration(:attribute_name).with_value(attribute_value)
83
83
  end
@@ -124,7 +124,7 @@ end
124
124
  describe FactoryGirl::DefinitionProxy, "adding callbacks" do
125
125
  subject { FactoryGirl::Definition.new }
126
126
  let(:proxy) { FactoryGirl::DefinitionProxy.new(subject) }
127
- let(:callback) { lambda { "my awesome callback!" } }
127
+ let(:callback) { -> { "my awesome callback!" } }
128
128
 
129
129
  context "#after_build" do
130
130
  before { proxy.after_build(&callback) }
@@ -147,7 +147,7 @@ describe FactoryGirl::DefinitionProxy, "#to_create" do
147
147
  let(:proxy) { FactoryGirl::DefinitionProxy.new(subject) }
148
148
 
149
149
  it "accepts a block to run in place of #save!" do
150
- to_create_block = lambda {|record| record.persist }
150
+ to_create_block = ->(record) { record.persist }
151
151
  proxy.to_create(&to_create_block)
152
152
  subject.to_create.should == to_create_block
153
153
  end
@@ -168,7 +168,7 @@ describe FactoryGirl::DefinitionProxy, "#factory" do
168
168
  end
169
169
 
170
170
  it "with a block" do
171
- child_block = lambda { }
171
+ child_block = -> { }
172
172
  proxy.factory(:child, {}, &child_block)
173
173
  proxy.child_factories.should include([:child, {}, child_block])
174
174
  end