module CucumberFactory::Factory
Constants
- ATTRIBUTES_PATTERN
- CLEAR_NAMED_RECORDS_STEP_DESCRIPTOR
- CREATION_STEP_DESCRIPTOR
- CREATION_STEP_DESCRIPTOR_WITH_TEXT_ATTRIBUTES
- NAMED_CREATION_STEP_DESCRIPTOR
-
We cannot use vararg blocks in the descriptors in Ruby 1.8, as explained by Aslak: www.ruby-forum.com/topic/182927. We use different descriptors and cucumber priority to work around it.
- NAMED_CREATION_STEP_DESCRIPTOR_WITH_TEXT_ATTRIBUTES
- NAMED_RECORDS_VARIABLE
- NAMED_RECORD_PATTERN
- RECORD_PATTERN
- RECORD_UPDATE_PATTERN
- TEXT_ATTRIBUTES_PATTERN
- TEXT_UPDATE_ATTR_PATTERN
- UPDATE_ATTR_PATTERN
- UPDATE_STEP_DESCRIPTOR
- UPDATE_STEP_DESCRIPTOR_WITH_TEXT_ATTRIBUTES
- VALUE_ARRAY
- VALUE_DECIMAL
- VALUE_FILE
- VALUE_INTEGER
- VALUE_LAST_RECORD
- VALUE_SCALAR
- VALUE_STRING
Public Class Methods
Source
# File lib/cucumber_factory/factory.rb, line 75 def add_steps(main) add_step(main, CREATION_STEP_DESCRIPTOR) add_step(main, NAMED_CREATION_STEP_DESCRIPTOR) add_step(main, CREATION_STEP_DESCRIPTOR_WITH_TEXT_ATTRIBUTES) add_step(main, NAMED_CREATION_STEP_DESCRIPTOR_WITH_TEXT_ATTRIBUTES) add_step(main, CLEAR_NAMED_RECORDS_STEP_DESCRIPTOR) add_step(main, UPDATE_STEP_DESCRIPTOR) add_step(main, UPDATE_STEP_DESCRIPTOR_WITH_TEXT_ATTRIBUTES) end
Private Class Methods
Source
# File lib/cucumber_factory/factory.rb, line 87 def add_step(main, descriptor) main.instance_eval { kind = descriptor[:kind] object = send(kind, *[descriptor[:pattern]].compact, &descriptor[:block]) # cucumber_factory steps get a low priority due to their generic syntax object.overridable(:priority => descriptor[:priority] ? -1 : -2) if kind != :Before object } end
Source
# File lib/cucumber_factory/factory.rb, line 286 def attribute_name_from_prose(prose) prose.downcase.gsub(' ', '_').to_sym end
Source
# File lib/cucumber_factory/factory.rb, line 182 def attribute_value(world, model_class, transient_attributes, attribute, value) associated, association_class = resolve_association(attribute, model_class, transient_attributes) value = if matches_fully?(value, VALUE_ARRAY) array_values = unquote(value).scan(VALUE_SCALAR) array_values.map { |v| attribute_value(world, model_class, transient_attributes, attribute, v) } elsif associated resolve_associated_value(world, model_class, association_class, attribute, value) else resolve_scalar_value(world, model_class, attribute, value) end value end
Source
# File lib/cucumber_factory/factory.rb, line 259 def file_value_to_path(string) # file paths are marked with a special keyword and enclosed with quotes. # Example: file:"/path/image.png" # This will extract the path (/path/image.png) from the text fragment above unquote string.sub(/\Afile:/, '') end
Source
# File lib/cucumber_factory/factory.rb, line 266 def full_regexp(partial_regexp) Regexp.new('\\A(?:' + partial_regexp.source + ')\\z', partial_regexp.options) end
Source
# File lib/cucumber_factory/factory.rb, line 106 def get_named_record(world, name) named_records(world)[name].tap do |record| record.reload if record.respond_to?(:reload) and record.respond_to?(:new_record?) and not record.new_record? end end
Source
# File lib/cucumber_factory/factory.rb, line 270 def matches_fully?(string, partial_regexp) string =~ full_regexp(partial_regexp) end
Source
# File lib/cucumber_factory/factory.rb, line 101 def named_records(world) hash = world.instance_variable_get(NAMED_RECORDS_VARIABLE) hash || reset_named_records(world) end
Source
# File lib/cucumber_factory/factory.rb, line 140 def parse_attributes(world, model_class, raw_attributes, raw_boolean_attributes, raw_multiline_attributes = nil, transient_attributes = []) attributes = {} if raw_attributes.try(:strip).present? raw_attribute_fragment_regex = /(?:the |and |with |but |,| )+(.*?) (#{VALUE_SCALAR}|#{VALUE_ARRAY}|#{VALUE_LAST_RECORD})/ raw_attributes.scan(raw_attribute_fragment_regex).each do |fragment| attribute = attribute_name_from_prose(fragment[0]) value = fragment[1] attributes[attribute] = attribute_value(world, model_class, transient_attributes, attribute, value) end unused_raw_attributes = raw_attributes.gsub(raw_attribute_fragment_regex, '') if unused_raw_attributes.present? raise ArgumentError, "Unable to parse attributes #{unused_raw_attributes.inspect}." end end if raw_boolean_attributes.try(:strip).present? raw_boolean_attributes.scan(/(?:which|who|that|is| )*(not )?(.+?)(?: and | but |,|$)+/).each do |fragment| flag = !fragment[0] # if the word 'not' didn't match above, this expression is true attribute = attribute_name_from_prose(fragment[1]) attributes[attribute] = flag end end if raw_multiline_attributes.present? # DocString e.g. "first name: Jane\nlast name: Jenny\n" if raw_multiline_attributes.is_a?(String) raw_multiline_attributes.split("\n").each do |fragment| raw_attribute, value = fragment.split(': ', 2) attribute = attribute_name_from_prose(raw_attribute) value = "\"#{value}\"" unless matches_fully?(value, /#{VALUE_ARRAY}|#{VALUE_FILE}/) attributes[attribute] = attribute_value(world, model_class, transient_attributes, attribute, value) end # DataTable e.g. in raw [["first name", "Jane"], ["last name", "Jenny"]] else raw_multiline_attributes.raw.each do |raw_attribute, value| attribute = attribute_name_from_prose(raw_attribute) value = "\"#{value}\"" unless matches_fully?(value, /#{VALUE_ARRAY}|#{VALUE_FILE}/) attributes[attribute] = attribute_value(world, model_class, transient_attributes, attribute, value) end end end attributes end
Source
# File lib/cucumber_factory/factory.rb, line 122 def parse_creation(world, raw_model, raw_variant, raw_attributes, raw_boolean_attributes, raw_multiline_attributes = nil) build_strategy, transient_attributes = CucumberFactory::BuildStrategy.from_prose(raw_model, raw_variant) model_class = build_strategy.model_class attributes = parse_attributes(world, model_class, raw_attributes, raw_boolean_attributes, raw_multiline_attributes, transient_attributes) record = build_strategy.create_record(attributes) remember_record_names(world, record, attributes) record end
Source
# File lib/cucumber_factory/factory.rb, line 116 def parse_named_creation(world, double_quote_name, single_quote_name, raw_model, raw_variant, raw_attributes, raw_boolean_attributes, raw_multiline_attributes = nil) record = parse_creation(world, raw_model, raw_variant, raw_attributes, raw_boolean_attributes, raw_multiline_attributes) name = [double_quote_name, single_quote_name].compact.first set_named_record(world, name, record) end
Source
# File lib/cucumber_factory/factory.rb, line 131 def parse_update(world, raw_model, raw_name, raw_attributes, raw_boolean_attributes, raw_multiline_attributes = nil) model_class = CucumberFactory::BuildStrategy.parse_model_class(raw_model) attributes = parse_attributes(world, model_class, raw_attributes, raw_boolean_attributes, raw_multiline_attributes) record = resolve_associated_value(world, model_class, model_class, model_class, raw_name) CucumberFactory::UpdateStrategy.new(record).assign_attributes(attributes) remember_record_names(world, record, attributes) record end
Source
# File lib/cucumber_factory/factory.rb, line 290 def remember_record_names(world, record, attributes) rememberable_values = attributes.values.select { |v| v.is_a?(String) || v.is_a?(Integer) } for value in rememberable_values set_named_record(world, value.to_s, record) end end
Source
# File lib/cucumber_factory/factory.rb, line 97 def reset_named_records(world) world.instance_variable_set(NAMED_RECORDS_VARIABLE, {}) end
Source
# File lib/cucumber_factory/factory.rb, line 220 def resolve_associated_value(world, model_class, association_class, attribute, value) if matches_fully?(value, VALUE_LAST_RECORD) raise(Error, "Cannot set last #{model_class}##{attribute} for polymorphic associations") unless association_class.present? CucumberFactory::Switcher.find_last(association_class) || raise(Error, "There is no last #{attribute}") elsif matches_fully?(value, VALUE_STRING) value = unquote(value) get_named_record(world, value) || transform_value(world, value) elsif matches_fully?(value, VALUE_INTEGER) value = value.to_s get_named_record(world, value) || transform_value(world, value) else raise Error, "Cannot set association #{model_class}##{attribute} to #{value}." end end
Source
# File lib/cucumber_factory/factory.rb, line 196 def resolve_association(attribute, model_class, transient_attributes) return unless model_class.respond_to?(:reflect_on_association) association = model_class.reflect_on_association(attribute) association_class = nil if association association_class = association.klass unless association.polymorphic? associated = true elsif transient_attributes.include?(attribute.to_sym) klass_name = attribute.to_s.camelize if Object.const_defined?(klass_name) association_class = klass_name.constantize associated = true elsif (factory_class = CucumberFactory::BuildStrategy.class_from_factory(attribute.to_s)) association_class = factory_class associated = true end else associated = false end [associated, association_class] end
Source
# File lib/cucumber_factory/factory.rb, line 236 def resolve_scalar_value(world, model_class, attribute, value) if matches_fully?(value, VALUE_STRING) value = unquote(value) value = transform_value(world, value) elsif matches_fully?(value, VALUE_INTEGER) value = value.to_i elsif matches_fully?(value, VALUE_DECIMAL) value = BigDecimal(value) elsif matches_fully?(value, VALUE_FILE) path = File.path("./#{file_value_to_path(value)}") value = File.new(path) else raise Error, "Cannot set attribute #{model_class}##{attribute} to #{value}." end value end
Source
# File lib/cucumber_factory/factory.rb, line 112 def set_named_record(world, name, record) named_records(world)[name] = record end
Source
# File lib/cucumber_factory/factory.rb, line 274 def transform_value(world, value) # Transforms were a feature available in Cucumber 1 and 2. # They have been kind-of replaced by ParameterTypes, which don't work with generic steps # like CucumberFactory's. # https://app.cucumber.pro/projects/cucumber-ruby/documents/branch/master/features/docs/writing_support_code/parameter_types.feature if world.respond_to?(:Transform) world.Transform(value) else value end end
Source
# File lib/cucumber_factory/factory.rb, line 253 def unquote(string) # This method removes quotes or brackets from the start and end from a string # Examples: 'single' => single, "double" => double, [1, 2, 3] => 1, 2, 3 string[1, string.length - 2] end