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
data/.autotest CHANGED
@@ -2,7 +2,7 @@ Autotest.add_hook :initialize do |at|
2
2
  at.clear_mappings
3
3
 
4
4
  at.add_mapping(%r{^test/.*_test\.rb$}) {|f, _| [f] }
5
- at.add_mapping(%r{^lib/factory_girl/(.*)\.rb$}) {|_, m| ["test/#{m[1]}_test.rb",
5
+ at.add_mapping(%r{^lib/factory_girl/(.*)\.rb$}) {|_, m| ["test/#{m[1]}_test.rb",
6
6
  "test/integration_test.rb"] }
7
7
  at.add_mapping(%r{^test/(test_helper|models)\.rb$}) { at.files_matching %r{^test/.*_test\.rb$} }
8
8
  at.add_mapping(%r{^lib/.*\.rb$}) { at.files_matching %r{^test/.*_test\.rb$} }
@@ -1,4 +1,4 @@
1
- Contributing to factory_girl:
1
+ Contributing to factory\_girl:
2
2
 
3
3
  1. Fork the [official repository](http://github.com/thoughtbot/factory_girl/tree/master).
4
4
  2. Make your changes in a topic branch.
data/Changelog CHANGED
@@ -1,3 +1,16 @@
1
+ 2.3.0 (November 18, 2011)
2
+ Registries are named, resulting in better messages when factories, traits,
3
+ or sequences cannot be found
4
+ Fix incorrect tests
5
+ Internals refactoring introducing FactoryGirl::NullFactory,
6
+ FactoryGirl::Definition, and FactoryGirl::DeclarationList
7
+ Use ActiveSupport for Hash#except and its delegation capabilities
8
+ Fix usage of callbacks when added via implicit traits
9
+ Use Bundler tasks and clean up dependencies
10
+ Fix failing spec for big letters in factory name passed as symbol
11
+ Add ability for traits to be added dynamically when creating an instance via
12
+ build, create, build_stubbed, or attributes_for
13
+
1
14
  2.2.0 (October 14, 2011)
2
15
  Clean up RSpec suite to not use 'should'
3
16
  Use create_list in step definitions
@@ -41,7 +54,7 @@
41
54
  Josh Nichols)
42
55
  Factory names ending in 's' no longer cause problems (thanks to Alex Sharp
43
56
  and Josh Owens)
44
-
57
+
45
58
  1.1.3 (September 12, 2008)
46
59
  Automatically pull in definitions from factories.rb, test/factories.rb, or
47
60
  spec/factories.rb
@@ -54,10 +67,10 @@
54
67
  1.1.1 (June 23, 2008)
55
68
  The attribute "name" no longer requires using #add_attribute
56
69
 
57
- 1.1.0 (June 3, 2008)
70
+ 1.1.0 (June 03, 2008)
58
71
  Added support for dependent attributes
59
72
  Fixed the attributes_for build strategy to not build associations
60
73
  Added support for sequences
61
74
 
62
- 1.0.0 (May 31, 208)
75
+ 1.0.0 (May 31, 2008)
63
76
  First version
data/GETTING_STARTED.md CHANGED
@@ -69,7 +69,7 @@ factory\_girl supports several different build strategies: build, create, attrib
69
69
  attrs = FactoryGirl.attributes_for(:user)
70
70
 
71
71
  # Returns an object with all defined attributes stubbed out
72
- stub = FactoryGirl.build_stubbed(:user
72
+ stub = FactoryGirl.build_stubbed(:user)
73
73
 
74
74
  # Passing a block to any of the methods above will yield the return object
75
75
  FactoryGirl.create(:user) do |user|
@@ -87,7 +87,7 @@ If repeating "FactoryGirl" is too verbose for you, you can mix the syntax method
87
87
 
88
88
  # rspec
89
89
  RSpec.configure do |config|
90
- config.include Factory::Syntax::Methods
90
+ config.include FactoryGirl::Syntax::Methods
91
91
  end
92
92
 
93
93
  # Test::Unit
@@ -404,6 +404,26 @@ You can also override individual attributes granted by a trait in subclasses.
404
404
  end
405
405
  end
406
406
 
407
+ Traits can also be passed in as a list of symbols when you construct an instance from FactoryGirl.
408
+
409
+ factory :user do
410
+ name "Friendly User"
411
+
412
+ trait :male do
413
+ name "John Doe"
414
+ gender "Male"
415
+ end
416
+
417
+ trait :admin do
418
+ admin true
419
+ end
420
+ end
421
+
422
+ # creates an admin user with gender "Male" and name "Jon Snow"
423
+ FactoryGirl.create(:user, :admin, :male, :name => "Jon Snow")
424
+
425
+ This ability works with `build`, `build_stubbed`, `attributes_for`, and `create`.
426
+
407
427
  Callbacks
408
428
  ---------
409
429
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- factory_girl (2.2.0)
4
+ factory_girl (2.3.0)
5
5
  activesupport
6
6
 
7
7
  GEM
data/Rakefile CHANGED
@@ -1,13 +1,13 @@
1
1
  require 'rubygems'
2
- require 'bundler/setup'
2
+ require 'bundler'
3
3
  require 'rake'
4
- require 'rcov/rcovtask'
5
- require 'date'
6
- require 'rake/gempackagetask'
7
- require 'rspec/core/rake_task'
8
- require 'cucumber/rake/task'
9
4
  require 'appraisal'
10
5
  require 'yard'
6
+ require 'rspec/core/rake_task'
7
+ require 'cucumber/rake/task'
8
+ require 'rcov/rcovtask'
9
+
10
+ Bundler::GemHelper.install_tasks
11
11
 
12
12
  desc 'Default: run the specs and features.'
13
13
  task :default => 'spec:unit' do
@@ -30,9 +30,11 @@ desc "Run the unit and acceptance specs"
30
30
  task :spec => ['spec:unit', 'spec:acceptance']
31
31
 
32
32
  desc 'Performs code coverage on the factory_girl plugin.'
33
- Rcov::RcovTask.new do |t|
34
- t.test_files = FileList['spec/*_spec.rb']
35
- t.verbose = true
33
+ RSpec::Core::RakeTask.new(:rcov) do |task|
34
+ task.pattern = 'spec/**/*_spec.rb'
35
+ task.rcov = true
36
+ task.rspec_opts = "--format progress"
37
+ task.rcov_opts = %{--exclude osx\/objc,spec,gems\/ --aggregate coverage/coverage.data}
36
38
  end
37
39
 
38
40
  desc "Clean files generated by rake tasks"
@@ -43,12 +45,6 @@ Cucumber::Rake::Task.new(:features) do |t|
43
45
  t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'progress')]
44
46
  end
45
47
 
46
- eval("$specification = begin; #{IO.read('factory_girl.gemspec')}; end")
47
- Rake::GemPackageTask.new($specification) do |package|
48
- package.need_zip = true
49
- package.need_tar = true
50
- end
51
-
52
48
  YARD::Rake::YardocTask.new do |t|
53
49
  end
54
50
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.2.0)
4
+ factory_girl (2.3.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.2.0)
4
+ factory_girl (2.3.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.2.0)
4
+ factory_girl (2.3.0)
5
5
  activesupport
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/joshuaclayton/dev/gems/factory_girl
3
3
  specs:
