eyes_selenium 3.15.16 → 3.15.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/applitools/selenium/scripts/process_page_and_poll.rb +588 -0
- data/lib/applitools/selenium/visual_grid/render_task.rb +4 -3
- data/lib/applitools/selenium/visual_grid/running_test.rb +2 -2
- data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +22 -2
- data/lib/applitools/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 639b145cb841a63e971d9a5aa43aa05b502b446399691aa3b368db0309febe0f
|
4
|
+
data.tar.gz: 3509ad0fd6e0b581c14fd9f054e770b48ca083434337020b665d4c51ce5cdb1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5119825b6662f502a0ae55b7d0cd424b2fa05c5707d4f11e40fa8b57aed082fb281bd4639c8c733bb369a612e947e06fe48b57788a9fd81cce26ef21cc1fa7f0
|
7
|
+
data.tar.gz: 8125963685a0efbe5081a6676e37052570b34eeca579162a6d45cb31f48124bd5cdd924c848a3163fd88f2e2106bd247d31080d046d8bda6be8a1f1589bd8c6a
|
@@ -0,0 +1,588 @@
|
|
1
|
+
module Applitools
|
2
|
+
module Selenium
|
3
|
+
module Scripts
|
4
|
+
PROCESS_PAGE_AND_POLL = <<'END'
|
5
|
+
// @applitools/dom-snapshot@1.2.4
|
6
|
+
function __processPageAndPoll() {
|
7
|
+
var processPageAndPoll = (function () {
|
8
|
+
'use strict';
|
9
|
+
|
10
|
+
// This code was copied and modified from https://github.com/beatgammit/base64-js/blob/bf68aaa277/index.js
|
11
|
+
// License: https://github.com/beatgammit/base64-js/blob/bf68aaa277d9de7007cc0c58279c411bb10670ac/LICENSE
|
12
|
+
|
13
|
+
function arrayBufferToBase64(ab) {
|
14
|
+
const lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
|
15
|
+
|
16
|
+
const uint8 = new Uint8Array(ab);
|
17
|
+
const len = uint8.length;
|
18
|
+
const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
|
19
|
+
const parts = [];
|
20
|
+
const maxChunkLength = 16383; // must be multiple of 3
|
21
|
+
|
22
|
+
let tmp;
|
23
|
+
|
24
|
+
// go through the array every three bytes, we'll deal with trailing stuff later
|
25
|
+
for (let i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
26
|
+
parts.push(encodeChunk(i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength));
|
27
|
+
}
|
28
|
+
|
29
|
+
// pad the end with zeros, but make sure to not forget the extra bytes
|
30
|
+
if (extraBytes === 1) {
|
31
|
+
tmp = uint8[len - 1];
|
32
|
+
parts.push(lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3f] + '==');
|
33
|
+
} else if (extraBytes === 2) {
|
34
|
+
tmp = (uint8[len - 2] << 8) + uint8[len - 1];
|
35
|
+
parts.push(lookup[tmp >> 10] + lookup[(tmp >> 4) & 0x3f] + lookup[(tmp << 2) & 0x3f] + '=');
|
36
|
+
}
|
37
|
+
|
38
|
+
return parts.join('');
|
39
|
+
|
40
|
+
function tripletToBase64(num) {
|
41
|
+
return (
|
42
|
+
lookup[(num >> 18) & 0x3f] +
|
43
|
+
lookup[(num >> 12) & 0x3f] +
|
44
|
+
lookup[(num >> 6) & 0x3f] +
|
45
|
+
lookup[num & 0x3f]
|
46
|
+
);
|
47
|
+
}
|
48
|
+
|
49
|
+
function encodeChunk(start, end) {
|
50
|
+
let tmp;
|
51
|
+
const output = [];
|
52
|
+
for (let i = start; i < end; i += 3) {
|
53
|
+
tmp = ((uint8[i] << 16) & 0xff0000) + ((uint8[i + 1] << 8) & 0xff00) + (uint8[i + 2] & 0xff);
|
54
|
+
output.push(tripletToBase64(tmp));
|
55
|
+
}
|
56
|
+
return output.join('');
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
var arrayBufferToBase64_1 = arrayBufferToBase64;
|
61
|
+
|
62
|
+
function extractLinks(doc = document) {
|
63
|
+
const srcsetUrls = [...doc.querySelectorAll('img[srcset],source[srcset]')]
|
64
|
+
.map(srcsetEl =>
|
65
|
+
srcsetEl
|
66
|
+
.getAttribute('srcset')
|
67
|
+
.split(',')
|
68
|
+
.map(str => str.trim().split(/\s+/)[0]),
|
69
|
+
)
|
70
|
+
.reduce((acc, urls) => acc.concat(urls), []);
|
71
|
+
|
72
|
+
const srcUrls = [...doc.querySelectorAll('img[src],source[src]')].map(srcEl =>
|
73
|
+
srcEl.getAttribute('src'),
|
74
|
+
);
|
75
|
+
|
76
|
+
const hrefUrls = [...doc.querySelectorAll('image')]
|
77
|
+
.map(hrefEl => hrefEl.getAttribute('href') || hrefEl.getAttribute('xlink:href'))
|
78
|
+
.filter(Boolean);
|
79
|
+
|
80
|
+
const cssUrls = [...doc.querySelectorAll('link[rel="stylesheet"]')].map(link =>
|
81
|
+
link.getAttribute('href'),
|
82
|
+
);
|
83
|
+
|
84
|
+
const videoPosterUrls = [...doc.querySelectorAll('video[poster]')].map(videoEl =>
|
85
|
+
videoEl.getAttribute('poster'),
|
86
|
+
);
|
87
|
+
|
88
|
+
return [...srcsetUrls, ...srcUrls, ...hrefUrls, ...cssUrls, ...videoPosterUrls];
|
89
|
+
}
|
90
|
+
|
91
|
+
var extractLinks_1 = extractLinks;
|
92
|
+
|
93
|
+
/* eslint-disable no-use-before-define */
|
94
|
+
|
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
|
+
};
|
103
|
+
|
104
|
+
const domNodes = [
|
105
|
+
{
|
106
|
+
nodeType: NODE_TYPES.DOCUMENT,
|
107
|
+
},
|
108
|
+
];
|
109
|
+
domNodes[0].childNodeIndexes = childrenFactory(domNodes, docNode.childNodes);
|
110
|
+
return domNodes;
|
111
|
+
|
112
|
+
function childrenFactory(domNodes, elementNodes) {
|
113
|
+
if (!elementNodes || elementNodes.length === 0) return null;
|
114
|
+
|
115
|
+
const childIndexes = [];
|
116
|
+
elementNodes.forEach(elementNode => {
|
117
|
+
const index = elementNodeFactory(domNodes, elementNode);
|
118
|
+
if (index !== null) {
|
119
|
+
childIndexes.push(index);
|
120
|
+
}
|
121
|
+
});
|
122
|
+
|
123
|
+
return childIndexes;
|
124
|
+
}
|
125
|
+
|
126
|
+
function elementNodeFactory(domNodes, elementNode) {
|
127
|
+
let node, manualChildNodeIndexes;
|
128
|
+
const {nodeType} = elementNode;
|
129
|
+
if ([NODE_TYPES.ELEMENT, NODE_TYPES.DOCUMENT_FRAGMENT_NODE].includes(nodeType)) {
|
130
|
+
if (elementNode.nodeName !== 'SCRIPT') {
|
131
|
+
if (
|
132
|
+
elementNode.nodeName === 'STYLE' &&
|
133
|
+
elementNode.sheet &&
|
134
|
+
elementNode.sheet.cssRules.length
|
135
|
+
) {
|
136
|
+
domNodes.push({
|
137
|
+
nodeType: NODE_TYPES.TEXT,
|
138
|
+
nodeValue: [...elementNode.sheet.cssRules].map(rule => rule.cssText).join(''),
|
139
|
+
});
|
140
|
+
manualChildNodeIndexes = [domNodes.length - 1];
|
141
|
+
}
|
142
|
+
|
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
|
+
};
|
171
|
+
|
172
|
+
if (elementNode.shadowRoot) {
|
173
|
+
node.shadowRootIndex = elementNodeFactory(domNodes, elementNode.shadowRoot);
|
174
|
+
}
|
175
|
+
|
176
|
+
if (elementNode.checked && !elementNode.attributes.checked) {
|
177
|
+
node.attributes.push({name: 'checked', value: 'checked'});
|
178
|
+
}
|
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});
|
185
|
+
}
|
186
|
+
} 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
|
+
};
|
198
|
+
}
|
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
|
+
};
|
209
|
+
}
|
210
|
+
|
211
|
+
if (node) {
|
212
|
+
domNodes.push(node);
|
213
|
+
return domNodes.length - 1;
|
214
|
+
} else {
|
215
|
+
// console.log(`Unknown nodeType: ${nodeType}`);
|
216
|
+
return null;
|
217
|
+
}
|
218
|
+
|
219
|
+
function nodeAttributes({attributes = {}}) {
|
220
|
+
return Object.keys(attributes).filter(k => attributes[k].localName);
|
221
|
+
}
|
222
|
+
}
|
223
|
+
}
|
224
|
+
|
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
|
248
|
+
}
|
249
|
+
})
|
250
|
+
.filter(x => !!x);
|
251
|
+
}
|
252
|
+
|
253
|
+
var extractFrames_1 = extractFrames;
|
254
|
+
|
255
|
+
function uniq(arr) {
|
256
|
+
const result = [];
|
257
|
+
new Set(arr).forEach(v => v && result.push(v));
|
258
|
+
return result;
|
259
|
+
}
|
260
|
+
|
261
|
+
var uniq_1 = uniq;
|
262
|
+
|
263
|
+
function aggregateResourceUrlsAndBlobs(resourceUrlsAndBlobsArr) {
|
264
|
+
return resourceUrlsAndBlobsArr.reduce(
|
265
|
+
({resourceUrls: allResourceUrls, blobsObj: allBlobsObj}, {resourceUrls, blobsObj}) => ({
|
266
|
+
resourceUrls: uniq_1(allResourceUrls.concat(resourceUrls)),
|
267
|
+
blobsObj: Object.assign(allBlobsObj, blobsObj),
|
268
|
+
}),
|
269
|
+
{resourceUrls: [], blobsObj: {}},
|
270
|
+
);
|
271
|
+
}
|
272
|
+
|
273
|
+
var aggregateResourceUrlsAndBlobs_1 = aggregateResourceUrlsAndBlobs;
|
274
|
+
|
275
|
+
function makeGetResourceUrlsAndBlobs({processResource, aggregateResourceUrlsAndBlobs}) {
|
276
|
+
return function getResourceUrlsAndBlobs(doc, baseUrl, urls) {
|
277
|
+
return Promise.all(
|
278
|
+
urls.map(url => processResource(url, doc, baseUrl, getResourceUrlsAndBlobs.bind(null, doc))),
|
279
|
+
).then(resourceUrlsAndBlobsArr => aggregateResourceUrlsAndBlobs(resourceUrlsAndBlobsArr));
|
280
|
+
};
|
281
|
+
}
|
282
|
+
|
283
|
+
var getResourceUrlsAndBlobs = makeGetResourceUrlsAndBlobs;
|
284
|
+
|
285
|
+
function filterInlineUrl(absoluteUrl) {
|
286
|
+
return /^(blob|https?):/.test(absoluteUrl);
|
287
|
+
}
|
288
|
+
|
289
|
+
var filterInlineUrl_1 = filterInlineUrl;
|
290
|
+
|
291
|
+
function absolutizeUrl(url, absoluteUrl) {
|
292
|
+
return new URL(url, absoluteUrl).href;
|
293
|
+
}
|
294
|
+
|
295
|
+
var absolutizeUrl_1 = absolutizeUrl;
|
296
|
+
|
297
|
+
function makeProcessResource({
|
298
|
+
fetchUrl,
|
299
|
+
findStyleSheetByUrl,
|
300
|
+
extractResourcesFromStyleSheet,
|
301
|
+
isSameOrigin,
|
302
|
+
cache = {},
|
303
|
+
}) {
|
304
|
+
return function processResource(absoluteUrl, doc, baseUrl, getResourceUrlsAndBlobs) {
|
305
|
+
return cache[absoluteUrl] || (cache[absoluteUrl] = doProcessResource(absoluteUrl));
|
306
|
+
|
307
|
+
function doProcessResource(url) {
|
308
|
+
return fetchUrl(url)
|
309
|
+
.catch(e => {
|
310
|
+
if (probablyCORS(e, url)) {
|
311
|
+
return {probablyCORS: true, url};
|
312
|
+
} else {
|
313
|
+
throw e;
|
314
|
+
}
|
315
|
+
})
|
316
|
+
.then(({url, type, value, probablyCORS}) => {
|
317
|
+
if (probablyCORS) {
|
318
|
+
return {resourceUrls: [url]};
|
319
|
+
}
|
320
|
+
const result = {blobsObj: {[url]: {type, value}}};
|
321
|
+
if (/text\/css/.test(type)) {
|
322
|
+
const styleSheet = findStyleSheetByUrl(url, doc);
|
323
|
+
if (!styleSheet) {
|
324
|
+
return result;
|
325
|
+
}
|
326
|
+
const resourceUrls = extractResourcesFromStyleSheet(styleSheet, doc.defaultView)
|
327
|
+
.map(resourceUrl => absolutizeUrl_1(resourceUrl, url.replace(/^blob:/, '')))
|
328
|
+
.filter(filterInlineUrl_1);
|
329
|
+
return getResourceUrlsAndBlobs(baseUrl, resourceUrls).then(
|
330
|
+
({resourceUrls, blobsObj}) => ({
|
331
|
+
resourceUrls,
|
332
|
+
blobsObj: Object.assign(blobsObj, {[url]: {type, value}}),
|
333
|
+
}),
|
334
|
+
);
|
335
|
+
} else {
|
336
|
+
return result;
|
337
|
+
}
|
338
|
+
})
|
339
|
+
.catch(err => {
|
340
|
+
console.log('[dom-snapshot] error while fetching', url, err);
|
341
|
+
return {};
|
342
|
+
});
|
343
|
+
}
|
344
|
+
|
345
|
+
function probablyCORS(err, url) {
|
346
|
+
const msgCORS = err.message && err.message.includes('Failed to fetch');
|
347
|
+
const nameCORS = err.name && err.name.includes('TypeError');
|
348
|
+
return msgCORS && nameCORS && !isSameOrigin(url, baseUrl);
|
349
|
+
}
|
350
|
+
};
|
351
|
+
}
|
352
|
+
|
353
|
+
var processResource = makeProcessResource;
|
354
|
+
|
355
|
+
/* global window */
|
356
|
+
|
357
|
+
function fetchUrl(url, fetch = window.fetch) {
|
358
|
+
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
|
+
})),
|
364
|
+
);
|
365
|
+
}
|
366
|
+
|
367
|
+
var fetchUrl_1 = fetchUrl;
|
368
|
+
|
369
|
+
function makeFindStyleSheetByUrl({styleSheetCache}) {
|
370
|
+
return function findStyleSheetByUrl(url, doc) {
|
371
|
+
return styleSheetCache[url] || [...doc.styleSheets].find(styleSheet => styleSheet.href === url);
|
372
|
+
};
|
373
|
+
}
|
374
|
+
|
375
|
+
var findStyleSheetByUrl = makeFindStyleSheetByUrl;
|
376
|
+
|
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
|
+
function makeExtractResourcesFromStyleSheet({styleSheetCache}) {
|
391
|
+
return function extractResourcesFromStyleSheet(styleSheet, win = window) {
|
392
|
+
return uniq_1(
|
393
|
+
[...(styleSheet.cssRules || [])].reduce((acc, rule) => {
|
394
|
+
if (rule instanceof win.CSSImportRule) {
|
395
|
+
styleSheetCache[rule.styleSheet.href] = rule.styleSheet;
|
396
|
+
return acc.concat(rule.href);
|
397
|
+
} 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));
|
401
|
+
} else if (rule instanceof win.CSSStyleRule) {
|
402
|
+
for (let i = 0, ii = rule.style.length; i < ii; i++) {
|
403
|
+
const urls = getUrlFromCssText_1(rule.style.getPropertyValue(rule.style[i]));
|
404
|
+
urls.length && (acc = acc.concat(urls));
|
405
|
+
}
|
406
|
+
}
|
407
|
+
return acc;
|
408
|
+
}, []),
|
409
|
+
);
|
410
|
+
};
|
411
|
+
}
|
412
|
+
|
413
|
+
var extractResourcesFromStyleSheet = makeExtractResourcesFromStyleSheet;
|
414
|
+
|
415
|
+
function extractResourceUrlsFromStyleAttrs(cdt) {
|
416
|
+
return cdt.reduce((acc, node) => {
|
417
|
+
if (node.nodeType === 1) {
|
418
|
+
const styleAttr =
|
419
|
+
node.attributes && node.attributes.find(attr => attr.name.toUpperCase() === 'STYLE');
|
420
|
+
|
421
|
+
if (styleAttr) acc = acc.concat(getUrlFromCssText_1(styleAttr.value));
|
422
|
+
}
|
423
|
+
return acc;
|
424
|
+
}, []);
|
425
|
+
}
|
426
|
+
|
427
|
+
var extractResourceUrlsFromStyleAttrs_1 = extractResourceUrlsFromStyleAttrs;
|
428
|
+
|
429
|
+
function makeExtractResourceUrlsFromStyleTags(extractResourcesFromStyleSheet) {
|
430
|
+
return function extractResourceUrlsFromStyleTags(doc) {
|
431
|
+
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));
|
437
|
+
}, []),
|
438
|
+
);
|
439
|
+
};
|
440
|
+
}
|
441
|
+
|
442
|
+
var extractResourceUrlsFromStyleTags = makeExtractResourceUrlsFromStyleTags;
|
443
|
+
|
444
|
+
function isSameOrigin(url, baseUrl) {
|
445
|
+
const blobOrData = /^(blob|data):/;
|
446
|
+
if (blobOrData.test(url)) return true;
|
447
|
+
if (blobOrData.test(baseUrl)) return false;
|
448
|
+
|
449
|
+
const {origin} = new URL(url, baseUrl);
|
450
|
+
const {origin: baseOrigin} = new URL(baseUrl);
|
451
|
+
return origin === baseOrigin;
|
452
|
+
}
|
453
|
+
|
454
|
+
var isSameOrigin_1 = isSameOrigin;
|
455
|
+
|
456
|
+
function processPage(doc = document) {
|
457
|
+
const styleSheetCache = {};
|
458
|
+
const extractResourcesFromStyleSheet$$1 = extractResourcesFromStyleSheet({styleSheetCache});
|
459
|
+
const findStyleSheetByUrl$$1 = findStyleSheetByUrl({styleSheetCache});
|
460
|
+
const processResource$$1 = processResource({
|
461
|
+
fetchUrl: fetchUrl_1,
|
462
|
+
findStyleSheetByUrl: findStyleSheetByUrl$$1,
|
463
|
+
extractResourcesFromStyleSheet: extractResourcesFromStyleSheet$$1,
|
464
|
+
absolutizeUrl: absolutizeUrl_1,
|
465
|
+
isSameOrigin: isSameOrigin_1,
|
466
|
+
});
|
467
|
+
|
468
|
+
const getResourceUrlsAndBlobs$$1 = getResourceUrlsAndBlobs({
|
469
|
+
processResource: processResource$$1,
|
470
|
+
aggregateResourceUrlsAndBlobs: aggregateResourceUrlsAndBlobs_1,
|
471
|
+
});
|
472
|
+
|
473
|
+
const extractResourceUrlsFromStyleTags$$1 = extractResourceUrlsFromStyleTags(
|
474
|
+
extractResourcesFromStyleSheet$$1,
|
475
|
+
);
|
476
|
+
|
477
|
+
return doProcessPage(doc);
|
478
|
+
|
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);
|
484
|
+
|
485
|
+
const links = uniq_1(
|
486
|
+
extractLinks_1(doc)
|
487
|
+
.concat(extractResourceUrlsFromStyleAttrs_1(cdt))
|
488
|
+
.concat(extractResourceUrlsFromStyleTags$$1(doc)),
|
489
|
+
)
|
490
|
+
.map(absolutizeThisUrl)
|
491
|
+
.filter(filterInlineUrlsIfExisting);
|
492
|
+
|
493
|
+
const resourceUrlsAndBlobsPromise = getResourceUrlsAndBlobs$$1(doc, url, links);
|
494
|
+
|
495
|
+
const frameDocs = extractFrames_1(doc);
|
496
|
+
const processFramesPromise = frameDocs.map(doProcessPage);
|
497
|
+
|
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
|
+
}),
|
507
|
+
);
|
508
|
+
|
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
|
+
}
|
516
|
+
}
|
517
|
+
}
|
518
|
+
|
519
|
+
function blobsObjToArray(blobsObj) {
|
520
|
+
return Object.keys(blobsObj).map(blobUrl =>
|
521
|
+
Object.assign(
|
522
|
+
{
|
523
|
+
url: blobUrl.replace(/^blob:/, ''),
|
524
|
+
},
|
525
|
+
blobsObj[blobUrl],
|
526
|
+
),
|
527
|
+
);
|
528
|
+
}
|
529
|
+
|
530
|
+
function filterInlineUrlsIfExisting(absoluteUrl) {
|
531
|
+
return absoluteUrl && filterInlineUrl_1(absoluteUrl);
|
532
|
+
}
|
533
|
+
|
534
|
+
var processPage_1 = processPage;
|
535
|
+
|
536
|
+
function processPageAndSerialize(doc) {
|
537
|
+
return processPage_1(doc).then(serializeFrame);
|
538
|
+
}
|
539
|
+
|
540
|
+
function serializeFrame(frame) {
|
541
|
+
frame.blobs = frame.blobs.map(({url, type, value}) => ({
|
542
|
+
url,
|
543
|
+
type,
|
544
|
+
value: arrayBufferToBase64_1(value),
|
545
|
+
}));
|
546
|
+
frame.frames.forEach(serializeFrame);
|
547
|
+
return frame;
|
548
|
+
}
|
549
|
+
|
550
|
+
var processPageAndSerialize_1 = processPageAndSerialize;
|
551
|
+
|
552
|
+
const EYES_NAME_SPACE = '__EYES__APPLITOOLS__';
|
553
|
+
|
554
|
+
function processPageAndPoll(doc) {
|
555
|
+
if (!window[EYES_NAME_SPACE]) {
|
556
|
+
window[EYES_NAME_SPACE] = {};
|
557
|
+
}
|
558
|
+
if (!window[EYES_NAME_SPACE].processPageAndSerializeResult) {
|
559
|
+
window[EYES_NAME_SPACE].processPageAndSerializeResult = {
|
560
|
+
status: 'WIP',
|
561
|
+
value: null,
|
562
|
+
error: null,
|
563
|
+
};
|
564
|
+
processPageAndSerialize_1(doc)
|
565
|
+
.then(r => ((resultObject.status = 'SUCCESS'), (resultObject.value = r)))
|
566
|
+
.catch(e => ((resultObject.status = 'ERROR'), (resultObject.error = e.message)));
|
567
|
+
}
|
568
|
+
|
569
|
+
const resultObject = window[EYES_NAME_SPACE].processPageAndSerializeResult;
|
570
|
+
if (resultObject.status === 'SUCCESS') {
|
571
|
+
window[EYES_NAME_SPACE].processPageAndSerializeResult = null;
|
572
|
+
}
|
573
|
+
|
574
|
+
return JSON.stringify(resultObject);
|
575
|
+
}
|
576
|
+
|
577
|
+
var processPageAndPoll_1 = processPageAndPoll;
|
578
|
+
|
579
|
+
return processPageAndPoll_1;
|
580
|
+
|
581
|
+
}());
|
582
|
+
|
583
|
+
return processPageAndPoll.apply(this, arguments);
|
584
|
+
}
|
585
|
+
END
|
586
|
+
end
|
587
|
+
end
|
588
|
+
end
|
@@ -12,9 +12,9 @@ module Applitools
|
|
12
12
|
:rendering_info, :request_resources, :dom_url_mod, :result, :region_selectors, :size_mode,
|
13
13
|
:region_to_check, :script_hooks
|
14
14
|
|
15
|
-
def initialize(name,
|
15
|
+
def initialize(name, script_result, running_test, resource_cache, put_cache, rendering_info, server_connector, region_selectors, size_mode, region, script_hooks, mod = nil)
|
16
16
|
self.result = nil
|
17
|
-
self.script =
|
17
|
+
self.script = script_result
|
18
18
|
self.running_test = running_test
|
19
19
|
self.resource_cache = resource_cache
|
20
20
|
self.put_cache = put_cache
|
@@ -121,7 +121,8 @@ module Applitools
|
|
121
121
|
end
|
122
122
|
|
123
123
|
def script_data
|
124
|
-
@script_data ||= Oj.load script
|
124
|
+
# @script_data ||= Oj.load script
|
125
|
+
@script_data ||= script
|
125
126
|
end
|
126
127
|
|
127
128
|
def prepare_data_for_rg(data)
|
@@ -153,10 +153,10 @@ module Applitools
|
|
153
153
|
watch_open[open_task] = false
|
154
154
|
end
|
155
155
|
|
156
|
-
def check(tag, target,
|
156
|
+
def check(tag, target, result, visual_grid_manager, region_selectors, size_mod, region_to_check, mod = nil)
|
157
157
|
render_task = RenderTask.new(
|
158
158
|
"Render #{eyes.config.short_description} - #{tag}",
|
159
|
-
|
159
|
+
result,
|
160
160
|
self,
|
161
161
|
visual_grid_manager.resource_cache,
|
162
162
|
visual_grid_manager.put_cache,
|
@@ -2,6 +2,7 @@ require 'applitools/selenium/configuration'
|
|
2
2
|
module Applitools
|
3
3
|
module Selenium
|
4
4
|
class VisualGridEyes
|
5
|
+
DOM_EXTRACTION_TIMEOUT = 300 #seconds or 5 minutes
|
5
6
|
extend Forwardable
|
6
7
|
|
7
8
|
def_delegators 'Applitools::EyesLogger', :logger, :log_handler, :log_handler=
|
@@ -81,16 +82,35 @@ module Applitools
|
|
81
82
|
script = <<-END
|
82
83
|
var callback = arguments[arguments.length - 1]; return (#{Applitools::Selenium::Scripts::PROCESS_RESOURCES})().then(JSON.stringify).then(callback, function(err) {callback(err.stack || err.toString())});
|
83
84
|
END
|
85
|
+
script = <<-END
|
86
|
+
#{Applitools::Selenium::Scripts::PROCESS_PAGE_AND_POLL} return __processPageAndPoll();
|
87
|
+
END
|
84
88
|
begin
|
85
89
|
sleep wait_before_screenshots
|
86
90
|
|
87
|
-
script_result = driver.execute_async_script(script).freeze
|
91
|
+
# script_result = driver.execute_async_script(script).freeze
|
92
|
+
|
93
|
+
dom_snapshot_start_time = Time.now()
|
94
|
+
result = {}
|
95
|
+
script_result = nil
|
96
|
+
loop do
|
97
|
+
script_result = driver.execute_script(script)
|
98
|
+
begin
|
99
|
+
result = Oj.load(script_result)
|
100
|
+
break if result['status'] == 'SUCCESS'
|
101
|
+
dom_snapshot_time = Time.now - dom_snapshot_start_time
|
102
|
+
raise Applitools::EyesError, 'Timeout error while getting dom snapshot!' if dom_snapshot_time > DOM_EXTRACTION_TIMEOUT
|
103
|
+
rescue Oj::ParseError => e
|
104
|
+
Applitools::EyesLogger.warn e.message
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
88
108
|
mod = Digest::SHA2.hexdigest(script_result)
|
89
109
|
|
90
110
|
region_x_paths = get_regions_x_paths(target)
|
91
111
|
|
92
112
|
test_list.each do |t|
|
93
|
-
t.check(tag, target,
|
113
|
+
t.check(tag, target, result['value'].dup, visual_grid_manager, region_x_paths, size_mod, region_to_check, mod)
|
94
114
|
end
|
95
115
|
test_list.each { |t| t.becomes_not_rendered}
|
96
116
|
rescue StandardError => e
|
data/lib/applitools/version.rb
CHANGED
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.
|
4
|
+
version: 3.15.17
|
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-05-
|
11
|
+
date: 2019-05-29 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.
|
19
|
+
version: 3.15.17
|
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
|
+
version: 3.15.17
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: selenium-webdriver
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,6 +109,7 @@ files:
|
|
109
109
|
- lib/applitools/selenium/rgrid_dom.rb
|
110
110
|
- lib/applitools/selenium/sauce/driver.rb
|
111
111
|
- lib/applitools/selenium/scripts/get_element_xpath.rb
|
112
|
+
- lib/applitools/selenium/scripts/process_page_and_poll.rb
|
112
113
|
- lib/applitools/selenium/scripts/process_page_and_serialize.rb
|
113
114
|
- lib/applitools/selenium/scroll_position_provider.rb
|
114
115
|
- lib/applitools/selenium/selenium_eyes.rb
|