diff --git a/cucumber.yml b/cucumber.yml new file mode 100644 index 0000000..7538cab --- /dev/null +++ b/cucumber.yml @@ -0,0 +1 @@ +default: -r features features diff --git a/features/factory_girl_steps.feature b/features/factory_girl_steps.feature index 51bdf9b..d2a3b21 100644 --- a/features/factory_girl_steps.feature +++ b/features/factory_girl_steps.feature @@ -18,3 +18,25 @@ Feature: Use step definitions generated by factories | title | three | | body | third | And there should be 3 posts + + Scenario: create a post with a new author + Given the following post exists: + | Title | a title | + | Author | ID: 123 | + Then I should find the following for the last post: + | title | a title | + | author_id | 123 | + And I should find the following for the last user: + | id | 123 | + + Scenario: create a post with an existing author + Given the following user exists: + | ID | 123 | + | Name | Joe | + And the following post exists: + | Title | a title | + | Author | Name: Joe | + Then I should find the following for the last post: + | title | a title | + | author_id | 123 | + And there should be 1 user diff --git a/features/step_definitions/database_steps.rb b/features/step_definitions/database_steps.rb index 22c1f38..f15a094 100644 --- a/features/step_definitions/database_steps.rb +++ b/features/step_definitions/database_steps.rb @@ -1,15 +1,18 @@ -Then /^I should find the following for the last post:$/ do |table| - last_post = Post.last or raise "No posts exist" - attributes = table.rows.inject({}) {|res, (key, value)| res.merge(key => value) } +Then /^I should find the following for the last (.*):$/ do |model, table| + model_class = model.camelize.constantize + last_instance = model_class.last or raise "No #{model.pluralize} exist" + attributes = table.raw.inject({}) {|res, (key, value)| res.merge(key => value) } attributes.each do |key, value| - last_post.attributes[key].should == value + last_instance.attributes[key].to_s.should == value end end -Then /^there should be (\d+) posts$/ do |count| - Post.count.should == count.to_i +Then /^there should be (\d+) (.*)$/ do |count, model| + model_class = model.singularize.camelize.constantize + model_class.count.should == count.to_i end Before do Post.delete_all + User.delete_all end diff --git a/features/support/factories.rb b/features/support/factories.rb index 412b64d..da38f89 100644 --- a/features/support/factories.rb +++ b/features/support/factories.rb @@ -6,18 +6,31 @@ ActiveRecord::Base.establish_connection( class CreateSchema < ActiveRecord::Migration def self.up create_table :posts, :force => true do |t| + t.integer :author_id t.string :title t.string :body end + + create_table :users, :force => true do |t| + t.string :name + end end end CreateSchema.suppress_messages { CreateSchema.migrate(:up) } +class User < ActiveRecord::Base +end + class Post < ActiveRecord::Base + belongs_to :author, :class_name => 'User' +end + +Factory.define :user do |f| end Factory.define :post do |f| + f.association :author, :factory => :user end require 'factory_girl/step_definitions' diff --git a/lib/factory_girl/attribute/association.rb b/lib/factory_girl/attribute/association.rb index d6b8a04..d5f5276 100644 --- a/lib/factory_girl/attribute/association.rb +++ b/lib/factory_girl/attribute/association.rb @@ -3,6 +3,8 @@ class Factory class Association < Attribute #:nodoc: + attr_reader :factory + def initialize(name, factory, overrides) super(name) @factory = factory diff --git a/lib/factory_girl/factory.rb b/lib/factory_girl/factory.rb index 206049f..78b3ce1 100644 --- a/lib/factory_girl/factory.rb +++ b/lib/factory_girl/factory.rb @@ -305,6 +305,10 @@ class Factory end end + def associations + attributes.select {|attribute| attribute.is_a?(Attribute::Association) } + end + private def class_for (class_or_to_s) diff --git a/lib/factory_girl/step_definitions.rb b/lib/factory_girl/step_definitions.rb index 119e6bb..4e4f537 100644 --- a/lib/factory_girl/step_definitions.rb +++ b/lib/factory_girl/step_definitions.rb @@ -1,14 +1,25 @@ module FactoryGirlStepHelpers - def convert_ast_table_to_attribute_hash(table) - table.rows.inject({}) do |result, (human_key, value)| - key = human_key.downcase.gsub(' ', '_').to_sym + def convert_vertical_table_to_hash(table) + table.raw.inject({}) do |result, (key, value)| result.merge(key => value) end end - def convert_human_hash_to_attribute_hash(human_hash) + def convert_association_string_to_instance(factory_name, assignment) + attribute, value = assignment.split(':', 2) + attributes = convert_human_hash_to_attribute_hash(attribute => value.strip) + factory = Factory.factory_by_name(factory_name) + model_class = factory.build_class + model_class.find(:first, :conditions => attributes) or + Factory(factory_name, attributes) + end + + def convert_human_hash_to_attribute_hash(human_hash, associations = []) human_hash.inject({}) do |attribute_hash, (human_key, value)| key = human_key.downcase.gsub(' ', '_').to_sym + if association = associations.detect {|association| association.name == key } + value = convert_association_string_to_instance(association.factory, value) + end attribute_hash.merge(key => value) end end @@ -18,14 +29,15 @@ World(FactoryGirlStepHelpers) Factory.factories.values.each do |factory| Given "the following #{factory.human_name} exists:" do |table| - attributes = convert_ast_table_to_attribute_hash(table) + human_hash = convert_vertical_table_to_hash(table) + attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations) Factory.create(factory.factory_name, attributes) end # TODO: support irregular pluralizations Given "the following #{factory.human_name}s exist:" do |table| table.hashes.each do |human_hash| - attributes = convert_human_hash_to_attribute_hash(human_hash) + attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations) Factory.create(factory.factory_name, attributes) end end diff --git a/spec/factory_girl/attribute/association_spec.rb b/spec/factory_girl/attribute/association_spec.rb index 981f326..e5fa682 100644 --- a/spec/factory_girl/attribute/association_spec.rb +++ b/spec/factory_girl/attribute/association_spec.rb @@ -12,6 +12,10 @@ describe Factory::Attribute::Association do @attr.name.should == @name end + it "should have a factory" do + @attr.factory.should == @factory + end + it "should tell the proxy to associate when being added to a proxy" do proxy = "proxy" stub(proxy).associate diff --git a/spec/factory_girl/factory_spec.rb b/spec/factory_girl/factory_spec.rb index cc79757..6f31e58 100644 --- a/spec/factory_girl/factory_spec.rb +++ b/spec/factory_girl/factory_spec.rb @@ -134,6 +134,16 @@ describe Factory do factory.attributes.should include(attr) end + it "should return associations" do + factory = Factory.new(:post) + factory.association(:author) + factory.association(:editor) + factory.associations.each do |association| + association.should be_a(Factory::Attribute::Association) + end + factory.associations.size.should == 2 + end + it "should add an association with overrides" do factory = Factory.new(:post) name = :user