4
- factory_girl (2.2.0)
4
+ factory_girl (2.3.0)
5
5
  activesupport
6
6
 
7
7
  GEM
data/lib/factory_girl.rb CHANGED
@@ -1,9 +1,12 @@
1
+ require "active_support/core_ext/module/delegation"
2
+
1
3
  require 'factory_girl/proxy'
2
4
  require 'factory_girl/proxy/build'
3
5
  require 'factory_girl/proxy/create'
4
6
  require 'factory_girl/proxy/attributes_for'
5
7
  require 'factory_girl/proxy/stub'
6
8
  require 'factory_girl/registry'
9
+ require 'factory_girl/null_factory'
7
10
  require 'factory_girl/factory'
8
11
  require 'factory_girl/attribute'
9
12
  require 'factory_girl/attribute/static'
@@ -11,6 +14,7 @@ require 'factory_girl/attribute/dynamic'
11
14
  require 'factory_girl/attribute/association'
12
15
  require 'factory_girl/attribute/sequence'
13
16
  require 'factory_girl/callback'
17
+ require 'factory_girl/declaration_list'
14
18
  require 'factory_girl/declaration'
15
19
  require 'factory_girl/declaration/static'
16
20
  require 'factory_girl/declaration/dynamic'
@@ -20,6 +24,7 @@ require 'factory_girl/sequence'
20
24
  require 'factory_girl/attribute_list'
