Module: SnapDiff::BrowserHelpers
- Defined in:
- lib/snap_diff/browser_helpers.rb
Constant Summary collapse
- IMAGE_WAIT_SCRIPT =
<<~JS function pending_image() { const images = document.images for (var i = 0; i < images.length; i++) { if (!images[i].complete && images[i].loading !== "lazy") { return images[i].src } } return false }(window) JS
- HIDE_CARET_SCRIPT =
<<~JS if (!document.getElementById('csdHideCaretStyle')) { let style = document.createElement('style'); style.setAttribute('id', 'csdHideCaretStyle'); document.head.appendChild(style); let styleSheet = style.sheet; styleSheet.insertRule("* { caret-color: transparent !important; }", 0); } JS
- DISABLE_ANIMATIONS_SCRIPT =
<<~JS if (!document.getElementById('csdDisableAnimationsStyle')) { let style = document.createElement('style'); style.setAttribute('id', 'csdDisableAnimationsStyle'); style.textContent = '*, *::before, *::after { animation-duration: 0s !important; animation-delay: 0s !important; transition-duration: 0s !important; transition-delay: 0s !important; }'; document.head.appendChild(style); } JS
- FIND_ACTIVE_ELEMENT_SCRIPT =
<<~JS function activeElement(){ const ae = document.activeElement; if (ae.nodeName === "INPUT" || ae.nodeName === "TEXTAREA") { ae.blur(); return ae; } return null; }(window); JS
- GET_BOUNDING_CLIENT_RECT_SCRIPT =
<<~JS [ this.getBoundingClientRect().left, this.getBoundingClientRect().top, this.getBoundingClientRect().right, this.getBoundingClientRect().bottom ] JS
Class Method Summary collapse
-
.all_visible_regions_for(selector) ⇒ Object
minimum: 0is load-bearing (issue #272). - .blur_from_focused_element ⇒ Object
-
.bounds_for_css(*css_selectors) ⇒ Object
The one seam that knows, per selector, whether it found anything --
all_visible_regions_foris called once per selector and the caller gets back one flattened list. - .current_capybara_driver_class ⇒ Object
- .disable_animations ⇒ Object
- .hide_caret ⇒ Object
- .pending_image_to_load ⇒ Object
- .region_for(element) ⇒ Object
- .resize_to(window_size) ⇒ Object
- .resize_window_if_needed ⇒ Object
- .selenium? ⇒ Boolean
- .session ⇒ Object
- .window_size_is_wrong?(expected_window_size = nil) ⇒ Boolean
Class Method Details
.all_visible_regions_for(selector) ⇒ Object
minimum: 0 is load-bearing (issue #272). Capybara's all defaults to
minimum: 1 and blocks in synchronize until the count is satisfied,
so every skip_area/crop selector matching nothing burned a full
Capybara.default_max_wait_time -- 5s by default, per selector, per
screenshot. One project measured %w[picture img] on an image-less
page at 10s per screenshot, 44% of their suite.
Waiting is the wrong semantic here regardless of the cost: these selectors describe a MASK over whatever is currently on the page. A selector that matches nothing has nothing to mask, and that answer is available immediately.
120 121 122 |
# File 'lib/snap_diff/browser_helpers.rb', line 120 def self.all_visible_regions_for(selector) BrowserHelpers.session.all(selector, visible: true, minimum: 0).map { |el| region_for(el) } end |
.blur_from_focused_element ⇒ Object
96 97 98 |
# File 'lib/snap_diff/browser_helpers.rb', line 96 def self.blur_from_focused_element session.evaluate_script(FIND_ACTIVE_ELEMENT_SCRIPT) end |
.bounds_for_css(*css_selectors) ⇒ Object
The one seam that knows, per selector, whether it found anything --
all_visible_regions_for is called once per selector and the caller
gets back one flattened list. The run-level tally is fed here (#277b)
rather than in AreaCalculator for exactly that reason: by the time
the regions are concatenated the attribution is gone.
38 39 40 41 42 43 44 |
# File 'lib/snap_diff/browser_helpers.rb', line 38 def self.bounds_for_css(*css_selectors) css_selectors.reduce([]) do |regions, selector| found = all_visible_regions_for(selector) SnapDiff::Reporting.record_selector_use(selector, matched: !found.empty?) regions.concat(found) end end |
.current_capybara_driver_class ⇒ Object
136 137 138 |
# File 'lib/snap_diff/browser_helpers.rb', line 136 def self. session.driver.class end |
.disable_animations ⇒ Object
81 82 83 |
# File 'lib/snap_diff/browser_helpers.rb', line 81 def self.disable_animations session.execute_script(DISABLE_ANIMATIONS_SCRIPT) end |
.hide_caret ⇒ Object
68 69 70 |
# File 'lib/snap_diff/browser_helpers.rb', line 68 def self.hide_caret session.execute_script(HIDE_CARET_SCRIPT) end |
.pending_image_to_load ⇒ Object
132 133 134 |
# File 'lib/snap_diff/browser_helpers.rb', line 132 def self.pending_image_to_load BrowserHelpers.session.evaluate_script(IMAGE_WAIT_SCRIPT) end |
.region_for(element) ⇒ Object
124 125 126 |
# File 'lib/snap_diff/browser_helpers.rb', line 124 def self.region_for(element) element.evaluate_script(GET_BOUNDING_CLIENT_RECT_SCRIPT).map { |point| point.negative? ? 0 : point.ceil.to_i } end |
.resize_to(window_size) ⇒ Object
16 17 18 19 20 21 22 |
# File 'lib/snap_diff/browser_helpers.rb', line 16 def self.resize_to(window_size) if session.driver.respond_to?(:resize) session.driver.resize(*window_size) elsif BrowserHelpers.selenium? session.driver.browser.manage.window.resize_to(*window_size) end end |
.resize_window_if_needed ⇒ Object
8 9 10 11 12 13 14 |
# File 'lib/snap_diff/browser_helpers.rb', line 8 def self.resize_window_if_needed # The respond_to? guard this replaced existed because the legacy # mattr_accessor might not be installed yet; Config always has the # attribute, so only the value matters now. window_size = SnapDiff.config.window_size resize_to(window_size) if window_size end |
.selenium? ⇒ Boolean
24 25 26 |
# File 'lib/snap_diff/browser_helpers.rb', line 24 def self.selenium? <= Capybara::Selenium::Driver end |
.session ⇒ Object
128 129 130 |
# File 'lib/snap_diff/browser_helpers.rb', line 128 def self.session Capybara.current_session end |
.window_size_is_wrong?(expected_window_size = nil) ⇒ Boolean
28 29 30 31 |
# File 'lib/snap_diff/browser_helpers.rb', line 28 def self.window_size_is_wrong?(expected_window_size = nil) selenium? && expected_window_size && session.driver.browser.manage.window.size != ::Selenium::WebDriver::Dimension.new(*expected_window_size) end |