eyes_selenium 3.14.3 → 3.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/lib/applitools/selenium/border_aware_element_content_location_provider.rb +2 -0
  3. data/lib/applitools/selenium/browser.rb +66 -56
  4. data/lib/applitools/selenium/context_based_scale_provider.rb +2 -0
  5. data/lib/applitools/selenium/css_transform/css_transform.rb +21 -0
  6. data/lib/applitools/selenium/css_translate_element_position_provider.rb +48 -0
  7. data/lib/applitools/selenium/css_translate_position_provider.rb +29 -10
  8. data/lib/applitools/selenium/dom_capture/dom_capture.rb +113 -0
  9. data/lib/applitools/selenium/dom_capture/dom_capture_script.rb +103 -0
  10. data/lib/applitools/selenium/driver.rb +9 -2
  11. data/lib/applitools/selenium/element.rb +2 -0
  12. data/lib/applitools/selenium/element_position_provider.rb +3 -1
  13. data/lib/applitools/selenium/entire_element_screenshot.rb +20 -0
  14. data/lib/applitools/selenium/eyes.rb +203 -396
  15. data/lib/applitools/selenium/eyes_screenshot.rb +60 -0
  16. data/lib/applitools/selenium/eyes_target_locator.rb +12 -24
  17. data/lib/applitools/selenium/fixed_cut_provider.rb +48 -0
  18. data/lib/applitools/selenium/frame.rb +11 -1
  19. data/lib/applitools/selenium/frame_chain.rb +9 -1
  20. data/lib/applitools/selenium/full_page_capture_algorithm.rb +85 -50
  21. data/lib/applitools/selenium/fullpage_screenshot.rb +37 -0
  22. data/lib/applitools/selenium/keyboard.rb +2 -0
  23. data/lib/applitools/selenium/mouse.rb +2 -0
  24. data/lib/applitools/selenium/move_to_region_visibility_strategy.rb +2 -0
  25. data/lib/applitools/selenium/nop_region_visibility_strategy.rb +2 -0
  26. data/lib/applitools/selenium/region_provider.rb +91 -0
  27. data/lib/applitools/selenium/sauce/driver.rb +2 -0
  28. data/lib/applitools/selenium/scroll_position_provider.rb +13 -2
  29. data/lib/applitools/selenium/takes_screenshot_image_provider.rb +5 -3
  30. data/lib/applitools/selenium/target.rb +32 -6
  31. data/lib/applitools/selenium/viewport_screenshot.rb +46 -0
  32. data/lib/applitools/selenium/viewport_size.rb +2 -0
  33. data/lib/applitools/version.rb +3 -1
  34. data/lib/eyes_selenium.rb +4 -9
  35. metadata +16 -27
  36. data/lib/applitools/capybara.rb +0 -8
  37. data/lib/applitools/poltergeist/applitools_compatible.rb +0 -32
  38. data/lib/applitools/poltergeist/driver.rb +0 -11
  39. data/lib/applitools/selenium/capybara/capybara_settings.rb +0 -23
  40. data/lib/applitools/selenium/capybara/driver.rb +0 -37
  41. data/lib/applitools/selenium/eyes_full_page_screenshot.rb +0 -47
  42. data/lib/applitools/selenium/eyes_web_driver_screenshot.rb +0 -341
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  require 'socket'
2
4
  require 'selenium-webdriver'
3
5
 
@@ -137,13 +139,19 @@ module Applitools::Selenium
137
139
 
138
140
  def find_element(*args)
139
141
  how, what = extract_args(args)
140
-
142
+ return find_element_by_name_or_id(what) if how == :name_or_id
141
143
  # Make sure that "how" is a valid locator.
142
144
  raise ArgumentError, "cannot find element by: #{how.inspect}" unless FINDERS[how.to_sym]
143
145
 
144
146
  Applitools::Selenium::Element.new(self, driver.find_element(how, what))
145
147
  end
146
148
 
149
+ def find_element_by_name_or_id(name_or_id)
150
+ found_by_name = find_elements name: name_or_id
151
+ return found_by_name.first unless found_by_name.empty?
152
+ find_element id: name_or_id
153
+ end
154
+
147
155
  # Finds elements in a window.
148
156
  # @param [Symbol] how Defines the way that +what+ parameter will be interpreted (finder). Can be one
149
157
  # of: +:class+, +:class_name+, +:css+, +:id+, +:link+, +:link_text+, +:name+, +:partial_link_text+, +:tag_name+,
@@ -278,7 +286,6 @@ module Applitools::Selenium
278
286
  when :frame
279
287
  logger.info 'Frame.'
280
288
  frame_location_size = Applitools::Selenium::BorderAwareElementContentLocationProvider.new target_frame
