vitalish-factory_girl 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.rdoc +67 -121
  2. data/Rakefile +103 -29
  3. data/VERSION +1 -0
  4. data/lib/factory_girl/aliases.rb +32 -3
  5. data/lib/factory_girl/attribute/association.rb +1 -1
  6. data/lib/factory_girl/attribute/callback.rb +1 -1
  7. data/lib/factory_girl/attribute/dynamic.rb +3 -3
  8. data/lib/factory_girl/attribute/static.rb +1 -1
  9. data/lib/factory_girl/attribute.rb +3 -3
  10. data/lib/factory_girl/factory.rb +354 -164
  11. data/lib/factory_girl/proxy/attributes_for.rb +1 -1
  12. data/lib/factory_girl/proxy/build.rb +5 -7
  13. data/lib/factory_girl/proxy/create.rb +3 -2
  14. data/lib/factory_girl/proxy/stub.rb +5 -19
  15. data/lib/factory_girl/proxy.rb +23 -7
  16. data/lib/factory_girl/sequence.rb +40 -5
  17. data/lib/factory_girl/step_definitions.rb +13 -19
  18. data/lib/factory_girl/syntax/blueprint.rb +5 -5
  19. data/lib/factory_girl/syntax/generate.rb +8 -13
  20. data/lib/factory_girl/syntax/make.rb +7 -9
  21. data/lib/factory_girl/syntax/sham.rb +8 -11
  22. data/lib/factory_girl/syntax.rb +7 -7
  23. data/lib/factory_girl.rb +19 -8
  24. data/spec/factory_girl/aliases_spec.rb +5 -9
  25. data/spec/factory_girl/attribute/association_spec.rb +4 -4
  26. data/spec/factory_girl/attribute/callback_spec.rb +4 -4
  27. data/spec/factory_girl/attribute/dynamic_spec.rb +10 -21
  28. data/spec/factory_girl/attribute/static_spec.rb +6 -6
  29. data/spec/factory_girl/attribute_spec.rb +6 -6
  30. data/spec/factory_girl/factory_spec.rb +465 -305
  31. data/spec/factory_girl/proxy/attributes_for_spec.rb +3 -3
  32. data/spec/factory_girl/proxy/build_spec.rb +13 -18
  33. data/spec/factory_girl/proxy/create_spec.rb +13 -18
  34. data/spec/factory_girl/proxy/stub_spec.rb +6 -7
  35. data/spec/factory_girl/proxy_spec.rb +3 -3
  36. data/spec/factory_girl/sequence_spec.rb +39 -16
  37. data/spec/factory_girl/syntax/blueprint_spec.rb +34 -0
  38. data/spec/factory_girl/syntax/generate_spec.rb +57 -0
  39. data/spec/factory_girl/syntax/make_spec.rb +35 -0
  40. data/spec/factory_girl/syntax/sham_spec.rb +35 -0
  41. data/spec/integration_spec.rb +304 -0
  42. data/spec/models.rb +43 -0
  43. data/spec/spec_helper.rb +10 -85
  44. metadata +15 -3
@@ -1,12 +1,12 @@
1
- module FactoryGirl
1
+ class Factory
2
2
  # Provides alternate syntaxes for factory_girl. If you don't like the default
3
- # syntax for defining or using factories, look at one of the
4
- # FactoryGirl::Syntax modules:
3
+ # syntax for defining or using factories, look at one of the Factory::Syntax
4
+ # modules:
5
5
  #
6
- # * FactoryGirl::Syntax::Blueprint: definition syntax similar to Machinist
7
- # * FactoryGirl::Syntax::Generate: usage syntax similar to Object Daddy
8
- # * FactoryGirl::Syntax::Make: usage syntax similar to Machinist
9
- # * FactoryGirl::Syntax::Sham: sequence syntax similar to Machinist
6
+ # * Factory::Syntax::Blueprint: definition syntax similar to Machinist
7
+ # * Factory::Syntax::Generate: usage syntax similar to Object Daddy
8
+ # * Factory::Syntax::Make: usage syntax similar to Machinist
9
+ # * Factory::Syntax::Sham: sequence syntax similar to Machinist
10
10
  module Syntax
11
11
  end
12
12
  end
data/lib/factory_girl.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'active_support'
1
2
  require 'factory_girl/proxy'
2
3
  require 'factory_girl/proxy/build'
3
4
  require 'factory_girl/proxy/create'
@@ -11,14 +12,24 @@ require 'factory_girl/attribute/association'
11
12
  require 'factory_girl/attribute/callback'
12
13
  require 'factory_girl/sequence'
13
14
  require 'factory_girl/aliases'
14
- require 'factory_girl/definition_proxy'
15
- require 'factory_girl/syntax/default'
16
- require 'factory_girl/syntax/vintage'
17
- require 'factory_girl/find_definitions'
18
- require 'factory_girl/deprecated'
19
- require 'factory_girl/version'
20
15
 
21
- if defined?(Rails) && Rails::VERSION::MAJOR == 2
22
- require 'factory_girl/rails2'
16
+ # Shortcut for Factory.default_strategy.
17
+ #
18
+ # Example:
19
+ # Factory(:user, :name => 'Joe')
20
+ def Factory (name, attrs = {})
21
+ Factory.default_strategy(name, attrs)
22
+ end
23
+
24
+ if defined? Rails.configuration
25
+ Rails.configuration.after_initialize do
26
+ Factory.definition_file_paths = [
27
+ File.join(RAILS_ROOT, 'test', 'factories'),
28
+ File.join(RAILS_ROOT, 'spec', 'factories')
29
+ ]
30
+ Factory.find_definitions
31
+ end
32
+ else
33
+ Factory.find_definitions
23
34
  end
24
35
 
@@ -1,21 +1,17 @@
1
- require 'spec_helper'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
2
 
3
3
  describe Factory, "aliases" do
4
4
 
5
5
  it "should include an attribute as an alias for itself by default" do
6
- FactoryGirl.aliases_for(:test).should include(:test)
6
+ Factory.aliases_for(:test).should include(:test)
7
7
  end
