lib/cucumber/core/test/data_table.rb
# frozen_string_literal: true module Cucumber module Core module Test # Step Definitions that match a plain text Step with a multiline argument table # will receive it as an instance of DataTable. A DataTable object holds the data of a # table parsed from a feature file and lets you access and manipulate the data # in different ways. # # For example: # # Given I have: # | a | b | # | c | d | # # And a matching StepDefinition: # # Given /I have:/ do |table| # data = table.raw # end # # This will store <tt>[['a', 'b'], ['c', 'd']]</tt> in the <tt>data</tt> variable. # class DataTable # Creates a new instance. +raw+ should be an Array of Array of String # or an Array of Hash # You don't typically create your own DataTable objects - Cucumber will do # it internally and pass them to your Step Definitions. # def initialize(rows) raw = ensure_array_of_array(rows) verify_rows_are_same_length(raw) @raw = raw.freeze end attr_reader :raw def describe_to(visitor, *args) visitor.data_table(self, *args) end def to_step_definition_arg dup end def data_table? true end def doc_string? false end # Creates a copy of this table # def dup self.class.new(raw.dup) end # Returns a new, transposed table. Example: # # | a | 7 | 4 | # | b | 9 | 2 | # # Gets converted into the following: # # | a | b | # | 7 | 9 | # | 4 | 2 | # def transpose self.class.new(raw.transpose) end def map(&block) new_raw = raw.map do |row| row.map(&block) end self.class.new(new_raw) end def lines_count raw.count end def ==(other) other.class == self.class && raw == other.raw end def inspect %{#<#{self.class} #{raw.inspect})>} end private def verify_rows_are_same_length(raw) raw.transpose rescue IndexError raise ArgumentError, 'Rows must all be the same length' end def ensure_array_of_array(array) array[0].is_a?(Hash) ? hashes_to_array(array) : array end def hashes_to_array(hashes) header = hashes[0].keys.sort [header] + hashes.map { |hash| header.map { |key| hash[key] } } end end end end end