-
-
Save chrisbloom7/1513688 to your computer and use it in GitHub Desktop.
A modified version of the cucumber steps included in factory_girl, which will set an instance variable based on the factory/factories being generated. Drop this file into the features/support folder and don't require the original factory_girl/step_definit
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Assumes you have a factory named :customer defined with attributes first_name and last_name | |
Feature: Testing customized factory_girl step definitions | |
As an open source advocate | |
I | |
Want to make sure that my customized step definitions don't throw any errors | |
Scenario: Generating factories from a table | |
Given the following customers exist: | |
| first_name | last_name | | |
| Bob | Smith | | |
| Jane | Doe | | |
Then an instance variable named "@customers" should be set | |
And the instance variable "@customers" should contain the following customer objects: | |
| first_name | last_name | | |
| Bob | Smith | | |
| Jane | Doe | | |
Scenario: Generating a single factory | |
Given a customer exists | |
Then an instance variable named "@customer" should be set | |
And the instance variable "@customer" should contain a customer object | |
Scenario: Generating multiple factories | |
Given 10 customers exist | |
Then an instance variable named "@customers" should be set | |
And the instance variable "@customers" should contain 10 customer objects | |
Scenario: Generating a single factory with a specific attribute value | |
Given a customer exists with a first name of "Foo" | |
Then an instance variable named "@customer" should be set | |
And the instance variable "@customer" should contain a customer object with a "first_name" of "Foo" | |
Scenario: Generating multiple factories with a specific attribute value | |
Given 15 customers exist with a last name of "Baz" | |
Then an instance variable named "@customers" should be set | |
And the instance variable "@customers" should contain 15 customer objects each with a "last_name" of "Baz" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Then /^an instance variable named "([^"]*)" should be set$/ do |var| | |
instance_variable_defined?(var.to_s).should be_true | |
end | |
Then /^the instance variable "([^"]*)" should contain the following customer objects:$/ do |var, table| | |
customers = table.hashes | |
columns = table.column_names | |
var = instance_variable_get(var.to_s) | |
var.class.to_s.should eq("Array") | |
var.each do |objekt| | |
objekt.class.to_s.should eq("Customer") | |
attrs = columns.each.collect {|attr| objekt.send(attr)} | |
customers.include?(Hash[columns.zip(attrs)]).should be_true | |
end | |
end | |
Then /^the instance variable "([^"]*)" should contain a customer object$/ do |var| | |
var = instance_variable_get(var.to_s) | |
var.class.to_s.should eq("Customer") | |
end | |
Then /^the instance variable "([^"]*)" should contain (\d+) customer objects$/ do |var, count| | |
var = instance_variable_get(var.to_s) | |
var.class.to_s.should eq("Array") | |
var.size.should eq(count.to_i) | |
var.each do |objekt| | |
objekt.class.to_s.should eq("Customer") | |
end | |
end | |
Then /^the instance variable "([^"]*)" should contain a customer object with a "([^"]*)" of "([^"]*)"$/ do |var, attr, val| | |
var = instance_variable_get(var.to_s) | |
var.class.to_s.should eq("Customer") | |
var.send(attr).should eq(val) | |
end | |
Then /^the instance variable "([^"]*)" should contain (\d+) customer objects each with a "([^"]*)" of "([^"]*)"$/ do |var, count, attr, val| | |
var = instance_variable_get(var.to_s) | |
var.class.to_s.should eq("Array") | |
var.size.should eq(count.to_i) | |
var.each do |objekt| | |
objekt.class.to_s.should eq("Customer") | |
objekt.send(attr).should eq(val) | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Original Source: https://gist.github.com/485974 | |
# Updated on 2011-12-23 to use current version of http://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/step_definitions.rb | |
# Updated on 2012-04-29 to be more robust, support aliased factory names, and fail gracefully if setting an instance variable raises an error. | |
# Original comments follow: | |
## Stolen from: http://github.com/thoughtbot/factory_girl/blob/master/lib/factory_girl/step_definitions.rb | |
## and slightly modified so that steps which create only a single record, save | |
## that record to an instance variable, so you can do things like: | |
## | |
## Given I am logged in as an admin | |
## And a post exists with a title of "Awesome Post" | |
## When I go to the post | |
## Then I should see "Awesome Post" | |
## And I should see a link to edit the post | |
## | |
## Since the Given creates a @post instance, it can be referred to like this: | |
## | |
## # paths.rb: | |
## when /the post/ | |
## post_path(@post) | |
## | |
## # post_steps.rb: | |
## Then /^I should see a link to edit the post$/ | |
## page.should have_xpath("//a[@href=#{edit_post_path(@post)}]") | |
## end | |
## | |
## This can make your steps a bit more brittle if you're not careful, but for | |
## me the trade-off for DRY, readable steps is worth it. | |
## | |
## Ideally I could require 'factory_girl/step_definitions.rb' and just | |
## redefine the steps I wanted to change, but that raises | |
## an ambiguous step error. Haven't figured out how to get around that yet. | |
## Oh well, in the meantime, I'm just dropping this in with the rest of my | |
## step definitions. | |
module FactoryGirl | |
class StepDefinitions | |
cattr_accessor :create_instance_variables | |
end | |
StepDefinitions.create_instance_variables = true | |
end | |
module FactoryGirlStepHelpers | |
def convert_human_hash_to_attribute_hash(human_hash, associations = []) | |
HumanHashToAttributeHash.new(human_hash, associations).attributes | |
end | |
def dehumanize_factory_name(human_name) | |
human_name.to_s.downcase.gsub(/ +/,'_') | |
end | |
def update_instance_variable(instance_variable_name, value) | |
if FactoryGirl::StepDefinitions.create_instance_variables | |
begin | |
instance_variable_set("@#{instance_variable_name}", value) | |
rescue NameError => e | |
warn "Could not create an instance variable named \"#{instance_variable_name}\" because \"#{e.message}\". If you need access to this instance variable you will need to create your own step definition and set it manually." | |
end | |
end | |
end | |
class HumanHashToAttributeHash | |
attr_reader :associations | |
def initialize(human_hash, associations) | |
@human_hash = human_hash | |
@associations = associations | |
end | |
def attributes(strategy = CreateAttributes) | |
@human_hash.inject({}) do |attribute_hash, (human_key, value)| | |
attributes = strategy.new(self, *process_key_value(human_key, value)) | |
attribute_hash.merge({ attributes.key => attributes.value }) | |
end | |
end | |
private | |
def process_key_value(key, value) | |
value = value.strip if value.is_a?(String) | |
[key.downcase.gsub(' ', '_').to_sym, value] | |
end | |
class AssociationManager | |
def initialize(human_hash_to_attributes_hash, key, value) | |
@human_hash_to_attributes_hash = human_hash_to_attributes_hash | |
@key = key | |
@value = value | |
end | |
def association | |
@human_hash_to_attributes_hash.associations.detect {|association| association.name == @key } | |
end | |
def association_instance | |
return unless association | |
if attributes_hash = nested_attribute_hash | |
factory.build_class.first(conditions: attributes_hash.attributes(FindAttributes)) or | |
FactoryGirl.create(association.factory, attributes_hash.attributes) | |
end | |
end | |
private | |
def factory | |
FactoryGirl.factory_by_name(association.factory) | |
end | |
def nested_attribute_hash | |
attribute, value = @value.split(':', 2) | |
return if value.blank? | |
HumanHashToAttributeHash.new({ attribute => value }, factory.associations) | |
end | |
end | |
class AttributeStrategy | |
attr_reader :key, :value, :association_manager | |
def initialize(human_hash_to_attributes_hash, key, value) | |
@association_manager = AssociationManager.new(human_hash_to_attributes_hash, key, value) | |
@key = key | |
@value = value | |
end | |
end | |
class FindAttributes < AttributeStrategy | |
def initialize(human_hash_to_attributes_hash, key, value) | |
super | |
if association_manager.association | |
@key = "#{@key}_id" | |
@value = association_manager.association_instance.try(:id) | |
end | |
end | |
end | |
class CreateAttributes < AttributeStrategy | |
def initialize(human_hash_to_attributes_hash, key, value) | |
super | |
if association_manager.association | |
@value = association_manager.association_instance | |
end | |
end | |
end | |
end | |
end | |
World(FactoryGirlStepHelpers) | |
FactoryGirl.factories.each do |factory| | |
factory.compile | |
factory.human_names.each do |human_name| | |
attribute_names_for_model = if factory.build_class.respond_to?(:attribute_names) | |
factory.build_class.attribute_names | |
elsif factory.build_class.respond_to?(:columns) | |
factory.build_class.columns.map do |column| | |
column.respond_to?(:name) ? column.name : column.to_s | |
end | |
else | |
[] | |
end | |
Given /^the following (#{human_name}|#{human_name.pluralize}) exists?:?$/i do |instance_name, table| | |
factories = [] | |
table.hashes.each do |human_hash| | |
attributes = convert_human_hash_to_attribute_hash(human_hash, factory.associations) | |
factories << FactoryGirl.create(factory.name, attributes) | |
end | |
update_instance_variable(dehumanize_factory_name(instance_name), factories) | |
end | |
Given /^an? #{human_name} exists$/i do | |
update_instance_variable(dehumanize_factory_name(human_name), FactoryGirl.create(factory.name)) | |
end | |
Given /^(\d+) #{human_name.pluralize} exist$/i do |count| | |
update_instance_variable(dehumanize_factory_name(human_name.pluralize), FactoryGirl.create_list(factory.name, count.to_i)) | |
end | |
attribute_names_for_model.each do |attribute_name| | |
human_column_name = attribute_name.downcase.gsub('_', ' ') | |
Given /^an? #{human_name} exists with an? #{human_column_name} of "([^"]*)"$/i do |value| | |
update_instance_variable(dehumanize_factory_name(human_name), FactoryGirl.create(factory.name, attribute_name => value)) | |
end | |
Given /^(\d+) #{human_name.pluralize} exist with an? #{human_column_name} of "([^"]*)"$/i do |count, value| | |
update_instance_variable(dehumanize_factory_name(human_name.pluralize), FactoryGirl.create_list(factory.name, count.to_i, attribute_name => value)) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment