Refactor :table selector filters
This commit is contained in:
parent
5bc3f445ae
commit
5e133126c3
|
@ -459,100 +459,92 @@ Capybara.add_selector(:table, locator_type: [String, Symbol]) do
|
|||
expression_filter(:with_cols, valid_values: [Array]) do |xpath, cols|
|
||||
col_conditions = cols.map do |col|
|
||||
if col.is_a? Hash
|
||||
col.reduce(nil) do |xp, (header, cell)|
|
||||
header_xp = XPath.descendant(:th)[XPath.string.n.is(header)]
|
||||
cell_xp = XPath.descendant(:tr)[header_xp].descendant(:td)
|
||||
next cell_xp[XPath.string.n.is(cell)] unless xp
|
||||
|
||||
table_ancestor = XPath.ancestor(:table)[1]
|
||||
xp = XPath::Expression.new(:join, table_ancestor, xp)
|
||||
cell_xp[XPath.string.n.is(cell) & XPath.position.equals(xp.preceding_sibling(:td).count.plus(1))]
|
||||
col.reduce(nil) do |xp, (header, cell_str)|
|
||||
header = XPath.descendant(:th)[XPath.string.n.is(header)]
|
||||
td = XPath.descendant(:tr)[header].descendant(:td)
|
||||
cell_condition = XPath.string.n.is(cell_str)
|
||||
cell_condition &= prev_col_position?(XPath.ancestor(:table)[1].join(xp)) if xp
|
||||
td[cell_condition]
|
||||
end
|
||||
else
|
||||
cells_xp = col.reduce(nil) do |xp, cell|
|
||||
cell_conditions = [XPath.string.n.is(cell)]
|
||||
if xp
|
||||
prev_row_xp = XPath::Expression.new(:join, XPath.ancestor(:tr)[1].preceding_sibling(:tr), xp)
|
||||
cell_conditions << XPath.position.equals(prev_row_xp.preceding_sibling(:td).count.plus(1))
|
||||
cells_xp = col.reduce(nil) do |prev_cell, cell_str|
|
||||
cell_condition = XPath.string.n.is(cell_str)
|
||||
|
||||
if prev_cell
|
||||
prev_cell = XPath.ancestor(:tr)[1].preceding_sibling(:tr).join(prev_cell)
|
||||
cell_condition &= prev_col_position?(prev_cell)
|
||||
end
|
||||
XPath.descendant(:td)[cell_conditions.reduce :&]
|
||||
|
||||
XPath.descendant(:td)[cell_condition]
|
||||
end
|
||||
XPath::Expression.new(:join, XPath.descendant(:tr), cells_xp)
|
||||
XPath.descendant(:tr).join(cells_xp)
|
||||
end
|
||||
end.reduce(:&)
|
||||
xpath[col_conditions]
|
||||
end
|
||||
|
||||
expression_filter(:cols, valid_values: [Array]) do |xpath, cols|
|
||||
raise ArgumentError, ":cols must be an Array of Arrays" unless cols.all? { |col| col.is_a? Array }
|
||||
raise ArgumentError, ':cols must be an Array of Arrays' unless cols.all? { |col| col.is_a? Array }
|
||||
|
||||
rows = cols.transpose
|
||||
xpath = xpath[XPath.descendant(:tbody).descendant(:tr).count.equals(rows.size) | (XPath.descendant(:tr).count.equals(rows.size) & ~XPath.descendant(:tbody))]
|
||||
|
||||
col_conditions = rows.map do |row|
|
||||
row_conditions = row.map do |cell|
|
||||
XPath.self(:td)[XPath.string.n.is(cell)]
|
||||
end
|
||||
row_conditions = row_conditions.reverse.reduce do |cond, cell|
|
||||
cell[XPath.following_sibling[cond]]
|
||||
end
|
||||
row_xpath = XPath.descendant(:tr)[XPath.descendant(:td)[row_conditions]]
|
||||
row_xpath[XPath.descendant(:td).count.equals(row.size)]
|
||||
end.reduce(:&)
|
||||
|
||||
xpath[col_conditions]
|
||||
col_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)
|
||||
xpath[match_row_count(rows.size)][col_conditions]
|
||||
end
|
||||
|
||||
expression_filter(:with_rows, valid_values: [Array]) do |xpath, rows|
|
||||
rows_conditions = rows.map do |row|
|
||||
if row.is_a? Hash
|
||||
row_conditions = row.map do |header, cell|
|
||||
header_xp = XPath.ancestor(:table)[1].descendant(:tr)[1].descendant(:th)[XPath.string.n.is(header)]
|
||||
XPath.descendant(:td)[
|
||||
XPath.string.n.is(cell) & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
||||
]
|
||||
end.reduce(:&)
|
||||
XPath.descendant(:tr)[row_conditions]
|
||||
else
|
||||
row_conditions = row.map do |cell|
|
||||
XPath.self(:td)[XPath.string.n.is(cell)]
|
||||
end
|
||||
row_conditions = row_conditions.reverse.reduce do |cond, cell|
|
||||
cell[XPath.following_sibling[cond]]
|
||||
end
|
||||
XPath.descendant(:tr)[XPath.descendant(:td)[row_conditions]]
|
||||
end
|
||||
end.reduce(:&)
|
||||
rows_conditions = rows.map { |row| match_row(row) }.reduce(:&)
|
||||
xpath[rows_conditions]
|
||||
end
|
||||
|
||||
expression_filter(:rows, valid_values: [Array]) do |xpath, rows|
|
||||
xpath = xpath[XPath.descendant(:tbody).descendant(:tr).count.equals(rows.size) | (XPath.descendant(:tr).count.equals(rows.size) & ~XPath.descendant(:tbody))]
|
||||
rows_conditions = rows.map do |row|
|
||||
row_xpath = if row.is_a? Hash
|
||||
row_conditions = row.map do |header, cell|
|
||||
rows_conditions = rows.map { |row| match_row(row, match_size: true) }.reduce(:&)
|
||||
xpath[match_row_count(rows.size)][rows_conditions]
|
||||
end
|
||||
|
||||
describe_expression_filters do |caption: nil, **|
|
||||
" with caption \"#{caption}\"" if caption
|
||||
end
|
||||
|
||||
def prev_col_position?(cell)
|
||||
XPath.position.equals(cell_position(cell))
|
||||
end
|
||||
|
||||
def cell_position(cell)
|
||||
cell.preceding_sibling(:td).count.plus(1)
|
||||
end
|
||||
|
||||
def match_row(row, match_size: false)
|
||||
xp = XPath.descendant(:tr)[
|
||||
if row.is_a? Hash
|
||||
row_match_cells_to_headers(row)
|
||||
else
|
||||
XPath.descendant(:td)[row_match_ordered_cells(row)]
|
||||
end
|
||||
]
|
||||
xp = xp[XPath.descendant(:td).count.equals(row.size)] if match_size
|
||||
xp
|
||||
end
|
||||
|
||||
def match_row_count(size)
|
||||
XPath.descendant(:tbody).descendant(:tr).count.equals(size) | (XPath.descendant(:tr).count.equals(size) & ~XPath.descendant(:tbody))
|
||||
end
|
||||
|
||||
def row_match_cells_to_headers(row)
|
||||
row.map do |header, cell|
|
||||
header_xp = XPath.ancestor(:table)[1].descendant(:tr)[1].descendant(:th)[XPath.string.n.is(header)]
|
||||
XPath.descendant(:td)[
|
||||
XPath.string.n.is(cell) & XPath.position.equals(header_xp.preceding_sibling.count.plus(1))
|
||||
]
|
||||
end.reduce(:&)
|
||||
XPath.descendant(:tr)[row_conditions]
|
||||
else
|
||||
end
|
||||
|
||||
def row_match_ordered_cells(row)
|
||||
row_conditions = row.map do |cell|
|
||||
XPath.self(:td)[XPath.string.n.is(cell)]
|
||||
end
|
||||
row_conditions = row_conditions.reverse.reduce do |cond, cell|
|
||||
row_conditions.reverse.reduce do |cond, cell|
|
||||
cell[XPath.following_sibling[cond]]
|
||||
end
|
||||
XPath.descendant(:tr)[XPath.descendant(:td)[row_conditions]]
|
||||
end
|
||||
row_xpath[XPath.descendant(:td).count.equals(row.size)]
|
||||
end.reduce(:&)
|
||||
xpath[rows_conditions]
|
||||
end
|
||||
|
||||
describe_expression_filters do |caption: nil, **|
|
||||
" with caption \"#{caption}\"" if caption
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -7,3 +7,11 @@ module XPath
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
module XPath
|
||||
module DSL
|
||||
def join(*expressions)
|
||||
XPath::Expression.new(:join, *[self, expressions].flatten)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -49,8 +49,8 @@ Capybara::SpecHelper.spec '#has_table?' do
|
|||
%w[Thomas Walpole Oceanside],
|
||||
%w[Danilo Wilkinson Johnsonville],
|
||||
%w[Vern Konopelski Everette],
|
||||
["Ratke", "Lawrence", "East Sorayashire"],
|
||||
["Palmer", "Sawayn", "West Trinidad"]
|
||||
['Ratke', 'Lawrence', 'East Sorayashire'],
|
||||
['Palmer', 'Sawayn', 'West Trinidad']
|
||||
])
|
||||
end
|
||||
|
||||
|
@ -84,8 +84,8 @@ Capybara::SpecHelper.spec '#has_table?' do
|
|||
%w[Thomas Walpole Oceanside],
|
||||
%w[Danilo Wilkinson Johnsonville],
|
||||
%w[Vern Konopelski Everette],
|
||||
["Ratke", "Lawrence", "East Sorayashire"],
|
||||
["Palmer", "Sawayn", "West Trinidad"]
|
||||
['Ratke', 'Lawrence', 'East Sorayashire'],
|
||||
['Palmer', 'Sawayn', 'West Trinidad']
|
||||
])
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue