factory_girl 2.2.0 → 2.3.0

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