eyes_selenium 3.15.39 → 3.15.40

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/lib/applitools/selenium/browser_types.rb +1 -0
  3. data/lib/applitools/selenium/browsers_info.rb +24 -23
  4. data/lib/applitools/selenium/concerns/selenium_eyes.rb +154 -0
  5. data/lib/applitools/selenium/configuration.rb +5 -4
  6. data/lib/applitools/selenium/css_parser/find_embedded_resources.rb +4 -1
  7. data/lib/applitools/selenium/css_translate_position_provider.rb +1 -1
  8. data/lib/applitools/selenium/devices.rb +1 -0
  9. data/lib/applitools/selenium/dom_capture/dom_capture.rb +9 -8
  10. data/lib/applitools/selenium/dom_capture/dom_capture_script.rb +3 -1
  11. data/lib/applitools/selenium/external_css_resources.rb +7 -3
  12. data/lib/applitools/selenium/eyes.rb +2 -3
  13. data/lib/applitools/selenium/full_page_capture_algorithm.rb +5 -1
  14. data/lib/applitools/selenium/orientations.rb +1 -0
  15. data/lib/applitools/selenium/render_browser_info_fluent.rb +3 -1
  16. data/lib/applitools/selenium/render_resources.rb +12 -5
  17. data/lib/applitools/selenium/rgrid_dom.rb +4 -8
  18. data/lib/applitools/selenium/scripts/get_element_xpath.rb +3 -1
  19. data/lib/applitools/selenium/scripts/process_page_and_poll.rb +154 -72
  20. data/lib/applitools/selenium/scripts/process_page_and_serialize.rb +3 -1
  21. data/lib/applitools/selenium/selenium_eyes.rb +66 -221
  22. data/lib/applitools/selenium/stitch_modes.rb +2 -1
  23. data/lib/applitools/selenium/target.rb +31 -14
  24. data/lib/applitools/selenium/test_list.rb +16 -10
  25. data/lib/applitools/selenium/visual_grid/chrome_emulation_info.rb +2 -1
  26. data/lib/applitools/selenium/visual_grid/emulation_base_info.rb +2 -1
  27. data/lib/applitools/selenium/visual_grid/eyes_connector.rb +13 -7
  28. data/lib/applitools/selenium/visual_grid/render_browser_info.rb +2 -1
  29. data/lib/applitools/selenium/visual_grid/render_info.rb +2 -1
  30. data/lib/applitools/selenium/visual_grid/render_request.rb +4 -3
  31. data/lib/applitools/selenium/visual_grid/render_requests.rb +2 -1
  32. data/lib/applitools/selenium/visual_grid/render_task.rb +71 -46
  33. data/lib/applitools/selenium/visual_grid/resource_cache.rb +4 -3
  34. data/lib/applitools/selenium/visual_grid/running_test.rb +26 -4
  35. data/lib/applitools/selenium/visual_grid/thread_pool.rb +3 -2
  36. data/lib/applitools/selenium/visual_grid/vg_match_window_data.rb +9 -3
  37. data/lib/applitools/selenium/visual_grid/vg_region.rb +2 -1
  38. data/lib/applitools/selenium/visual_grid/vg_resource.rb +8 -7
  39. data/lib/applitools/selenium/visual_grid/vg_task.rb +2 -1
  40. data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +114 -168
  41. data/lib/applitools/selenium/visual_grid/visual_grid_runner.rb +38 -11
  42. data/lib/applitools/selenium/visual_grid/web_element_region.rb +3 -1
  43. data/lib/applitools/version.rb +1 -1
  44. data/lib/eyes_selenium.rb +1 -1
  45. metadata +5 -4
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: false
1
2
  module Applitools
2
3
  module Selenium
3
4
  class RGridDom
@@ -13,21 +14,16 @@ module Applitools
13
14
  self.resources = options[:resources]
14
15
  self.hash_format = 'sha256'
15
16
  self.data = {
16
- 'resources' => resources,
17
- 'domNodes' => dom_nodes
17
+ 'resources' => resources,
18
+ 'domNodes' => dom_nodes
18
19
  }
19
20
  self.hash = calculate_sha_256
20
21
  end
21
22
 
22
23
  def calculate_sha_256
23
- # str = Applitools::Utils.stringify_for_hash(data)
24
24
  Digest::SHA256.hexdigest(content)
25
25
  end
26
26
 
27
- # def hash
28
- # calculate_sha_256
29
- # end
30
-
31
27
  def content
32
28
  Oj.dump(json_value(data.sort.to_h))
33
29
  end
@@ -41,4 +37,4 @@ module Applitools
41
37
  end
42
38
  end
43
39
  end
44
- end
40
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  module Selenium
3
5
  module Scripts
@@ -22,4 +24,4 @@ module Applitools
22
24
  END
23
25
  end
24
26
  end
25
- end
27
+ end
@@ -1,13 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  module Selenium
3
5
  module Scripts
4
6
  PROCESS_PAGE_AND_POLL = <<'END'
5
- /* @applitools/dom-snapshot@2.2.1 */
7
+ /* @applitools/dom-snapshot@3.1.4 */
6
8
 