21
25
  require 'factory_girl/trait'
22
26
  require 'factory_girl/aliases'
27
+ require 'factory_girl/definition'
23
28
  require 'factory_girl/definition_proxy'
24
29
  require 'factory_girl/syntax/methods'
25
30
  require 'factory_girl/syntax/default'
@@ -44,7 +49,7 @@ module FactoryGirl
44
49
  class DuplicateDefinitionError < RuntimeError; end
45
50
 
46
51
  def self.factories
47
- @factories ||= Registry.new
52
+ @factories ||= Registry.new("Factory")
48
53
  end
49
54
 
50
55
  def self.register_factory(factory)
@@ -56,7 +61,7 @@ module FactoryGirl
56
61
  end
57
62
 
58
63
  def self.sequences
59
- @sequences ||= Registry.new
64
+ @sequences ||= Registry.new("Sequence")
60
65
  end
61
66
 
62
67
  def self.register_sequence(sequence)
@@ -68,7 +73,7 @@ module FactoryGirl
68
73
  end
69
74
 
70
75
  def self.traits
71
- @traits ||= Registry.new
76
+ @traits ||= Registry.new("Trait")
72
77
  end
73
78
 
74
79
  def self.register_trait(trait)
@@ -52,5 +52,13 @@ module FactoryGirl
52
52
  "rather than 'f.#{attribute_name} = value'"
53
53
  end
54
54
  end
55
+
56
+ def set_proxy_value(proxy, value)
57
+ if @ignored
58
+ proxy.set_ignored(name, value)
59
+ else
60
+ proxy.set(name, value)
61
+ end
62
+ end
55
63
  end
56
64
  end
@@ -12,11 +12,7 @@ module FactoryGirl
12
12
  raise SequenceAbuseError
13
13
  end
14
14
 
15
- if @ignored
16
- proxy.set_ignored(name, value)
17
- else
18
- proxy.set(name, value)
19
- end
15
+ set_proxy_value(proxy, value)
20
16
  end
21
17
  end
22
18
  end
@@ -9,11 +9,7 @@ module FactoryGirl
9
9
 
10
10
  def add_to(proxy)
11
11
  value = FactoryGirl.generate(@sequence)
12
- if @ignored
13
- proxy.set_ignored(name, value)
14
- else
15
- proxy.set(name, value)
16
- end
12
+ set_proxy_value(proxy, value)
17
13
  end
18
14
  end
19
15
 
@@ -11,11 +11,7 @@ module FactoryGirl
11
11
  end
12
12
 
13
13
  def add_to(proxy)
14
- if @ignored
15
- proxy.set_ignored(name, @value)
16
- else
17
- proxy.set(name, @value)
18
- end
14
+ set_proxy_value(proxy, @value)
19
15
  end
20
16
 
21
17
  def priority
@@ -2,47 +2,27 @@ module FactoryGirl
2
2
  class AttributeList
3
3
  include Enumerable
4
4
 
5
- attr_reader :callbacks, :declarations
6
-
7
- def initialize
8
- @attributes = {}
9
- @declarations = []
10
- @overridable = false
11
- @callbacks = []
12
- end
13
-
14
- def declare_attribute(declaration)
15
- @declarations << declaration
16
- declaration
5
+ def initialize(name = nil)
6
+ @name = name
7
+ @attributes = {}
17
8
  end
