1
0
Fork 0
mirror of https://github.com/thoughtbot/factory_bot.git synced 2022-11-09 11:43:51 -05:00

Moved definition loading syntax out of the factory class; moved everything into a FactoryGirl module

This commit is contained in:
Joe Ferris 2010-06-24 09:45:57 -04:00
parent 2a39afe527
commit 8b4a6a1c3a
44 changed files with 670 additions and 678 deletions

View file

@ -2,7 +2,7 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
require 'factory_girl' require 'factory_girl'
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.name = %q{factory_girl} s.name = %q{factory_girl}
s.version = Factory::VERSION s.version = FactoryGirl::VERSION
s.summary = %q{factory_girl provides a framework and DSL for defining and s.summary = %q{factory_girl provides a framework and DSL for defining and
using model instance factories.} using model instance factories.}
s.description = %q{factory_girl provides a framework and DSL for defining and s.description = %q{factory_girl provides a framework and DSL for defining and

View file

@ -13,8 +13,9 @@ require 'factory_girl/sequence'
require 'factory_girl/aliases' require 'factory_girl/aliases'
require 'factory_girl/definition_proxy' require 'factory_girl/definition_proxy'
require 'factory_girl/syntax/default' require 'factory_girl/syntax/default'
require 'factory_girl/find_definitions'
class Factory module FactoryGirl
VERSION = "1.3.1" VERSION = "1.3.1"
end end

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class << self class << self
attr_accessor :aliases #:nodoc: attr_accessor :aliases #:nodoc:
@ -8,35 +8,7 @@ class Factory
[/(.*)/, '\1_id'] [/(.*)/, '\1_id']
] ]
# Defines a new alias for attributes. def self.aliases_for(attribute) #:nodoc:
#
# Arguments:
# * pattern: +Regexp+
# A pattern that will be matched against attributes when looking for
# aliases. Contents captured in the pattern can be used in the alias.
# * replace: +String+
# The alias that results from the matched pattern. Captured strings can
# be substituted like with +String#sub+.
#
# Example:
#
# Factory.alias /(.*)_confirmation/, '\1'
#
# factory_girl starts with aliases for foreign keys, so that a :user
# association can be overridden by a :user_id parameter:
#
# Factory.define :post do |p|
# p.association :user
# end
#
# # The user association will not be built in this example. The user_id
# # will be used instead.
# Factory(:post, :user_id => 1)
def self.alias (pattern, replace)
self.aliases << [pattern, replace]
end
def self.aliases_for (attribute) #:nodoc:
aliases.collect do |params| aliases.collect do |params|
pattern, replace = *params pattern, replace = *params
if pattern.match(attribute.to_s) if pattern.match(attribute.to_s)
@ -46,5 +18,4 @@ class Factory
end end
end.compact << attribute end.compact << attribute
end end
end end

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
# Raised when defining an invalid attribute: # Raised when defining an invalid attribute:
# * Defining an attribute which has a name ending in "=" # * Defining an attribute which has a name ending in "="

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Attribute #:nodoc: class Attribute #:nodoc:
class Association < Attribute #:nodoc: class Association < Attribute #:nodoc:

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Attribute #:nodoc: class Attribute #:nodoc:
class Callback < Attribute #:nodoc: class Callback < Attribute #:nodoc:

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Attribute #:nodoc: class Attribute #:nodoc:
class Dynamic < Attribute #:nodoc: class Dynamic < Attribute #:nodoc:
@ -9,7 +9,7 @@ class Factory
def add_to(proxy) def add_to(proxy)
value = @block.arity.zero? ? @block.call : @block.call(proxy) value = @block.arity.zero? ? @block.call : @block.call(proxy)
if Factory::Sequence === value if FactoryGirl::Sequence === value
raise SequenceAbuseError raise SequenceAbuseError
end end
proxy.set(name, value) proxy.set(name, value)

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Attribute #:nodoc: class Attribute #:nodoc:
class Static < Attribute #:nodoc: class Static < Attribute #:nodoc:

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class DefinitionProxy class DefinitionProxy
instance_methods.each do |method| instance_methods.each do |method|
undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$|^instance_eval$)/ undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$|^instance_eval$)/

View file

@ -1,4 +1,22 @@
class Factory module FactoryGirl
class << self
attr_accessor :factories #:nodoc:
end
self.factories = {}
def self.factory_by_name(name)
factories[name.to_sym] or raise ArgumentError.new("No such factory: #{name.to_s}")
end
def self.register_factory(factory)
name = factory.factory_name
if self.factories[name]
raise DuplicateDefinitionError, "Factory already defined: #{name}"
end
self.factories[name] = factory
end
# Raised when a factory is defined that attempts to instantiate itself. # Raised when a factory is defined that attempts to instantiate itself.
class AssociationDefinitionError < RuntimeError class AssociationDefinitionError < RuntimeError
end end
@ -11,180 +29,145 @@ class Factory
class DuplicateDefinitionError < RuntimeError class DuplicateDefinitionError < RuntimeError
end end
class << self class Factory
attr_accessor :factories #:nodoc: attr_reader :factory_name #:nodoc:
attr_reader :attributes #:nodoc:
# An Array of strings specifying locations that should be searched for def class_name #:nodoc:
# factory definitions. By default, factory_girl will attempt to require @options[:class] || factory_name
# "factories," "test/factories," and "spec/factories." Only the first
# existing file will be loaded.
attr_accessor :definition_file_paths
end
self.factories = {}
self.definition_file_paths = %w(factories test/factories spec/factories)
attr_reader :factory_name #:nodoc:
attr_reader :attributes #:nodoc:
def self.register_factory(factory)
name = factory.factory_name
if self.factories[name]
raise DuplicateDefinitionError, "Factory already defined: #{name}"
end end
self.factories[name] = factory
end
def class_name #:nodoc: def build_class #:nodoc:
@options[:class] || factory_name @build_class ||= class_for(class_name)
end
def build_class #:nodoc:
@build_class ||= class_for(class_name)
end
def default_strategy #:nodoc:
@options[:default_strategy] || :create
end
def initialize (name, options = {}) #:nodoc:
assert_valid_options(options)
@factory_name = factory_name_for(name)
@options = options
@attributes = []
end
def inherit_from(parent) #:nodoc:
@options[:class] ||= parent.class_name
@options[:default_strategy] ||= parent.default_strategy
parent.attributes.each do |attribute|
unless attribute_defined?(attribute.name)
@attributes << attribute.clone
end
end end
end
def define_attribute(attribute) def default_strategy #:nodoc:
name = attribute.name @options[:default_strategy] || :create
# TODO: move these checks into Attribute
if attribute_defined?(name)
raise AttributeDefinitionError, "Attribute already defined: #{name}"
end end
if attribute.respond_to?(:factory) && attribute.factory == self.factory_name
raise AssociationDefinitionError, "Self-referencing association '#{name}' in factory '#{self.factory_name}'" def initialize (name, options = {}) #:nodoc:
assert_valid_options(options)
@factory_name = factory_name_for(name)
@options = options
@attributes = []
end end
@attributes << attribute
end
def add_callback(name, &block) def inherit_from(parent) #:nodoc:
unless [:after_build, :after_create, :after_stub].include?(name.to_sym) @options[:class] ||= parent.class_name
raise InvalidCallbackNameError, "#{name} is not a valid callback name. Valid callback names are :after_build, :after_create, and :after_stub" @options[:default_strategy] ||= parent.default_strategy
end parent.attributes.each do |attribute|
@attributes << Attribute::Callback.new(name.to_sym, block) unless attribute_defined?(attribute.name)
end @attributes << attribute.clone
def self.find_definitions #:nodoc:
definition_file_paths.each do |path|
require("#{path}.rb") if File.exists?("#{path}.rb")
if File.directory? path
Dir[File.join(path, '*.rb')].each do |file|
require file
end end
end end
end end
end
def run (proxy_class, overrides) #:nodoc: def define_attribute(attribute)
proxy = proxy_class.new(build_class) name = attribute.name
overrides = symbolize_keys(overrides) # TODO: move these checks into Attribute
overrides.each {|attr, val| proxy.set(attr, val) } if attribute_defined?(name)
passed_keys = overrides.keys.collect {|k| Factory.aliases_for(k) }.flatten raise AttributeDefinitionError, "Attribute already defined: #{name}"
@attributes.each do |attribute| end
unless passed_keys.include?(attribute.name) if attribute.respond_to?(:factory) && attribute.factory == self.factory_name
attribute.add_to(proxy) raise AssociationDefinitionError, "Self-referencing association '#{name}' in factory '#{self.factory_name}'"
end
@attributes << attribute
end
def add_callback(name, &block)
unless [:after_build, :after_create, :after_stub].include?(name.to_sym)
raise InvalidCallbackNameError, "#{name} is not a valid callback name. Valid callback names are :after_build, :after_create, and :after_stub"
end
@attributes << Attribute::Callback.new(name.to_sym, block)
end
def run (proxy_class, overrides) #:nodoc:
proxy = proxy_class.new(build_class)
overrides = symbolize_keys(overrides)
overrides.each {|attr, val| proxy.set(attr, val) }
passed_keys = overrides.keys.collect {|k| FactoryGirl.aliases_for(k) }.flatten
@attributes.each do |attribute|
unless passed_keys.include?(attribute.name)
attribute.add_to(proxy)
end
end
proxy.result
end
def human_name(*args, &block)
if args.size == 0 && block.nil?
factory_name.to_s.gsub('_', ' ')
else
add_attribute(:human_name, *args, &block)
end end
end end
proxy.result
end
def self.factory_by_name (name) def associations
factories[name.to_sym] or raise ArgumentError.new("No such factory: #{name.to_s}") attributes.select {|attribute| attribute.is_a?(Attribute::Association) }
end
def human_name(*args, &block)
if args.size == 0 && block.nil?
factory_name.to_s.gsub('_', ' ')
else
add_attribute(:human_name, *args, &block)
end end
end
def associations private
attributes.select {|attribute| attribute.is_a?(Attribute::Association) }
end
private def class_for (class_or_to_s)
if class_or_to_s.respond_to?(:to_sym)
def class_for (class_or_to_s) class_name = variable_name_to_class_name(class_or_to_s)
if class_or_to_s.respond_to?(:to_sym) class_name.split('::').inject(Object) do |object, string|
class_name = variable_name_to_class_name(class_or_to_s) object.const_get(string)
class_name.split('::').inject(Object) do |object, string| end
object.const_get(string) else
class_or_to_s
end end
else
class_or_to_s
end end
end
def factory_name_for (class_or_to_s) def factory_name_for (class_or_to_s)
if class_or_to_s.respond_to?(:to_sym) if class_or_to_s.respond_to?(:to_sym)
class_or_to_s.to_sym class_or_to_s.to_sym
else else
class_name_to_variable_name(class_or_to_s).to_sym class_name_to_variable_name(class_or_to_s).to_sym
end
end end
end
def attribute_defined? (name) def attribute_defined? (name)
!@attributes.detect {|attr| attr.name == name && !attr.is_a?(Factory::Attribute::Callback) }.nil? !@attributes.detect {|attr| attr.name == name && !attr.is_a?(Attribute::Callback) }.nil?
end
def assert_valid_options(options)
invalid_keys = options.keys - [:class, :parent, :default_strategy]
unless invalid_keys == []
raise ArgumentError, "Unknown arguments: #{invalid_keys.inspect}"
end end
assert_valid_strategy(options[:default_strategy]) if options[:default_strategy]
end
def assert_valid_strategy(strategy) def assert_valid_options(options)
unless Factory::Proxy.const_defined? variable_name_to_class_name(strategy) invalid_keys = options.keys - [:class, :parent, :default_strategy]
raise ArgumentError, "Unknown strategy: #{strategy}" unless invalid_keys == []
raise ArgumentError, "Unknown arguments: #{invalid_keys.inspect}"
end
assert_valid_strategy(options[:default_strategy]) if options[:default_strategy]
end end
end
# Based on ActiveSupport's underscore inflector def assert_valid_strategy(strategy)
def class_name_to_variable_name(name) unless Proxy.const_defined? variable_name_to_class_name(strategy)
name.to_s.gsub(/::/, '/'). raise ArgumentError, "Unknown strategy: #{strategy}"
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). end
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
# Based on ActiveSupport's camelize inflector
def variable_name_to_class_name(name)
name.to_s.
gsub(/\/(.?)/) { "::#{$1.upcase}" }.
gsub(/(?:^|_)(.)/) { $1.upcase }
end
# From ActiveSupport
def symbolize_keys(hash)
hash.inject({}) do |options, (key, value)|
options[(key.to_sym rescue key) || key] = value
options
end end
end
# Based on ActiveSupport's underscore inflector
def class_name_to_variable_name(name)
name.to_s.gsub(/::/, '/').
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
gsub(/([a-z\d])([A-Z])/,'\1_\2').
tr("-", "_").
downcase
end
# Based on ActiveSupport's camelize inflector
def variable_name_to_class_name(name)
name.to_s.
gsub(/\/(.?)/) { "::#{$1.upcase}" }.
gsub(/(?:^|_)(.)/) { $1.upcase }
end
# From ActiveSupport
def symbolize_keys(hash)
hash.inject({}) do |options, (key, value)|
options[(key.to_sym rescue key) || key] = value
options
end
end
end
end end

