module Gherkin module Pickles class Compiler def initialize(id_generator) @id_generator = id_generator end def compile(gherkin_document, source) pickles = [] return pickles unless gherkin_document.feature feature = gherkin_document.feature language = feature.language tags = feature.tags compile_feature(pickles, language, tags, feature, source) pickles end private def compile_feature(pickles, language, tags, feature, source) feature_background_steps = [] feature.children.each do |child| if child.background feature_background_steps.concat(child.background.steps) elsif child.rule compile_rule(pickles, language, tags, feature_background_steps, child.rule, source) else scenario = child.scenario if scenario.examples.empty? compile_scenario(tags, feature_background_steps, scenario, language, pickles, source) else compile_scenario_outline(tags, feature_background_steps, scenario, language, pickles, source) end end end end def compile_rule(pickles, language, tags, feature_background_steps, rule, source) rule_background_steps = feature_background_steps.dup rule.children.each do |child| if child.background rule_background_steps.concat(child.background.steps) else scenario = child.scenario if scenario.examples.empty? compile_scenario(tags, rule_background_steps, scenario, language, pickles, source) else compile_scenario_outline(tags, rule_background_steps, scenario, language, pickles, source) end end end end def compile_scenario(feature_tags, background_steps, scenario, language, pickles, source) steps = scenario.steps.empty? ? [] : [].concat(pickle_steps(background_steps)) tags = [].concat(feature_tags).concat(scenario.tags) scenario.steps.each do |step| steps.push(pickle_step(step)) end pickle = Cucumber::Messages::Pickle.new( uri: source.uri, id: @id_generator.new_id, tags: pickle_tags(tags), name: scenario.name, language: language, ast_node_ids: [scenario.id], steps: steps ) pickles.push(pickle) end def compile_scenario_outline(feature_tags, background_steps, scenario, language, pickles, source) scenario.examples.reject { |examples| examples.table_header.nil? }.each do |examples| variable_cells = examples.table_header.cells examples.table_body.each do |values_row| value_cells = values_row.cells steps = scenario.steps.empty? ? [] : [].concat(pickle_steps(background_steps)) tags = [].concat(feature_tags).concat(scenario.tags).concat(examples.tags) scenario.steps.each do |scenario_outline_step| step_props = pickle_step_props(scenario_outline_step, variable_cells, values_row) steps.push(Cucumber::Messages::Pickle::PickleStep.new(step_props)) end pickle = Cucumber::Messages::Pickle.new( uri: source.uri, id: @id_generator.new_id, name: interpolate(scenario.name, variable_cells, value_cells), language: language, steps: steps, tags: pickle_tags(tags), ast_node_ids: [ scenario.id, values_row.id ], ) pickles.push(pickle) end end end def interpolate(name, variable_cells, value_cells) variable_cells.each_with_index do |variable_cell, n| value_cell = value_cells[n] name = name.gsub('<' + variable_cell.value + '>', value_cell.value) end name end def pickle_steps(steps) steps.map do |step| pickle_step(step) end end def pickle_step(step) Cucumber::Messages::Pickle::PickleStep.new(pickle_step_props(step, [], nil)) end def pickle_step_props(step, variable_cells, values_row) value_cells = values_row ? values_row.cells : [] props = { id: @id_generator.new_id, ast_node_ids: [step.id], text: interpolate(step.text, variable_cells, value_cells), } if values_row props[:ast_node_ids].push(values_row.id) end if step.data_table data_table = Cucumber::Messages::PickleStepArgument.new( data_table: pickle_data_table(step.data_table, variable_cells, value_cells) ) props[:argument] = data_table end if step.doc_string doc_string = Cucumber::Messages::PickleStepArgument.new( doc_string: pickle_doc_string(step.doc_string, variable_cells, value_cells) ) props[:argument] = doc_string end props end def pickle_data_table(data_table, variable_cells, value_cells) Cucumber::Messages::PickleStepArgument::PickleTable.new( rows: data_table.rows.map do |row| Cucumber::Messages::PickleStepArgument::PickleTable::PickleTableRow.new( cells: row.cells.map do |cell| Cucumber::Messages::PickleStepArgument::PickleTable::PickleTableRow::PickleTableCell.new( value: interpolate(cell.value, variable_cells, value_cells) ) end ) end ) end def pickle_doc_string(doc_string, variable_cells, value_cells) props = { content: interpolate(doc_string.content, variable_cells, value_cells) } if doc_string.media_type props[:media_type] = interpolate(doc_string.media_type, variable_cells, value_cells) end Cucumber::Messages::PickleStepArgument::PickleDocString.new(props) end def pickle_tags(tags) tags.map {|tag| pickle_tag(tag)} end def pickle_tag(tag) Cucumber::Messages::Pickle::PickleTag.new( name: tag.name, ast_node_id: tag.id ) end end end end