1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
|
# 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, *)
visitor.data_table(self, *)
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
|