View file

@ -0,0 +1,25 @@
module FactoryGirl
class << self
attr_accessor :factories #:nodoc:
# An Array of strings specifying locations that should be searched for
# factory definitions. By default, factory_girl will attempt to require
# "factories," "test/factories," and "spec/factories." Only the first
# existing file will be loaded.
attr_accessor :definition_file_paths
end
self.definition_file_paths = %w(factories test/factories spec/factories)
def self.find_definitions #:nodoc:
definition_file_paths.each do |path|
require("#{path}.rb") if File.exists?("#{path}.rb")
if File.directory? path
Dir[File.join(path, '*.rb')].each do |file|
require file
end
end
end
end
end

View file

@ -1,5 +1,4 @@
class Factory module FactoryGirl
class Proxy #:nodoc: class Proxy #:nodoc:
attr_reader :callbacks attr_reader :callbacks
@ -75,5 +74,4 @@ class Factory
raise NotImplementedError, "Strategies must return a result" raise NotImplementedError, "Strategies must return a result"
end end
end end
end end

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Proxy #:nodoc: class Proxy #:nodoc:
class AttributesFor < Proxy #:nodoc: class AttributesFor < Proxy #:nodoc:
def initialize(klass) def initialize(klass)

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Proxy #:nodoc: class Proxy #:nodoc:
class Build < Proxy #:nodoc: class Build < Proxy #:nodoc:
def initialize(klass) def initialize(klass)
@ -14,12 +14,12 @@ class Factory
end end
def associate(name, factory_name, overrides) def associate(name, factory_name, overrides)
factory = Factory.factory_by_name(factory_name) factory = FactoryGirl.factory_by_name(factory_name)
set(name, factory.run(Proxy::Create, overrides)) set(name, factory.run(Proxy::Create, overrides))
end end
def association(factory_name, overrides = {}) def association(factory_name, overrides = {})
factory = Factory.factory_by_name(factory_name) factory = FactoryGirl.factory_by_name(factory_name)
factory.run(Proxy::Create, overrides) factory.run(Proxy::Create, overrides)
end end

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Proxy #:nodoc: class Proxy #:nodoc:
class Create < Build #:nodoc: class Create < Build #:nodoc:
def result def result

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
class Proxy class Proxy
class Stub < Proxy #:nodoc: class Stub < Proxy #:nodoc:
@@next_id = 1000 @@next_id = 1000
@ -42,12 +42,12 @@ class Factory
end end
def associate(name, factory_name, overrides) def associate(name, factory_name, overrides)
factory = Factory.factory_by_name(factory_name) factory = FactoryGirl.factory_by_name(factory_name)
set(name, factory.run(Proxy::Stub, overrides)) set(name, factory.run(Proxy::Stub, overrides))
end end
def association(factory_name, overrides = {}) def association(factory_name, overrides = {})
factory = Factory.factory_by_name(factory_name) factory = FactoryGirl.factory_by_name(factory_name)
factory.run(Proxy::Stub, overrides) factory.run(Proxy::Stub, overrides)
end end

View file

@ -1 +1 @@
Rails.configuration.after_initialize { Factory.find_definitions } Rails.configuration.after_initialize { FactoryGirl.find_definitions }

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
# Raised when calling Factory.sequence from a dynamic attribute block # Raised when calling Factory.sequence from a dynamic attribute block
class SequenceAbuseError < StandardError; end class SequenceAbuseError < StandardError; end
@ -7,7 +7,7 @@ class Factory
# using next. # using next.
class Sequence class Sequence
def initialize (&proc) #:nodoc: def initialize(&proc) #:nodoc:
@proc = proc @proc = proc
@value = 0 @value = 0
end end
@ -24,40 +24,4 @@ class Factory
attr_accessor :sequences #:nodoc: attr_accessor :sequences #:nodoc:
end end
self.sequences = {} self.sequences = {}
# Defines a new sequence that can be used to generate unique values in a specific format.
#
# Arguments:
# name: (Symbol)
# A unique name for this sequence. This name will be referenced when
# calling next to generate new values from this sequence.
# block: (Proc)
# The code to generate each value in the sequence. This block will be
# called with a unique number each time a value in the sequence is to be
# generated. The block should return the generated value for the
# sequence.
#
# Example:
#
# Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
def self.sequence (name, &block)
self.sequences[name] = Sequence.new(&block)
end
# Generates and returns the next value in a sequence.
#
# Arguments:
# name: (Symbol)
# The name of the sequence that a value should be generated for.
#
# Returns:
# The next value in the sequence. (Object)
def self.next (sequence)
unless self.sequences.key?(sequence)
raise "No such sequence: #{sequence}"
end
self.sequences[sequence].next
end
end end

View file

@ -3,7 +3,7 @@ module FactoryGirlStepHelpers
attribute, value = assignment.split(':', 2) attribute, value = assignment.split(':', 2)
return if value.blank? return if value.blank?
attributes = convert_human_hash_to_attribute_hash(attribute => value.strip) attributes = convert_human_hash_to_attribute_hash(attribute => value.strip)
factory = Factory.factory_by_name(factory_name) factory = FactoryGirl.factory_by_name(factory_name)
model_class = factory.build_class model_class = factory.build_class
model_class.find(:first, :conditions => attributes) or model_class.find(:first, :conditions => attributes) or
Factory(factory_name, attributes) Factory(factory_name, attributes)
@ -22,11 +22,11 @@ end
World(FactoryGirlStepHelpers) World(FactoryGirlStepHelpers)
Factory.factories.values.each do |factory| FactoryGirl.factories.values.each do |factory|
Given /^the following (?:#{factory.human_name}|#{factory.human_name.pluralize}) exists?:$/ do |table| Given /^the following (?:#{factory.human_name}|#{factory.human_name.pluralize}) exists?:$/ do |table|
table.hashes.each do |human_hash| table.hashes.each do |human_hash|
attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations) attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations)
factory.run(Factory::Proxy::Create, attributes) factory.run(FactoryGirl::Proxy::Create, attributes)
end end
end end

View file