8
8
 
9
9
  it "should include the root of a foreign key as an alias by default" do
10
- FactoryGirl.aliases_for(:test_id).should include(:test)
10
+ Factory.aliases_for(:test_id).should include(:test)
11
11
  end
12
12
 
13
13
  it "should include an attribute's foreign key as an alias by default" do
14
- FactoryGirl.aliases_for(:test).should include(:test_id)
15
- end
16
-
17
- it "should NOT include an attribute as an alias when it starts with underscore" do
18
- FactoryGirl.aliases_for(:_id).should_not include(:id)
14
+ Factory.aliases_for(:test).should include(:test_id)
19
15
  end
20
16
 
21
17
  describe "after adding an alias" do
@@ -25,7 +21,7 @@ describe Factory, "aliases" do
25
21
  end
26
22
 
27
23
  it "should return the alias in the aliases list" do
28
- FactoryGirl.aliases_for(:test_suffix).should include(:test)
24
+ Factory.aliases_for(:test_suffix).should include(:test)
29
25
  end
30
26
 
31
27
  end
@@ -1,11 +1,11 @@
1
- require 'spec_helper'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
2
 
3
- describe FactoryGirl::Attribute::Association do
3
+ describe Factory::Attribute::Association do
4
4
  before do
5
5
  @name = :author
6
6
  @factory = :user
7
7
  @overrides = { :first_name => 'John' }
8
- @attr = FactoryGirl::Attribute::Association.new(@name, @factory, @overrides)
8
+ @attr = Factory::Attribute::Association.new(@name, @factory, @overrides)
9
9
  end
10
10
 
11
11
  it "should have a name" do
@@ -24,6 +24,6 @@ describe FactoryGirl::Attribute::Association do
24
24
  end
25
25
 
26
26
  it "should convert names to symbols" do
27
- FactoryGirl::Attribute::Association.new('name', :user, {}).name.should == :name
27
+ Factory::Attribute::Association.new('name', :user, {}).name.should == :name
28
28
  end
29
29
  end
@@ -1,10 +1,10 @@
1
- require 'spec_helper'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
2
 
3
- describe FactoryGirl::Attribute::Callback do
3
+ describe Factory::Attribute::Callback do
4
4
  before do
5
5
  @name = :after_create
6
6
  @block = proc{ 'block' }
7
- @attr = FactoryGirl::Attribute::Callback.new(@name, @block)
7
+ @attr = Factory::Attribute::Callback.new(@name, @block)
8
8
  end
9
9
 
10
10
  it "should have a name" do
@@ -18,6 +18,6 @@ describe FactoryGirl::Attribute::Callback do
18
18
  end
19
19
 
20
20
  it "should convert names to symbols" do
21
- FactoryGirl::Attribute::Callback.new('name', nil).name.should == :name
21
+ Factory::Attribute::Callback.new('name', nil).name.should == :name
22
22
  end
23
23
  end
@@ -1,10 +1,10 @@
1
- require 'spec_helper'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
2
 
3
- describe FactoryGirl::Attribute::Dynamic do
3
+ describe Factory::Attribute::Dynamic do
4
4
  before do
5
5
  @name = :first_name
6
6
  @block = lambda { 'value' }
7
- @attr = FactoryGirl::Attribute::Dynamic.new(@name, @block)
7
+ @attr = Factory::Attribute::Dynamic.new(@name, @block)
8
8
  end
9
9
 
10
10
  it "should have a name" do
@@ -20,41 +20,30 @@ describe FactoryGirl::Attribute::Dynamic do
20
20
 
21
21
  it "should yield the proxy to the block when adding its value to a proxy" do
22
22
  @block = lambda {|a| a }
23
- @attr = FactoryGirl::Attribute::Dynamic.new(:user, @block)
23
+ @attr = Factory::Attribute::Dynamic.new(:user, @block)
24
24
  @proxy = "proxy"
25
25
  stub(@proxy).set
26
26
  @attr.add_to(@proxy)
27
27
  @proxy.should have_received.set(:user, @proxy)
28
28
  end
29
29
 
30
- it "evaluates the block with in the context of the proxy without an argument" do
31
- result = 'other attribute value'
32
- @block = lambda { other_attribute }
33
- @attr = FactoryGirl::Attribute::Dynamic.new(:user, @block)
34
- @proxy = "proxy"
35
- stub(@proxy).set
36
- stub(@proxy).other_attribute { result }
37
- @attr.add_to(@proxy)
38
- @proxy.should have_received.set(:user, result)
39
- end
40
-
41
30
  it "should raise an error when defining an attribute writer" do
42
31
  lambda {
43
- FactoryGirl::Attribute::Dynamic.new('test=', nil)
44
- }.should raise_error(FactoryGirl::AttributeDefinitionError)
32
+ Factory::Attribute::Dynamic.new('test=', nil)
33
+ }.should raise_error(Factory::AttributeDefinitionError)
45
34
  end
46
35
 
47
36
  it "should raise an error when returning a sequence" do
48
- stub(Factory).sequence { FactoryGirl::Sequence.new }
37
+ stub(Factory).sequence { Factory::Sequence.new }
49
38
  block = lambda { Factory.sequence(:email) }
50
- attr = FactoryGirl::Attribute::Dynamic.new(:email, block)
39
+ attr = Factory::Attribute::Dynamic.new(:email, block)
51
40
  proxy = stub!.set.subject
52
41
  lambda {
53
42
  attr.add_to(proxy)
54
- }.should raise_error(FactoryGirl::SequenceAbuseError)
43
+ }.should raise_error(Factory::SequenceAbuseError)
55
44
  end
56
45
 
57
46
  it "should convert names to symbols" do
58
- FactoryGirl::Attribute::Dynamic.new('name', nil).name.should == :name
47
+ Factory::Attribute::Dynamic.new('name', nil).name.should == :name
59
48
  end
60
49
  end
@@ -1,10 +1,10 @@
1
- require 'spec_helper'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
2
2
 
