Ignore hints gathering if one of the elements is stale

This commit is contained in:
Thomas Walpole 2019-04-16 14:03:12 -07:00
parent cd71d0230b
commit 21b0e4fbc4
1 changed files with 47 additions and 37 deletions

View File

@ -18,44 +18,21 @@ module Capybara
hints = []
if (els.size > 2) && !ENV['DISABLE_CAPYBARA_SELENIUM_OPTIMIZATIONS']
els = filter_by_text(els, texts) unless texts.empty?
begin
els = filter_by_text(els, texts) unless texts.empty?
hints_js, functions = build_hints_js(uses_visibility, styles)
hints_js = +''
functions = []
if uses_visibility && !is_displayed_atom.empty?
hints_js << <<~VISIBILITY_JS
var vis_func = #{is_displayed_atom};
VISIBILITY_JS
functions << 'vis_func'
end
if styles.is_a? Hash
hints_js << <<~STYLE_JS
var style_func = function(el){
var el_styles = window.getComputedStyle(el);
return #{styles.keys.map(&:to_s)}.reduce(function(res, style){
res[style] = el_styles[style];
return res;
}, {});
};
STYLE_JS
functions << 'style_func'
end
unless functions.empty?
hints_js << <<~EACH_JS
return arguments[0].map(function(el){
return [#{functions.join(',')}].map(function(fn){ return fn.call(null, el) });
});
EACH_JS
hints = es_context.execute_script hints_js, els
hints.map! do |results|
result = {}
result[:style] = results.pop if styles.is_a? Hash
result[:visible] = results.pop if uses_visibility
result
unless functions.empty?
hints = es_context.execute_script(hints_js, els).map! do |results|
hint = {}
hint[:style] = results.pop if functions.include?(:style_func)
hint[:visible] = results.pop if functions.include?(:vis_func)
hint
end
end
rescue ::Selenium::WebDriver::Error::StaleElementReferenceError
# warn 'Unexpected Stale Element Error - skipping optimization'
hints = []
end
end
els.map.with_index { |el, idx| build_node(el, hints[idx] || {}) }
@ -63,7 +40,7 @@ module Capybara
def filter_by_text(elements, texts)
es_context.execute_script <<~JS, elements, texts
var texts = arguments[1]
var texts = arguments[1];
return arguments[0].filter(function(el){
var content = el.textContent.toLowerCase();
return texts.every(function(txt){ return content.indexOf(txt.toLowerCase()) != -1 });
@ -71,6 +48,39 @@ module Capybara
JS
end
def build_hints_js(uses_visibility, styles)
functions = []
hints_js = +''
if uses_visibility && !is_displayed_atom.empty?
hints_js << <<~VISIBILITY_JS
var vis_func = #{is_displayed_atom};
VISIBILITY_JS
functions << :vis_func
end
if styles.is_a? Hash
hints_js << <<~STYLE_JS
var style_func = function(el){
var el_styles = window.getComputedStyle(el);
return #{styles.keys.map(&:to_s)}.reduce(function(res, style){
res[style] = el_styles[style];
return res;
}, {});
};
STYLE_JS
functions << :style_func
end
hints_js << <<~EACH_JS
return arguments[0].map(function(el){
return [#{functions.join(',')}].map(function(fn){ return fn.call(null, el) });
});
EACH_JS
[hints_js, functions]
end
def es_context
respond_to?(:execute_script) ? self : driver
end