@ -1,12 +1,12 @@
class Factory module FactoryGirl
# Provides alternate syntaxes for factory_girl. If you don't like the default # Provides alternate syntaxes for factory_girl. If you don't like the default
# syntax for defining or using factories, look at one of the Factory::Syntax # syntax for defining or using factories, look at one of the Factory::Syntax
# modules: # modules:
# #
# * Factory::Syntax::Blueprint: definition syntax similar to Machinist # * FactoryGirl::Syntax::Blueprint: definition syntax similar to Machinist
# * Factory::Syntax::Generate: usage syntax similar to Object Daddy # * FactoryGirl::Syntax::Generate: usage syntax similar to Object Daddy
# * Factory::Syntax::Make: usage syntax similar to Machinist # * FactoryGirl::Syntax::Make: usage syntax similar to Machinist
# * Factory::Syntax::Sham: sequence syntax similar to Machinist # * FactoryGirl::Syntax::Sham: sequence syntax similar to Machinist
module Syntax module Syntax
end end
end end

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
module Syntax module Syntax
# Extends ActiveRecord::Base to provide a make class method, which is an # Extends ActiveRecord::Base to provide a make class method, which is an
@ -27,9 +27,9 @@ class Factory
def blueprint(&block) def blueprint(&block)
instance = Factory.new(name.underscore, :class => self) instance = Factory.new(name.underscore, :class => self)
proxy = Factory::DefinitionProxy.new(instance) proxy = FactoryGirl::DefinitionProxy.new(instance)
proxy.instance_eval(&block) proxy.instance_eval(&block)
Factory.register_factory(instance) FactoryGirl.register_factory(instance)
end end
end end
@ -39,4 +39,4 @@ class Factory
end end
end end
ActiveRecord::Base.send(:include, Factory::Syntax::Blueprint::ActiveRecord) ActiveRecord::Base.send(:include, FactoryGirl::Syntax::Blueprint::ActiveRecord)

View file

@ -1,125 +1,196 @@
class Factory module FactoryGirl
# Defines a new factory that can be used by the build strategies (create and module Syntax
# build) to build new objects. module Default
# module Factory
# Arguments: # Defines a new factory that can be used by the build strategies (create and
# * name: +Symbol+ or +String+ # build) to build new objects.
# A unique name used to identify this factory. #
# * options: +Hash+ # Arguments:
# # * name: +Symbol+ or +String+
# Options: # A unique name used to identify this factory.
# * class: +Symbol+, +Class+, or +String+ # * options: +Hash+
# The class that will be used when generating instances for this factory. If not specified, the class will be guessed from the factory name. #
# * parent: +Symbol+ # Options:
# The parent factory. If specified, the attributes from the parent # * class: +Symbol+, +Class+, or +String+
# factory will be copied to the current one with an ability to override # The class that will be used when generating instances for this factory. If not specified, the class will be guessed from the factory name.
# them. # * parent: +Symbol+
# * default_strategy: +Symbol+ # The parent factory. If specified, the attributes from the parent
# The strategy that will be used by the Factory shortcut method. # factory will be copied to the current one with an ability to override
# Defaults to :create. # them.
# # * default_strategy: +Symbol+
# Yields: +Factory+ # The strategy that will be used by the Factory shortcut method.
# The newly created factory. # Defaults to :create.
def self.define(name, options = {}) #
factory = Factory.new(name, options) # Yields: +Factory+
proxy = Factory::DefinitionProxy.new(factory) # The newly created factory.
yield(proxy) def self.define(name, options = {})
if parent = options.delete(:parent) factory = FactoryGirl::Factory.new(name, options)
factory.inherit_from(Factory.factory_by_name(parent)) proxy = FactoryGirl::DefinitionProxy.new(factory)
yield(proxy)
if parent = options.delete(:parent)
factory.inherit_from(FactoryGirl.factory_by_name(parent))
end
FactoryGirl.register_factory(factory)
end
# Generates and returns a Hash of attributes from this factory. Attributes
# can be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this set.
#
# Returns: +Hash+
# A set of attributes that can be used to build an instance of the class
# this factory generates.
def self.attributes_for(name, overrides = {})
FactoryGirl.factory_by_name(name).run(Proxy::AttributesFor, overrides)
end
# Generates and returns an instance from this factory. Attributes can be
# individually overridden by passing in a Hash of attribute => value pairs.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# An instance of the class this factory generates, with generated attributes
# assigned.
def self.build(name, overrides = {})
FactoryGirl.factory_by_name(name).run(Proxy::Build, overrides)
end
# Generates, saves, and returns an instance from this factory. Attributes can
# be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# Instances are saved using the +save!+ method, so ActiveRecord models will
# raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# A saved instance of the class this factory generates, with generated
# attributes assigned.
def self.create(name, overrides = {})
FactoryGirl.factory_by_name(name).run(Proxy::Create, overrides)
end
# Generates and returns an object with all attributes from this factory
# stubbed out. Attributes can be individually overridden by passing in a Hash
# of attribute => value pairs.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# An object with generated attributes stubbed out.
def self.stub(name, overrides = {})
FactoryGirl.factory_by_name(name).run(Proxy::Stub, overrides)
end
# Executes the default strategy for the given factory. This is usually create,
# but it can be overridden for each factory.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# The result of the default strategy.
def self.default_strategy(name, overrides = {})
self.send(FactoryGirl.factory_by_name(name).default_strategy, name, overrides)
end
# Defines a new sequence that can be used to generate unique values in a specific format.
#
# Arguments:
# name: (Symbol)
# A unique name for this sequence. This name will be referenced when
# calling next to generate new values from this sequence.
# block: (Proc)
# The code to generate each value in the sequence. This block will be
# called with a unique number each time a value in the sequence is to be
# generated. The block should return the generated value for the
# sequence.
#
# Example:
#
# Factory.sequence(:email) {|n| "somebody_#{n}@example.com" }
def self.sequence(name, &block)
FactoryGirl.sequences[name] = Sequence.new(&block)
end
# Generates and returns the next value in a sequence.
#
# Arguments:
# name: (Symbol)
# The name of the sequence that a value should be generated for.
#
# Returns:
# The next value in the sequence. (Object)
def self.next(sequence)
unless FactoryGirl.sequences.key?(sequence)
raise "No such sequence: #{sequence}"
end
FactoryGirl.sequences[sequence].next
end
# Defines a new alias for attributes.
#
# Arguments:
# * pattern: +Regexp+
# A pattern that will be matched against attributes when looking for
# aliases. Contents captured in the pattern can be used in the alias.
# * replace: +String+
# The alias that results from the matched pattern. Captured strings can
# be substituted like with +String#sub+.
#
# Example:
#
# Factory.alias /(.*)_confirmation/, '\1'
#
# factory_girl starts with aliases for foreign keys, so that a :user
# association can be overridden by a :user_id parameter:
#
# Factory.define :post do |p|
# p.association :user
# end
#
# # The user association will not be built in this example. The user_id
# # will be used instead.
# Factory(:post, :user_id => 1)
def self.alias(pattern, replace)
FactoryGirl.aliases << [pattern, replace]
end
end
# Shortcut for Factory.default_strategy.
#
# Example:
# Factory(:user, :name => 'Joe')
def Factory(name, attrs = {})
Factory.default_strategy(name, attrs)
end
end end
register_factory(factory)
end
# Generates and returns a Hash of attributes from this factory. Attributes
# can be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this set.
#
# Returns: +Hash+
# A set of attributes that can be used to build an instance of the class
# this factory generates.
def self.attributes_for (name, overrides = {})
factory_by_name(name).run(Proxy::AttributesFor, overrides)
end
# Generates and returns an instance from this factory. Attributes can be
# individually overridden by passing in a Hash of attribute => value pairs.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# An instance of the class this factory generates, with generated attributes
# assigned.
def self.build (name, overrides = {})
factory_by_name(name).run(Proxy::Build, overrides)
end
# Generates, saves, and returns an instance from this factory. Attributes can
# be individually overridden by passing in a Hash of attribute => value
# pairs.
#
# Instances are saved using the +save!+ method, so ActiveRecord models will
# raise ActiveRecord::RecordInvalid exceptions for invalid attribute sets.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# A saved instance of the class this factory generates, with generated
# attributes assigned.
def self.create (name, overrides = {})
factory_by_name(name).run(Proxy::Create, overrides)
end
# Generates and returns an object with all attributes from this factory
# stubbed out. Attributes can be individually overridden by passing in a Hash
# of attribute => value pairs.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# An object with generated attributes stubbed out.
def self.stub (name, overrides = {})
factory_by_name(name).run(Proxy::Stub, overrides)
end
# Executes the default strategy for the given factory. This is usually create,
# but it can be overridden for each factory.
#
# Arguments:
# * name: +Symbol+ or +String+
# The name of the factory that should be used.
# * overrides: +Hash+
# Attributes to overwrite for this instance.
#
# Returns: +Object+
# The result of the default strategy.
def self.default_strategy (name, overrides = {})
self.send(factory_by_name(name).default_strategy, name, overrides)
end end
end end
# Shortcut for Factory.default_strategy. include FactoryGirl::Syntax::Default
#
# Example:
# Factory(:user, :name => 'Joe')
def Factory (name, attrs = {})
Factory.default_strategy(name, attrs)
end

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
module Syntax module Syntax
# Extends ActiveRecord::Base to provide generation methods for factories. # Extends ActiveRecord::Base to provide generation methods for factories.
@ -40,7 +40,7 @@ class Factory
module ClassMethods #:nodoc: module ClassMethods #:nodoc:
def generate(overrides = {}, &block) def generate(overrides = {}, &block)
factory = Factory.factory_by_name(name.underscore) factory = FactoryGirl.factory_by_name(name.underscore)
instance = factory.run(Proxy::Build, overrides) instance = factory.run(Proxy::Build, overrides)
instance.save instance.save
yield(instance) if block_given? yield(instance) if block_given?
@ -48,14 +48,14 @@ class Factory
end end
def generate!(overrides = {}, &block) def generate!(overrides = {}, &block)
factory = Factory.factory_by_name(name.underscore) factory = FactoryGirl.factory_by_name(name.underscore)
instance = factory.run(Proxy::Create, overrides) instance = factory.run(Proxy::Create, overrides)
yield(instance) if block_given? yield(instance) if block_given?
instance instance
end end
def spawn(overrides = {}, &block) def spawn(overrides = {}, &block)
factory = Factory.factory_by_name(name.underscore) factory = FactoryGirl.factory_by_name(name.underscore)
instance = factory.run(Proxy::Build, overrides) instance = factory.run(Proxy::Build, overrides)
yield(instance) if block_given? yield(instance) if block_given?
instance instance
@ -68,4 +68,4 @@ class Factory
end end
end end
ActiveRecord::Base.send(:include, Factory::Syntax::Generate::ActiveRecord) ActiveRecord::Base.send(:include, FactoryGirl::Syntax::Generate::ActiveRecord)

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
module Syntax module Syntax
# Extends ActiveRecord::Base to provide a make class method, which is a # Extends ActiveRecord::Base to provide a make class method, which is a
@ -26,7 +26,7 @@ class Factory
module ClassMethods #:nodoc: module ClassMethods #:nodoc:
def make(overrides = {}) def make(overrides = {})
Factory.factory_by_name(name.underscore).run(Proxy::Create, overrides) FactoryGirl.factory_by_name(name.underscore).run(Proxy::Create, overrides)
end end
end end
@ -36,4 +36,4 @@ class Factory
end end
end end
ActiveRecord::Base.send(:include, Factory::Syntax::Make::ActiveRecord) ActiveRecord::Base.send(:include, FactoryGirl::Syntax::Make::ActiveRecord)

