eyes_selenium 3.15.26 → 3.15.27

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d296beb9d397fda23bb4559c1bbbe0dcc62a8a517a41340048588fbdf6c911df
4
- data.tar.gz: 5d6a5b7b4d6cdd32e9a51ebd36929bc57923f64402ec64bfea8e43d349106c8f
3
+ metadata.gz: 2af28e148f60211bf2c09ac96275d229be3ab6af88f5855e9f0e302ea51d10b9
4
+ data.tar.gz: 71e12dbc9d0b9409011d77e9b444c7be1206243c3c936acfe59cbabdff421c09
5
5
  SHA512:
6
- metadata.gz: a3c793ece4f587ee303af163e6aba396e49f6a9021cb045e6e67281c3ff9a8f5cf41e473d87f0dd3e89c4aaf778ace87ca54bf5c7167ea0263e58e9e89b646ed
7
- data.tar.gz: 9fef8d433b59ecbd31557be05592a7edb41d6ddec641fbc5ea63e81b52642a12c7ffe98fdd48353278a2d33dd716b8034ae8a8af0f8d9427a6ff5e5214c1d582
6
+ metadata.gz: e41c8a4d0be46ce3f407aed3d846bf70c8513179420d0f0c25cc633aa89c1af85e11896e010eab98d8d305d6a5e4f9cdd5c926e32201ebd78f02c9778ddddd4c
7
+ data.tar.gz: 25c70ecb50a750956bd32aa0d02e3ac014b87fd869f598d0dea7c2f3b2497e7189d8fc9e18c29059481d3483b6cc47af7f431fedfc71dc7c341987ac0d560340
@@ -2,7 +2,8 @@ module Applitools
2
2
  module Selenium
3
3
  module Scripts
4
4
  PROCESS_PAGE_AND_POLL = <<'END'