18
9
 
19
10
  def define_attribute(attribute)
20
- if !overridable? && attribute_defined?(attribute.name)
21
- raise AttributeDefinitionError, "Attribute already defined: #{attribute.name}"
22
- end
11
+ ensure_attribute_not_self_referencing! attribute
12
+ ensure_attribute_not_defined! attribute
23
13
 
24
14
  add_attribute attribute
25
15
  end
26
16
 
27
- def add_callback(callback)
28
- @callbacks << callback
29
- end
30
-
31
17
  def each(&block)
32
18
  flattened_attributes.each(&block)
33
19
  end
34
20
 
35
21
  def apply_attributes(attributes_to_apply)
36
- attributes_to_apply.callbacks.reverse.each { |callback| prepend_callback(callback) }
37
22
  new_attributes = []
38
23
 
39
24
  attributes_to_apply.each do |attribute|
40
- new_attribute = if !overridable? && defined_attribute = find_attribute(attribute.name)
41
- defined_attribute
42
- else
43
- attribute
44
- end
45
-
25
+ new_attribute = find_attribute(attribute.name) || attribute
46
26
  delete_attribute(attribute.name)
47
27
  new_attributes << new_attribute
48
28
  end
@@ -50,32 +30,14 @@ module FactoryGirl
50
30
  prepend_attributes new_attributes
51
31
  end
52
32
 
53
- def overridable
54
- @overridable = true
55
- end
56
-
57
- def overridable?
58
- @overridable
59
- end
60
-
61
- def size
62
- to_a.size
63
- end
64
-
65
33
  private
66
34
 
67
35
  def add_attribute(attribute)
68
- delete_attribute(attribute.name) if overridable?
69
-
70
36
  @attributes[attribute.priority] ||= []
71
37
  @attributes[attribute.priority] << attribute
72
38
  attribute
73
39
  end
74
40
 
75
- def prepend_callback(callback)
76
- @callbacks.unshift(callback)
77
- end
78
-
79
41
  def prepend_attributes(new_attributes)
80
42
  new_attributes.group_by {|attr| attr.priority }.each do |priority, attributes|
81
43
  @attributes[priority] ||= []
@@ -90,6 +52,18 @@ module FactoryGirl
90
52
  end.flatten
91
53
  end
92
54
 
55
+ def ensure_attribute_not_defined!(attribute)
56
+ if attribute_defined?(attribute.name)
57
+ raise AttributeDefinitionError, "Attribute already defined: #{attribute.name}"
58
+ end
59
+ end
60
+
61
+ def ensure_attribute_not_self_referencing!(attribute)
62
+ if attribute.respond_to?(:factory) && attribute.factory == @name
63
+ raise AssociationDefinitionError, "Self-referencing association '#{attribute.name}' in '#{attribute.factory}'"
64
+ end
65
+ end
66
+
93
67
  def attribute_defined?(attribute_name)
94
68
  !!find_attribute(attribute_name)
95
69
  end
@@ -18,6 +18,11 @@ module FactoryGirl
18
18
  end
19
19
  end
20
20
 
21
+ def ==(other)
22
+ name == other.name &&
23
+ block == other.block
24
+ end
25
+
21
26
  private
22
27
 
23
28
  def check_name
@@ -15,5 +15,8 @@ module FactoryGirl
15
15
  def to_attributes
16
16
  build
17
17
  end
18
+
19
+ protected
20
+ attr_reader :ignored
18
21
  end
19
22
  end
@@ -6,6 +6,14 @@ module FactoryGirl
6
6
  @options = options
7
7
  end
8
8
 
9
+ def ==(other)
10
+ name == other.name &&
11
+ options == other.options
12
+ end
13
+
14
+ protected
15
+ attr_reader :options
16
+
9
17
  private
10
18
 
11
19
  def build