View file

@ -1,4 +1,4 @@
class Factory module FactoryGirl
module Syntax module Syntax
# Adds a Sham module, which provides an alternate interface to # Adds a Sham module, which provides an alternate interface to
@ -24,9 +24,9 @@ class Factory
module Sham #:nodoc: module Sham #:nodoc:
def self.method_missing(name, &block) def self.method_missing(name, &block)
if block_given? if block_given?
Factory.sequences[name] = Sequence.new(&block) FactoryGirl.sequences[name] = Sequence.new(&block)
else else
Factory.sequences[name].next FactoryGirl.sequences[name].next
end end
end end
@ -39,4 +39,4 @@ class Factory
end end
end end
include Factory::Syntax::Sham include FactoryGirl::Syntax::Sham

View file

@ -52,10 +52,6 @@ describe "integration" do
end end
end end
after do
Factory.factories.clear
end
describe "a generated attributes hash" do describe "a generated attributes hash" do
before do before do
@ -276,7 +272,7 @@ describe "integration" do
it "should raise Factory::SequenceAbuseError" do it "should raise Factory::SequenceAbuseError" do
lambda { lambda {
Factory(:sequence_abuser) Factory(:sequence_abuser)
}.should raise_error(Factory::SequenceAbuseError) }.should raise_error(FactoryGirl::SequenceAbuseError)
end end
describe "an instance with callbacks" do describe "an instance with callbacks" do

View file

@ -11,11 +11,6 @@ describe "default syntax" do
end end
end end
after do
Factory.factories.clear
Factory.sequences.clear
end
describe "after making an instance" do describe "after making an instance" do
before do before do
@instance = Factory(:user, :last_name => 'Rye') @instance = Factory(:user, :last_name => 'Rye')
@ -40,9 +35,9 @@ end
describe Factory, "given a parent factory" do describe Factory, "given a parent factory" do
before do before do
@parent = Factory.new(:object) @parent = FactoryGirl::Factory.new(:object)
@parent.define_attribute(Factory::Attribute::Static.new(:name, 'value')) @parent.define_attribute(FactoryGirl::Attribute::Static.new(:name, 'value'))
Factory.register_factory(@parent) FactoryGirl.register_factory(@parent)
end end
it "should raise an ArgumentError when trying to use a non-existent factory as parent" do it "should raise an ArgumentError when trying to use a non-existent factory as parent" do
@ -59,14 +54,12 @@ describe "defining a factory" do
@proxy = "proxy" @proxy = "proxy"
stub(@factory).factory_name { @name } stub(@factory).factory_name { @name }
@options = { :class => 'magic' } @options = { :class => 'magic' }
stub(Factory).new { @factory } stub(FactoryGirl::Factory).new { @factory }
stub(Factory::DefinitionProxy).new { @proxy } stub(FactoryGirl::DefinitionProxy).new { @proxy }
end end
after { Factory.factories.clear }
it "should create a new factory using the specified name and options" do it "should create a new factory using the specified name and options" do
mock(Factory).new(@name, @options) { @factory } mock(FactoryGirl::Factory).new(@name, @options) { @factory }
Factory.define(@name, @options) {|f| } Factory.define(@name, @options) {|f| }
end end
@ -80,12 +73,12 @@ describe "defining a factory" do
it "should add the factory to the list of factories" do it "should add the factory to the list of factories" do
Factory.define(@name) {|f| } Factory.define(@name) {|f| }
@factory.should == Factory.factories[@name] @factory.should == FactoryGirl.factories[@name]
end end
it "should allow a factory to be found by name" do it "should allow a factory to be found by name" do
Factory.define(@name) {|f| } Factory.define(@name) {|f| }
Factory.factory_by_name(@name).should == @factory FactoryGirl.factory_by_name(@name).should == @factory
end end
end end
@ -94,38 +87,38 @@ describe "after defining a factory" do
@name = :user @name = :user
@factory = "factory" @factory = "factory"
Factory.factories[@name] = @factory FactoryGirl.factories[@name] = @factory
end end
it "should use Proxy::AttributesFor for Factory.attributes_for" do it "should use Proxy::AttributesFor for Factory.attributes_for" do
mock(@factory).run(Factory::Proxy::AttributesFor, :attr => 'value') { 'result' } mock(@factory).run(FactoryGirl::Proxy::AttributesFor, :attr => 'value') { 'result' }
Factory.attributes_for(@name, :attr => 'value').should == 'result' Factory.attributes_for(@name, :attr => 'value').should == 'result'
end end
it "should use Proxy::Build for Factory.build" do it "should use Proxy::Build for Factory.build" do
mock(@factory).run(Factory::Proxy::Build, :attr => 'value') { 'result' } mock(@factory).run(FactoryGirl::Proxy::Build, :attr => 'value') { 'result' }
Factory.build(@name, :attr => 'value').should == 'result' Factory.build(@name, :attr => 'value').should == 'result'
end end
it "should use Proxy::Create for Factory.create" do it "should use Proxy::Create for Factory.create" do
mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } mock(@factory).run(FactoryGirl::Proxy::Create, :attr => 'value') { 'result' }
Factory.create(@name, :attr => 'value').should == 'result' Factory.create(@name, :attr => 'value').should == 'result'
end end
it "should use Proxy::Stub for Factory.stub" do it "should use Proxy::Stub for Factory.stub" do
mock(@factory).run(Factory::Proxy::Stub, :attr => 'value') { 'result' } mock(@factory).run(FactoryGirl::Proxy::Stub, :attr => 'value') { 'result' }
Factory.stub(@name, :attr => 'value').should == 'result' Factory.stub(@name, :attr => 'value').should == 'result'
end end
it "should use default strategy option as Factory.default_strategy" do it "should use default strategy option as Factory.default_strategy" do
stub(@factory).default_strategy { :create } stub(@factory).default_strategy { :create }
mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } mock(@factory).run(FactoryGirl::Proxy::Create, :attr => 'value') { 'result' }
Factory.default_strategy(@name, :attr => 'value').should == 'result' Factory.default_strategy(@name, :attr => 'value').should == 'result'
end end
it "should use the default strategy for the global Factory method" do it "should use the default strategy for the global Factory method" do
stub(@factory).default_strategy { :create } stub(@factory).default_strategy { :create }
mock(@factory).run(Factory::Proxy::Create, :attr => 'value') { 'result' } mock(@factory).run(FactoryGirl::Proxy::Create, :attr => 'value') { 'result' }
Factory(@name, :attr => 'value').should == 'result' Factory(@name, :attr => 'value').should == 'result'
end end
@ -141,3 +134,46 @@ describe "after defining a factory" do
end end
end end
end end
describe "defining a sequence" do
before do
@sequence = "sequence"
@name = :count
stub(FactoryGirl::Sequence).new { @sequence }
end
it "should create a new sequence" do
mock(FactoryGirl::Sequence).new() { @sequence }
Factory.sequence(@name)
end
it "should use the supplied block as the sequence generator" do
stub(FactoryGirl::Sequence).new.yields(1)
yielded = false
Factory.sequence(@name) {|n| yielded = true }
(yielded).should be
end
end
describe "after defining a sequence" do
before do
@sequence = "sequence"
@name = :test
@value = '1 2 5'
stub(@sequence).next { @value }
stub(FactoryGirl::Sequence).new { @sequence }
Factory.sequence(@name) {}
end
it "should call next on the sequence when sent next" do
mock(@sequence).next
Factory.next(@name)
end
it "should return the value from the sequence" do
Factory.next(@name).should == @value
end
end

View file

@ -15,11 +15,6 @@ describe "a factory using sham syntax" do
end end
end end
after do
Factory.factories.clear
Factory.sequences.clear
end
describe "after making an instance" do describe "after making an instance" do
before do before do
@instance = Factory(:user, :last_name => 'Rye') @instance = Factory(:user, :last_name => 'Rye')

View file

@ -3,15 +3,15 @@ require 'spec_helper'
describe Factory, "aliases" do describe Factory, "aliases" do
it "should include an attribute as an alias for itself by default" do it "should include an attribute as an alias for itself by default" do
Factory.aliases_for(:test).should include(:test) FactoryGirl.aliases_for(:test).should include(:test)
end end
it "should include the root of a foreign key as an alias by default" do it "should include the root of a foreign key as an alias by default" do
Factory.aliases_for(:test_id).should include(:test) FactoryGirl.aliases_for(:test_id).should include(:test)
end end
it "should include an attribute's foreign key as an alias by default" do it "should include an attribute's foreign key as an alias by default" do
Factory.aliases_for(:test).should include(:test_id) FactoryGirl.aliases_for(:test).should include(:test_id)
end end
describe "after adding an alias" do describe "after adding an alias" do
@ -21,7 +21,7 @@ describe Factory, "aliases" do
end end
it "should return the alias in the aliases list" do it "should return the alias in the aliases list" do
Factory.aliases_for(:test_suffix).should include(:test) FactoryGirl.aliases_for(:test_suffix).should include(:test)
end end
end end

View file