5
- // @applitools/dom-snapshot@1.2.4
5
+ /* @applitools/dom-snapshot@1.4.6 */
6
+
6
7
  function __processPageAndPoll() {
7
8
  var processPageAndPoll = (function () {
8
9
  'use strict';
@@ -60,7 +61,7 @@ function __processPageAndPoll() {
60
61
  var arrayBufferToBase64_1 = arrayBufferToBase64;
61
62
 
62
63
  function extractLinks(doc = document) {
63
- const srcsetUrls = [...doc.querySelectorAll('img[srcset],source[srcset]')]
64
+ const srcsetUrls = Array.from(doc.querySelectorAll('img[srcset],source[srcset]'))
64
65
  .map(srcsetEl =>
65
66
  srcsetEl
66
67
  .getAttribute('srcset')
@@ -69,188 +70,228 @@ function __processPageAndPoll() {
69
70
  )
70
71
  .reduce((acc, urls) => acc.concat(urls), []);
71
72
 
72
- const srcUrls = [...doc.querySelectorAll('img[src],source[src]')].map(srcEl =>
73
+ const srcUrls = Array.from(doc.querySelectorAll('img[src],source[src]')).map(srcEl =>
73
74
  srcEl.getAttribute('src'),
74
75
  );
75
76
 
76
- const hrefUrls = [...doc.querySelectorAll('image')]
77
+ const imageUrls = Array.from(doc.querySelectorAll('image,use'))
77
78
  .map(hrefEl => hrefEl.getAttribute('href') || hrefEl.getAttribute('xlink:href'))
79
+ .filter(u => u && u[0] !== '#');
80
+
81
+ const objectUrls = Array.from(doc.querySelectorAll('object'))
82
+ .map(el => el.getAttribute('data'))
78
83
  .filter(Boolean);
79
84
 
80
- const cssUrls = [...doc.querySelectorAll('link[rel="stylesheet"]')].map(link =>
85
+ const cssUrls = Array.from(doc.querySelectorAll('link[rel="stylesheet"]')).map(link =>
81
86
  link.getAttribute('href'),
82
87
  );
83
88
 
84
- const videoPosterUrls = [...doc.querySelectorAll('video[poster]')].map(videoEl =>
89
+ const videoPosterUrls = Array.from(doc.querySelectorAll('video[poster]')).map(videoEl =>
85
90
  videoEl.getAttribute('poster'),
86
91
  );
87
92
 
88
- return [...srcsetUrls, ...srcUrls, ...hrefUrls, ...cssUrls, ...videoPosterUrls];
93
+ return Array.from(srcsetUrls)
94
+ .concat(Array.from(srcUrls))
95
+ .concat(Array.from(imageUrls))
96
+ .concat(Array.from(cssUrls))
97
+ .concat(Array.from(videoPosterUrls))
98
+ .concat(Array.from(objectUrls));
89
99
  }
90
100
 
91
101
  var extractLinks_1 = extractLinks;
92
102
 
93
- /* eslint-disable no-use-before-define */
103
+ function absolutizeUrl(url, absoluteUrl) {
104
+ return new URL(url, absoluteUrl).href;
105
+ }
106
+
107
+ var absolutizeUrl_1 = absolutizeUrl;
94
108
 
95
- function domNodesToCdt(docNode) {
96
- const NODE_TYPES = {
97
- ELEMENT: 1,
98
- TEXT: 3,
99
- DOCUMENT: 9,
100
- DOCUMENT_TYPE: 10,
101
- DOCUMENT_FRAGMENT_NODE: 11,
102
- };
109
+ function uuid() {
110
+ return window.crypto.getRandomValues(new Uint32Array(1))[0];
111
+ }
112
+
113
+ var uuid_1 = uuid;
103
114
 
104
- const domNodes = [
105
- {
106
- nodeType: NODE_TYPES.DOCUMENT,
107
- },
108
- ];
109
- domNodes[0].childNodeIndexes = childrenFactory(domNodes, docNode.childNodes);
110
- return domNodes;
115
+ function isInlineFrame(frame) {
116
+ return (
117
+ frame && frame.contentDocument && !/^https?:$/.test(frame.contentDocument.location.protocol)
118
+ );
119
+ }
120
+
121
+ var isInlineFrame_1 = isInlineFrame;
122
+
123
+ function domNodesToCdt(docNode, url) {
124
+ const cdt = [{nodeType: Node.DOCUMENT_NODE}];
125
+ const docRoots = [docNode];
126
+ const canvasElements = [];
127
+ const inlineFrames = [];
128
+
129
+ cdt[0].childNodeIndexes = childrenFactory(cdt, docNode.childNodes);
130
+ return {cdt, docRoots, canvasElements, inlineFrames};
111
131
 
112
- function childrenFactory(domNodes, elementNodes) {
132
+ function childrenFactory(cdt, elementNodes) {
113
133
  if (!elementNodes || elementNodes.length === 0) return null;
114
134
 
115
135
  const childIndexes = [];
116
- elementNodes.forEach(elementNode => {
117
- const index = elementNodeFactory(domNodes, elementNode);
136
+ Array.prototype.forEach.call(elementNodes, elementNode => {
137
+ const index = elementNodeFactory(cdt, elementNode);
118
138
  if (index !== null) {
119
139
  childIndexes.push(index);
120
140
  }
121
141
  });
122
-
123
142
  return childIndexes;
124
143
  }
125
144
 
126
- function elementNodeFactory(domNodes, elementNode) {
145
+ function elementNodeFactory(cdt, elementNode) {
127
146
  let node, manualChildNodeIndexes;
128
147
  const {nodeType} = elementNode;
129
- if ([NODE_TYPES.ELEMENT, NODE_TYPES.DOCUMENT_FRAGMENT_NODE].includes(nodeType)) {
148
+ let dummyUrl, frameBase;
149
+
150
+ if ([Node.ELEMENT_NODE, Node.DOCUMENT_FRAGMENT_NODE].includes(nodeType)) {
130
151
  if (elementNode.nodeName !== 'SCRIPT') {
131
152
  if (
132
153
  elementNode.nodeName === 'STYLE' &&
133
154
  elementNode.sheet &&
134
155
  elementNode.sheet.cssRules.length
135
156
  ) {
136
- domNodes.push({
137
- nodeType: NODE_TYPES.TEXT,
138
- nodeValue: [...elementNode.sheet.cssRules].map(rule => rule.cssText).join(''),
139
- });
140
- manualChildNodeIndexes = [domNodes.length - 1];
157
+ cdt.push(getCssRulesNode(elementNode));
158
+ manualChildNodeIndexes = [cdt.length - 1];
141
159
  }
142
160
 
143
- node = {
144
- nodeType: nodeType,
145
- nodeName: elementNode.nodeName,
146
- attributes: nodeAttributes(elementNode).map(key => {
147
- let value = elementNode.attributes[key].value;
148
- const name = elementNode.attributes[key].localName;
149
-
150
- if (/^blob:/.test(value)) {
151
- value = value.replace(/^blob:/, '');
152
- } else if (
153
- elementNode.nodeName === 'IFRAME' &&
154
- name === 'src' &&
155
- !elementNode.contentDocument &&
156
- !value.match(/^\s*data:/)
157
- ) {
158
- value = '';
159
- }
160
- return {
161
- name,
162
- value,
163
- };
164
- }),
165
- childNodeIndexes:
166
- manualChildNodeIndexes ||
167
- (elementNode.childNodes.length
168
- ? childrenFactory(domNodes, elementNode.childNodes)
169
- : []),
170
- };
161
+ node = getBasicNode(elementNode);
162
+ node.childNodeIndexes =
163
+ manualChildNodeIndexes ||
164
+ (elementNode.childNodes.length ? childrenFactory(cdt, elementNode.childNodes) : []);
171
165
 
172
166
  if (elementNode.shadowRoot) {
173
- node.shadowRootIndex = elementNodeFactory(domNodes, elementNode.shadowRoot);
167
+ node.shadowRootIndex = elementNodeFactory(cdt, elementNode.shadowRoot);
168
+ docRoots.push(elementNode.shadowRoot);
174
169
  }
175
170
 
176
- if (elementNode.checked && !elementNode.attributes.checked) {
177
- node.attributes.push({name: 'checked', value: 'checked'});
171
+ if (elementNode.nodeName === 'CANVAS') {
172
+ dummyUrl = absolutizeUrl_1(`applitools-canvas-${uuid_1()}.png`, url);
173
+ node.attributes.push({name: 'data-applitools-src', value: dummyUrl});
174
+ canvasElements.push({element: elementNode, url: dummyUrl});
178
175
  }
179
- if (
180
- elementNode.value !== undefined &&
181
- elementNode.attributes.value === undefined &&
182
- elementNode.tagName === 'INPUT'
183
- ) {
184
- node.attributes.push({name: 'value', value: elementNode.value});
176
+
177
+ if (elementNode.nodeName === 'IFRAME' && isInlineFrame_1(elementNode)) {
178
+ frameBase = getFrameBaseUrl(elementNode);
179
+ dummyUrl = absolutizeUrl_1(`?applitools-iframe=${uuid_1()}`, frameBase || url);
180
+ node.attributes.push({name: 'data-applitools-src', value: dummyUrl});
181
+ inlineFrames.push({element: elementNode, url: dummyUrl});
185
182
  }
186
183
  } else {
187
- node = {
188
- nodeType: NODE_TYPES.ELEMENT,
189
- nodeName: 'SCRIPT',
190
- attributes: nodeAttributes(elementNode)
191
- .map(key => ({
192
- name: elementNode.attributes[key].localName,
193
- value: elementNode.attributes[key].value,
194
- }))
195
- .filter(attr => attr.name !== 'src'),
196
- childNodeIndexes: [],
197
- };
184
+ node = getScriptNode(elementNode);
198
185
  }
199
- } else if (nodeType === NODE_TYPES.TEXT) {
200
- node = {
201
- nodeType: NODE_TYPES.TEXT,
202
- nodeValue: elementNode.nodeValue,
203
- };
204
- } else if (nodeType === NODE_TYPES.DOCUMENT_TYPE) {
205
- node = {
206
- nodeType: NODE_TYPES.DOCUMENT_TYPE,
207
- nodeName: elementNode.nodeName,
208
- };
186
+ } else if (nodeType === Node.TEXT_NODE) {
187
+ node = getTextNode(elementNode);
188
+ } else if (nodeType === Node.DOCUMENT_TYPE_NODE) {
189
+ node = getDocNode(elementNode);
209
190
  }
210
191
 
211
192
  if (node) {
212
- domNodes.push(node);
213
- return domNodes.length - 1;
193
+ cdt.push(node);
194
+ return cdt.length - 1;
214
195
  } else {
215
- // console.log(`Unknown nodeType: ${nodeType}`);
216
196
  return null;
217
197
  }
198
+ }
218
199
 
219
- function nodeAttributes({attributes = {}}) {
220
- return Object.keys(attributes).filter(k => attributes[k].localName);
221
- }
200
+ function nodeAttributes({attributes = {}}) {
201
+ return Object.keys(attributes).filter(k => attributes[k] && attributes[k].name);
222
202
  }
223
- }
224
203
 
225
- var domNodesToCdt_1 = domNodesToCdt;
226
- var NODE_TYPES = {
227
- ELEMENT: 1,
228
- TEXT: 3,
229
- DOCUMENT: 9,
230
- DOCUMENT_TYPE: 10,
231
- };
232
- domNodesToCdt_1.NODE_TYPES = NODE_TYPES;
233
-
234
- function extractFrames(doc = document) {
235
- return [...doc.querySelectorAll('iframe[src]:not([src=""])')]
236
- .map(srcEl => {
237
- try {
238
- const contentDoc = srcEl.contentDocument;
239
- return (
240
- contentDoc &&
241
- /^https?:$/.test(contentDoc.location.protocol) &&
242
- contentDoc.defaultView &&
243
- contentDoc.defaultView.frameElement &&
244
- contentDoc
245
- );
246
- } catch (err) {
247
- //for CORS frames
204
+ function getCssRulesNode(elementNode) {
205
+ return {
206
+ nodeType: Node.TEXT_NODE,
207
+ nodeValue: Array.from(elementNode.sheet.cssRules)
208
+ .map(rule => rule.cssText)
209
+ .join(''),
210
+ };
211
+ }
212
+
213
+ function getBasicNode(elementNode) {
214
+ const node = {
215
+ nodeType: elementNode.nodeType,
216
+ nodeName: elementNode.nodeName,
217
+ attributes: nodeAttributes(elementNode).map(key => {
218
+ let value = elementNode.attributes[key].value;
219
+ const name = elementNode.attributes[key].name;
220
+ if (/^blob:/.test(value)) {
221
+ value = value.replace(/^blob:/, '');
222
+ }
223
+ return {
224
+ name,
225
+ value,
226
+ };
227
+ }),
228
+ };
229
+
230
+ if (elementNode.tagName === 'INPUT' && ['checkbox', 'radio'].includes(elementNode.type)) {
231
+ if (elementNode.attributes.checked && !elementNode.checked) {
232
+ const idx = node.attributes.findIndex(a => a.name === 'checked');
233
+ node.attributes.splice(idx, 1);
234
+ }
235
+ if (!elementNode.attributes.checked && elementNode.checked) {
236
+ node.attributes.push({name: 'checked'});
248
237
  }
249
- })
250
- .filter(x => !!x);
238
+ }
239
+
240
+ if (
241
+ elementNode.tagName === 'INPUT' &&
242
+ elementNode.type === 'text' &&
243
+ (elementNode.attributes.value && elementNode.attributes.value.value) !== elementNode.value
244
+ ) {
245
+ const nodeAttr = node.attributes.find(a => a.name === 'value');
246
+ if (nodeAttr) {
247
+ nodeAttr.value = elementNode.value;
248
+ } else {
249
+ node.attributes.push({name: 'value', value: elementNode.value});
250
+ }
251
+ }
252
+ return node;
253
+ }
254
+
255
+ function getScriptNode(elementNode) {
256
+ return {
257
+ nodeType: Node.ELEMENT_NODE,
258
+ nodeName: 'SCRIPT',
259
+ attributes: nodeAttributes(elementNode)
260
+ .map(key => ({
261
+ name: elementNode.attributes[key].name,
262
+ value: elementNode.attributes[key].value,
263
+ }))
264
+ .filter(attr => attr.name !== 'src'),
265
+ childNodeIndexes: [],
266
+ };
267
+ }
268
+
269
+ function getTextNode(elementNode) {
270
+ return {
271
+ nodeType: Node.TEXT_NODE,
272
+ nodeValue: elementNode.nodeValue,
273
+ };
274
+ }
275
+
276
+ function getDocNode(elementNode) {
277
+ return {
278
+ nodeType: Node.DOCUMENT_TYPE_NODE,
279
+ nodeName: elementNode.nodeName,
280
+ };
281
+ }
282
+
283
+ function getFrameBaseUrl(frameElement) {
284
+ const href =
285
+ frameElement.contentDocument.querySelectorAll('base') &&
286
+ frameElement.contentDocument.querySelectorAll('base')[0] &&
287
+ frameElement.contentDocument.querySelectorAll('base')[0].href;
288
+ if (href && !href.includes('about:blank')) {
289
+ return href;
290
+ }
291
+ }
251
292
  }
252
293
 
253
- var extractFrames_1 = extractFrames;
294
+ var domNodesToCdt_1 = domNodesToCdt;
254
295
 
255
296
  function uniq(arr) {
256
297
  const result = [];
@@ -273,9 +314,9 @@ function __processPageAndPoll() {
273
314
  var aggregateResourceUrlsAndBlobs_1 = aggregateResourceUrlsAndBlobs;
274
315
 
275
316
  function makeGetResourceUrlsAndBlobs({processResource, aggregateResourceUrlsAndBlobs}) {
276
- return function getResourceUrlsAndBlobs(doc, baseUrl, urls) {
317
+ return function getResourceUrlsAndBlobs(documents, baseUrl, urls) {
277
318
  return Promise.all(
278
- urls.map(url => processResource(url, doc, baseUrl, getResourceUrlsAndBlobs.bind(null, doc))),
319
+ urls.map(url => processResource(url, documents, baseUrl, getResourceUrlsAndBlobs)),
279
320
  ).then(resourceUrlsAndBlobsArr => aggregateResourceUrlsAndBlobs(resourceUrlsAndBlobsArr));
280
321
  };
281
322
  }
@@ -288,26 +329,74 @@ function __processPageAndPoll() {
288
329
 
289
330
  var filterInlineUrl_1 = filterInlineUrl;
290
331
 
291
- function absolutizeUrl(url, absoluteUrl) {
292
- return new URL(url, absoluteUrl).href;
332
+ function toUnAnchoredUri(url) {
333
+ const m = url && url.match(/(^[^#]*)/);
334
+ const res = (m && m[1]) || url;
335
+ return (res && res.replace(/\?\s*$/, '')) || url;
293
336
  }
294
337
 
295
- var absolutizeUrl_1 = absolutizeUrl;
338
+ var toUnAnchoredUri_1 = toUnAnchoredUri;
339
+
340
+ function createTempStylsheet(cssContent) {
341
+ if (!cssContent) {
342
+ console.log('[dom-snapshot] error createTempStylsheet called without cssContent');
343
+ return;
344
+ }
345
+ const head = document.head || document.querySelectorAll('head')[0];
346
+ const style = document.createElement('style');
347
+ style.type = 'text/css';
348
+ style.setAttribute('data-desc', 'Applitools tmp variable created by DOM SNAPSHOT');
349
+ head.appendChild(style);
350
+
351
+ // This is required for IE8 and below.
352
+ if (style.styleSheet) {
353
+ style.styleSheet.cssText = cssContent;
354
+ } else {
355
+ style.appendChild(document.createTextNode(cssContent));
356
+ }
357
+ return style.sheet;
358
+ }
359
+
360
+ var createTempStyleSheet = createTempStylsheet;
361
+
362
+ function makeExtractResourcesFromStyle({extractResourcesFromStyleSheet}) {
363
+ return function extractResourcesFromStyle(styleSheet, cssContent, doc = document) {
364
+ let corsFreeStyleSheet;
365
+ try {
366
+ styleSheet.cssRules;
367
+ corsFreeStyleSheet = styleSheet;
368
+ } catch (e) {
369
+ console.log(
370
+ `[dom-snapshot] could not access cssRules for ${styleSheet.href} ${e}\ncreating temp style for access.`,
371
+ );
372
+ corsFreeStyleSheet = createTempStyleSheet(cssContent);
373
+ }
374
+
375
+ const result = extractResourcesFromStyleSheet(corsFreeStyleSheet, doc);
376
+ if (corsFreeStyleSheet !== styleSheet) {
377
+ corsFreeStyleSheet.ownerNode.parentNode.removeChild(corsFreeStyleSheet.ownerNode);
378
+ }
379
+ return result;
380
+ };
381
+ }
382
+
383
+ var extractResourcesFromStyle = makeExtractResourcesFromStyle;
296
384
 
297
385
  function makeProcessResource({
298
386
  fetchUrl,
299
387
  findStyleSheetByUrl,
300
388
  extractResourcesFromStyleSheet,
301
- isSameOrigin,
389
+ extractResourcesFromSvg,
302
390
  cache = {},
303
391
  }) {
304
- return function processResource(absoluteUrl, doc, baseUrl, getResourceUrlsAndBlobs) {
392
+ const extractResourcesFromStyle$$1 = extractResourcesFromStyle({extractResourcesFromStyleSheet});
393
+ return function processResource(absoluteUrl, documents, baseUrl, getResourceUrlsAndBlobs) {
305
394
  return cache[absoluteUrl] || (cache[absoluteUrl] = doProcessResource(absoluteUrl));
306
395
 
307
396
  function doProcessResource(url) {
308
397
  return fetchUrl(url)
309
398
  .catch(e => {
310
- if (probablyCORS(e, url)) {
399
+ if (probablyCORS(e)) {
311
400
  return {probablyCORS: true, url};
312
401
  } else {
313
402
  throw e;
@@ -317,24 +406,35 @@ function __processPageAndPoll() {
317
406
  if (probablyCORS) {
318
407
  return {resourceUrls: [url]};
319
408
  }
320
- const result = {blobsObj: {[url]: {type, value}}};
409
+
410
+ let resourceUrls;
411
+ let result = {blobsObj: {[url]: {type, value}}};
321
412
  if (/text\/css/.test(type)) {
322
- const styleSheet = findStyleSheetByUrl(url, doc);
323
- if (!styleSheet) {
324
- return result;
413
+ const styleSheet = findStyleSheetByUrl(url, documents);
414
+ if (styleSheet) {
415
+ resourceUrls = extractResourcesFromStyle$$1(styleSheet, value, documents[0]);
416
+ }
417
+ } else if (/image\/svg/.test(type)) {
418
+ try {
419
+ resourceUrls = extractResourcesFromSvg(value);
420
+ } catch (e) {
421
+ console.log('could not parse svg content', e);
325
422
  }
326
- const resourceUrls = extractResourcesFromStyleSheet(styleSheet, doc.defaultView)
423
+ }
424
+
425
+ if (resourceUrls) {
426
+ resourceUrls = resourceUrls
427
+ .map(toUnAnchoredUri_1)
327
428
  .map(resourceUrl => absolutizeUrl_1(resourceUrl, url.replace(/^blob:/, '')))
328
429
  .filter(filterInlineUrl_1);
329
- return getResourceUrlsAndBlobs(baseUrl, resourceUrls).then(
430
+ result = getResourceUrlsAndBlobs(documents, baseUrl, resourceUrls).then(
330
431
  ({resourceUrls, blobsObj}) => ({
331
432
  resourceUrls,
332
433
  blobsObj: Object.assign(blobsObj, {[url]: {type, value}}),
333
434
  }),
334
435
  );
335
- } else {
336
- return result;
337
436
  }
437
+ return result;
338
438
  })
339
439
  .catch(err => {
340
440
  console.log('[dom-snapshot] error while fetching', url, err);
@@ -342,62 +442,114 @@ function __processPageAndPoll() {
342
442
  });
343
443
  }
344
444
 
345
- function probablyCORS(err, url) {
346
- const msgCORS = err.message && err.message.includes('Failed to fetch');
445
+ function probablyCORS(err) {
446
+ const msgCORS =
447
+ err.message &&
448
+ (err.message.includes('Failed to fetch') || err.message.includes('Network request failed'));
347
449
  const nameCORS = err.name && err.name.includes('TypeError');
348
- return msgCORS && nameCORS && !isSameOrigin(url, baseUrl);
450
+ return msgCORS && nameCORS;
349
451
  }
350
452
  };
351
453
  }
352
454
 
353
455
  var processResource = makeProcessResource;
354
456
 
457
+ function getUrlFromCssText(cssText) {
458
+ const re = /url\((?!['"]?:)['"]?([^'")]*)['"]?\)/g;
459
+ const ret = [];
460
+ let result;
461
+ while ((result = re.exec(cssText)) !== null) {
462
+ ret.push(result[1]);
463
+ }
464
+ return ret;
465
+ }
466
+
467
+ var getUrlFromCssText_1 = getUrlFromCssText;
468
+
469
+ function flat(arr) {
470
+ return [].concat(...arr);
471
+ }
472
+
473
+ var flat_1 = flat;
474
+
475
+ function makeExtractResourcesFromSvg({parser, decoder, extractResourceUrlsFromStyleTags}) {
476
+ return function(svgArrayBuffer) {
477
+ const decooder = decoder || new TextDecoder('utf-8');
478
+ const svgStr = decooder.decode(svgArrayBuffer);
479
+ const domparser = parser || new DOMParser();
480
+ const doc = domparser.parseFromString(svgStr, 'image/svg+xml');
481
+
482
+ const fromImages = Array.from(doc.getElementsByTagName('image'))
483
+ .concat(Array.from(doc.getElementsByTagName('use')))
484
+ .map(e => e.getAttribute('href') || e.getAttribute('xlink:href'));
485
+ const fromObjects = Array.from(doc.getElementsByTagName('object')).map(e =>
486
+ e.getAttribute('data'),
487
+ );
488
+ const fromStyleTags = extractResourceUrlsFromStyleTags(doc, false);
489
+ const fromStyleAttrs = urlsFromStyleAttrOfDoc(doc);
490
+
491
+ return fromImages
492
+ .concat(fromObjects)
493
+ .concat(fromStyleTags)
494
+ .concat(fromStyleAttrs)
495
+ .filter(u => u[0] !== '#');
496
+ };
497
+ }
498
+
499
+ function urlsFromStyleAttrOfDoc(doc) {
500
+ return flat_1(
501
+ Array.from(doc.querySelectorAll('*[style]'))
502
+ .map(e => e.style.cssText)
503
+ .map(getUrlFromCssText_1)
504
+ .filter(Boolean),
505
+ );
506
+ }
507
+
508
+ var makeExtractResourcesFromSvg_1 = makeExtractResourcesFromSvg;
509
+
355
510
  /* global window */
356
511
 
357
512
  function fetchUrl(url, fetch = window.fetch) {
358
513
  return fetch(url, {cache: 'force-cache', credentials: 'same-origin'}).then(resp =>
359
- resp.arrayBuffer().then(buff => ({
360
- url,
361
- type: resp.headers.get('Content-Type'),
362
- value: buff,
363
- })),
514
+ resp.status === 200
515
+ ? resp.arrayBuffer().then(buff => ({
516
+ url,
517
+ type: resp.headers.get('Content-Type'),
518
+ value: buff,
519
+ }))
520
+ : Promise.reject(`bad status code ${resp.status}`),
364
521
  );
365
522
  }
366
523
 
367
524
  var fetchUrl_1 = fetchUrl;
368
525
 
369
526
  function makeFindStyleSheetByUrl({styleSheetCache}) {
370
- return function findStyleSheetByUrl(url, doc) {
371
- return styleSheetCache[url] || [...doc.styleSheets].find(styleSheet => styleSheet.href === url);
527
+ return function findStyleSheetByUrl(url, documents) {
528
+ const allStylesheets = flat_1(documents.map(d => Array.from(d.styleSheets)));
529
+ return (
530
+ styleSheetCache[url] ||
531
+ allStylesheets.find(styleSheet => styleSheet.href && toUnAnchoredUri_1(styleSheet.href) === url)
532
+ );
372
533
  };
373
534
  }
374
535
 
375
536
  var findStyleSheetByUrl = makeFindStyleSheetByUrl;
376
537
 
377
- function getUrlFromCssText(cssText) {
378
- const re = /url\((?!['"]?:)['"]?([^'")]*)['"]?\)/g;
379
- const ret = [];
380
- let result;
381
- while ((result = re.exec(cssText)) !== null) {
382
- ret.push(result[1]);
383
- }
384
- return ret;
385
- }
386
-
387
- var getUrlFromCssText_1 = getUrlFromCssText;
388
-
389
- // NOTE this code is very similar to the node part of visual-grid-client, but there is a different related to the browser's cssom with import rules
390
538
  function makeExtractResourcesFromStyleSheet({styleSheetCache}) {
391
- return function extractResourcesFromStyleSheet(styleSheet, win = window) {
539
+ return function extractResourcesFromStyleSheet(styleSheet, doc) {
540
+ const win = doc.defaultView || (doc.ownerDocument && doc.ownerDocument.defaultView) || window;
392
541
  return uniq_1(
393
- [...(styleSheet.cssRules || [])].reduce((acc, rule) => {
542
+ Array.from(styleSheet.cssRules || []).reduce((acc, rule) => {
394
543
  if (rule instanceof win.CSSImportRule) {
395
544
  styleSheetCache[rule.styleSheet.href] = rule.styleSheet;
396
545
  return acc.concat(rule.href);
397
546
  } else if (rule instanceof win.CSSFontFaceRule) {
398
- return acc.concat(getUrlFromCssText_1(rule.style.getPropertyValue('src')));
399
- } else if (rule instanceof win.CSSSupportsRule || rule instanceof win.CSSMediaRule) {
400
- return acc.concat(extractResourcesFromStyleSheet(rule));
547
+ return acc.concat(getUrlFromCssText_1(rule.cssText));
548
+ } else if (
549
+ (win.CSSSupportsRule && rule instanceof win.CSSSupportsRule) ||
550
+ rule instanceof win.CSSMediaRule
551
+ ) {
552
+ return acc.concat(extractResourcesFromStyleSheet(rule, doc));
401
553
  } else if (rule instanceof win.CSSStyleRule) {
402
554
  for (let i = 0, ii = rule.style.length; i < ii; i++) {
403
555
  const urls = getUrlFromCssText_1(rule.style.getPropertyValue(rule.style[i]));
@@ -427,13 +579,15 @@ function __processPageAndPoll() {
427
579
  var extractResourceUrlsFromStyleAttrs_1 = extractResourceUrlsFromStyleAttrs;
428
580
 
429
581
  function makeExtractResourceUrlsFromStyleTags(extractResourcesFromStyleSheet) {
430
- return function extractResourceUrlsFromStyleTags(doc) {
582
+ return function extractResourceUrlsFromStyleTags(doc, onlyDocStylesheet = true) {
431
583
  return uniq_1(
432
- [...doc.getElementsByTagName('style')].reduce((resourceUrls, styleEl) => {
433
- const styleSheet = [...doc.styleSheets].find(
434
- styleSheet => styleSheet.ownerNode === styleEl,
435
- );
436
- return resourceUrls.concat(extractResourcesFromStyleSheet(styleSheet, doc.defaultView));
584
+ Array.from(doc.querySelectorAll('style')).reduce((resourceUrls, styleEl) => {
585
+ const styleSheet = onlyDocStylesheet
586
+ ? Array.from(doc.styleSheets).find(styleSheet => styleSheet.ownerNode === styleEl)
587
+ : styleEl.sheet;
588
+ return styleSheet
589
+ ? resourceUrls.concat(extractResourcesFromStyleSheet(styleSheet, doc))
590
+ : resourceUrls;
437
591
  }, []),
438
592
  );
439
593
  };
@@ -441,28 +595,90 @@ function __processPageAndPoll() {
441
595
 
442
596
  var extractResourceUrlsFromStyleTags = makeExtractResourceUrlsFromStyleTags;
443
597
 
444
- function isSameOrigin(url, baseUrl) {
445
- const blobOrData = /^(blob|data):/;
446
- if (blobOrData.test(url)) return true;
447
- if (blobOrData.test(baseUrl)) return false;
598
+ function base64ToArrayBuffer(base64) {
599
+ var binary_string = window.atob(base64);
600
+ var len = binary_string.length;
601
+ var bytes = new Uint8Array(len);
602
+ for (var i = 0; i < len; i++) {
603
+ bytes[i] = binary_string.charCodeAt(i);
604
+ }
605
+ return bytes.buffer;
606
+ }
607
+
608
+ var base64ToArrayBuffer_1 = base64ToArrayBuffer;
609
+
610
+ function buildCanvasBlobs(canvasElements) {
611
+ return canvasElements.map(({url, element}) => {
612
+ const data = element.toDataURL('image/png');
613
+ const value = base64ToArrayBuffer_1(data.split(',')[1]);
614
+ return {url, type: 'image/png', value};
615
+ });
616
+ }
617
+
618
+ var buildCanvasBlobs_1 = buildCanvasBlobs;
619
+
620
+ function extractFrames(documents = [document]) {
621
+ const iframes = flat_1(
622
+ documents.map(d => Array.from(d.querySelectorAll('iframe[src]:not([src=""])'))),
623
+ );
624
+ return iframes
625
+ .filter(f => isAccessibleFrame(f) && !isInlineFrame_1(f))
626
+ .map(f => f.contentDocument);
627
+ }
628
+
629
+ function isAccessibleFrame(frame) {
630
+ try {
631
+ const doc = frame.contentDocument;
632
+ return !!(doc && doc.defaultView && doc.defaultView.frameElement);
633
+ } catch (err) {
634
+ // for CORS frames
635
+ }
636
+ }
637
+
638
+ var extractFrames_1 = extractFrames;
639
+
640
+ const getBaesUrl = function(doc) {
641
+ const baseUrl = doc.querySelectorAll('base')[0] && doc.querySelectorAll('base')[0].href;
642
+ if (baseUrl) {
643
+ return baseUrl;
644
+ }
645
+ const frameElement = doc.defaultView && doc.defaultView.frameElement;
646
+ if (frameElement) {
647
+ return frameElement.src || getBaesUrl(frameElement.ownerDocument);
648
+ }
649
+ return doc.location.href;
650
+ };
651
+
652
+ var getBaseUrl = getBaesUrl;
448
653
 
449
- const {origin} = new URL(url, baseUrl);
450
- const {origin: baseOrigin} = new URL(baseUrl);
451
- return origin === baseOrigin;
654
+ function toUriEncoding(url) {
655
+ const result =
656
+ (url &&
657
+ url.replace(/(\\[0-9a-fA-F]{1,6}\s?)/g, s => {
658
+ const int = parseInt(s.substr(1).trim(), 16);
659
+ return String.fromCodePoint(int);
660
+ })) ||
661
+ url;
662
+ return result;
452
663
  }
453
664
 
454
- var isSameOrigin_1 = isSameOrigin;
665
+ var toUriEncoding_1 = toUriEncoding;
455
666
 
456
667
  function processPage(doc = document) {
457
668
  const styleSheetCache = {};
458
669
  const extractResourcesFromStyleSheet$$1 = extractResourcesFromStyleSheet({styleSheetCache});
459
670
  const findStyleSheetByUrl$$1 = findStyleSheetByUrl({styleSheetCache});
671
+ const extractResourceUrlsFromStyleTags$$1 = extractResourceUrlsFromStyleTags(
672
+ extractResourcesFromStyleSheet$$1,
673
+ );
674
+
675
+ const extractResourcesFromSvg = makeExtractResourcesFromSvg_1({extractResourceUrlsFromStyleTags: extractResourceUrlsFromStyleTags$$1});
460
676
  const processResource$$1 = processResource({
461
677
  fetchUrl: fetchUrl_1,
462
678
  findStyleSheetByUrl: findStyleSheetByUrl$$1,
463
679
  extractResourcesFromStyleSheet: extractResourcesFromStyleSheet$$1,
680
+ extractResourcesFromSvg,
464
681
  absolutizeUrl: absolutizeUrl_1,
465
- isSameOrigin: isSameOrigin_1,
466
682
  });
467
683
 
468
684
  const getResourceUrlsAndBlobs$$1 = getResourceUrlsAndBlobs({
@@ -470,52 +686,60 @@ function __processPageAndPoll() {
470
686
  aggregateResourceUrlsAndBlobs: aggregateResourceUrlsAndBlobs_1,
471
687
  });
472
688
 
473
- const extractResourceUrlsFromStyleTags$$1 = extractResourceUrlsFromStyleTags(
474
- extractResourcesFromStyleSheet$$1,
475
- );
476
-
477
689
  return doProcessPage(doc);
478
690
 
479
- function doProcessPage(doc) {
480
- const frameElement = doc.defaultView && doc.defaultView.frameElement;
481
- const url = frameElement ? frameElement.src : doc.location.href;
482
-
483
- const cdt = domNodesToCdt_1(doc);
691
+ function doProcessPage(doc, baesUrl = null) {
692
+ const url = baesUrl || getBaseUrl(doc);
693
+ const {cdt, docRoots, canvasElements, inlineFrames} = domNodesToCdt_1(doc, url);
484
694
 
695
+ const linkUrls = flat_1(docRoots.map(extractLinks_1));
696
+ const styleTagUrls = flat_1(docRoots.map(extractResourceUrlsFromStyleTags$$1));
697
+ const absolutizeThisUrl = getAbsolutizeByUrl(url);
485
698
  const links = uniq_1(
486
- extractLinks_1(doc)
487
- .concat(extractResourceUrlsFromStyleAttrs_1(cdt))
488
- .concat(extractResourceUrlsFromStyleTags$$1(doc)),
699
+ Array.from(linkUrls)
700
+ .concat(Array.from(styleTagUrls))
701
+ .concat(extractResourceUrlsFromStyleAttrs_1(cdt)),
489
702
  )
703
+ .map(toUnAnchoredUri_1)
704
+ .map(toUriEncoding_1)
490
705
  .map(absolutizeThisUrl)
491
706
  .filter(filterInlineUrlsIfExisting);
492
707
 
493
- const resourceUrlsAndBlobsPromise = getResourceUrlsAndBlobs$$1(doc, url, links);
494
-
495
- const frameDocs = extractFrames_1(doc);
496
- const processFramesPromise = frameDocs.map(doProcessPage);
708
+ const resourceUrlsAndBlobsPromise = getResourceUrlsAndBlobs$$1(docRoots, url, links);
709
+ const canvasBlobs = buildCanvasBlobs_1(canvasElements);
497
710
 
498
- return Promise.all([resourceUrlsAndBlobsPromise, ...processFramesPromise]).then(
499
- ([{resourceUrls, blobsObj}, ...framesResults]) => ({
500
- cdt,
501
- url,
502
- resourceUrls,
503
- blobs: blobsObjToArray(blobsObj),
504
- frames: framesResults,
505
- srcAttr: frameElement ? frameElement.getAttribute('src') : undefined,
506
- }),
711
+ const frameDocs = extractFrames_1(docRoots);
712
+ const processFramesPromise = frameDocs.map(f => doProcessPage(f, null));
713
+ const processInlineFramesPromise = inlineFrames.map(({element, url}) =>
714
+ doProcessPage(element.contentDocument, url),
507
715
  );
508
716
 
509
- function absolutizeThisUrl(someUrl) {
510
- try {
511
- return absolutizeUrl_1(someUrl, url);
512
- } catch (err) {
513
- // can't do anything with a non-absolute url
514
- }
515
- }
717
+ const frameElement = doc.defaultView && doc.defaultView.frameElement;
718
+ return Promise.all([
719
+ resourceUrlsAndBlobsPromise,
720
+ ...processFramesPromise,
721
+ ...processInlineFramesPromise,
722
+ ]).then(([{resourceUrls, blobsObj}, ...framesResults]) => ({
723
+ cdt,
724
+ url,
725
+ resourceUrls,
726
+ blobs: [...blobsObjToArray(blobsObj), ...canvasBlobs],
727
+ frames: framesResults,
728
+ srcAttr: frameElement ? frameElement.getAttribute('src') : undefined,
729
+ }));
516
730
  }
517
731
  }
518
732
 
733
+ function getAbsolutizeByUrl(url) {
734
+ return function(someUrl) {
735
+ try {
736
+ return absolutizeUrl_1(someUrl, url);
737
+ } catch (err) {
738
+ // can't do anything with a non-absolute url
739
+ }
740
+ };
741
+ }
742
+
519
743
  function blobsObjToArray(blobsObj) {
520
744
  return Object.keys(blobsObj).map(blobUrl =>
521
745
  Object.assign(
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: false
2
2
 
3
3
  module Applitools
4
- VERSION = '3.15.26'.freeze
4
+ VERSION = '3.15.27'.freeze
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eyes_selenium
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.15.26
4
+ version: 3.15.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Applitools Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-05 00:00:00.000000000 Z
11
+ date: 2019-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: eyes_core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 3.15.26
19
+ version: 3.15.27
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 3.15.26
26
+ version: 3.15.27
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: selenium-webdriver
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  version: '0'
160
160
  requirements: []
161
161
  rubyforge_project:
162
- rubygems_version: 2.7.7
162
+ rubygems_version: 2.7.10
163
163
  signing_key:
164
164
  specification_version: 4
165
165
  summary: Applitools Ruby Selenium SDK