Module: Capybara::JsFinders
- Extended by:
- XPath
- Defined in:
- lib/capybara-js_finders.rb,
lib/capybara-js_finders/version.rb
Constant Summary collapse
- LR =
Left range
"lr".freeze
- RR =
Right range
"rr".freeze
- TR =
Top range
"tr".freeze
- BR =
Bottom range
"br".freeze
- XpathTrue =
"(1=1)"- NEW_METHODS =
[:find_cell, :static_page].freeze
- SCRIPT =
TODO: This script is only prototype compatible. Let it discover jquery or prototype and use proper methods.
If element left offset is 5 and element width is 10 then it cannot occupy pixels from 5 to 15 because that would give us 11px width. Element must occupy pixels from 6 to 15 or from 5 to 14 (including).
I assume that the former answer is correct. Element starts on 6th pixel and that's why offset is equal to 5. TODO: Make sure there is test for that!
" xpathResult = document.evaluate( \"\#{descendant(:th, :td)}\", document, null, XPathResult.ANY_TYPE, null);\n var ary = [];\n var td;\n while( td = xpathResult.iterateNext() ){\n ary.push(td);\n }\n ary.each(function(ele){\n try{\n var dimensions = ele.getDimensions();\n var offset = ele.cumulativeOffset();\n\n ele.setAttribute('\#{LR}', offset.left + 1);\n ele.setAttribute('\#{RR}', offset.left + dimensions.width);\n ele.setAttribute('\#{TR}', offset.top + 1);\n ele.setAttribute('\#{BR}', offset.top + dimensions.height);\n } catch(err){\n /* ele.getDimensions() sometimes raises an exception, just skip ele in such case, there is nothing we can do about it! */\n }\n });\n"- VERSION =
"0.4.3"
Class Method Summary collapse
-
.cell_condition(columns, rows) ⇒ Object
Condition for td to be under one of column and on the same level as one of the rows and cannot be the same cell as one of the row-header or column-header.
- .not_equal_to(headers) ⇒ Object
- .overlaps_column(column) ⇒ Object
- .overlaps_columns(columns) ⇒ Object
-
.overlaps_horizontal(clr, crr) ⇒ Object
clr, crr - Column left and right range.
- .overlaps_row(row) ⇒ Object
- .overlaps_rows(rows) ⇒ Object
-
.overlaps_vertical(rtr, rbr) ⇒ Object
rtr, rbr - row top and bottom range.
Instance Method Summary collapse
-
#find_cell(options = {}) ⇒ Object
:column - text which should appear in the table column, or td/th Capybara::Node::Element object [or Array of them] representing the columns which narrow the search area of the table.
- #static_page(&block) ⇒ Object
Methods included from XPath
Class Method Details
.cell_condition(columns, rows) ⇒ Object
Condition for td to be under one of column and on the same level as one of the rows and cannot be the same cell as one of the row-header or column-header
89 90 91 92 |
# File 'lib/capybara-js_finders.rb', line 89 def self.cell_condition(columns, rows) xpath = "( #{overlaps_rows(rows)} ) and ( #{overlaps_columns(columns)} ) and (#{not_equal_to(columns + rows)})" return xpath end |
.not_equal_to(headers) ⇒ Object
81 82 83 84 85 |
# File 'lib/capybara-js_finders.rb', line 81 def self.not_equal_to(headers) headers.reject{|h| h == true}.map do |h| "( ./@#{TR} != #{h[TR]} or ./@#{BR} != #{h[BR]} or ./@#{LR} != #{h[LR]} or ./@#{RR} != #{h[RR]} )" end.join(" and ") end |
.overlaps_column(column) ⇒ Object
56 57 58 |
# File 'lib/capybara-js_finders.rb', line 56 def self.overlaps_column(column) overlaps_horizontal(column[LR], column[RR]) end |
.overlaps_columns(columns) ⇒ Object
49 50 51 52 53 54 |
# File 'lib/capybara-js_finders.rb', line 49 def self.overlaps_columns(columns) return XpathTrue if columns.first == true columns_xpath = columns.map{|column| overlaps_column(column) }.join(" or ") columns_xpath = "( #{columns_xpath} )" return columns_xpath end |
.overlaps_horizontal(clr, crr) ⇒ Object
clr, crr - Column left and right range
61 62 63 |
# File 'lib/capybara-js_finders.rb', line 61 def self.overlaps_horizontal(clr, crr) "(./@#{RR} >= #{clr} and ./@#{LR} <= #{crr})" end |
.overlaps_row(row) ⇒ Object
72 73 74 |
# File 'lib/capybara-js_finders.rb', line 72 def self.overlaps_row(row) overlaps_vertical(row[TR], row[BR]) end |
.overlaps_rows(rows) ⇒ Object
65 66 67 68 69 70 |
# File 'lib/capybara-js_finders.rb', line 65 def self.overlaps_rows(rows) return XpathTrue if rows.first == true rows_xpath = rows.map{|row| overlaps_row(row) }.join(" or ") rows_xpath = "( #{rows_xpath} )" return rows_xpath end |
.overlaps_vertical(rtr, rbr) ⇒ Object
rtr, rbr - row top and bottom range
77 78 79 |
# File 'lib/capybara-js_finders.rb', line 77 def self.overlaps_vertical(rtr, rbr) "(./@#{BR} >= #{rtr} and ./@#{TR} <= #{rbr})" end |
Instance Method Details
#find_cell(options = {}) ⇒ Object
:column - text which should appear in the table column, or td/th Capybara::Node::Element object [or Array of them] representing the columns which narrow the search area of the table. Nil is allowed.
:row - text which should appear in the row of the table, or td/th Capybara::Node::Element object [or Array of them] representing the columns which narrow the search area of the table. Nil is allowed. :text - text which should appear in the cell :multicolumn - set to true if finding column by test should return multiple results instead of just one :multirow - set to true if finding rows by test should return multiple results instead of just one
:visible :with
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/capybara-js_finders.rb', line 105 def find_cell( = {}) # TODO: Jak pierwszy arg to string to wywolaj cell zamiast tego columns = case [:column] when String method = [:multicolumn] ? :all : :find send(method, :xpath, XPath::HTML.cell([:column]) ) # TODO: jak all to musi byc conajmniej 1 when ::Node::Element [:column] when Array [:column].each{|x| raise ArgumentError unless x.is_a?(::Node::Element) } when NilClass true else raise ArgumentError end columns = Array.wrap(columns) rows = case [:row] when String method = [:multirow] ? :all : :find send(method, :xpath, XPath::HTML.cell([:row]) ) # TODO: jak all to musi byc conajmniej 1 when ::Node::Element [:row] when Array [:row].each{|x| raise ArgumentError unless x.is_a?(::Node::Element) } when NilClass true else raise ArgumentError end rows = Array.wrap(rows) if @static_page execute_script(SCRIPT) unless @executed @executed = true else execute_script(SCRIPT) end xpath = JsFinders.cell_condition(columns, rows) xpath = ".//td[ #{xpath} ]" # TODO: td or th ? # puts xpath find(:xpath, xpath, ) end |
#static_page(&block) ⇒ Object
150 151 152 153 154 155 156 |
# File 'lib/capybara-js_finders.rb', line 150 def static_page(&block) @static_page = true return block.call ensure @executed = false @static_page = false end |