7
- function __processPageAndPoll() {
8
- var processPageAndPoll = (function () {
9
+ function __processPageAndSerializePoll() {
10
+ var processPageAndSerializePoll = (function () {
9
11
  'use strict';
10
12
 
13
+ const EYES_NAME_SPACE = '__EYES__APPLITOOLS__';
14
+
15
+ function pullify(script, win = window) {
16
+ return function() {
17
+ const scriptName = script.name;
18
+ if (!win[EYES_NAME_SPACE]) {
19
+ win[EYES_NAME_SPACE] = {};
20
+ }
21
+ if (!win[EYES_NAME_SPACE][scriptName]) {
22
+ win[EYES_NAME_SPACE][scriptName] = {
23
+ status: 'WIP',
24
+ value: null,
25
+ error: null,
26
+ };
27
+ script
28
+ .apply(null, arguments)
29
+ .then(r => ((resultObject.status = 'SUCCESS'), (resultObject.value = r)))
30
+ .catch(e => ((resultObject.status = 'ERROR'), (resultObject.error = e.message)));
31
+ }
32
+
33
+ const resultObject = win[EYES_NAME_SPACE][scriptName];
34
+ if (resultObject.status === 'SUCCESS') {
35
+ win[EYES_NAME_SPACE][scriptName] = null;
36
+ }
37
+
38
+ return JSON.stringify(resultObject);
39
+ };
40
+ }
41
+
42
+ var pollify = pullify;
43
+
11
44
  // This code was copied and modified from https://github.com/beatgammit/base64-js/blob/bf68aaa277/index.js
12
45
  // License: https://github.com/beatgammit/base64-js/blob/bf68aaa277d9de7007cc0c58279c411bb10670ac/LICENSE
13
46
 
@@ -134,6 +167,21 @@ function __processPageAndPoll() {
134
167
 
135
168
  var absolutizeUrl_1 = absolutizeUrl;
136
169
 
170
+ const NEED_MAP_INPUT_TYPES = new Set([
171
+ 'date',
172
+ 'datetime-local',
173
+ 'email',
174
+ 'month',
175
+ 'number',
176
+ 'password',
177
+ 'search',
178
+ 'tel',
179
+ 'text',
180
+ 'time',
181
+ 'url',
182
+ 'week',
183
+ ]);
184
+
137
185
  function domNodesToCdt(docNode, baseUrl) {
138
186
  const cdt = [{nodeType: Node.DOCUMENT_NODE}];
139
187
  const docRoots = [docNode];
@@ -171,6 +219,11 @@ function __processPageAndPoll() {
171
219
  manualChildNodeIndexes = [cdt.length - 1];
172
220
  }
173
221
 
222
+ if (elementNode.tagName === 'TEXTAREA' && elementNode.value !== elementNode.textContent) {
223
+ cdt.push(getTextContentNode(elementNode));
224
+ manualChildNodeIndexes = [cdt.length - 1];
225
+ }
226
+
174
227
  node = getBasicNode(elementNode);
175
228
  node.childNodeIndexes =
176
229
  manualChildNodeIndexes ||
@@ -226,6 +279,13 @@ function __processPageAndPoll() {
226
279
  };
227
280
  }
228
281
 
282
+ function getTextContentNode(elementNode) {
283
+ return {
284
+ nodeType: Node.TEXT_NODE,
285
+ nodeValue: elementNode.value,
286
+ };
287
+ }
288
+
229
289
  function getBasicNode(elementNode) {
230
290
  const node = {
231
291
  nodeType: elementNode.nodeType,
@@ -255,7 +315,7 @@ function __processPageAndPoll() {
255
315
 
256
316
  if (
257
317
  elementNode.tagName === 'INPUT' &&
258
- elementNode.type === 'text' &&
318
+ NEED_MAP_INPUT_TYPES.has(elementNode.type) &&
259
319
  (elementNode.attributes.value && elementNode.attributes.value.value) !== elementNode.value
260
320
  ) {
261
321
  const nodeAttr = node.attributes.find(a => a.name === 'value');
@@ -265,6 +325,13 @@ function __processPageAndPoll() {
265
325
  node.attributes.push({name: 'value', value: elementNode.value});
266
326
  }
267
327
  }
328
+
329
+ if (elementNode.tagName === 'OPTION' && elementNode.parentElement.value === elementNode.value) {
330
+ const nodeAttr = node.attributes.find(a => a.name === 'selected');
331
+ if (!nodeAttr) {
332
+ node.attributes.push({name: 'selected', value: ''});
333
+ }
334
+ }
268
335
  return node;
269
336
  }
270
337
 
@@ -410,7 +477,7 @@ function __processPageAndPoll() {
410
477
  value,
411
478
  styleSheet,
412
479
  );
413
- dependentUrls = extractResourcesFromStyleSheet(corsFreeStyleSheet, documents[0]);
480
+ dependentUrls = extractResourcesFromStyleSheet(corsFreeStyleSheet);
414
481
  cleanStyleSheet();
415
482
  }
416
483
  } else if (/image\/svg/.test(type)) {
@@ -495,6 +562,19 @@ function __processPageAndPoll() {
495
562
  const domparser = parser || new DOMParser();
496
563
  const doc = domparser.parseFromString(svgStr, 'image/svg+xml');
497
564
 
565
+ const srcsetUrls = Array.from(doc.querySelectorAll('img[srcset]'))
566
+ .map(srcsetEl =>
567
+ srcsetEl
568
+ .getAttribute('srcset')
569
+ .split(', ')
570
+ .map(str => str.trim().split(/\s+/)[0]),
571
+ )
572
+ .reduce((acc, urls) => acc.concat(urls), []);
573
+
574
+ const srcUrls = Array.from(doc.querySelectorAll('img[src]')).map(srcEl =>
575
+ srcEl.getAttribute('src'),
576
+ );
577
+
498
578
  const fromHref = Array.from(doc.querySelectorAll('image,use,link[rel="stylesheet"]')).map(
499
579
  e => e.getAttribute('href') || e.getAttribute('xlink:href'),
500
580
  );
@@ -504,7 +584,9 @@ function __processPageAndPoll() {
504
584
  const fromStyleTags = extractResourceUrlsFromStyleTags(doc, false);
505
585
  const fromStyleAttrs = urlsFromStyleAttrOfDoc(doc);
506
586
 
507
- return fromHref
587
+ return srcsetUrls
588
+ .concat(srcUrls)
589
+ .concat(fromHref)
508
590
  .concat(fromObjects)
509
591
  .concat(fromStyleTags)
510
592
  .concat(fromStyleAttrs)
@@ -526,53 +608,78 @@ function __processPageAndPoll() {
526
608
  /* global window */
527
609
 
528
610
  function fetchUrl(url, fetch = window.fetch) {
529
- return fetch(url, {cache: 'force-cache', credentials: 'same-origin'}).then(resp =>
530
- resp.status === 200
531
- ? resp.arrayBuffer().then(buff => ({
532
- url,
533
- type: resp.headers.get('Content-Type'),
534
- value: buff,
535
- }))
536
- : Promise.reject(`bad status code ${resp.status}`),
537
- );
611
+ // Why return a `new Promise` like this? Because people like Atlassian do horrible things.
612
+ // They monkey patched window.fetch, and made it so it throws a synchronous exception if the route is not well known.
613
+ // Returning a new Promise guarantees that `fetchUrl` is the async function that it declares to be.
614
+ return new Promise((resolve, reject) => {
615
+ return fetch(url, {cache: 'force-cache', credentials: 'same-origin'})
616
+ .then(resp =>
617
+ resp.status === 200
618
+ ? resp.arrayBuffer().then(buff => ({
619
+ url,
620
+ type: resp.headers.get('Content-Type'),
621
+ value: buff,
622
+ }))
623
+ : Promise.reject(`bad status code ${resp.status}`),
624
+ )
625
+ .then(resolve)
626
+ .catch(err => reject(err));
627
+ });
538
628
  }
539
629
 
540
630
  var fetchUrl_1 = fetchUrl;
541
631
 
632
+ function sanitizeAuthUrl(urlStr) {
633
+ const url = new URL(urlStr);
634
+ if (url.username && url.password) {
635
+ return urlStr.replace(`${url.username}:${url.password}@`, '');
636
+ }
637
+ return urlStr;
638
+ }
639
+
640
+ var sanitizeAuthUrl_1 = sanitizeAuthUrl;
641
+
542
642
  function makeFindStyleSheetByUrl({styleSheetCache}) {
543
643
  return function findStyleSheetByUrl(url, documents) {
544
644
  const allStylesheets = flat_1(documents.map(d => Array.from(d.styleSheets)));
545
645
  return (
546
646
  styleSheetCache[url] ||
547
- allStylesheets.find(styleSheet => styleSheet.href && toUnAnchoredUri_1(styleSheet.href) === url)
647
+ allStylesheets.find(styleSheet => {
648
+ const styleUrl = styleSheet.href && toUnAnchoredUri_1(styleSheet.href);
649
+ return styleUrl && sanitizeAuthUrl_1(styleUrl) === url;
650
+ })
548
651
  );
549
652
  };
550
653
  }
551
654
 
552
655
  var findStyleSheetByUrl = makeFindStyleSheetByUrl;
553
656
 
554
- function makeExtractResourcesFromStyleSheet({styleSheetCache}) {
555
- return function extractResourcesFromStyleSheet(styleSheet, doc) {
556
- const win = doc.defaultView || (doc.ownerDocument && doc.ownerDocument.defaultView) || window;
657
+ function makeExtractResourcesFromStyleSheet({styleSheetCache, CSSRule = window.CSSRule}) {
658
+ return function extractResourcesFromStyleSheet(styleSheet) {
557
659
  const urls = uniq_1(
558
660
  Array.from(styleSheet.cssRules || []).reduce((acc, rule) => {
559
- if (rule instanceof win.CSSImportRule) {
560
- styleSheetCache[rule.styleSheet.href] = rule.styleSheet;
561
- return acc.concat(rule.href);
562
- } else if (rule instanceof win.CSSFontFaceRule) {
563
- return acc.concat(getUrlFromCssText_1(rule.cssText));
564
- } else if (
565
- (win.CSSSupportsRule && rule instanceof win.CSSSupportsRule) ||
566
- rule instanceof win.CSSMediaRule
567
- ) {
568
- return acc.concat(extractResourcesFromStyleSheet(rule, doc));
569
- } else if (rule instanceof win.CSSStyleRule) {
570
- for (let i = 0, ii = rule.style.length; i < ii; i++) {
571
- const urls = getUrlFromCssText_1(rule.style.getPropertyValue(rule.style[i]));
572
- urls.length && (acc = acc.concat(urls));
573
- }
574
- }
575
- return acc;
661
+ const getRuleUrls = {
662
+ [CSSRule.IMPORT_RULE]: () => {
663
+ if (rule.styleSheet) {
664
+ styleSheetCache[rule.styleSheet.href] = rule.styleSheet;
665
+ return rule.href;
666
+ }
667
+ },
668
+ [CSSRule.FONT_FACE_RULE]: () => getUrlFromCssText_1(rule.cssText),
669
+ [CSSRule.SUPPORTS_RULE]: () => extractResourcesFromStyleSheet(rule),
670
+ [CSSRule.MEDIA_RULE]: () => extractResourcesFromStyleSheet(rule),
671
+ [CSSRule.STYLE_RULE]: () => {
672
+ let rv = [];
673
+ for (let i = 0, ii = rule.style.length; i < ii; i++) {
674
+ const urls = getUrlFromCssText_1(rule.style.getPropertyValue(rule.style[i]));
675
+ rv = rv.concat(urls);
676
+ }
677
+ return rv;
678
+ },
679
+ }[rule.type];
680
+
681
+ const urls = (getRuleUrls && getRuleUrls()) || [];
682
+ return acc.concat(urls);
576
683
  }, []),
577
684
  );
578
685
  return urls.filter(u => u[0] !== '#');
@@ -603,7 +710,7 @@ function __processPageAndPoll() {
603
710
  ? Array.from(doc.styleSheets).find(styleSheet => styleSheet.ownerNode === styleEl)
604
711
  : styleEl.sheet;
605
712
  return styleSheet
606
- ? resourceUrls.concat(extractResourcesFromStyleSheet(styleSheet, doc))
713
+ ? resourceUrls.concat(extractResourcesFromStyleSheet(styleSheet))
607
714
  : resourceUrls;
608
715
  }, []),
609
716
  );
@@ -776,7 +883,7 @@ function __processPageAndPoll() {
776
883
 
777
884
  var sessionCache = makeSessionCache;
778
885
 
779
- function processPage(doc = document, {showLogs, useSessionCache} = {}) {
886
+ function processPage(doc = document, {showLogs, useSessionCache, dontFetchResources} = {}) {
780
887
  const log$$1 = showLogs ? log(Date.now()) : noop;
781
888
  log$$1('processPage start');
782
889
  const sessionCache$$1 = useSessionCache && sessionCache({log: log$$1});
@@ -826,12 +933,12 @@ function __processPageAndPoll() {
826
933
  .map(toUnAnchoredUri_1)
827
934
  .filter(filterInlineUrlsIfExisting);
828
935
 
829
- const resourceUrlsAndBlobsPromise = getResourceUrlsAndBlobs$$1({documents: docRoots, urls}).then(
830
- result => {
831
- sessionCache$$1 && sessionCache$$1.persist();
832
- return result;
833
- },
834
- );
936
+ const resourceUrlsAndBlobsPromise = dontFetchResources
937
+ ? Promise.resolve({resourceUrls: urls, blobsObj: {}})
938
+ : getResourceUrlsAndBlobs$$1({documents: docRoots, urls}).then(result => {
939
+ sessionCache$$1 && sessionCache$$1.persist();
940
+ return result;
941
+ });
835
942
  const canvasBlobs = buildCanvasBlobs_1(canvasElements);
836
943
  const frameDocs = extractFrames_1(docRoots);
837
944
 
@@ -907,38 +1014,13 @@ function __processPageAndPoll() {
907
1014
 
908
1015
  var processPageAndSerialize_1 = processPageAndSerialize;
909
1016
 
910
- const EYES_NAME_SPACE = '__EYES__APPLITOOLS__';
911
-
912
- function processPageAndPoll(doc) {
913
- if (!window[EYES_NAME_SPACE]) {
914
- window[EYES_NAME_SPACE] = {};
915
- }
916
- if (!window[EYES_NAME_SPACE].processPageAndSerializeResult) {
917
- window[EYES_NAME_SPACE].processPageAndSerializeResult = {
918
- status: 'WIP',
919
- value: null,
920
- error: null,
921
- };
922
- processPageAndSerialize_1(doc)
923
- .then(r => ((resultObject.status = 'SUCCESS'), (resultObject.value = r)))
924
- .catch(e => ((resultObject.status = 'ERROR'), (resultObject.error = e.message)));
925
- }
926
-
927
- const resultObject = window[EYES_NAME_SPACE].processPageAndSerializeResult;
928
- if (resultObject.status === 'SUCCESS') {
929
- window[EYES_NAME_SPACE].processPageAndSerializeResult = null;
930
- }
931
-
932
- return JSON.stringify(resultObject);
933
- }
934
-
935
- var processPageAndPoll_1 = processPageAndPoll;
1017
+ var processPageAndSerializePoll = pollify(processPageAndSerialize_1);
936
1018
 
937
- return processPageAndPoll_1;
1019
+ return processPageAndSerializePoll;
938
1020
 
939
1021
  }());
940
1022
 
941
- return processPageAndPoll.apply(this, arguments);
1023
+ return processPageAndSerializePoll.apply(this, arguments);
942
1024
  }
943
1025
  END
944
1026
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Applitools
2
4
  module Selenium
3
5
  module Scripts
@@ -531,4 +533,4 @@ function __processPageAndSerialize() {
531
533
  END
532
534
  end
533
535
  end
534
- end
536
+ end
@@ -3,6 +3,7 @@
3
3
  module Applitools::Selenium
4
4
  # The main API gateway for the SDK
5
5
  class SeleniumEyes < Applitools::EyesBase
6
+ include Applitools::Selenium::Concerns::SeleniumEyes
6
7
  # @!visibility private
7
8
  UNKNOWN_DEVICE_PIXEL_RATIO = 0
8
9
 
@@ -11,8 +12,6 @@ module Applitools::Selenium
11
12
 
12
13
  DEFAULT_WAIT_BEFORE_SCREENSHOTS = 0.1 # Seconds
13
14
 
14
- USE_DEFAULT_MATCH_TIMEOUT = -1
15
-
16
15
  DEFAULT_STITCHING_OVERLAP = 50 # Pixels
17
16
 
18
17
  ENTIRE_ELEMENT_SCREENSHOT = 0
@@ -96,10 +95,10 @@ module Applitools::Selenium
96
95
  # @return [Applitools::RectangleSize] explicit_entire_size
97
96
 
98
97
  attr_accessor :base_agent_id, :screenshot, :force_full_page_screenshot, :hide_scrollbars,
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, :use_dom, :enable_patterns,
102
- :config
98
+ :wait_before_screenshots, :debug_screenshots, :stitch_mode, :disable_horizontal_scrolling,
99
+ :disable_vertical_scrolling, :explicit_entire_size, :debug_screenshot_provider, :stitching_overlap,
100
+ :full_page_capture_algorithm_left_top_offset, :screenshot_type, :send_dom, :use_dom, :enable_patterns,
101
+ :config
103
102
  attr_reader :driver
104
103
 
105
104
  def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
@@ -124,8 +123,8 @@ module Applitools::Selenium
124
123
  self.region_visibility_strategy = MoveToRegionVisibilityStrategy.new
125
124
  self.debug_screenshots = false
126
125
  self.debug_screenshot_provider = Applitools::DebugScreenshotProvider.new
127
- .tag_access { tag_for_debug }
128
- .debug_flag_access { debug_screenshots }
126
+ .tag_access { tag_for_debug }
127
+ .debug_flag_access { debug_screenshots }
129
128
  self.disable_horizontal_scrolling = false
130
129
  self.disable_vertical_scrolling = false
131
130
  self.explicit_entire_size = nil
@@ -138,7 +137,6 @@ module Applitools::Selenium
138
137
  self.prevent_dom_processing = false
139
138
  end
140
139
 
141
-
142
140
  def ensure_config
143
141
  self.config = Applitools::Selenium::Configuration.new
144
142
  end
@@ -183,7 +181,7 @@ module Applitools::Selenium
183
181
 
184
182
  self.eyes_screenshot_factory = lambda do |image|
185
183
  Applitools::Selenium::ViewportScreenshot.new(
186
- image, driver: @driver, force_offset: position_provider.force_offset
184
+ image, driver: @driver, force_offset: position_provider.force_offset
187
185
  )
188
186
  end
189
187
 
@@ -207,44 +205,6 @@ module Applitools::Selenium
207
205
 
208
206
  private :perform_driver_specific_settings
209
207
 
210
- # Sets the stitch mode.
211
- #
212
- # @param [Hash] value The desired type of stitching (:SCROLL is default).
213
- # @option value [Symbol] :css use Css to perform stitching.
214
- # @option value [Symbol] :scroll Scroll to perform stitching.
215
- # @return [Symbol] The type of stitching.
216
- # def stitch_mode=(value)
217
- # @stitch_mode = if value.to_s.upcase == Applitools::STITCH_MODE[:css].to_s
218
- # Applitools::STITCH_MODE[:css]
219
- # else
220
- # Applitools::STITCH_MODE[:scroll]
221
- # end
222
- # unless driver.nil?
223
- # self.position_provider = self.class.position_provider(
224
- # stitch_mode, driver, disable_horizontal_scrolling, disable_vertical_scrolling, explicit_entire_size
225
- # )
226
- # end
227
- # if stitch_mode == Applitools::STITCH_MODE[:css]
228
- # @css_transition_original_hide_scrollbars = hide_scrollbars
229
- # self.hide_scrollbars = true
230
- # else
231
- # self.hide_scrollbars = @css_transition_original_hide_scrollbars || false
232
- # end
233
- # value
234
- # end
235
-
236
- # Takes a snapshot of the application under test and matches it with the expected output.
237
- #
238
- # @param [String] tag An optional tag to be assosiated with the snapshot.
239
- # @param [Fixnum] match_timeout The amount of time to retry matching (seconds)
240
- def check_window(tag = nil, match_timeout = USE_DEFAULT_MATCH_TIMEOUT)
241
- target = Applitools::Selenium::Target.window.tap do |t|
242
- t.timeout(match_timeout)
243
- t.fully if force_full_page_screenshot
244
- end
245
- check(tag, target)
246
- end
247
-
248
208
  # @!visibility private
249
209
  def title
250
210
  return driver.title unless dont_get_title
@@ -279,8 +239,8 @@ module Applitools::Selenium
279
239
 
280
240
  self.eyes_screenshot_factory = lambda do |image|
281
241
  Applitools::Selenium::ViewportScreenshot.new(
282
- image,
283
- region_provider: region_to_check
242
+ image,
243
+ region_provider: region_to_check
284
244
  )
285
245
  end
286
246
 
@@ -298,8 +258,10 @@ module Applitools::Selenium
298
258
  eyes_element = target_to_check.region_to_check.call(driver)
299
259
 
300
260
  unless force_full_page_screenshot
301
- region_visibility_strategy.move_to_region original_position_provider,
302
- Applitools::Location.new(eyes_element.location.x.to_i, eyes_element.location.y.to_i)
261
+ region_visibility_strategy.move_to_region(
262
+ original_position_provider,
263
+ Applitools::Location.new(eyes_element.location.x.to_i, eyes_element.location.y.to_i)
264
+ )
303
265
  driver.find_element(:css, 'html').scroll_data_attribute = true
304
266
  end
305
267
 
@@ -315,10 +277,10 @@ module Applitools::Selenium
315
277
  inside_a_frame = !driver.frame_chain.empty?
316
278
 
317
279
  self.screenshot_type = self.class.obtain_screenshot_type(
318
- is_element,
319
- inside_a_frame,
320
- target_to_check.options[:stitch_content],
321
- force_full_page_screenshot
280
+ is_element,
281
+ inside_a_frame,
282
+ target_to_check.options[:stitch_content],
283
+ force_full_page_screenshot
322
284
  )
323
285
 
324
286
  case screenshot_type
@@ -329,14 +291,14 @@ module Applitools::Selenium
329
291
  eyes_element.scroll_data_attribute = true
330
292
  eyes_element.overflow_data_attribute = original_overflow
331
293
  self.position_provider = Applitools::Selenium::CssTranslateElementPositionProvider.new(
332
- driver,
333
- eyes_element
294
+ driver,
295
+ eyes_element
334
296
  )
335
297
  end
336
298
  end
337
299
 
338
300
  check_window_base(
339
- region_provider, timeout, match_data
301
+ region_provider, timeout, match_data
340
302
  )
341
303
  ensure
342
304
  eyes_element.overflow = original_overflow unless original_overflow.nil?
@@ -352,38 +314,6 @@ module Applitools::Selenium
352
314
  self.prevent_dom_processing = false
353
315
  end
354
316
 
355
- # Validates the contents of an iframe and matches it with the expected output.
356
- #
357
- # @param [Hash] options The specific parameters of the desired screenshot.
358
- # @option options [Array] :target_frames The frames to check.
359
- def check_in_frame(options)
360
- frames = options.delete :target_frames
361
-
362
- Applitools::ArgumentGuard.is_a? options, 'options', Hash
363
- Applitools::ArgumentGuard.is_a? frames, 'target_frames: []', Array
364
-
365
- return yield if block_given? && frames.empty?
366
-
367
- original_frame_chain = driver.frame_chain
368
-
369
- logger.info 'Switching to target frame according to frames path...'
370
- driver.switch_to.frames(frames_path: frames)
371
- frame_chain_to_reset = driver.frame_chain
372
- logger.info 'Done!'
373
-
374
- ensure_frame_visible
375
-
376
- yield if block_given?
377
-
378
- reset_frames_scroll_position(frame_chain_to_reset)
379
-
380
- logger.info 'Switching back into top level frame...'
381
- driver.switch_to.default_content
382
- return unless original_frame_chain
383
- logger.info 'Switching back into original frame...'
384
- driver.switch_to.frames frame_chain: original_frame_chain
385
- end
386
-
387
317
  # Creates a region instance.
388
318
  #
389
319
  # @param [Applitools::Element] element The element.
@@ -400,16 +330,16 @@ module Applitools::Selenium
400
330
  border_bottom_width = element.border_bottom_width
401
331
 
402
332
  Applitools::Region.new(
403
- p.x.round + border_left_width,
404
- p.y.round + border_top_width,
405
- d.width - border_left_width - border_right_width,
406
- d.height - border_top_width - border_bottom_width
333
+ p.x.round + border_left_width,
334
+ p.y.round + border_top_width,
335
+ d.width - border_left_width - border_right_width,
336
+ d.height - border_top_width - border_bottom_width
407
337
  ).tap do |r|
408
338
  border_padding = Applitools::PaddingBounds.new(
409
- border_left_width,
410
- border_top_width,
411
- border_right_width,
412
- border_bottom_width
339
+ border_left_width,
340
+ border_top_width,
341
+ border_right_width,
342
+ border_bottom_width
413
343
  )
414
344
  r.padding(border_padding)
415
345
  end
@@ -418,95 +348,6 @@ module Applitools::Selenium
418
348
  private :check_in_frame
419
349
  private :region_for_element
420
350
 
421
- # Takes a snapshot of the application under test and matches a region of
422
- # a specific element with the expected region output.
423
- #
424
- # @param [Applitools::Selenium::Element] element Represents a region to check.
425
- # @param [Symbol] how a finder, such :css or :id. Selects a finder will be used to find an element
426
- # See Selenium::Webdriver::Element#find_element documentation for full list of possible finders.
427
- # @param [String] what The value will be passed to a specified finder. If finder is :css it must be a css selector.
428
- # @param [Hash] options
429
- # @option options [String] :tag An optional tag to be associated with the snapshot.
430
- # @option options [Fixnum] :match_timeout The amount of time to retry matching. (Seconds)
431
- # @option options [Boolean] :stitch_content If set to true, will try to get full content of the element
432
- # (including hidden content due overflow settings) by scrolling the element,
433
- # taking and stitching partial screenshots.
434
- # @example Check region by element
435
- # check_region(element, tag: 'Check a region by element', match_timeout: 3, stitch_content: false)
436
- # @example Check region by css selector
437
- # check_region(:css, '.form-row .input#e_mail', tag: 'Check a region by element', match_timeout: 3,
438
- # stitch_content: false)
439
- # @!parse def check_region(element, how=nil, what=nil, options = {}); end
440
- def check_region(*args)
441
- options = { timeout: USE_DEFAULT_MATCH_TIMEOUT, tag: nil }.merge! Applitools::Utils.extract_options!(args)
442
- target = Applitools::Selenium::Target.new.region(*args).timeout(options[:match_timeout])
443
- target.fully if options[:stitch_content]
444
- check(options[:tag], target)
445
- end
446
-
447
- # Validates the contents of an iframe and matches it with the expected output.
448
- #
449
- # @param [Hash] options The specific parameters of the desired screenshot.
450
- # @option options [Fixnum] :timeout The amount of time to retry matching. (Seconds)
451
- # @option options [String] :tag An optional tag to be associated with the snapshot.
452
- # @option options [String] :frame Frame element or frame name or frame id.
453
- # @option options [String] :name_or_id The name or id of the target frame (deprecated. use :frame instead).
454
- # @option options [String] :frame_element The frame element (deprecated. use :frame instead).
455
- # @return [Applitools::MatchResult] The match results.
456
-
457
- def check_frame(options = {})
458
- options = { timeout: USE_DEFAULT_MATCH_TIMEOUT, tag: nil }.merge!(options)
459
- frame = options[:frame] || options[:frame_element] || options[:name_or_id]
460
- target = Applitools::Selenium::Target.frame(frame).timeout(options[:timeout]).fully
461
- check(options[:tag], target)
462
- end
463
-
464
- # Validates the contents of a region in an iframe and matches it with the expected output.
465
- #
466
- # @param [Hash] options The specific parameters of the desired screenshot.
467
- # @option options [String] :name_or_id The name or id of the target frame (deprecated. use :frame instead).
468
- # @option options [String] :frame_element The frame element (deprecated. use :frame instead).
469
- # @option options [String] :frame Frame element or frame name or frame id.
470
- # @option options [String] :tag An optional tag to be associated with the snapshot.
471
- # @option options [Symbol] :by By which identifier to find the region (e.g :css, :id).
472
- # @option options [Fixnum] :timeout The amount of time to retry matching. (Seconds)
473
- # @option options [Boolean] :stitch_content Whether to stitch the content or not.
474
- # @return [Applitools::MatchResult] The match results.
475
- def check_region_in_frame(options = {})
476
- options = { timeout: USE_DEFAULT_MATCH_TIMEOUT, tag: nil, stitch_content: false }.merge!(options)
477
- Applitools::ArgumentGuard.not_nil options[:by], 'options[:by]'
478
- Applitools::ArgumentGuard.is_a? options[:by], 'options[:by]', Array
479
-
480
- how_what = options.delete(:by)
481
- frame = options[:frame] || options[:frame_element] || options[:name_or_id]
482
-
483
- target = Applitools::Selenium::Target.new.timeout(options[:timeout])
484
- target.frame(frame) if frame
485
- target.fully if options[:stitch_content]
486
- target.region(*how_what)
487
-
488
- check(options[:tag], target)
489
- end
490
-
491
- # Use this method to perform seamless testing with selenium through eyes driver.
492
- # It yields a block and passes to it an Applitools::Selenium::Driver instance, which wraps standard driver.
493
- # Using Selenium methods inside the 'test' block will send the messages to Selenium
494
- # after creating the Eyes triggers for them. Options are similar to {open}
495
- # @yieldparam driver [Applitools::Selenium::Driver] Gives a driver to a block, which translates calls to a native
496
- # Selemium::Driver instance
497
- # @example
498
- # eyes.test(app_name: 'my app', test_name: 'my test') do |driver|
499
- # driver.get "http://www.google.com"
500
- # driver.check_window("initial")
501
- # end
502
- def test(options = {}, &_block)
503
- open(options)
504
- yield(driver)
505
- close
506
- ensure
507
- abort_if_not_closed
508
- end
509
-
510
351
  # @!visibility private
511
352
  def scroll_to_region
512
353
  region_visibility_strategy.is_a? Applitools::Selenium::MoveToRegionVisibilityStrategy
@@ -531,17 +372,21 @@ module Applitools::Selenium
531
372
  end
532
373
  end
533
374
 
375
+ def close_async
376
+ close(false)
377
+ end
378
+
534
379
  private
535
380
 
536
381
  attr_accessor :check_frame_or_element, :region_to_check, :dont_get_title,
537
- :device_pixel_ratio, :position_provider, :scale_provider, :tag_for_debug,
538
- :region_visibility_strategy, :eyes_screenshot_factory, :force_driver_resolution_as_viewport_size,
539
- :prevent_dom_processing
382
+ :device_pixel_ratio, :position_provider, :scale_provider, :tag_for_debug,
383
+ :region_visibility_strategy, :eyes_screenshot_factory, :force_driver_resolution_as_viewport_size,
384
+ :prevent_dom_processing
540
385
 
541
386
  def image_provider
542
387
  Applitools::Selenium::TakesScreenshotImageProvider.new(
543
- driver,
544
- debug_screenshot_provider: debug_screenshot_provider
388
+ driver,
389
+ debug_screenshot_provider: debug_screenshot_provider
545
390
  )
546
391
  end
547
392
 
@@ -561,7 +406,7 @@ module Applitools::Selenium
561
406
 
562
407
  begin
563
408
  algo = Applitools::Selenium::FullPageCaptureAlgorithm.new(
564
- debug_screenshot_provider: debug_screenshot_provider
409
+ debug_screenshot_provider: debug_screenshot_provider
565
410
  )
566
411
  case screenshot_type
567
412
  when ENTIRE_ELEMENT_SCREENSHOT
@@ -587,15 +432,15 @@ module Applitools::Selenium
587
432
  region_provider = Applitools::Selenium::RegionProvider.new(driver, Applitools::Region::EMPTY)
588
433
 
589
434
  full_page_image = algo.get_stitched_region(
590
- image_provider: image_provider,
591
- region_to_check: region_provider,
592
- origin_provider: Applitools::Selenium::ScrollPositionProvider.new(driver),
593
- position_provider: position_provider,
594
- scale_provider: scale_provider,
595
- cut_provider: cut_provider,
596
- wait_before_screenshots: wait_before_screenshots,
597
- eyes_screenshot_factory: eyes_screenshot_factory,
598
- stitching_overlap: stitching_overlap
435
+ image_provider: image_provider,
436
+ region_to_check: region_provider,
437
+ origin_provider: Applitools::Selenium::ScrollPositionProvider.new(driver),
438
+ position_provider: position_provider,
439
+ scale_provider: scale_provider,
440
+ cut_provider: cut_provider,
441
+ wait_before_screenshots: wait_before_screenshots,
442
+ eyes_screenshot_factory: eyes_screenshot_factory,
443
+ stitching_overlap: stitching_overlap
599
444
  )
600
445
 
601
446
  # binding.pry
@@ -606,8 +451,8 @@ module Applitools::Selenium
606
451
  end
607
452
  logger.info 'Creating EyesWebDriver screenshot instance..'
608
453
  result = Applitools::Selenium::FullpageScreenshot.new(
609
- full_page_image,
610
- region_provider: region_to_check
454
+ full_page_image,
455
+ region_provider: region_to_check
611
456
  )
612
457
  logger.info 'Done creating EyesWebDriver screenshot instance!'
613
458
  result
@@ -616,22 +461,22 @@ module Applitools::Selenium
616
461
  def entire_element_screenshot(algo)
617
462
  logger.info 'Entire element screenshot requested'
618
463
  entire_frame_or_element = algo.get_stitched_region(
619
- image_provider: image_provider,
620
- region_to_check: region_to_check,
621
- origin_provider: position_provider,
622
- position_provider: position_provider,
623
- scale_provider: scale_provider,
624
- cut_provider: cut_provider,
625
- wait_before_screenshots: wait_before_screenshots,
626
- eyes_screenshot_factory: eyes_screenshot_factory,
627
- stitching_overlap: stitching_overlap,
628
- top_left_position: full_page_capture_algorithm_left_top_offset
464
+ image_provider: image_provider,
465
+ region_to_check: region_to_check,
466
+ origin_provider: position_provider,
467
+ position_provider: position_provider,
468
+ scale_provider: scale_provider,
469
+ cut_provider: cut_provider,
470
+ wait_before_screenshots: wait_before_screenshots,
471
+ eyes_screenshot_factory: eyes_screenshot_factory,
472
+ stitching_overlap: stitching_overlap,
473
+ top_left_position: full_page_capture_algorithm_left_top_offset
629
474
  )
630
475
 
631
476
  logger.info 'Building screenshot object (EyesStitchedElementScreenshot)...'
632
477
  result = Applitools::Selenium::EntireElementScreenshot.new(
633
- entire_frame_or_element,
634
- region_provider: region_to_check
478
+ entire_frame_or_element,
479
+ region_provider: region_to_check
635
480
  )
636
481
  logger.info 'Done!'
637
482
  result
@@ -692,7 +537,7 @@ module Applitools::Selenium
692
537
 
693
538
  begin
694
539
  self.scale_provider = Applitools::Selenium::ContextBasedScaleProvider.new(position_provider.entire_size,
695
- viewport_size, device_pixel_ratio)
540
+ viewport_size, device_pixel_ratio)
696
541
  rescue StandardError
697
542
  logger.info 'Failed to set ContextBasedScaleProvider'
698
543
  logger.info 'Using FixedScaleProvider instead'
@@ -856,7 +701,7 @@ module Applitools::Selenium
856
701
 
857
702
  class << self
858
703
  def position_provider(stitch_mode, driver, disable_horizontal = false, disable_vertical = false,
859
- explicit_entire_size = nil)
704
+ explicit_entire_size = nil)
860
705
 
861
706
  max_width = nil
862
707
  max_height = nil
@@ -867,10 +712,10 @@ module Applitools::Selenium
867
712
  case stitch_mode
868
713
  when Applitools::Selenium::StitchModes::SCROLL
869
714
  Applitools::Selenium::ScrollPositionProvider.new(driver, disable_horizontal, disable_vertical,
870
- max_width, max_height)
715
+ max_width, max_height)
871
716
  when Applitools::Selenium::StitchModes::CSS
872
717
  Applitools::Selenium::CssTranslatePositionProvider.new(driver, disable_horizontal, disable_vertical,
873
- max_width, max_height)
718
+ max_width, max_height)
874
719
  end
875
720
  end
876
721
  end