require 'nokogiri' module Cucumber module Web module Tableish # This method returns an Array of Array of String, using CSS3 selectors. # This is particularly handy when using Cucumber's Table#diff! method. # # The +row_selector+ argument must be a String, and picks out all the rows # from the web page's DOM. If the number of cells in each row differs, it # will be constrained by (or padded with) the number of cells in the first row # # The +column_selectors+ argument must be a String or a Proc, picking out # cells from each row. If you pass a Proc, it will be yielded an instance # of Nokogiri::HTML::Element. # # == Example with a table # # # # # # # # # # # # # # #
tooldude
webratbryan
cucumberaslak
# # t = tableish('table#tools tr', 'td,th') # # == Example with a dl # #
#
webrat
#
bryan
#
cucumber
#
aslak
#
# # t = tableish('dl#tools dt', lambda{|dt| [dt, dt.next.next]}) # def tableish(row_selector, column_selectors) html = defined?(Capybara) ? body : response_body _tableish(html, row_selector, column_selectors) end def _tableish(html, row_selector, column_selectors) #:nodoc doc = Nokogiri::HTML(html) spans = nil max_cols = 0 # Parse the table. rows = doc.search(row_selector).map do |row| cells = case(column_selectors) when String row.search(column_selectors) when Proc column_selectors.call(row) end # TODO: max_cols should be sum of colspans max_cols = [max_cols, cells.length].max spans ||= Array.new(max_cols, 1) cell_index = 0 cells = (0...spans.length).inject([]) do |array, n| span = spans[n] cell = if span > 1 row_span, col_span = 1, 1 nil else cell = cells[cell_index] row_span, col_span = _parse_spans(cell) if col_span > 1 ((n + 1)...(n + col_span)).each do |m| spans[m] = row_span + 1 end end cell_index +=1 cell end spans[n] = row_span > 1 ? row_span : ([span - 1, 1].max) array << case cell when String then cell.strip when nil then '' else cell.text.strip end array end cells end end def _parse_spans(cell) cell.is_a?(Nokogiri::XML::Node) ? [cell.attributes['rowspan'].to_s.to_i || 1, cell.attributes['colspan'].to_s.to_i || 1] : [1, 1] end end end end World(Cucumber::Web::Tableish)