281
-
282
289
  return parent.frame_chain!.push(
283
290
  Applitools::Selenium::Frame.new(
284
291
  reference: target_frame, frame_id: '',
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module Applitools::Selenium
2
4
  class Element < SimpleDelegator
3
5
  JS_GET_COMPUTED_STYLE_FORMATTED_STR = <<-JS.freeze
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools::Selenium
2
4
  # @!visibility private
3
5
  class ElementPositionProvider
@@ -30,7 +32,7 @@ module Applitools::Selenium
30
32
  # Gets the enitire size of the element.
31
33
  #
32
34
  # @return [Applitools::RectangleSize] The size of the element.
33
- def entire_size
35
+ def entire_size(_image_width, _image_height)
34
36
  logger.info 'entire_size()'
35
37
  result = Applitools::RectangleSize.new(element.scroll_width, element.scroll_height)
36
38
  logger.info "Entire size: #{result}"
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'eyes_screenshot'
4
+
5
+ module Applitools::Selenium
6
+ # @!visibility private
7
+ class EntireElementScreenshot < Applitools::Selenium::EyesScreenshot
8
+ def sub_screenshot(*_args)
9
+ self
10
+ end
11
+
12
+ def screenshot_offset
13
+ region_provider.eye_region.location
14
+ end
15
+
16
+ def top_left_location
17
+ @top_left_location ||= screenshot_offset
18
+ end
19
+ end
20
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module Applitools::Selenium
2
4
  # The main API gateway for the SDK
3
5
  class Eyes < Applitools::EyesBase
@@ -13,6 +15,12 @@ module Applitools::Selenium
13
15
 
14
16
  DEFAULT_STITCHING_OVERLAP = 50 # Pixels
15
17
 
18
+ ENTIRE_ELEMENT_SCREENSHOT = 0
19
+
20
+ FULLPAGE_SCREENSHOT = 1
21
+
22
+ VIEWPORT_SCREENSHOT = 2
23
+
16
24
  extend Forwardable
17
25
  # @!visibility public
18
26
 
@@ -20,8 +28,6 @@ module Applitools::Selenium
20
28
  def eyes_driver(driver, eyes = nil)
21
29
  if driver.respond_to? :driver_for_eyes
22
30
  driver.driver_for_eyes eyes
23
- elsif defined?(::Capybara::Poltergeist) && (driver.is_a? ::Capybara::Poltergeist::Driver)
24
- Applitools::Poltergeist::Driver.new(eyes, driver: driver)
25
31
  else
26
32
  unless driver.is_a?(Applitools::Selenium::Driver)
27
33
  Applitools::EyesLogger.warn("Unrecognized driver type: (#{driver.class.name})!")
@@ -32,6 +38,20 @@ module Applitools::Selenium
32
38
  end
33
39
  end
34
40
 
41
+ def obtain_screenshot_type(is_element, inside_a_frame, stitch_content, force_fullpage)
42
+ if stitch_content || force_fullpage
43
+ unless inside_a_frame
44
+ return FULLPAGE_SCREENSHOT if force_fullpage && !stitch_content
45
+ return FULLPAGE_SCREENSHOT if stitch_content && !is_element
46
+ end
47
+ return ENTIRE_ELEMENT_SCREENSHOT if inside_a_frame
48
+ return ENTIRE_ELEMENT_SCREENSHOT if stitch_content
49
+ else
50
+ return VIEWPORT_SCREENSHOT unless stitch_content || force_fullpage
51
+ end
52
+ VIEWPORT_SCREENSHOT
53
+ end
54
+
35
55
  # Set the viewport size.
36
56
  #
37
57
  # @param [Applitools::Selenium::Driver] driver The driver instance.
@@ -76,8 +96,9 @@ module Applitools::Selenium
76
96
  # @return [Applitools::RectangleSize] explicit_entire_size
77
97
 
78
98
  attr_accessor :base_agent_id, :screenshot, :force_full_page_screenshot, :hide_scrollbars,
79
- :wait_before_screenshots, :debug_screenshot, :stitch_mode, :disable_horizontal_scrolling,
80
- :disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap
99
+ :wait_before_screenshots, :debug_screenshots, :stitch_mode, :disable_horizontal_scrolling,
100
+ :disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap,
101
+ :full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom
81
102
  attr_reader :driver
82
103
 
83
104
  def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
@@ -98,15 +119,18 @@ module Applitools::Selenium
98
119
  self.stitch_mode = Applitools::STITCH_MODE[:scroll]
99
120
  self.wait_before_screenshots = DEFAULT_WAIT_BEFORE_SCREENSHOTS
100
121
  self.region_visibility_strategy = MoveToRegionVisibilityStrategy.new
101
- self.debug_screenshot = false
122
+ self.debug_screenshots = false
102
123
  self.debug_screenshot_provider = Applitools::DebugScreenshotProvider.new
103
124
  .tag_access { tag_for_debug }
104
- .debug_flag_access { debug_screenshot }
125
+ .debug_flag_access { debug_screenshots }
105
126
  self.disable_horizontal_scrolling = false
106
127
  self.disable_vertical_scrolling = false
107
128
  self.explicit_entire_size = nil
108
129
  self.force_driver_resolution_as_viewport_size = false
109
130
  self.stitching_overlap = DEFAULT_STITCHING_OVERLAP
131
+ self.full_page_capture_algorithm_left_top_offset = Applitools::Location::TOP_LEFT
132
+ self.send_dom = false
133
+ self.prevent_dom_processing = false
110
134
  end
111
135
 
112
136
  # Starts a test
@@ -143,7 +167,7 @@ module Applitools::Selenium
143
167
  )
144
168
 
145
169
  self.eyes_screenshot_factory = lambda do |image|
146
- Applitools::Selenium::EyesWebDriverScreenshot.new(
170
+ Applitools::Selenium::ViewportScreenshot.new(
147
171
  image, driver: @driver, force_offset: position_provider.force_offset
148
172
  )
149
173
  end
@@ -161,12 +185,6 @@ module Applitools::Selenium
161
185
  send(method_name) if respond_to?(method_name, :include_private)
162
186
  end
163
187
 
164
- def perform_driver_settings_for_appium_driver
165
- self.region_visibility_strategy = NopRegionVisibilityStrategy.new
166
- self.force_driver_resolution_as_viewport_size = true
167
- end
168
-
169
- private :perform_driver_settings_for_appium_driver
170
188
  private :perform_driver_specific_settings
171
189
 
172
190
  # Sets the stitch mode.
@@ -231,84 +249,61 @@ module Applitools::Selenium
231
249
  logger.info "check(#{name}) is called"
232
250
  self.tag_for_debug = name
233
251
  Applitools::ArgumentGuard.is_a? target, 'target', Applitools::Selenium::Target
252
+ target_to_check = target.finalize
234
253
  original_overflow = nil
235
254
  original_position_provider = position_provider
236
255
  original_force_full_page_screenshot = force_full_page_screenshot
256
+
237
257
  eyes_element = nil
238
- timeout = target.options[:timeout] || USE_DEFAULT_MATCH_TIMEOUT
258
+ timeout = target_to_check.options[:timeout] || USE_DEFAULT_MATCH_TIMEOUT
259
+
239
260
  self.eyes_screenshot_factory = lambda do |image|
240
- Applitools::Selenium::EyesWebDriverScreenshot.new(
241
- image, driver: driver,
242
- force_offset: position_provider.force_offset,
243
- position_provider: self.class.position_provider(
244
- :SCROLL, driver, disable_horizontal_scrolling, disable_vertical_scrolling, explicit_entire_size
245
- )
261
+ Applitools::Selenium::ViewportScreenshot.new(
262
+ image,
263
+ region_provider: region_to_check
246
264
  )
247
265
  end
248
266
 
249
- # rubocop:disable BlockLength
250
- check_in_frame target_frames: target.frames do
267
+ self.prevent_dom_processing = !((!target.options[:send_dom].nil? && target.options[:send_dom]) || send_dom)
268
+
269
+ check_in_frame target_frames: target_to_check.frames do
251
270
  begin
252
271
  match_data = Applitools::MatchWindowData.new
253
272
  match_data.tag = name
254
273
  update_default_settings(match_data)
255
- match_data.read_target(target, driver)
256
- eyes_element = target.region_to_check.call(driver)
274
+ eyes_element = target_to_check.region_to_check.call(driver)
257
275
 
258
276
  unless force_full_page_screenshot
259
277
  region_visibility_strategy.move_to_region original_position_provider,
260
278
  Applitools::Location.new(eyes_element.location.x.to_i, eyes_element.location.y.to_i)
261
279
  end
262
280
 
263
- check_window = false
264
- if !target.frames.empty? && eyes_element.is_a?(Applitools::Region)
265
- # check_current_frame
266
- logger.info "check_region_in_frame(#{eyes_element})"
267
- region_provider = region_provider_for_frame
268
-
269
- elsif eyes_element.is_a? Applitools::Selenium::Element
270
- # check_element
271
- logger.info 'check_region(' \
272
- "#{Applitools::Region.from_location_size(eyes_element.location, eyes_element.size)})"
273
-
274
- use_coordinates =
275
- if position_provider.is_a?(Applitools::Selenium::CssTranslatePositionProvider) &&
276
- driver.frame_chain.empty?
277
- Applitools::EyesScreenshot::COORDINATE_TYPES[:context_as_is]
278
- else
279
- target.coordinate_type
280
- end
281
-
282
- region_provider = Applitools::RegionProvider.new(
283
- region_for_element(eyes_element), use_coordinates
284
- )
285
- else
286
- # check_window
287
- logger.info "check_window(match_timeout: #{timeout}, tag: #{match_data.tag})"
288
- region_provider = Applitools::RegionProvider.new(
289
- region_for_element(eyes_element),
290
- target.coordinate_type
291
- )
292
- check_window = true
293
- end
281
+ region_provider = Applitools::Selenium::RegionProvider.new(driver, region_for_element(eyes_element))
294
282
 
295
- if target.options[:stitch_content]
296
- check_window ? self.force_full_page_screenshot = true : self.check_frame_or_element = true
297
- if eyes_element.is_a? Applitools::Selenium::Element
298
- self.position_provider = Applitools::Selenium::ElementPositionProvider.new driver, eyes_element
283
+ self.region_to_check = region_provider
299
284
 
300
- original_overflow = eyes_element.overflow
301
- eyes_element.overflow = 'hidden'
302
- end
285
+ match_data.read_target(target_to_check, driver)
303
286
 
304
- region_provider = Applitools::RegionProvider.new(region_provider.region, target.coordinate_type)
287
+ is_element = eyes_element.is_a? Applitools::Selenium::Element
288
+ inside_a_frame = !driver.frame_chain.empty?
305
289
 
306
- self.region_to_check = region_provider
290
+ self.screenshot_type = self.class.obtain_screenshot_type(
291
+ is_element,
292
+ inside_a_frame,
293
+ target_to_check.options[:stitch_content],
294
+ force_full_page_screenshot
295
+ )
307
296
 
308
- region_provider = Applitools::RegionProvider.new(
309
- Applitools::Region::EMPTY,
310
- nil
311
- )
297
+ case screenshot_type
298
+ when ENTIRE_ELEMENT_SCREENSHOT
299
+ if eyes_element.is_a? Applitools::Selenium::Element
300
+ original_overflow = eyes_element.overflow
301
+ eyes_element.overflow = 'hidden'
302
+ self.position_provider = Applitools::Selenium::CssTranslateElementPositionProvider.new(
303
+ driver,
304
+ eyes_element
305
+ )
306
+ end
312
307
  end
313
308
 
314
309
  check_window_base(
@@ -320,10 +315,12 @@ module Applitools::Selenium
320
315
  self.force_full_page_screenshot = original_force_full_page_screenshot
321
316
  self.position_provider = original_position_provider
322
317
  self.region_to_check = nil
323
- region_visibility_strategy.return_to_original_position position_provider
318
+ self.full_page_capture_algorithm_left_top_offset = Applitools::Location::TOP_LEFT
319
+ region_visibility_strategy.return_to_original_position original_position_provider
324
320
  end
325
321
  # rubocop:enable BlockLength
326
322
  end
323
+ self.prevent_dom_processing = false
327
324
  end
328
325
 
329
326
  # Validates the contents of an iframe and matches it with the expected output.
@@ -339,12 +336,18 @@ module Applitools::Selenium
339
336
  return yield if block_given? && frames.empty?
340
337
 
341
338
  original_frame_chain = driver.frame_chain
339
+
342
340
  logger.info 'Switching to target frame according to frames path...'
343
341
  driver.switch_to.frames(frames_path: frames)
342
+ frame_chain_to_reset = driver.frame_chain
344
343
  logger.info 'Done!'
345
344
 
345
+ ensure_frame_visible
346
+
346
347
  yield if block_given?
347
348
 
349
+ reset_frames_scroll_position(frame_chain_to_reset)
350
+
348
351
  logger.info 'Switching back into top level frame...'
349
352
  driver.switch_to.default_content
350
353
  return unless original_frame_chain
@@ -368,41 +371,18 @@ module Applitools::Selenium
368
371
  border_bottom_width = element.border_bottom_width
369
372
 
370
373
  Applitools::Region.new(
371
- p.x + border_left_width,
372
- p.y + border_top_width,
374
+ p.x.round + border_left_width,
375
+ p.y.round + border_top_width,
373
376
  d.width - border_left_width - border_right_width,
374
377
  d.height - border_top_width - border_bottom_width
375
- )
376
- end
377
-
378
- # Returns the region of a given iframe.
379
- #
380
- # @return [Applitools::Region] The region of the iframe.
381
- def region_provider_for_frame
382
- Object.new.tap do |provider|
383
- current_frame_size = lambda do
384
- frame_region = Applitools::Region.from_location_size(
385
- Applitools::Location.new(0, 0), driver.frame_chain!.current_frame.size
386
- )
387
- begin
388
- frame_region.intersect Applitools::Region.from_location_size(
389
- Applitools::Location.new(0, 0),
390
- Applitools::Utils::EyesSeleniumUtils.entire_page_size(driver)
391
- )
392
- frame_region
393
- ensure
394
- frame_region
395
- end
396
- end
397
-
398
- provider.instance_eval do
399
- define_singleton_method :region do
400
- current_frame_size.call
401
- end
402
- define_singleton_method :coordinate_type do
403
- Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
404
- end
405
- end
378
+ ).tap do |r|
379
+ border_padding = Applitools::PaddingBounds.new(
380
+ border_left_width,
381
+ border_top_width,
382
+ border_right_width,
383
+ border_bottom_width
384
+ )
385
+ r.padding(border_padding)
406
386
  end
407
387
  end
408
388
 
@@ -512,15 +492,31 @@ module Applitools::Selenium
512
492
  end
513
493
  end
514
494
 
495
+ def dom_data
496
+ return {} if prevent_dom_processing
497
+ begin
498
+ Applitools::Selenium::DomCapture.get_window_dom(driver, logger)
499
+ rescue Applitools::EyesError => e
500
+ logger.error "DOM capture failed! #{e.message}"
501
+ return {}
502
+ end
503
+ end
504
+
515
505
  private
516
506
 
517
507
  attr_accessor :check_frame_or_element, :region_to_check, :dont_get_title,
518
508
  :device_pixel_ratio, :position_provider, :scale_provider, :tag_for_debug,
519
- :region_visibility_strategy, :eyes_screenshot_factory, :force_driver_resolution_as_viewport_size
509
+ :region_visibility_strategy, :eyes_screenshot_factory, :force_driver_resolution_as_viewport_size,
510
+ :prevent_dom_processing
520
511
 
521
- def capture_screenshot
522
- image_provider = Applitools::Selenium::TakesScreenshotImageProvider.new driver,
512
+ def image_provider
513
+ Applitools::Selenium::TakesScreenshotImageProvider.new(
514
+ driver,
523
515
  debug_screenshot_provider: debug_screenshot_provider
516
+ )
517
+ end
518
+
519
+ def capture_screenshot
524
520
  logger.info 'Getting screenshot (capture_screenshot() has been invoked)'
525
521
 
526
522
  update_scaling_params
@@ -534,72 +530,16 @@ module Applitools::Selenium
534
530
  end
535
531
 
536
532
  begin
537
- if check_frame_or_element
538
- logger.info 'Check frame/element requested'
539
- algo = Applitools::Selenium::FullPageCaptureAlgorithm.new(
540
- debug_screenshot_provider: debug_screenshot_provider
541
- )
542
-
543
- entire_frame_or_element = algo.get_stitched_region(
544
- image_provider: image_provider,
545
- region_to_check: region_to_check,
546
- origin_provider: position_provider,
547
- position_provider: position_provider,
548
- scale_provider: scale_provider,
549
- cut_provider: cut_provider,
550
- wait_before_screenshots: wait_before_screenshots,
551
- eyes_screenshot_factory: eyes_screenshot_factory,
552
- stitching_overlap: stitching_overlap
553
- )
554
-
555
- logger.info 'Building screenshot object...'
556
- self.screenshot = Applitools::Selenium::EyesWebDriverScreenshot.new entire_frame_or_element,
557
- driver: driver,
558
- entire_frame_size: Applitools::RectangleSize.new(entire_frame_or_element.width,
559
- entire_frame_or_element.height)
560
- elsif force_full_page_screenshot
561
- logger.info 'Full page screenshot requested'
562
- original_frame = driver.frame_chain
563
- driver.switch_to.default_content
564
- algo = Applitools::Selenium::FullPageCaptureAlgorithm.new(
565
- debug_screenshot_provider: debug_screenshot_provider
566
- )
567
- region_provider = Object.new
568
- region_provider.instance_eval do
569
- def region
570
- Applitools::Region::EMPTY
571
- end
572
-
573
- def coordinate_type
574
- nil
575
- end
576
- end
577
- full_page_image = algo.get_stitched_region image_provider: image_provider,
578
- region_to_check: region_provider,
579
- origin_provider: Applitools::Selenium::ScrollPositionProvider.new(driver),
580
- position_provider: position_provider,
581
- scale_provider: scale_provider,
582
- cut_provider: cut_provider,
583
- wait_before_screenshots: wait_before_screenshots,
584
- eyes_screenshot_factory: eyes_screenshot_factory,
585
- stitching_overlap: stitching_overlap
586
-
587
- unless driver.frame_chain.empty?
588
- logger.info 'Switching back to original frame...'
589
- driver.switch_to.frame original_frame
590
- logger.info 'Done switching!'
591
- end
592
- logger.info 'Creating EyesWebDriver screenshot instance..'
593
- ewd_screenshot = Applitools::Selenium::EyesFullPageScreenshot.new(full_page_image)
594
- logger.info 'Done creating EyesWebDriver screenshot instance!'
595
- ewd_screenshot
596
- else
597
- logger.info 'Screenshot requested...'
598
- sleep wait_before_screenshots
599
- image = image_provider.take_screenshot
600
- scale_provider.scale_image(image) if scale_provider
601
- cut_provider.cut(image) if cut_provider
602
- self.screenshot = eyes_screenshot_factory.call(image)
533
+ algo = Applitools::Selenium::FullPageCaptureAlgorithm.new(
534
+ debug_screenshot_provider: debug_screenshot_provider
535
+ )
536
+ case screenshot_type
537
+ when ENTIRE_ELEMENT_SCREENSHOT
538
+ self.screenshot = entire_element_screenshot(algo)
539
+ when FULLPAGE_SCREENSHOT
540
+ self.screenshot = full_page_screenshot(algo)
541
+ when VIEWPORT_SCREENSHOT
542
+ self.screenshot = viewport_screenshot
603
543
  end
604
544
  ensure
605
545
  begin
@@ -610,6 +550,75 @@ module Applitools::Selenium
610
550
  end
611
551
  end
612
552
 
553
+ def full_page_screenshot(algo)
554
+ logger.info 'Full page screenshot requested'
555
+ original_frame = driver.frame_chain
556
+ driver.switch_to.default_content
557
+ region_provider = Applitools::Selenium::RegionProvider.new(driver, Applitools::Region::EMPTY)
558
+
559
+ full_page_image = algo.get_stitched_region(
560
+ image_provider: image_provider,
561
+ region_to_check: region_provider,
562
+ origin_provider: Applitools::Selenium::ScrollPositionProvider.new(driver),
563
+ position_provider: position_provider,
564
+ scale_provider: scale_provider,
565
+ cut_provider: cut_provider,
566
+ wait_before_screenshots: wait_before_screenshots,
567
+ eyes_screenshot_factory: eyes_screenshot_factory,
568
+ stitching_overlap: stitching_overlap
569
+ )
570
+
571
+ # binding.pry
572
+ unless original_frame.empty?
573
+ logger.info 'Switching back to original frame...'
574
+ driver.switch_to.frames frame_chain: original_frame
575
+ logger.info 'Done switching!'
576
+ end
577
+ logger.info 'Creating EyesWebDriver screenshot instance..'
578
+ result = Applitools::Selenium::FullpageScreenshot.new(
579
+ full_page_image,
580
+ region_provider: region_to_check
581
+ )
582
+ logger.info 'Done creating EyesWebDriver screenshot instance!'
583
+ result
584
+ end
585
+
586
+ def entire_element_screenshot(algo)
587
+ logger.info 'Entire element screenshot requested'
588
+ entire_frame_or_element = algo.get_stitched_region(
589
+ image_provider: image_provider,
590
+ region_to_check: region_to_check,
591
+ origin_provider: position_provider,
592
+ position_provider: position_provider,
593
+ scale_provider: scale_provider,
594
+ cut_provider: cut_provider,
595
+ wait_before_screenshots: wait_before_screenshots,
596
+ eyes_screenshot_factory: eyes_screenshot_factory,
597
+ stitching_overlap: stitching_overlap,
598
+ top_left_position: full_page_capture_algorithm_left_top_offset
599
+ )
600
+
601
+ logger.info 'Building screenshot object (EyesStitchedElementScreenshot)...'
602
+ result = Applitools::Selenium::EntireElementScreenshot.new(
603
+ entire_frame_or_element,
604
+ region_provider: region_to_check
605
+ )
606
+ logger.info 'Done!'
607
+ result
608
+ end
609
+
610
+ def viewport_screenshot
611
+ logger.info 'Viewport screenshot requested'
612
+ sleep wait_before_screenshots
613
+ image = image_provider.take_screenshot
614
+ scale_provider.scale_image(image) if scale_provider
615
+ local_cut_provider = (
616
+ cut_provider || Applitools::Selenium::FixedCutProvider.viewport(image, viewport_size, region_to_check)
617
+ )
618
+ local_cut_provider.cut(image) if local_cut_provider
619
+ eyes_screenshot_factory.call(image)
620
+ end
621
+
613
622
  def vp_size=(value, skip_check_if_open = false)
614
623
  raise Applitools::EyesNotOpenException.new 'set_viewport_size: Eyes not open!' unless skip_check_if_open || open?
615
624
  original_frame = driver.frame_chain
@@ -749,62 +758,6 @@ module Applitools::Selenium
749
758
 
750
759
  protected
751
760
 
752
- def check_current_frame(match_timeout, tag)
753
- logger.info "check_current_frame(#{match_timeout}, #{tag})"
754
- self.check_frame_or_element = true
755
-
756
- region_provider = Object.new.tap do |provider|
757
- provider.instance_eval do
758
- define_singleton_method :region do
759
- Applitools::Region::EMPTY
760
- end
761
- define_singleton_method :coordinate_type do
762
- nil
763
- end
764
- end
765
- end
766
-
767
- self.region_to_check = Object.new.tap do |provider|
768
- current_frame_size = lambda do
769
- frame_region = Applitools::Region.from_location_size(
770
- Applitools::Location.new(0, 0), driver.frame_chain!.current_frame.size
771
- )
772
- begin
773
- frame_region.intersect Applitools::Region.from_location_size(
774
- Applitools::Location.new(0, 0),
775
- Applitools::Utils::EyesSeleniumUtils.entire_page_size(driver)
776
- )
777
- frame_region
778
- ensure
779
- frame_region
780
- end
781
- end
782
-
783
- provider.instance_eval do
784
- define_singleton_method :region do
785
- current_frame_size.call
786
- end
787
- define_singleton_method :coordinate_type do
788
- Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
789
- end
790
- end
791
- end
792
-
793
- self.eyes_screenshot_factory = lambda do |image|
794
- Applitools::Selenium::EyesWebDriverScreenshot.new(
795
- image, driver: driver, force_offset: position_provider.force_offset
796
- )
797
- end
798
-
799
- match_data = Applitools::MatchWindowData.new.tap do |d|
800
- d.tag = tag
801
- d.ignore_mismatch = false
802
- d.match_level = default_match_settings[:match_level]
803
- end
804
-
805
- check_window_base region_provider, match_timeout, match_data
806
- end
807
-
808
761
  def app_environment
809
762
  app_env = super
810
763
  if app_env.os.nil?
@@ -839,175 +792,6 @@ module Applitools::Selenium
839
792
  app_env
840
793
  end
841
794
 
842
- # check a region, specified by element_or_selector parameter
843
- #
844
- # @param [Array] element_or_selector Array, which contains Applitools::Selenium::Element or [:finder, :value]
845
- # pair should be used in find_element
846
- # @param [Hash] options
847
- # @option options [String] :tag
848
- # @option options [Float] :tmatch_timeout
849
- def check_region_(element_or_selector, options = {})
850
- selector = element_or_selector if Applitools::Selenium::Driver::FINDERS.keys.include? element_or_selector.first
851
- element = element_or_selector.first if element_or_selector.first.instance_of? Applitools::Selenium::Element
852
- element = driver.find_element(*selector) unless element
853
- raise Applitools::EyesIllegalArgument.new 'You should pass :selector or :element!' unless element
854
-
855
- if !options[:tag].nil? && !options[:tag].empty?
856
- tag = options[:tag]
857
- self.tag_for_debug = tag
858
- end
859
-
860
- match_timeout = options[:match_timeout] || USE_DEFAULT_MATCH_TIMEOUT
861
-
862
- logger.info "check_region(element, #{match_timeout}, #{tag}): Ignored" && return if disabled?
863
- Applitools::ArgumentGuard.not_nil 'options[:element]', element
864
- logger.info "check_region(element: element, #{match_timeout}, #{tag})"
865
-
866
- location_as_point = element.location
867
- region_visibility_strategy.move_to_region position_provider,
868
- Applitools::Location.new(location_as_point.x.to_i, location_as_point.y.to_i)
869
-
870
- region_provider = Object.new.tap do |prov|
871
- prov.instance_eval do
872
- define_singleton_method :region do
873
- p = element.location
874
- d = element.size
875
- Applitools::Region.from_location_size p, d
876
- end
877
-
878
- define_singleton_method :coordinate_type do
879
- Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
880
- end
881
- end
882
- end
883
-
884
- self.eyes_screenshot_factory = lambda do |image|
885
- Applitools::Selenium::EyesWebDriverScreenshot.new(image, driver: driver)
886
- end
887
-
888
- match_data = Applitools::MatchWindowData.new.tap do |d|
889
- d.tag = tag
890
- d.ignore_mismatch = false
891
- d.match_level = default_match_settings[:match_level]
892
- end
893
-
894
- result = check_window_base(
895
- region_provider, match_timeout, match_data
896
- )
897
-
898
- logger.info 'Done! trying to scroll back to original position...'
899
- region_visibility_strategy.return_to_original_position position_provider
900
- logger.info 'Done!'
901
- result
902
- end
903
-
904
- # Checks an element, specified by +element_or_selector+ parameter
905
- #
906
- # @param [Array] element_or_selector Array, which contains Applitools::Selenium::Element or [:finder, :value]
907
- # pair should be used in find_element
908
- # @param [Hash] options
909
- # @option options [String] :tag
910
- # @option options [Float] :match_timeout
911
-
912
- def check_element(element_or_selector, options = {})
913
- selector = element_or_selector if Applitools::Selenium::Driver::FINDERS.keys.include? element_or_selector.first
914
- if !options[:tag].nil? && !options[:tag].empty?
915
- tag = options[:tag]
916
- self.tag_for_debug = tag
917
- end
918
- match_timeout = options[:match_timeout] || USE_DEFAULT_MATCH_TIMEOUT
919
-
920
- if disabled?
921
- logger.info "check_element(#{options.inject([]) { |res, (k, v)| res << "#{k}: #{v}" }.join(', ')}):" /
922
- ' Ignored'
923
- return
924
- end
925
-
926
- eyes_element = element_or_selector.first if element_or_selector.first.instance_of? Applitools::Selenium::Element
927
- eyes_element = driver.find_element(*selector) unless eyes_element
928
- raise Applitools::EyesIllegalArgument.new 'You should pass :selector or :element!' unless eyes_element
929
- eyes_element = Applitools::Selenium::Element.new(driver, eyes_element) unless
930
- eyes_element.is_a? Applitools::Selenium::Element
931
-
932
- location_as_point = eyes_element.location
933
- region_visibility_strategy.move_to_region position_provider,
934
- Applitools::Location.new(location_as_point.x.to_i, location_as_point.y.to_i)
935
-
936
- original_overflow = nil
937
- original_position_provider = position_provider
938
-
939
- begin
940
- self.check_frame_or_element = true
941
- self.position_provider = Applitools::Selenium::ElementPositionProvider.new driver, eyes_element
942
- original_overflow = eyes_element.overflow
943
- eyes_element.overflow = 'hidden'
944
-
945
- p = eyes_element.location
946
- d = eyes_element.size
947
-
948
- border_left_width = eyes_element.border_left_width
949
- border_top_width = eyes_element.border_top_width
950
- border_right_width = eyes_element.border_right_width
951
- border_bottom_width = eyes_element.border_bottom_width
952
-
953
- element_region = Applitools::Region.new(
954
- p.x + border_left_width,
955
- p.y + border_top_width,
956
- d.width - border_left_width - border_right_width,
957
- d.height - border_top_width - border_bottom_width
958
- )
959
-
960
- logger.info "Element region: #{element_region}"
961
-
962
- self.region_to_check = Object.new.tap do |prov|
963
- prov.instance_eval do
964
- define_singleton_method :region do
965
- element_region
966
- end
967
-
968
- define_singleton_method :coordinate_type do
969
- Applitools::EyesScreenshot::COORDINATE_TYPES[:context_relative]
970
- end
971
- end
972
- end
973
-
974
- base_check_region_provider = Object.new.tap do |prov|
975
- prov.instance_eval do
976
- define_singleton_method :region do
977
- Applitools::Region::EMPTY
978
- end
979
-
980
- define_singleton_method :coordinate_type do
981
- nil
982
- end
983
- end
984
- end
985
-
986
- self.eyes_screenshot_factory = lambda do |image|
987
- Applitools::Selenium::EyesWebDriverScreenshot.new(
988
- image, driver: driver, force_offset: position_provider.state
989
- )
990
- end
991
-
992
- match_data = Applitools::MatchWindowData.new.tap do |data|
993
- data.tag = tag
994
- data.ignore_mismatch = false
995
- data.match_level = default_match_settings[:match_level]
996
- end
997
-
998
- check_window_base(
999
- base_check_region_provider, match_timeout, match_data
1000
- )
1001
- ensure
1002
- eyes_element.overflow = original_overflow unless original_overflow.nil?
1003
- self.check_frame_or_element = false
1004
- self.position_provider = original_position_provider
1005
- self.region_to_check = nil
1006
-
1007
- region_visibility_strategy.return_to_original_position position_provider
1008
- end
1009
- end
1010
-
1011
795
  def inferred_environment
1012
796
  return @inferred_environment unless @inferred_environment.nil?
1013
797
 
@@ -1017,6 +801,29 @@ module Applitools::Selenium
1017
801
  nil
1018
802
  end
1019
803
 
804
+ def ensure_frame_visible
805
+ original_fc = driver.frame_chain
806
+ return original_fc if original_fc.empty?
807
+ fc = Applitools::Selenium::FrameChain.new other: original_fc
808
+ until fc.empty?
809
+ driver.switch_to.parent_frame
810
+ position_provider.position = fc.pop.location
811
+ end
812
+ driver.switch_to.frames(frame_chain: original_fc)
813
+ original_fc
814
+ end
815
+
816
+ def reset_frames_scroll_position(original_fc)
817
+ return original_fc if original_fc.empty?
818
+ fc = Applitools::Selenium::FrameChain.new other: original_fc
819
+ until fc.empty?
820
+ driver.switch_to.parent_frame
821
+ position_provider.position = fc.pop.parent_scroll_position
822
+ end
823
+ driver.switch_to.frames(frame_chain: original_fc)
824
+ original_fc
825
+ end
826
+
1020
827
  class << self
1021
828
  def position_provider(stitch_mode, driver, disable_horizontal = false, disable_vertical = false,
1022
829
  explicit_entire_size = nil)