3
- describe FactoryGirl::Attribute::Static do
3
+ describe Factory::Attribute::Static do
4
4
  before do
5
5
  @name = :first_name
6
6
  @value = 'John'
7
- @attr = FactoryGirl::Attribute::Static.new(@name, @value)
7
+ @attr = Factory::Attribute::Static.new(@name, @value)
8
8
  end
9
9
 
10
10
  it "should have a name" do
@@ -19,11 +19,11 @@ describe FactoryGirl::Attribute::Static do
19
19
 
20
20
  it "should raise an error when defining an attribute writer" do
21
21
  lambda {
22
- FactoryGirl::Attribute::Static.new('test=', nil)
23
- }.should raise_error(FactoryGirl::AttributeDefinitionError)
22
+ Factory::Attribute::Static.new('test=', nil)
23
+ }.should raise_error(Factory::AttributeDefinitionError)
24
24
  end
25
25
 
26
26
  it "should convert names to symbols" do
27
- FactoryGirl::Attribute::Static.new('name', nil).name.should == :name
27
+ Factory::Attribute::Static.new('name', nil).name.should == :name
28
28
  end
29
29
  end
@@ -1,9 +1,9 @@
1
- require 'spec_helper'
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
2
 
3
- describe FactoryGirl::Attribute do
3
+ describe Factory::Attribute do
4
4
  before do
5
5
  @name = :user
6
- @attr = FactoryGirl::Attribute.new(@name)
6
+ @attr = Factory::Attribute.new(@name)
7
7
  end
8
8
 
9
9
  it "should have a name" do
@@ -20,11 +20,11 @@ describe FactoryGirl::Attribute do
20
20
  it "should raise an error when defining an attribute writer" do
21
21
  error_message = %{factory_girl uses 'f.test value' syntax rather than 'f.test = value'}
22
22
  lambda {
23
- FactoryGirl::Attribute.new('test=')
24
- }.should raise_error(FactoryGirl::AttributeDefinitionError, error_message)
23
+ Factory::Attribute.new('test=')
24
+ }.should raise_error(Factory::AttributeDefinitionError, error_message)
25
25
  end
26
26
 
27
27
  it "should convert names to symbols" do
28
- FactoryGirl::Attribute.new('name').name.should == :name
28
+ Factory::Attribute.new('name').name.should == :name
29
29
  end
30
30
  end
@@ -1,411 +1,571 @@
1
- require 'spec_helper'
2
-
3
- describe FactoryGirl::Factory, "registering a factory" do
4
- before do
5
- @name = :user
6
- @factory = "factory"
7
- @aliases = [:one, :two]
8
- stub(@factory).name { @name }
9
- stub(@factory).aliases { @aliases }
10
- end
11
-
12
- it "should add the factory to the list of factories" do
13
- FactoryGirl.register_factory(@factory)
14
- FactoryGirl.factory_by_name(@name).should == @factory
15
- end
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
16
2
 
17
- it "should not allow a duplicate factory definition" do
18
- lambda {
19
- 2.times { FactoryGirl.register_factory(@factory) }
20
- }.should raise_error(FactoryGirl::DuplicateDefinitionError)
21
- end
3
+ describe Factory do
4
+ describe "defining a factory" do
5
+ before do
6
+ @name = :user
7
+ @factory = "factory"
8
+ stub(@factory).factory_name { @name }
9
+ @options = { :class => 'magic' }
10
+ stub(Factory).new { @factory }
11
+ end
22
12
 
23
- it "registers aliases" do
24
- FactoryGirl.register_factory(@factory)
25
- @aliases.each do |name|
26
- FactoryGirl.factory_by_name(name).should == @factory
13
+ it "should create a new factory using the specified name and options" do
14
+ mock(Factory).new(@name, @options) { @factory }
15
+ Factory.define(@name, @options) {|f| }
27
16
  end
28
- end
29
- end
30
17
 
31
- describe FactoryGirl::Factory do
32
- include DefinesConstants
18
+ it "should pass the factory do the block" do
19
+ yielded = nil
20
+ Factory.define(@name) do |y|
21
+ yielded = y
22
+ end
23
+ yielded.should == @factory
24
+ end
33
25
 
34
- before do
35
- @name = :user
36
- @class = define_class('User')
37
- @factory = FactoryGirl::Factory.new(@name)
38
- end
26
+ it "should add the factory to the list of factories" do
27
+ Factory.define(@name) {|f| }
28
+ @factory.should == Factory.factories[@name]
29
+ end
39
30
 
40
- it "should have a factory name" do
41
- @factory.name.should == @name
31
+ it "should allow that factory to be found by name" do
32
+ Factory.factory_by_name(@name).should == @factory
33
+ end
42
34
  end
43
35
 
44
- it "responds to factory_name" do
45
- @factory.factory_name.should == @name
46
- end
36
+ describe "a factory" do
37
+ before do
38
+ @name = :user
39
+ @class = User
40
+ @factory = Factory.new(@name)
41
+ end
47
42
 
48
- it "should have a build class" do
49
- @factory.build_class.should == @class
50
- end
43
+ it "should have a factory name" do
44
+ @factory.factory_name.should == @name
45
+ end
51
46
 
52
- it "should have a default strategy" do
53
- @factory.default_strategy.should == :create
54
- end
47
+ it "should have a build class" do
48
+ @factory.build_class.should == @class
49
+ end
55
50
 
56
- it "should not allow the same attribute to be added twice" do
57
- lambda {
58
- 2.times { @factory.define_attribute FactoryGirl::Attribute::Static.new(:name, 'value') }
59
- }.should raise_error(FactoryGirl::AttributeDefinitionError)
60
- end
51
+ it "should have a default strategy" do
52
+ @factory.default_strategy.should == :create
53
+ end
61
54
 