@ -1,11 +1,11 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Attribute::Association do describe FactoryGirl::Attribute::Association do
before do before do
@name = :author @name = :author
@factory = :user @factory = :user
@overrides = { :first_name => 'John' } @overrides = { :first_name => 'John' }
@attr = Factory::Attribute::Association.new(@name, @factory, @overrides) @attr = FactoryGirl::Attribute::Association.new(@name, @factory, @overrides)
end end
it "should have a name" do it "should have a name" do
@ -24,6 +24,6 @@ describe Factory::Attribute::Association do
end end
it "should convert names to symbols" do it "should convert names to symbols" do
Factory::Attribute::Association.new('name', :user, {}).name.should == :name FactoryGirl::Attribute::Association.new('name', :user, {}).name.should == :name
end end
end end

View file

@ -1,10 +1,10 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Attribute::Callback do describe FactoryGirl::Attribute::Callback do
before do before do
@name = :after_create @name = :after_create
@block = proc{ 'block' } @block = proc{ 'block' }
@attr = Factory::Attribute::Callback.new(@name, @block) @attr = FactoryGirl::Attribute::Callback.new(@name, @block)
end end
it "should have a name" do it "should have a name" do
@ -18,6 +18,6 @@ describe Factory::Attribute::Callback do
end end
it "should convert names to symbols" do it "should convert names to symbols" do
Factory::Attribute::Callback.new('name', nil).name.should == :name FactoryGirl::Attribute::Callback.new('name', nil).name.should == :name
end end
end end

View file

@ -1,10 +1,10 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Attribute::Dynamic do describe FactoryGirl::Attribute::Dynamic do
before do before do
@name = :first_name @name = :first_name
@block = lambda { 'value' } @block = lambda { 'value' }
@attr = Factory::Attribute::Dynamic.new(@name, @block) @attr = FactoryGirl::Attribute::Dynamic.new(@name, @block)
end end
it "should have a name" do it "should have a name" do
@ -20,7 +20,7 @@ describe Factory::Attribute::Dynamic do
it "should yield the proxy to the block when adding its value to a proxy" do it "should yield the proxy to the block when adding its value to a proxy" do
@block = lambda {|a| a } @block = lambda {|a| a }
@attr = Factory::Attribute::Dynamic.new(:user, @block) @attr = FactoryGirl::Attribute::Dynamic.new(:user, @block)
@proxy = "proxy" @proxy = "proxy"
stub(@proxy).set stub(@proxy).set
@attr.add_to(@proxy) @attr.add_to(@proxy)
@ -29,21 +29,21 @@ describe Factory::Attribute::Dynamic do
it "should raise an error when defining an attribute writer" do it "should raise an error when defining an attribute writer" do
lambda { lambda {
Factory::Attribute::Dynamic.new('test=', nil) FactoryGirl::Attribute::Dynamic.new('test=', nil)
}.should raise_error(Factory::AttributeDefinitionError) }.should raise_error(FactoryGirl::AttributeDefinitionError)
end end
it "should raise an error when returning a sequence" do it "should raise an error when returning a sequence" do
stub(Factory).sequence { Factory::Sequence.new } stub(Factory).sequence { FactoryGirl::Sequence.new }
block = lambda { Factory.sequence(:email) } block = lambda { Factory.sequence(:email) }
attr = Factory::Attribute::Dynamic.new(:email, block) attr = FactoryGirl::Attribute::Dynamic.new(:email, block)
proxy = stub!.set.subject proxy = stub!.set.subject
lambda { lambda {
attr.add_to(proxy) attr.add_to(proxy)
}.should raise_error(Factory::SequenceAbuseError) }.should raise_error(FactoryGirl::SequenceAbuseError)
end end
it "should convert names to symbols" do it "should convert names to symbols" do
Factory::Attribute::Dynamic.new('name', nil).name.should == :name FactoryGirl::Attribute::Dynamic.new('name', nil).name.should == :name
end end
end end

View file

@ -1,10 +1,10 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Attribute::Static do describe FactoryGirl::Attribute::Static do
before do before do
@name = :first_name @name = :first_name
@value = 'John' @value = 'John'
@attr = Factory::Attribute::Static.new(@name, @value) @attr = FactoryGirl::Attribute::Static.new(@name, @value)
end end
it "should have a name" do it "should have a name" do
@ -19,11 +19,11 @@ describe Factory::Attribute::Static do
it "should raise an error when defining an attribute writer" do it "should raise an error when defining an attribute writer" do
lambda { lambda {
Factory::Attribute::Static.new('test=', nil) FactoryGirl::Attribute::Static.new('test=', nil)
}.should raise_error(Factory::AttributeDefinitionError) }.should raise_error(FactoryGirl::AttributeDefinitionError)
end end
it "should convert names to symbols" do it "should convert names to symbols" do
Factory::Attribute::Static.new('name', nil).name.should == :name FactoryGirl::Attribute::Static.new('name', nil).name.should == :name
end end
end end

View file

@ -1,9 +1,9 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Attribute do describe FactoryGirl::Attribute do
before do before do
@name = :user @name = :user
@attr = Factory::Attribute.new(@name) @attr = FactoryGirl::Attribute.new(@name)
end end
it "should have a name" do it "should have a name" do
@ -20,11 +20,11 @@ describe Factory::Attribute do
it "should raise an error when defining an attribute writer" do it "should raise an error when defining an attribute writer" do
error_message = %{factory_girl uses 'f.test value' syntax rather than 'f.test = value'} error_message = %{factory_girl uses 'f.test value' syntax rather than 'f.test = value'}
lambda { lambda {
Factory::Attribute.new('test=') FactoryGirl::Attribute.new('test=')
}.should raise_error(Factory::AttributeDefinitionError, error_message) }.should raise_error(FactoryGirl::AttributeDefinitionError, error_message)
end end
it "should convert names to symbols" do it "should convert names to symbols" do
Factory::Attribute.new('name').name.should == :name FactoryGirl::Attribute.new('name').name.should == :name
end end
end end

View file

@ -1,23 +1,23 @@
require 'spec_helper' require 'spec_helper'
describe Factory::DefinitionProxy do describe FactoryGirl::DefinitionProxy do
let(:factory) { Factory.new(:object) } let(:factory) { FactoryGirl::Factory.new(:object) }
subject { Factory::DefinitionProxy.new(factory) } subject { FactoryGirl::DefinitionProxy.new(factory) }
it "should add a static attribute for type" do it "should add a static attribute for type" do
subject.type subject.type
factory.attributes.last.should be_kind_of(Factory::Attribute::Static) factory.attributes.last.should be_kind_of(FactoryGirl::Attribute::Static)
end end
it "should add a static attribute for id" do it "should add a static attribute for id" do
subject.id subject.id
factory.attributes.last.should be_kind_of(Factory::Attribute::Static) factory.attributes.last.should be_kind_of(FactoryGirl::Attribute::Static)
end end
it "should add a static attribute when an attribute is defined with a value" do it "should add a static attribute when an attribute is defined with a value" do
attribute = 'attribute' attribute = 'attribute'
stub(attribute).name { :name } stub(attribute).name { :name }
mock(Factory::Attribute::Static).new(:name, 'value') { attribute } mock(FactoryGirl::Attribute::Static).new(:name, 'value') { attribute }
mock(factory).define_attribute(attribute) mock(factory).define_attribute(attribute)
subject.add_attribute(:name, 'value') subject.add_attribute(:name, 'value')
end end
@ -26,7 +26,7 @@ describe Factory::DefinitionProxy do
attribute = 'attribute' attribute = 'attribute'
stub(attribute).name { :name } stub(attribute).name { :name }
block = lambda {} block = lambda {}
mock(Factory::Attribute::Dynamic).new(:name, block) { attribute } mock(FactoryGirl::Attribute::Dynamic).new(:name, block) { attribute }
mock(factory).define_attribute(attribute) mock(factory).define_attribute(attribute)
subject.add_attribute(:name, &block) subject.add_attribute(:name, &block)
end end
@ -34,38 +34,38 @@ describe Factory::DefinitionProxy do
it "should raise for an attribute with a value and a block" do it "should raise for an attribute with a value and a block" do
lambda { lambda {
subject.add_attribute(:name, 'value') {} subject.add_attribute(:name, 'value') {}
}.should raise_error(Factory::AttributeDefinitionError) }.should raise_error(FactoryGirl::AttributeDefinitionError)
end end
describe "adding an attribute using a in-line sequence" do describe "adding an attribute using a in-line sequence" do
it "should create the sequence" do it "should create the sequence" do
mock(Factory::Sequence).new mock(FactoryGirl::Sequence).new
subject.sequence(:name) {} subject.sequence(:name) {}
end end
it "should add a dynamic attribute" do it "should add a dynamic attribute" do
attribute = 'attribute' attribute = 'attribute'
stub(attribute).name { :name } stub(attribute).name { :name }
mock(Factory::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute } mock(FactoryGirl::Attribute::Dynamic).new(:name, is_a(Proc)) { attribute }
subject.sequence(:name) {} subject.sequence(:name) {}
factory.attributes.should include(attribute) factory.attributes.should include(attribute)
end end
end end
it "should add a callback attribute when the after_build attribute is defined" do it "should add a callback attribute when the after_build attribute is defined" do
mock(Factory::Attribute::Callback).new(:after_build, is_a(Proc)) { 'after_build callback' } mock(FactoryGirl::Attribute::Callback).new(:after_build, is_a(Proc)) { 'after_build callback' }
subject.after_build {} subject.after_build {}
factory.attributes.should include('after_build callback') factory.attributes.should include('after_build callback')
end end
it "should add a callback attribute when the after_create attribute is defined" do it "should add a callback attribute when the after_create attribute is defined" do
mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' } mock(FactoryGirl::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
subject.after_create {} subject.after_create {}
factory.attributes.should include('after_create callback') factory.attributes.should include('after_create callback')
end end
it "should add a callback attribute when the after_stub attribute is defined" do it "should add a callback attribute when the after_stub attribute is defined" do
mock(Factory::Attribute::Callback).new(:after_stub, is_a(Proc)) { 'after_stub callback' } mock(FactoryGirl::Attribute::Callback).new(:after_stub, is_a(Proc)) { 'after_stub callback' }
subject.after_stub {} subject.after_stub {}
factory.attributes.should include('after_stub callback') factory.attributes.should include('after_stub callback')
end end
@ -74,7 +74,7 @@ describe Factory::DefinitionProxy do
name = :user name = :user
attr = 'attribute' attr = 'attribute'
stub(attr).name { name } stub(attr).name { name }
mock(Factory::Attribute::Association).new(name, name, {}) { attr } mock(FactoryGirl::Attribute::Association).new(name, name, {}) { attr }
subject.association(name) subject.association(name)
factory.attributes.should include(attr) factory.attributes.should include(attr)
end end
@ -84,7 +84,7 @@ describe Factory::DefinitionProxy do
attr = 'attribute' attr = 'attribute'
overrides = { :first_name => 'Ben' } overrides = { :first_name => 'Ben' }
stub(attr).name { name } stub(attr).name { name }
mock(Factory::Attribute::Association).new(name, name, overrides) { attr } mock(FactoryGirl::Attribute::Association).new(name, name, overrides) { attr }
subject.association(name, overrides) subject.association(name, overrides)
factory.attributes.should include(attr) factory.attributes.should include(attr)
end end
@ -93,7 +93,7 @@ describe Factory::DefinitionProxy do
attribute = 'attribute' attribute = 'attribute'
stub(attribute).name { :name } stub(attribute).name { :name }
block = lambda {} block = lambda {}
mock(Factory::Attribute::Static).new(:name, 'value') { attribute } mock(FactoryGirl::Attribute::Static).new(:name, 'value') { attribute }
subject.send(:name, 'value') subject.send(:name, 'value')
factory.attributes.should include(attribute) factory.attributes.should include(attribute)
end end

View file

@ -1,33 +1,31 @@
require 'spec_helper' require 'spec_helper'
describe Factory, "registering a factory" do describe FactoryGirl::Factory, "registering a factory" do
before do before do
@name = :user @name = :user
@factory = "factory" @factory = "factory"
stub(@factory).factory_name { @name } stub(@factory).factory_name { @name }
end end
after { Factory.factories.clear }
it "should add the factory to the list of factories" do it "should add the factory to the list of factories" do
Factory.register_factory(@factory) FactoryGirl.register_factory(@factory)
Factory.factory_by_name(@name).should == @factory FactoryGirl.factory_by_name(@name).should == @factory
end end
it "should not allow a duplicate factory definition" do it "should not allow a duplicate factory definition" do
lambda { lambda {
2.times { Factory.register_factory(@factory) } 2.times { FactoryGirl.register_factory(@factory) }
}.should raise_error(Factory::DuplicateDefinitionError) }.should raise_error(FactoryGirl::DuplicateDefinitionError)
end end
end end
describe Factory do describe FactoryGirl::Factory do
include DefinesConstants include DefinesConstants
before do before do
@name = :user @name = :user
@class = define_constant('User') @class = define_constant('User')
@factory = Factory.new(@name) @factory = FactoryGirl::Factory.new(@name)
end end
it "should have a factory name" do it "should have a factory name" do
@ -44,12 +42,12 @@ describe Factory do
it "should not allow the same attribute to be added twice" do it "should not allow the same attribute to be added twice" do
lambda { lambda {
2.times { @factory.define_attribute Factory::Attribute::Static.new(:name, 'value') } 2.times { @factory.define_attribute FactoryGirl::Attribute::Static.new(:name, 'value') }
}.should raise_error(Factory::AttributeDefinitionError) }.should raise_error(FactoryGirl::AttributeDefinitionError)
end end
it "should add a callback attribute when defining a callback" do it "should add a callback attribute when defining a callback" do
mock(Factory::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' } mock(FactoryGirl::Attribute::Callback).new(:after_create, is_a(Proc)) { 'after_create callback' }
@factory.add_callback(:after_create) {} @factory.add_callback(:after_create) {}
@factory.attributes.should include('after_create callback') @factory.attributes.should include('after_create callback')
end end
@ -57,7 +55,7 @@ describe Factory do
it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do it "should raise an InvalidCallbackNameError when defining a callback with an invalid name" do
lambda{ lambda{
@factory.add_callback(:invalid_callback_name) {} @factory.add_callback(:invalid_callback_name) {}
}.should raise_error(Factory::InvalidCallbackNameError) }.should raise_error(FactoryGirl::InvalidCallbackNameError)
end end
describe "after adding an attribute" do describe "after adding an attribute" do
@ -69,43 +67,43 @@ describe Factory do
stub(@attribute).add_to stub(@attribute).add_to
stub(@proxy).set stub(@proxy).set
stub(@proxy).result { 'result' } stub(@proxy).result { 'result' }
stub(Factory::Attribute::Static).new { @attribute } stub(FactoryGirl::Attribute::Static).new { @attribute }
stub(Factory::Proxy::Build).new { @proxy } stub(FactoryGirl::Proxy::Build).new { @proxy }
@factory.define_attribute(@attribute) @factory.define_attribute(@attribute)
end end
it "should create the right proxy using the build class when running" do it "should create the right proxy using the build class when running" do
mock(Factory::Proxy::Build).new(@factory.build_class) { @proxy } mock(FactoryGirl::Proxy::Build).new(@factory.build_class) { @proxy }
@factory.run(Factory::Proxy::Build, {}) @factory.run(FactoryGirl::Proxy::Build, {})
end end
it "should add the attribute to the proxy when running" do it "should add the attribute to the proxy when running" do
mock(@attribute).add_to(@proxy) mock(@attribute).add_to(@proxy)
@factory.run(Factory::Proxy::Build, {}) @factory.run(FactoryGirl::Proxy::Build, {})
end end
it "should return the result from the proxy when running" do it "should return the result from the proxy when running" do
mock(@proxy).result() { 'result' } mock(@proxy).result() { 'result' }
@factory.run(Factory::Proxy::Build, {}).should == 'result' @factory.run(FactoryGirl::Proxy::Build, {}).should == 'result'
end end
end end
it "should return associations" do it "should return associations" do
factory = Factory.new(:post) factory = FactoryGirl::Factory.new(:post)
factory.define_attribute(Factory::Attribute::Association.new(:author, :author, {})) factory.define_attribute(FactoryGirl::Attribute::Association.new(:author, :author, {}))
factory.define_attribute(Factory::Attribute::Association.new(:editor, :editor, {})) factory.define_attribute(FactoryGirl::Attribute::Association.new(:editor, :editor, {}))
factory.associations.each do |association| factory.associations.each do |association|
association.should be_a(Factory::Attribute::Association) association.should be_a(FactoryGirl::Attribute::Association)
end end
factory.associations.size.should == 2 factory.associations.size.should == 2
end end
it "should raise for a self referencing association" do it "should raise for a self referencing association" do
factory = Factory.new(:post) factory = FactoryGirl::Factory.new(:post)
lambda { lambda {
factory.define_attribute(Factory::Attribute::Association.new(:parent, :post, {})) factory.define_attribute(FactoryGirl::Attribute::Association.new(:parent, :post, {}))
}.should raise_error(Factory::AssociationDefinitionError) }.should raise_error(FactoryGirl::AssociationDefinitionError)
end end
describe "when overriding generated attributes with a hash" do describe "when overriding generated attributes with a hash" do
@ -116,32 +114,32 @@ describe Factory do
end end
it "should return the overridden value in the generated attributes" do it "should return the overridden value in the generated attributes" do
attr = Factory::Attribute::Static.new(@name, 'The price is wrong, Bob!') attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
@factory.define_attribute(attr) @factory.define_attribute(attr)
result = @factory.run(Factory::Proxy::AttributesFor, @hash) result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
result[@name].should == @value result[@name].should == @value
end end
it "should not call a lazy attribute block for an overridden attribute" do it "should not call a lazy attribute block for an overridden attribute" do
attr = Factory::Attribute::Dynamic.new(@name, lambda { flunk }) attr = FactoryGirl::Attribute::Dynamic.new(@name, lambda { flunk })
@factory.define_attribute(attr) @factory.define_attribute(attr)
result = @factory.run(Factory::Proxy::AttributesFor, @hash) result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
end end
it "should override a symbol parameter with a string parameter" do it "should override a symbol parameter with a string parameter" do
attr = Factory::Attribute::Static.new(@name, 'The price is wrong, Bob!') attr = FactoryGirl::Attribute::Static.new(@name, 'The price is wrong, Bob!')
@factory.define_attribute(attr) @factory.define_attribute(attr)
@hash = { @name.to_s => @value } @hash = { @name.to_s => @value }
result = @factory.run(Factory::Proxy::AttributesFor, @hash) result = @factory.run(FactoryGirl::Proxy::AttributesFor, @hash)
result[@name].should == @value result[@name].should == @value
end end
end end
describe "overriding an attribute with an alias" do describe "overriding an attribute with an alias" do
before do before do
@factory.define_attribute(Factory::Attribute::Static.new(:test, 'original')) @factory.define_attribute(FactoryGirl::Attribute::Static.new(:test, 'original'))
Factory.alias(/(.*)_alias/, '\1') Factory.alias(/(.*)_alias/, '\1')
@result = @factory.run(Factory::Proxy::AttributesFor, @result = @factory.run(FactoryGirl::Proxy::AttributesFor,
:test_alias => 'new') :test_alias => 'new')
end end
@ -159,13 +157,13 @@ describe Factory do
end end
it "should create a new factory using the class of the parent" do it "should create a new factory using the class of the parent" do
child = Factory.new(:child) child = FactoryGirl::Factory.new(:child)
child.inherit_from(@factory) child.inherit_from(@factory)
child.build_class.should == @factory.build_class child.build_class.should == @factory.build_class
end end
it "should create a new factory while overriding the parent class" do it "should create a new factory while overriding the parent class" do
child = Factory.new(:child, :class => String) child = FactoryGirl::Factory.new(:child, :class => String)
child.inherit_from(@factory) child.inherit_from(@factory)
child.build_class.should == String child.build_class.should == String
end end
@ -173,26 +171,26 @@ describe Factory do
describe "given a parent with attributes" do describe "given a parent with attributes" do
before do before do
@parent_attr = :name @parent_attr = :name
@factory.define_attribute(Factory::Attribute::Static.new(@parent_attr, 'value')) @factory.define_attribute(FactoryGirl::Attribute::Static.new(@parent_attr, 'value'))
end end
it "should create a new factory with attributes of the parent" do it "should create a new factory with attributes of the parent" do
child = Factory.new(:child) child = FactoryGirl::Factory.new(:child)
child.inherit_from(@factory) child.inherit_from(@factory)
child.attributes.size.should == 1 child.attributes.size.should == 1
child.attributes.first.name.should == @parent_attr child.attributes.first.name.should == @parent_attr
end end
it "should allow a child to define additional attributes" do it "should allow a child to define additional attributes" do
child = Factory.new(:child) child = FactoryGirl::Factory.new(:child)
child.define_attribute(Factory::Attribute::Static.new(:email, 'value')) child.define_attribute(FactoryGirl::Attribute::Static.new(:email, 'value'))
child.inherit_from(@factory) child.inherit_from(@factory)
child.attributes.size.should == 2 child.attributes.size.should == 2
end end
it "should allow to override parent attributes" do it "should allow to override parent attributes" do
child = Factory.new(:child) child = FactoryGirl::Factory.new(:child)
@child_attr = Factory::Attribute::Static.new(@parent_attr, 'value') @child_attr = FactoryGirl::Attribute::Static.new(@parent_attr, 'value')
child.define_attribute(@child_attr) child.define_attribute(@child_attr)
child.inherit_from(@factory) child.inherit_from(@factory)
child.attributes.size.should == 1 child.attributes.size.should == 1
@ -202,16 +200,16 @@ describe Factory do
it "inherit all callbacks" do it "inherit all callbacks" do
@factory.add_callback(:after_stub) { |object| object.name = 'Stubby' } @factory.add_callback(:after_stub) { |object| object.name = 'Stubby' }
child = Factory.new(:child) child = FactoryGirl::Factory.new(:child)
child.inherit_from(@factory) child.inherit_from(@factory)
child.attributes.last.should be_kind_of(Factory::Attribute::Callback) child.attributes.last.should be_kind_of(FactoryGirl::Attribute::Callback)
end end
end end
describe Factory, "when defined with a custom class" do describe FactoryGirl::Factory, "when defined with a custom class" do
before do before do
@class = Float @class = Float
@factory = Factory.new(:author, :class => @class) @factory = FactoryGirl::Factory.new(:author, :class => @class)
end end
it "should use the specified class as the build class" do it "should use the specified class as the build class" do
@ -219,11 +217,11 @@ describe Factory, "when defined with a custom class" do
end end
end end
describe Factory, "when defined with a class instead of a name" do describe FactoryGirl::Factory, "when defined with a class instead of a name" do
before do before do
@class = ArgumentError @class = ArgumentError
@name = :argument_error @name = :argument_error
@factory = Factory.new(@class) @factory = FactoryGirl::Factory.new(@class)
end end
it "should guess the name from the class" do it "should guess the name from the class" do
@ -235,10 +233,10 @@ describe Factory, "when defined with a class instead of a name" do
end end
end end
describe Factory, "when defined with a custom class name" do describe FactoryGirl::Factory, "when defined with a custom class name" do
before do before do
@class = ArgumentError @class = ArgumentError
@factory = Factory.new(:author, :class => :argument_error) @factory = FactoryGirl::Factory.new(:author, :class => :argument_error)
end end
it "should use the specified class as the build class" do it "should use the specified class as the build class" do
@ -246,14 +244,14 @@ describe Factory, "when defined with a custom class name" do
end end
end end
describe Factory, "with a name ending in s" do describe FactoryGirl::Factory, "with a name ending in s" do
include DefinesConstants include DefinesConstants
before do before do
define_constant('Business') define_constant('Business')
@name = :business @name = :business
@class = Business @class = Business
@factory = Factory.new(@name) @factory = FactoryGirl::Factory.new(@name)
end end
it "should have a factory name" do it "should have a factory name" do
@ -265,10 +263,10 @@ describe Factory, "with a name ending in s" do
end end
end end
describe Factory, "with a string for a name" do describe FactoryGirl::Factory, "with a string for a name" do
before do before do
@name = :string @name = :string
@factory = Factory.new(@name.to_s) {} @factory = FactoryGirl::Factory.new(@name.to_s) {}
end end
it "should convert the string to a symbol" do it "should convert the string to a symbol" do
@ -276,19 +274,19 @@ describe Factory, "with a string for a name" do
end end
end end
describe Factory, "registered with a string name" do describe FactoryGirl::Factory, "registered with a string name" do
before do before do
@name = :string @name = :string
@factory = Factory.new(@name) @factory = FactoryGirl::Factory.new(@name)
Factory.register_factory(@factory) FactoryGirl.register_factory(@factory)
end end
it "should store the factory using a symbol" do it "should store the factory using a symbol" do
Factory.factories[@name].should == @factory FactoryGirl.factories[@name].should == @factory
end end
end end
describe Factory, "for namespaced class" do describe FactoryGirl::Factory, "for namespaced class" do
include DefinesConstants include DefinesConstants
before do before do
@ -300,17 +298,17 @@ describe Factory, "for namespaced class" do
end end
it "should build namespaced class passed by string" do it "should build namespaced class passed by string" do
factory = Factory.new(@name.to_s, :class => @class.name) factory = FactoryGirl::Factory.new(@name.to_s, :class => @class.name)
factory.build_class.should == @class factory.build_class.should == @class
end end
it "should build Admin::Settings class from Admin::Settings string" do it "should build Admin::Settings class from Admin::Settings string" do
factory = Factory.new(@name.to_s, :class => 'admin/settings') factory = FactoryGirl::Factory.new(@name.to_s, :class => 'admin/settings')
factory.build_class.should == @class factory.build_class.should == @class
end end
end end
describe Factory do describe FactoryGirl::Factory do
include DefinesConstants include DefinesConstants
before do before do
@ -320,19 +318,19 @@ describe Factory do
it "should raise an ArgumentError when trying to use a non-existent strategy" do it "should raise an ArgumentError when trying to use a non-existent strategy" do
lambda { lambda {
Factory.new(:object, :default_strategy => :nonexistent) {} FactoryGirl::Factory.new(:object, :default_strategy => :nonexistent) {}
}.should raise_error(ArgumentError) }.should raise_error(ArgumentError)
end end
it "should create a new factory with a specified default strategy" do it "should create a new factory with a specified default strategy" do
factory = Factory.new(:object, :default_strategy => :stub) factory = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
factory.default_strategy.should == :stub factory.default_strategy.should == :stub
end end
describe 'defining a child factory without setting default strategy' do describe 'defining a child factory without setting default strategy' do
before do before do
@parent = Factory.new(:object, :default_strategy => :stub) @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
@child = Factory.new(:child_object) @child = FactoryGirl::Factory.new(:child_object)
@child.inherit_from(@parent) @child.inherit_from(@parent)
end end
@ -343,8 +341,8 @@ describe Factory do
describe 'defining a child factory with a default strategy' do describe 'defining a child factory with a default strategy' do
before do before do
@parent = Factory.new(:object, :default_strategy => :stub) @parent = FactoryGirl::Factory.new(:object, :default_strategy => :stub)
@child = Factory.new(:child_object2, :default_strategy => :build) @child = FactoryGirl::Factory.new(:child_object2, :default_strategy => :build)
@child.inherit_from(@parent) @child.inherit_from(@parent)
end end
@ -355,85 +353,3 @@ describe Factory do
end end
describe "definition loading" do
def self.in_directory_with_files(*files)
before do
@pwd = Dir.pwd
@tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
FileUtils.mkdir_p @tmp_dir
Dir.chdir(@tmp_dir)
files.each do |file|
FileUtils.mkdir_p File.dirname(file)
FileUtils.touch file
stub(Factory).require(file)
end
end
after do
Dir.chdir(@pwd)
FileUtils.rm_rf(@tmp_dir)
end
end
def require_definitions_from(file)
simple_matcher do |given, matcher|
has_received = have_received.method_missing(:require, file)
result = has_received.matches?(given)
matcher.description = "require definitions from #{file}"
matcher.failure_message = has_received.failure_message
result
end
end
share_examples_for "finds definitions" do
before do
stub(Factory).require
Factory.find_definitions
end
subject { Factory }
end
describe "with factories.rb" do
in_directory_with_files 'factories.rb'
it_should_behave_like "finds definitions"
it { should require_definitions_from('factories.rb') }
end
%w(spec test).each do |dir|
describe "with a factories file under #{dir}" do
in_directory_with_files File.join(dir, 'factories.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories.rb") }
end
describe "with a factories file under #{dir}/factories" do
in_directory_with_files File.join(dir, 'factories', 'post_factory.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
end
describe "with several factories files under #{dir}/factories" do
in_directory_with_files File.join(dir, 'factories', 'post_factory.rb'),
File.join(dir, 'factories', 'person_factory.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
end
describe "with nested and unnested factories files under #{dir}" do
in_directory_with_files File.join(dir, 'factories.rb'),
File.join(dir, 'factories', 'post_factory.rb'),
File.join(dir, 'factories', 'person_factory.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories.rb") }
it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
end
end
it "should return the factory name without underscores for the human name" do
factory = Factory.new(:name_with_underscores)
factory.human_name.should == 'name with underscores'
end
end

View file

@ -0,0 +1,79 @@
require 'spec_helper'
share_examples_for "finds definitions" do
before do
stub(FactoryGirl).require
FactoryGirl.find_definitions
end
subject { FactoryGirl }
end
describe "definition loading" do
def self.in_directory_with_files(*files)
before do
@pwd = Dir.pwd
@tmp_dir = File.join(File.dirname(__FILE__), 'tmp')
FileUtils.mkdir_p @tmp_dir
Dir.chdir(@tmp_dir)
files.each do |file|
FileUtils.mkdir_p File.dirname(file)
FileUtils.touch file
stub(Factory).require(file)
end
end
after do
Dir.chdir(@pwd)
FileUtils.rm_rf(@tmp_dir)
end
end
def require_definitions_from(file)
simple_matcher do |given, matcher|
has_received = have_received.method_missing(:require, file)
result = has_received.matches?(given)
matcher.description = "require definitions from #{file}"
matcher.failure_message = has_received.failure_message
result
end
end
describe "with factories.rb" do
in_directory_with_files 'factories.rb'
it_should_behave_like "finds definitions"
it { should require_definitions_from('factories.rb') }
end
%w(spec test).each do |dir|
describe "with a factories file under #{dir}" do
in_directory_with_files File.join(dir, 'factories.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories.rb") }
end
describe "with a factories file under #{dir}/factories" do
in_directory_with_files File.join(dir, 'factories', 'post_factory.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
end
describe "with several factories files under #{dir}/factories" do
in_directory_with_files File.join(dir, 'factories', 'post_factory.rb'),
File.join(dir, 'factories', 'person_factory.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
end
describe "with nested and unnested factories files under #{dir}" do
in_directory_with_files File.join(dir, 'factories.rb'),
File.join(dir, 'factories', 'post_factory.rb'),
File.join(dir, 'factories', 'person_factory.rb')
it_should_behave_like "finds definitions"
it { should require_definitions_from("#{dir}/factories.rb") }
it { should require_definitions_from("#{dir}/factories/post_factory.rb") }
it { should require_definitions_from("#{dir}/factories/person_factory.rb") }
end
end
end

View file

@ -1,8 +1,8 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Proxy::AttributesFor do describe FactoryGirl::Proxy::AttributesFor do
before do before do
@proxy = Factory::Proxy::AttributesFor.new(@class) @proxy = FactoryGirl::Proxy::AttributesFor.new(@class)
end end
describe "when asked to associate with another factory" do describe "when asked to associate with another factory" do

View file

@ -1,6 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Proxy::Build do describe FactoryGirl::Proxy::Build do
before do before do
@class = Class.new @class = Class.new
@instance = "built-instance" @instance = "built-instance"
@ -10,7 +10,7 @@ describe Factory::Proxy::Build do
stub(@instance, :attribute=) stub(@instance, :attribute=)
stub(@instance, :owner=) stub(@instance, :owner=)
@proxy = Factory::Proxy::Build.new(@class) @proxy = FactoryGirl::Proxy::Build.new(@class)
end end
it "should instantiate the class" do it "should instantiate the class" do
@ -21,14 +21,14 @@ describe Factory::Proxy::Build do
before do before do
@association = "associated-instance" @association = "associated-instance"
@associated_factory = "associated-factory" @associated_factory = "associated-factory"
stub(Factory).factory_by_name { @associated_factory } stub(FactoryGirl).factory_by_name { @associated_factory }
stub(@associated_factory).run { @association } stub(@associated_factory).run { @association }
@overrides = { 'attr' => 'value' } @overrides = { 'attr' => 'value' }
@proxy.associate(:owner, :user, @overrides) @proxy.associate(:owner, :user, @overrides)
end end
it "should create the associated instance" do it "should create the associated instance" do
@associated_factory.should have_received.run(Factory::Proxy::Create, @overrides) @associated_factory.should have_received.run(FactoryGirl::Proxy::Create, @overrides)
end end
it "should set the associated instance" do it "should set the associated instance" do
@ -39,11 +39,11 @@ describe Factory::Proxy::Build do
it "should run create when building an association" do it "should run create when building an association" do
association = "associated-instance" association = "associated-instance"
associated_factory = "associated-factory" associated_factory = "associated-factory"
stub(Factory).factory_by_name { associated_factory } stub(FactoryGirl).factory_by_name { associated_factory }
stub(associated_factory).run { association } stub(associated_factory).run { association }
overrides = { 'attr' => 'value' } overrides = { 'attr' => 'value' }
@proxy.association(:user, overrides).should == association @proxy.association(:user, overrides).should == association
associated_factory.should have_received.run(Factory::Proxy::Create, overrides) associated_factory.should have_received.run(FactoryGirl::Proxy::Create, overrides)
end end
it "should return the built instance when asked for the result" do it "should return the built instance when asked for the result" do

View file

@ -1,6 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Proxy::Create do describe FactoryGirl::Proxy::Create do
before do before do
@class = Class.new @class = Class.new
@instance = "built-instance" @instance = "built-instance"
@ -11,7 +11,7 @@ describe Factory::Proxy::Create do
stub(@instance, :owner=) stub(@instance, :owner=)
stub(@instance).save! stub(@instance).save!
@proxy = Factory::Proxy::Create.new(@class) @proxy = FactoryGirl::Proxy::Create.new(@class)
end end
it "should instantiate the class" do it "should instantiate the class" do
@ -22,14 +22,14 @@ describe Factory::Proxy::Create do
before do before do
@association = "associated-instance" @association = "associated-instance"
@associated_factory = "associated-factory" @associated_factory = "associated-factory"
stub(Factory).factory_by_name { @associated_factory } stub(FactoryGirl).factory_by_name { @associated_factory }
stub(@associated_factory).run { @association } stub(@associated_factory).run { @association }
@overrides = { 'attr' => 'value' } @overrides = { 'attr' => 'value' }
@proxy.associate(:owner, :user, @overrides) @proxy.associate(:owner, :user, @overrides)
end end
it "should create the associated instance" do it "should create the associated instance" do
@associated_factory.should have_received.run(Factory::Proxy::Create, @overrides) @associated_factory.should have_received.run(FactoryGirl::Proxy::Create, @overrides)
end end
it "should set the associated instance" do it "should set the associated instance" do
@ -40,11 +40,11 @@ describe Factory::Proxy::Create do
it "should run create when building an association" do it "should run create when building an association" do
association = "associated-instance" association = "associated-instance"
associated_factory = "associated-factory" associated_factory = "associated-factory"
stub(Factory).factory_by_name { associated_factory } stub(FactoryGirl).factory_by_name { associated_factory }
stub(associated_factory).run { association } stub(associated_factory).run { association }
overrides = { 'attr' => 'value' } overrides = { 'attr' => 'value' }
@proxy.association(:user, overrides).should == association @proxy.association(:user, overrides).should == association
associated_factory.should have_received.run(Factory::Proxy::Create, overrides) associated_factory.should have_received.run(FactoryGirl::Proxy::Create, overrides)
end end
describe "when asked for the result" do describe "when asked for the result" do

View file

@ -1,6 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Proxy::Stub do describe FactoryGirl::Proxy::Stub do
before do before do
@class = "class" @class = "class"
@instance = "instance" @instance = "instance"
@ -9,7 +9,7 @@ describe Factory::Proxy::Stub do
stub(@instance).id { 42 } stub(@instance).id { 42 }
stub(@instance).reload { @instance.connection.reload } stub(@instance).reload { @instance.connection.reload }
@stub = Factory::Proxy::Stub.new(@class) @stub = FactoryGirl::Proxy::Stub.new(@class)
end end
it "should not be a new record" do it "should not be a new record" do
@ -23,14 +23,14 @@ describe Factory::Proxy::Stub do
describe "when a user factory exists" do describe "when a user factory exists" do
before do before do
@user = "user" @user = "user"
stub(Factory).factory_by_name { @associated_factory } stub(FactoryGirl).factory_by_name { @associated_factory }
@associated_factory = 'associate-factory' @associated_factory = 'associate-factory'
end end
describe "when asked to associate with another factory" do describe "when asked to associate with another factory" do
before do before do
stub(@instance).owner { @user } stub(@instance).owner { @user }
mock(@associated_factory).run(Factory::Proxy::Stub, {}) { @user } mock(@associated_factory).run(FactoryGirl::Proxy::Stub, {}) { @user }
mock(@stub).set(:owner, @user) mock(@stub).set(:owner, @user)
@stub.associate(:owner, :user, {}) @stub.associate(:owner, :user, {})
@ -42,7 +42,7 @@ describe Factory::Proxy::Stub do
end end
it "should return the association when building one" do it "should return the association when building one" do
mock(@associated_factory).run(Factory::Proxy::Stub, {}) { @user } mock(@associated_factory).run(FactoryGirl::Proxy::Stub, {}) { @user }
@stub.association(:user).should == @user @stub.association(:user).should == @user
end end

View file

@ -1,8 +1,8 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Proxy do describe FactoryGirl::Proxy do
before do before do
@proxy = Factory::Proxy.new(Class.new) @proxy = FactoryGirl::Proxy.new(Class.new)
end end
it "should do nothing when asked to set an attribute to a value" do it "should do nothing when asked to set an attribute to a value" do

View file

@ -1,9 +1,9 @@
require 'spec_helper' require 'spec_helper'
describe Factory::Sequence do describe FactoryGirl::Sequence do
describe "a sequence" do describe "a sequence" do
before do before do
@sequence = Factory::Sequence.new {|n| "=#{n}" } @sequence = FactoryGirl::Sequence.new {|n| "=#{n}" }
end end
it "should start with a value of 1" do it "should start with a value of 1" do
@ -20,47 +20,4 @@ describe Factory::Sequence do
end end
end end
end end
describe "defining a sequence" do
before do
@sequence = "sequence"
@name = :count
stub(Factory::Sequence).new { @sequence }
end
it "should create a new sequence" do
mock(Factory::Sequence).new() { @sequence }
Factory.sequence(@name)
end
it "should use the supplied block as the sequence generator" do
stub(Factory::Sequence).new.yields(1)
yielded = false
Factory.sequence(@name) {|n| yielded = true }
(yielded).should be
end
end
describe "after defining a sequence" do
before do
@sequence = "sequence"
@name = :test
@value = '1 2 5'
stub(@sequence).next { @value }
stub(Factory::Sequence).new { @sequence }
Factory.sequence(@name) {}
end
it "should call next on the sequence when sent next" do
mock(@sequence).next
Factory.next(@name)
end
it "should return the value from the sequence" do
Factory.next(@name).should == @value
end
end
end end

View file

@ -11,8 +11,8 @@ require 'factory_girl'
Spec::Runner.configure do |config| Spec::Runner.configure do |config|
config.mock_with RR::Adapters::Rspec config.mock_with RR::Adapters::Rspec
config.after do config.after do
Factory.factories.clear FactoryGirl.factories.clear
Factory.sequences.clear FactoryGirl.sequences.clear
end end
end end