62
- it "should add a callback attribute when defining a callback" do
63
- mock(FactoryGirl::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
64
- @factory.add_callback(:after_create) {}
65
- @factory.attributes.should include('after_create callback')
66
- end
55
+ it "should not allow the same attribute to be added twice" do
56
+ lambda {
57
+ 2.times { @factory.add_attribute :first_name }
58
+ }.should raise_error(Factory::AttributeDefinitionError)
59
+ end
67
60
 
68
- it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do
69
- lambda{
70
- @factory.add_callback(:invalid_callback_name) {}
71
- }.should raise_error(FactoryGirl::InvalidCallbackNameError)
72
- end
61
+ it "should add a static attribute when an attribute is defined with a value" do
62
+ attribute = 'attribute'
63
+ stub(attribute).name { :name }
64
+ mock(Factory::Attribute::Static).new(:name, 'value') { attribute }
65
+ @factory.add_attribute(:name, 'value')
66
+ end
73
67
 
74
- describe "after adding an attribute" do
75
- before do
76
- @attribute = "attribute"
77
- @proxy = "proxy"
68
+ it "should add a dynamic attribute when an attribute is defined with a block" do
69
+ attribute = 'attribute'
70
+ stub(attribute).name { :name }
71
+ block = lambda {}
72
+ mock(Factory::Attribute::Dynamic).new(:name, block) { attribute }
73
+ @factory.add_attribute(:name, &block)
74
+ end
78
75
 
79
- stub(@attribute).name { :name }
80
- stub(@attribute).add_to
81
- stub(@proxy).set
82
- stub(@proxy).result { 'result' }
83
- stub(FactoryGirl::Attribute::Static).new { @attribute }
84
- stub(FactoryGirl::Proxy::Build).new { @proxy }
76
+ it "should raise for an attribute with a value and a block" do
77
+ lambda {
78
+ @factory.add_attribute(:name, 'value') {}
79
+ }.should raise_error(Factory::AttributeDefinitionError)
80
+ end
85
81
 
86
- @factory.define_attribute(@attribute)
82
+ describe "adding an attribute using a in-line sequence" do
83
+ it "should create the sequence" do
84
+ mock(Factory::Sequence).new
85
+ @factory.sequence(:name) {}
86
+ end
87
+
88
+ it "should add a dynamic attribute" do
89
+ attribute = 'attribute'
90
+ stub(attribute).name { :name }
91
+ mock(Factory::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute }
92
+ @factory.sequence(:name) {}
93
+ @factory.attributes.should include(attribute)
94
+ end
87
95
  end
88
96
 
89
- it "should create the right proxy using the build class when running" do
90
- mock(FactoryGirl::Proxy::Build).new(@factory.build_class) { @proxy }
91
- @factory.run(FactoryGirl::Proxy::Build, {})
97
+ describe "adding a callback" do
98
+ it "should add a callback attribute when the after_build attribute is defined" do
99
+ mock(Factory::Attribute::Callback).new(:after_build, is_a(Proc)) { 'after_build callback' }
100
+ @factory.after_build {}
101
+ @factory.attributes.should include('after_build callback')
102
+ end
103
+
104
+ it "should add a callback attribute when the after_create attribute is defined" do
105
+ mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
106
+ @factory.after_create {}
107
+ @factory.attributes.should include('after_create callback')
108
+ end
109
+
110
+ it "should add a callback attribute when the after_stub attribute is defined" do
111
+ mock(Factory::Attribute::Callback).new(:after_stub, is_a(Proc)) { 'after_stub callback' }
112
+ @factory.after_stub {}
113
+ @factory.attributes.should include('after_stub callback')
114
+ end
115
+
116
+ it "should add a callback attribute when defining a callback" do
117
+ mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
118
+ @factory.callback(:after_create) {}
119
+ @factory.attributes.should include('after_create callback')
120
+ end
121
+
122
+ it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do
123
+ lambda{
124
+ @factory.callback(:invalid_callback_name) {}
125
+ }.should raise_error(Factory::InvalidCallbackNameError)
126
+ end
92
127
  end
93
128
 
94
- it "should add the attribute to the proxy when running" do
95
- mock(@attribute).add_to(@proxy)
96
- @factory.run(FactoryGirl::Proxy::Build, {})
129
+ describe "after adding an attribute" do
130
+ before do
131
+ @attribute = "attribute"
132
+ @proxy = "proxy"
133
+
134
+ stub(@attribute).name { :name }
135
+ stub(@attribute).add_to
136
+ stub(@proxy).set
137
+ stub(@proxy).result { 'result' }
138
+ stub(Factory::Attribute::Static).new { @attribute }
139
+ stub(Factory::Proxy::Build).new { @proxy }
140
+
141
+ @factory.add_attribute(:name, 'value')
142
+ end
143
+
144
+ it "should create the right proxy using the build class when running" do
145
+ mock(Factory::Proxy::Build).new(@factory.build_class) { @proxy }
146
+ @factory.run(Factory::Proxy::Build, {})
147
+ end
148
+
149
+ it "should add the attribute to the proxy when running" do
150
+ mock(@attribute).add_to(@proxy)
151
+ @factory.run(Factory::Proxy::Build, {})
152
+ end
153
+
154
+ it "should return the result from the proxy when running" do
155
+ mock(@proxy).result() { 'result' }
156
+ @factory.run(Factory::Proxy::Build, {}).should == 'result'
157
+ end
97
158
  end
98
159
 
99
- it "should return the result from the proxy when running" do
100
- mock(@proxy).result() { 'result' }
101
- @factory.run(FactoryGirl::Proxy::Build, {}).should == 'result'
160
+ it "should add an association without a factory name or overrides" do
161
+ factory = Factory.new(:post)
162
+ name = :user
163
+ attr = 'attribute'
164
+ mock(Factory::Attribute::Association).new(name, name, {}) { attr }
165
+ factory.association(name)
166
+ factory.attributes.should include(attr)
102
167
  end
103
- end
104
168
 
105
- it "should return associations" do
106
- factory = FactoryGirl::Factory.new(:post)
107
- factory.define_attribute(FactoryGirl::Attribute::Association.new(:author, :author, {}))
108
- factory.define_attribute(FactoryGirl::Attribute::Association.new(:editor, :editor, {}))
109
- factory.associations.each do |association|
110
- association.should be_a(FactoryGirl::Attribute::Association)
169
+ it "should return associations" do
170
+ factory = Factory.new(:post)
171
+ factory.association(:author)
172
+ factory.association(:editor)
173
+ factory.associations.each do |association|
174
+ association.should be_a(Factory::Attribute::Association)
175
+ end
176
+ factory.associations.size.should == 2
111
177
  end
112
- factory.associations.size.should == 2
113
- end
114
178
 
115
- it "should raise for a self referencing association" do
116
- factory = FactoryGirl::Factory.new(:post)
117
- lambda {
118
- factory.define_attribute(FactoryGirl::Attribute::Association.new(:parent, :post, {}))
119
- }.should raise_error(FactoryGirl::AssociationDefinitionError)
120
- end
179
+ it "should add an association with overrides" do
180
+ factory = Factory.new(:post)
181
+ name = :user
182
+ attr = 'attribute'
183
+ overrides = { :first_name => 'Ben' }
184
+ mock(Factory::Attribute::Association).new(name, name, overrides) { attr }
185
+ factory.association(name, overrides)
186
+ factory.attributes.should include(attr)
187
+ end
121
188
 
122
- describe "when overriding generated attributes with a hash" do
123
- before do
124
- @name = :name
125
- @value = 'The price is right!'
126
- @hash = { @name => @value }
189
+ it "should add an association with a factory name" do
190
+ factory = Factory.new(:post)
191
+ attr = 'attribute'
192
+ mock(Factory::Attribute::Association).new(:author, :user, {}) { attr }
193
+ factory.association(:author, :factory => :user)
194
+ factory.attributes.should include(attr)
127
195
  end
128
196
 
129
- it "should return the overridden value in the generated attributes" do
130
- attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
131
- @factory.define_attribute(attr)
132
- result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
133
- result[@name].should == @value
197
+ it "should add an association with a factory name and overrides" do
198
+ factory = Factory.new(:post)
199
+ attr = 'attribute'
200
+ mock(Factory::Attribute::Association).new(:author, :user, :first_name => 'Ben') { attr }
201
+ factory.association(:author, :factory => :user, :first_name => 'Ben')
202
+ factory.attributes.should include(attr)
134
203
  end
135
204
 
136
- it "should not call a lazy attribute block for an overridden attribute" do
137
- attr = FactoryGirl::Attribute::Dynamic.new(@name, lambda { flunk })
138
- @factory.define_attribute(attr)
139
- result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
205
+ it "should raise for a self referencing association" do
206
+ factory = Factory.new(:post)
207
+ lambda {
208
+ factory.association(:parent, :factory => :post)
209
+ }.should raise_error(Factory::AssociationDefinitionError)
140
210
  end
141
211
 
142
- it "should override a symbol parameter with a string parameter" do
143
- attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
144
- @factory.define_attribute(attr)
145
- @hash = { @name.to_s => @value }
146
- result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
147
- result[@name].should == @value
212
+ it "should add an attribute using the method name when passed an undefined method" do
213
+ attribute = 'attribute'
214
+ stub(attribute).name { :name }
215
+ block = lambda {}
216
+ mock(Factory::Attribute::Static).new(:name, 'value') { attribute }
217
+ @factory.send(:name, 'value')
218
+ @factory.attributes.should include(attribute)
148
219
  end
149
- end
150
220
 
151
- describe "overriding an attribute with an alias" do
152
- before do
153
- @factory.define_attribute(FactoryGirl::Attribute::Static.new(:test, 'original'))
154
- Factory.alias(/(.*)_alias/, '\1')
155
- @result = @factory.run(FactoryGirl::Proxy::AttributesFor,
156
- :test_alias => 'new')
221
+ it "should allow human_name as a static attribute name" do
222
+ attribute = 'attribute'
223
+ stub(attribute).name { :name }
224
+ mock(Factory::Attribute::Static).new(:human_name, 'value') { attribute}
225
+ @factory.human_name 'value'
157
226
  end
158
227
 
159
- it "should use the passed in value for the alias" do
160
- @result[:test_alias].should == 'new'
228
+ it "should allow human_name as a dynamic attribute name" do
229
+ attribute = 'attribute'
230
+ stub(attribute).name { :name }
231
+ block = lambda {}
232
+ mock(Factory::Attribute::Dynamic).new(:human_name, block) { attribute }
233
+ @factory.human_name(&block)
161
234
  end
162
235
 
163
- it "should discard the predefined value for the attribute" do
164
- @result[:test].should be_nil
236
+ describe "when overriding generated attributes with a hash" do
237
+ before do
238
+ @attr = :name
239
+ @value = 'The price is right!'
240
+ @hash = { @attr => @value }
241
+ end
242
+
243
+ it "should return the overridden value in the generated attributes" do
244
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
245
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
246
+ result[@attr].should == @value
247
+ end
248
+
249
+ it "should not call a lazy attribute block for an overridden attribute" do
250
+ @factory.add_attribute(@attr) { flunk }
251
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
252
+ end
253
+
254
+ it "should override a symbol parameter with a string parameter" do
255
+ @factory.add_attribute(@attr, 'The price is wrong, Bob!')
256
+ @hash = { @attr.to_s => @value }
257
+ result = @factory.run(Factory::Proxy::AttributesFor, @hash)
258
+ result[@attr].should == @value
259
+ end
165
260
  end
166
- end
167
261
 
168
- it "should guess the build class from the factory name" do
169
- @factory.build_class.should == User
170
- end
262
+ describe "overriding an attribute with an alias" do
263
+ before do
264
+ @factory.add_attribute(:test, 'original')
265
+ Factory.alias(/(.*)_alias/, '\1')
266
+ @result = @factory.run(Factory::Proxy::AttributesFor,
267
+ :test_alias => 'new')
268
+ end
269
+
270
+ it "should use the passed in value for the alias" do
271
+ @result[:test_alias].should == 'new'
272
+ end
273
+
274
+ it "should discard the predefined value for the attribute" do
275
+ @result[:test].should be_nil
276
+ end
277
+ end
171
278
 
172
- it "should create a new factory using the class of the parent" do
173
- child = FactoryGirl::Factory.new(:child)
174
- child.inherit_from(@factory)
175
- child.build_class.should == @factory.build_class
176
- end
279
+ it "should guess the build class from the factory name" do
280
+ @factory.build_class.should == User
281
+ end
177
282
 
178
- it "should create a new factory while overriding the parent class" do
179
- child = FactoryGirl::Factory.new(:child, :class => String)
180
- child.inherit_from(@factory)
181
- child.build_class.should == String
182
- end
283
+ describe "when defined with a custom class" do
284
+ before do
285
+ @class = User
286
+ @factory = Factory.new(:author, :class => @class)
287
+ end
183
288
 
184
- describe "given a parent with attributes" do
185
- before do
186
- @parent_attr = :name
187
- @factory.define_attribute(FactoryGirl::Attribute::Static.new(@parent_attr, 'value'))
289
+ it "should use the specified class as the build class" do
290
+ @factory.build_class.should == @class
291
+ end
188
292
  end
189
293
 
190
- it "should create a new factory with attributes of the parent" do
191
- child = FactoryGirl::Factory.new(:child)
192
- child.inherit_from(@factory)
193
- child.attributes.size.should == 1
194
- child.attributes.first.name.should == @parent_attr
195
- end
294
+ describe "when defined with a class instead of a name" do
295
+ before do
296
+ @class = ArgumentError
297
+ @name = :argument_error
298
+ @factory = Factory.new(@class)
299
+ end
196
300
 
197
- it "should allow a child to define additional attributes" do
198
- child = FactoryGirl::Factory.new(:child)
199
- child.define_attribute(FactoryGirl::Attribute::Static.new(:email, 'value'))
200
- child.inherit_from(@factory)
201
- child.attributes.size.should == 2
301
+ it "should guess the name from the class" do
302
+ @factory.factory_name.should == @name
303
+ end
304
+
305
+ it "should use the class as the build class" do
306
+ @factory.build_class.should == @class
307
+ end
202
308
  end
203
309
 
204
- it "should allow to override parent attributes" do
205
- child = FactoryGirl::Factory.new(:child)
206
- @child_attr = FactoryGirl::Attribute::Static.new(@parent_attr, 'value')
207
- child.define_attribute(@child_attr)
208
- child.inherit_from(@factory)
209
- child.attributes.size.should == 1
210
- child.attributes.first.should == @child_attr
310
+ describe "when defined with a custom class name" do
311
+ before do
312
+ @class = ArgumentError
313
+ @factory = Factory.new(:author, :class => :argument_error)
314
+ end
315
+
316
+ it "should use the specified class as the build class" do
317
+ @factory.build_class.should == @class
318
+ end
211
319
  end
320
+ end
212
321
 
213
- it "should allow to use parent attributes in defining additional attributes" do
214
- User.class_eval { attr_accessor :name, :email }
322
+ describe "a factory with a name ending in s" do
323
+ before do
324
+ @name = :business
325
+ @class = Business
326
+ @factory = Factory.new(@name)
327
+ end
215
328
 
216
- child = FactoryGirl::Factory.new(:child)
217
- @child_attr = FactoryGirl::Attribute::Dynamic.new(:email, lambda {|u| "#{u.name}@example.com"})
218
- child.define_attribute(@child_attr)
219
- child.inherit_from(@factory)
220
- child.attributes.size.should == 2
329
+ it "should have a factory name" do
330
+ @factory.factory_name.should == @name
331
+ end
221
332
 
222
- result = child.run(FactoryGirl::Proxy::Build, {})
223
- result.email.should == 'value@example.com'
333
+ it "should have a build class" do
334
+ @factory.build_class.should == @class
224
335
  end
225
336
  end
226
337
 
227
- it "inherit all callbacks" do
228
- @factory.add_callback(:after_stub) { |object| object.name = 'Stubby' }
229
- child = FactoryGirl::Factory.new(:child)
230
- child.inherit_from(@factory)
231
- child.attributes.last.should be_kind_of(FactoryGirl::Attribute::Callback)
232
- end
233
- end
338
+ describe "a factory with a string for a name" do
339
+ before do
340
+ @name = :user
341
+ @factory = Factory.new(@name.to_s) {}
342
+ end
234
343
 
235
- describe FactoryGirl::Factory, "when defined with a custom class" do
236
- before do
237
- @class = Float
238
- @factory = FactoryGirl::Factory.new(:author, :class => @class)
344
+ it "should convert the string to a symbol" do
345
+ @factory.factory_name.should == @name
346
+ end
239
347
  end
240
348
 
241
- it "should use the specified class as the build class" do
242
- @factory.build_class.should == @class
243
- end
244
- end
349
+ describe "a factory defined with a string name" do
350
+ before do
351
+ Factory.factories = {}
352
+ @name = :user
353
+ @factory = Factory.define(@name.to_s) {}
354
+ end
245
355
 
246
- describe FactoryGirl::Factory, "when defined with a class instead of a name" do
247
- before do
248
- @class = ArgumentError
249
- @name = :argument_error
250
- @factory = FactoryGirl::Factory.new(@class)
356
+ it "should store the factory using a symbol" do
357
+ Factory.factories[@name].should == @factory
358
+ end
251
359
  end
252
360
 
253
- it "should guess the name from the class" do
254
- @factory.name.should == @name
255
- end
361
+ describe "after defining a factory" do
362
+ before do
363
+ @name = :user
364
+ @factory = "factory"
256
365
 
257
- it "should use the class as the build class" do
258
- @factory.build_class.should == @class
259
- end
260
- end
366
+ Factory.factories[@name] = @factory
367
+ end
261
368
 
262
- describe FactoryGirl::Factory, "when defined with a custom class name" do
263
- before do
264
- @class = ArgumentError
265
- @factory = FactoryGirl::Factory.new(:author, :class => :argument_error)
266
- end
369
+ after { Factory.factories.clear }
267
370
 
268
- it "should use the specified class as the build class" do
269
- @factory.build_class.should == @class
270
- end
271
- end
371
+ it "should use Proxy::AttributesFor for Factory.attributes_for" do
372
+ mock(@factory).run(Factory::Proxy::AttributesFor, :attr => 'value') { 'result' }
373
+ Factory.attributes_for(@name, :attr => 'value').should == 'result'
374
+ end
272
375
 
273
- describe FactoryGirl::Factory, "with a name ending in s" do
274
- include DefinesConstants
376
+ it "should use Proxy::Build for Factory.build" do
377
+ mock(@factory).run(Factory::Proxy::Build, :attr => 'value') { 'result' }
378
+ Factory.build(@name, :attr => 'value').should == 'result'
379
+ end
275
380
 
276
- before do
277
- define_class('Business')
278
- @name = :business
279
- @class = Business
280
- @factory = FactoryGirl::Factory.new(@name)
281
- end
381
+ it "should use Proxy::Create for Factory.create" do
382
+ mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
383
+ Factory.create(@name, :attr => 'value').should == 'result'
384
+ end
282
385
 
283
- it "should have a factory name" do
284
- @factory.name.should == @name
285
- end
386
+ it "should use Proxy::Stub for Factory.stub" do
387
+ mock(@factory).run(Factory::Proxy::Stub, :attr => 'value') { 'result' }
388
+ Factory.stub(@name, :attr => 'value').should == 'result'
389
+ end
286
390
 
287
- it "should have a build class" do
288
- @factory.build_class.should == @class
289
- end
290
- end
391
+ it "should use default strategy option as Factory.default_strategy" do
392
+ stub(@factory).default_strategy { :create }
393
+ mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
394
+ Factory.default_strategy(@name, :attr => 'value').should == 'result'
395
+ end
291
396
 
292
- describe FactoryGirl::Factory, "with a string for a name" do
293
- before do
294
- @name = :string
295
- @factory = FactoryGirl::Factory.new(@name.to_s) {}
296
- end
397
+ it "should use the default strategy for the global Factory method" do
398
+ stub(@factory).default_strategy { :create }
399
+ mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' }
400
+ Factory(@name, :attr => 'value').should == 'result'
401
+ end
297
402
 
298
- it "should convert the string to a symbol" do
299
- @factory.name.should == @name
300
- end
301
- end
403
+ [:build, :create, :attributes_for, :stub].each do |method|
404
+ it "should raise an ArgumentError on #{method} with a nonexistant factory" do
405
+ lambda { Factory.send(method, :bogus) }.should raise_error(ArgumentError)
406
+ end
302
407
 
303
- describe FactoryGirl::Factory, "registered with a string name" do
304
- before do
305
- @name = :string
306
- @factory = FactoryGirl::Factory.new(@name)
307
- FactoryGirl.register_factory(@factory)
408
+ it "should recognize either 'name' or :name for Factory.#{method}" do
409
+ stub(@factory).run
410
+ lambda { Factory.send(method, @name.to_s) }.should_not raise_error
411
+ lambda { Factory.send(method, @name.to_sym) }.should_not raise_error
412
+ end
413
+ end
308
414
  end
309
415
 
310
- it "should store the factory using a symbol" do
311
- FactoryGirl.factories[@name].should == @factory
312
- end
313
- end
416
+ describe 'defining a factory with a parent parameter' do
417
+ before do
418
+ @parent = Factory.define :object do |f|
419
+ f.name 'Name'
420
+ end
421
+ end
314
422
 
315
- describe FactoryGirl::Factory, "registered with a custom name" do
316
- before do
317
- @actual_name = :string
318
- @custom_name = :words
319
- @factory = FactoryGirl::Factory.new(@actual_name)
423
+ it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
424
+ lambda {
425
+ Factory.define(:child, :parent => :nonexsitent) {}
426
+ }.should raise_error(ArgumentError)
427
+ end
320
428
 
321
- FactoryGirl.register_factory(@factory, :as => @custom_name)
322
- end
429
+ it "should create a new factory using the class of the parent" do
430
+ child = Factory.define(:child, :parent => :object) {}
431
+ child.build_class.should == @parent.build_class
432
+ end
323
433
 
324
- it "finds the factory using the custom name" do
325
- FactoryGirl.factory_by_name(@custom_name).should == @factory
326
- end
327
- end
434
+ it "should create a new factory while overriding the parent class" do
435
+ class Other; end
328
436
 
329
- describe FactoryGirl::Factory, "for namespaced class" do
330
- include DefinesConstants
437
+ child = Factory.define(:child, :parent => :object, :class => Other) {}
438
+ child.build_class.should == Other
439
+ end
331
440
 
332
- before do
333
- define_class('Admin')
334
- define_class('Admin::Settings')
441
+ it "should create a new factory with attributes of the parent" do
442
+ child = Factory.define(:child, :parent => :object) {}
443
+ child.attributes.size.should == 1
444
+ child.attributes.first.name.should == :name
445
+ end
335
446
 
336
- @name = :settings
337
- @class = Admin::Settings
338
- end
447
+ it "should allow to define additional attributes" do
448
+ child = Factory.define(:child, :parent => :object) do |f|
449
+ f.email 'person@somebody.com'
450
+ end
451
+ child.attributes.size.should == 2
452
+ end
339
453
 
340
- it "should build namespaced class passed by string" do
341
- factory = FactoryGirl::Factory.new(@name.to_s, :class => @class.name)
342
- factory.build_class.should == @class
343
- end
454
+ it "should allow to override parent attributes" do
455
+ child = Factory.define(:child, :parent => :object) do |f|
456
+ f.name { 'Child Name' }
457
+ end
458
+ child.attributes.size.should == 1
459
+ child.attributes.first.should be_kind_of(Factory::Attribute::Dynamic)
460
+ end
344
461
 
345
- it "should build Admin::Settings class from Admin::Settings string" do
346
- factory = FactoryGirl::Factory.new(@name.to_s, :class => 'admin/settings')
347
- factory.build_class.should == @class
348
- end
349
- end
462
+ it "inherit all callbacks" do
463
+ Factory.define(:child, :parent => :object) do |f|
464
+ f.after_stub {|o| o.name = 'Stubby' }
465
+ end
350
466
 
351
- describe FactoryGirl::Factory do
352
- include DefinesConstants
467
+ grandchild = Factory.define(:grandchild, :parent => :child) do |f|
468
+ f.after_stub {|o| o.name = "#{o.name} McStubby" }
469
+ end
353
470
 
354
- before do
355
- define_class('User')
356
- define_class('Admin', User)
471
+ grandchild.attributes.size.should == 3
472
+ grandchild.attributes.first.should be_kind_of(Factory::Attribute::Callback)
473
+ grandchild.attributes[1].should be_kind_of(Factory::Attribute::Callback)
474
+ end
357
475
  end
358
476
 
359
- it "should raise an ArgumentError when trying to use a non-existent strategy" do
360
- lambda {
361
- FactoryGirl::Factory.new(:object, :default_strategy => :nonexistent) {}
362
- }.should raise_error(ArgumentError)
363
- end
477
+ describe 'defining a factory with a default strategy parameter' do
478
+ it "should raise an ArgumentError when trying to use a non-existent factory" do
479
+ lambda {
480
+ Factory.define(:object, :default_strategy => :nonexistent) {}
481
+ }.should raise_error(ArgumentError)
482
+ end
364
483
 
365
- it "should create a new factory with a specified default strategy" do
366
- factory = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
367
- factory.default_strategy.should == :stub
484
+ it "should create a new factory with a specified default strategy" do
485
+ factory = Factory.define(:object, :default_strategy => :stub) {}
486
+ factory.default_strategy.should == :stub
487
+ end
368
488
  end
369
489
 
370
- describe 'defining a child factory without setting default strategy' do
490
+ def self.in_directory_with_files(*files)
371
491
  before do
372
- @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
373
- @child = FactoryGirl::Factory.new(:child_object)
374
- @child.inherit_from(@parent)
492
+ @pwd = Dir.pwd
493
+ @tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
494
+ FileUtils.mkdir_p @tmp_dir
495
+ Dir.chdir(@tmp_dir)
496
+
497
+ files.each do |file|
498
+ FileUtils.mkdir_p File.dirname(file)
499
+ FileUtils.touch file
500
+ stub(Factory).require(file)
501
+ end
375
502
  end
376
503
 
377
- it "should inherit default strategy from its parent" do
378
- @child.default_strategy.should == :stub
504
+ after do
505
+ Dir.chdir(@pwd)
506
+ FileUtils.rm_rf(@tmp_dir)
379
507
  end
380
508
  end
381
509
 
382
- describe 'defining a child factory with a default strategy' do
383
- before do
384
- @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
385
- @child = FactoryGirl::Factory.new(:child_object2, :default_strategy => :build)
386
- @child.inherit_from(@parent)
510
+ def require_definitions_from(file)
511
+ simple_matcher do |given, matcher|
512
+ has_received = have_received.require(file)
513
+ result = has_received.matches?(given)
514
+ matcher.description = "require definitions from #{file}"
515
+ matcher.failure_message = has_received.failure_message
516
+ result
387
517
  end
518
+ end
388
519
 
389
- it "should override the default strategy from parent" do
390
- @child.default_strategy.should == :build
520
+ share_examples_for "finds definitions" do
521
+ before do
522
+ stub(Factory).require
523
+ Factory.find_definitions
391
524
  end
525
+ subject { Factory }
392
526
  end
393
527
 
394
- end
528
+ describe "with factories.rb" do
529
+ in_directory_with_files 'factories.rb'
530
+ it_should_behave_like "finds definitions"
531
+ it { should require_definitions_from('factories.rb') }
532
+ end
395
533
 
396
- describe FactoryGirl::Factory, "with an underscore in the name" do
397
- subject { FactoryGirl::Factory.new("happy_users") }
534
+ %w(spec test).each do |dir|
535
+ describe "with a factories file under #{dir}" do
536
+ in_directory_with_files File.join(dir, 'factories.rb')
537
+ it_should_behave_like "finds definitions"
538
+ it { should require_definitions_from("#{dir}/factories.rb") }
539
+ end
398
540
 
399
- it "has a human name" do
400
- subject.human_name.should == 'happy users'
401
- end
402
- end
541
+ describe "with a factories file under #{dir}/factories" do
542
+ in_directory_with_files File.join(dir, 'factories', 'post_factory.rb')
543
+ it_should_behave_like "finds definitions"
544
+ it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
545
+ end
403
546
 
547
+ describe "with several factories files under #{dir}/factories" do
548
+ in_directory_with_files File.join(dir, 'factories', 'post_factory.rb'),
549
+ File.join(dir, 'factories', 'person_factory.rb')
550
+ it_should_behave_like "finds definitions"
551
+ it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
552
+ it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
553
+ end
404
554
 
405
- describe FactoryGirl::Factory, "with aliases" do
406
- it "registers the aliases" do
407
- aliased_name = :guest
408
- factory = FactoryGirl::Factory.new("user", :aliases => [aliased_name])
409
- factory.aliases.should == [aliased_name]
555
+ describe "with nested and unnested factories files under #{dir}" do
556
+ in_directory_with_files File.join(dir, 'factories.rb'),
557
+ File.join(dir, 'factories', 'post_factory.rb'),
558
+ File.join(dir, 'factories', 'person_factory.rb')
559
+ it_should_behave_like "finds definitions"
560
+ it { should require_definitions_from("#{dir}/factories.rb") }
561
+ it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
562
+ it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
563
+ end
410
564
  end
565
+
566
+ it "should return the factory name without underscores for the human name" do
567
+ factory = Factory.new(:name_with_underscores)
568
+ factory.human_name.should == 'name with underscores'
569
+ end
570
+
411
571
  end