eyes_selenium 6.12.10 → 6.12.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -0
- data/eyes_selenium.gemspec +2 -5
- data/lib/applitools/eyes_selenium/version.rb +1 -1
- data/lib/applitools/selenium/browsers_info.rb +2 -0
- data/lib/applitools/selenium/concerns/selenium_eyes.rb +0 -33
- data/lib/applitools/selenium/driver.rb +1 -1
- data/lib/applitools/selenium/eyes.rb +1 -5
- data/lib/applitools/selenium/selenium_eyes.rb +15 -315
- data/lib/applitools/selenium/visual_grid/visual_grid_runner.rb +33 -92
- data/lib/eyes_selenium.rb +0 -2
- metadata +9 -64
- data/lib/applitools/selenium/css_parser/find_embedded_resources.rb +0 -102
- data/lib/applitools/selenium/dom_capture/dom_capture.rb +0 -172
- data/lib/applitools/selenium/dom_capture/dom_capture_script.rb +0 -611
- data/lib/applitools/selenium/external_css_resources.rb +0 -32
- data/lib/applitools/selenium/visual_grid/dom_snapshot_script.rb +0 -198
- data/lib/applitools/selenium/visual_grid/eyes_connector.rb +0 -170
- data/lib/applitools/selenium/visual_grid/render_info.rb +0 -24
- data/lib/applitools/selenium/visual_grid/render_request.rb +0 -24
- data/lib/applitools/selenium/visual_grid/render_requests.rb +0 -12
- data/lib/applitools/selenium/visual_grid/render_task.rb +0 -311
- data/lib/applitools/selenium/visual_grid/resource_cache.rb +0 -69
- data/lib/applitools/selenium/visual_grid/running_test.rb +0 -271
- data/lib/applitools/selenium/visual_grid/thread_pool.rb +0 -95
- data/lib/applitools/selenium/visual_grid/vg_match_window_data.rb +0 -187
- data/lib/applitools/selenium/visual_grid/vg_region.rb +0 -16
- data/lib/applitools/selenium/visual_grid/vg_resource.rb +0 -77
- data/lib/applitools/selenium/visual_grid/vg_task.rb +0 -53
- data/lib/applitools/selenium/visual_grid/visual_grid_eyes.rb +0 -494
- data/lib/applitools/selenium/visual_grid/web_element_region.rb +0 -16
|
@@ -1,611 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Applitools
|
|
4
|
-
module Selenium
|
|
5
|
-
module DomCapture
|
|
6
|
-
CAPTURE_FRAME_SCRIPT = <<'SCRIPT'
|
|
7
|
-
/* @applitools/dom-capture@7.1.3 */
|
|
8
|
-
|
|
9
|
-
function __captureDomAndPoll() {
|
|
10
|
-
var captureDomAndPoll = (function () {
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
const styleProps = [
|
|
14
|
-
'background-repeat',
|
|
15
|
-
'background-origin',
|
|
16
|
-
'background-position',
|
|
17
|
-
'background-color',
|
|
18
|
-
'background-image',
|
|
19
|
-
'background-size',
|
|
20
|
-
'border-width',
|
|
21
|
-
'border-color',
|
|
22
|
-
'border-style',
|
|
23
|
-
'color',
|
|
24
|
-
'display',
|
|
25
|
-
'font-size',
|
|
26
|
-
'line-height',
|
|
27
|
-
'margin',
|
|
28
|
-
'opacity',
|
|
29
|
-
'overflow',
|
|
30
|
-
'padding',
|
|
31
|
-
'visibility',
|
|
32
|
-
];
|
|
33
|
-
|
|
34
|
-
const rectProps = ['width', 'height', 'top', 'left'];
|
|
35
|
-
|
|
36
|
-
const ignoredTagNames = ['HEAD', 'SCRIPT'];
|
|
37
|
-
|
|
38
|
-
var defaultDomProps = {
|
|
39
|
-
styleProps,
|
|
40
|
-
rectProps,
|
|
41
|
-
ignoredTagNames,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
const bgImageRe = /url\((?!['"]?:)['"]?([^'")]*)['"]?\)/;
|
|
45
|
-
|
|
46
|
-
function getBackgroundImageUrl(cssText) {
|
|
47
|
-
const match = cssText ? cssText.match(bgImageRe) : undefined;
|
|
48
|
-
return match ? match[1] : match;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
var getBackgroundImageUrl_1 = getBackgroundImageUrl;
|
|
52
|
-
|
|
53
|
-
const psetTimeout = t =>
|
|
54
|
-
new Promise(res => {
|
|
55
|
-
setTimeout(res, t);
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
async function getImageSizes({bgImages, timeout = 5000, Image = window.Image}) {
|
|
59
|
-
return (
|
|
60
|
-
await Promise.all(
|
|
61
|
-
Array.from(bgImages).map(url =>
|
|
62
|
-
Promise.race([
|
|
63
|
-
new Promise(resolve => {
|
|
64
|
-
const img = new Image();
|
|
65
|
-
img.onload = () => resolve({url, width: img.naturalWidth, height: img.naturalHeight});
|
|
66
|
-
img.onerror = () => resolve();
|
|
67
|
-
img.src = url;
|
|
68
|
-
}),
|
|
69
|
-
psetTimeout(timeout),
|
|
70
|
-
]),
|
|
71
|
-
),
|
|
72
|
-
)
|
|
73
|
-
).reduce((images, curr) => {
|
|
74
|
-
if (curr) {
|
|
75
|
-
images[curr.url] = {width: curr.width, height: curr.height};
|
|
76
|
-
}
|
|
77
|
-
return images;
|
|
78
|
-
}, {});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
var getImageSizes_1 = getImageSizes;
|
|
82
|
-
|
|
83
|
-
function genXpath(el) {
|
|
84
|
-
if (!el.ownerDocument) return ''; // this is the document node
|
|
85
|
-
|
|
86
|
-
let xpath = '',
|
|
87
|
-
currEl = el,
|
|
88
|
-
doc = el.ownerDocument,
|
|
89
|
-
frameElement = doc.defaultView.frameElement;
|
|
90
|
-
while (currEl !== doc) {
|
|
91
|
-
xpath = `${currEl.tagName}[${getIndex(currEl)}]/${xpath}`;
|
|
92
|
-
currEl = currEl.parentNode;
|
|
93
|
-
}
|
|
94
|
-
if (frameElement) {
|
|
95
|
-
xpath = `${genXpath(frameElement)},${xpath}`;
|
|
96
|
-
}
|
|
97
|
-
return xpath.replace(/\/$/, '');
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function getIndex(el) {
|
|
101
|
-
return (
|
|
102
|
-
Array.prototype.filter
|
|
103
|
-
.call(el.parentNode.childNodes, node => node.tagName === el.tagName)
|
|
104
|
-
.indexOf(el) + 1
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
var genXpath_1 = genXpath;
|
|
109
|
-
|
|
110
|
-
function absolutizeUrl(url, absoluteUrl) {
|
|
111
|
-
return new URL(url, absoluteUrl).href;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
var absolutizeUrl_1 = absolutizeUrl;
|
|
115
|
-
|
|
116
|
-
function makeGetBundledCssFromCssText({
|
|
117
|
-
parseCss,
|
|
118
|
-
CSSImportRule,
|
|
119
|
-
absolutizeUrl,
|
|
120
|
-
getCssFromCache,
|
|
121
|
-
unfetchedToken,
|
|
122
|
-
}) {
|
|
123
|
-
return function getBundledCssFromCssText(cssText, styleBaseUrl) {
|
|
124
|
-
let unfetchedResources;
|
|
125
|
-
let bundledCss = '';
|
|
126
|
-
|
|
127
|
-
try {
|
|
128
|
-
const styleSheet = parseCss(cssText);
|
|
129
|
-
for (const rule of Array.from(styleSheet.cssRules)) {
|
|
130
|
-
if (rule instanceof CSSImportRule) {
|
|
131
|
-
const nestedUrl = absolutizeUrl(rule.href, styleBaseUrl);
|
|
132
|
-
const nestedResource = getCssFromCache(nestedUrl);
|
|
133
|
-
if (nestedResource !== undefined) {
|
|
134
|
-
const {
|
|
135
|
-
bundledCss: nestedCssText,
|
|
136
|
-
unfetchedResources: nestedUnfetchedResources,
|
|
137
|
-
} = getBundledCssFromCssText(nestedResource, nestedUrl);
|
|
138
|
-
|
|
139
|
-
nestedUnfetchedResources && (unfetchedResources = new Set(nestedUnfetchedResources));
|
|
140
|
-
bundledCss = `${nestedCssText}${bundledCss}`;
|
|
141
|
-
} else {
|
|
142
|
-
unfetchedResources = new Set([nestedUrl]);
|
|
143
|
-
bundledCss = `\n${unfetchedToken}${nestedUrl}${unfetchedToken}`;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
} catch (ex) {
|
|
148
|
-
console.log(`error during getBundledCssFromCssText, styleBaseUrl=${styleBaseUrl}`, ex);
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
bundledCss = `${bundledCss}${getCss(cssText, styleBaseUrl)}`;
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
bundledCss,
|
|
155
|
-
unfetchedResources,
|
|
156
|
-
};
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function getCss(newText, url) {
|
|
161
|
-
return `\n/** ${url} **/\n${newText}`;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
var getBundledCssFromCssText = makeGetBundledCssFromCssText;
|
|
165
|
-
|
|
166
|
-
function parseCss(styleContent) {
|
|
167
|
-
var doc = document.implementation.createHTMLDocument(''),
|
|
168
|
-
styleElement = doc.createElement('style');
|
|
169
|
-
styleElement.textContent = styleContent;
|
|
170
|
-
// the style will only be parsed once it is added to a document
|
|
171
|
-
doc.body.appendChild(styleElement);
|
|
172
|
-
|
|
173
|
-
return styleElement.sheet;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
var parseCss_1 = parseCss;
|
|
177
|
-
|
|
178
|
-
function makeFetchCss(fetch) {
|
|
179
|
-
return async function fetchCss(url) {
|
|
180
|
-
try {
|
|
181
|
-
const response = await fetch(url, {cache: 'force-cache'});
|
|
182
|
-
if (response.ok) {
|
|
183
|
-
return await response.text();
|
|
184
|
-
}
|
|
185
|
-
console.log('/failed to fetch (status ' + response.status + ') css from: ' + url + '/');
|
|
186
|
-
} catch (err) {
|
|
187
|
-
console.log('/failed to fetch (error ' + err.toString() + ') css from: ' + url + '/');
|
|
188
|
-
}
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
var fetchCss = makeFetchCss;
|
|
193
|
-
|
|
194
|
-
var getHrefAttr = function getHrefAttr(node) {
|
|
195
|
-
const attr = Array.from(node.attributes).find(attr => attr.name.toLowerCase() === 'href');
|
|
196
|
-
return attr && attr.value;
|
|
197
|
-
};
|
|
198
|
-
|
|
199
|
-
var isLinkToStyleSheet = function isLinkToStyleSheet(node) {
|
|
200
|
-
return (
|
|
201
|
-
node.nodeName &&
|
|
202
|
-
node.nodeName.toUpperCase() === 'LINK' &&
|
|
203
|
-
node.attributes &&
|
|
204
|
-
Array.from(node.attributes).find(
|
|
205
|
-
attr => attr.name.toLowerCase() === 'rel' && attr.value.toLowerCase() === 'stylesheet',
|
|
206
|
-
)
|
|
207
|
-
);
|
|
208
|
-
};
|
|
209
|
-
|
|
210
|
-
function isDataUrl(url) {
|
|
211
|
-
return url && url.startsWith('data:');
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
var isDataUrl_1 = isDataUrl;
|
|
215
|
-
|
|
216
|
-
function makeExtractCssFromNode({getCssFromCache, absolutizeUrl}) {
|
|
217
|
-
return function extractCssFromNode(node, baseUrl) {
|
|
218
|
-
let cssText, styleBaseUrl, isUnfetched;
|
|
219
|
-
if (isStyleElement(node)) {
|
|
220
|
-
cssText = Array.from(node.childNodes)
|
|
221
|
-
.map(node => node.nodeValue)
|
|
222
|
-
.join('');
|
|
223
|
-
styleBaseUrl = baseUrl;
|
|
224
|
-
} else if (isLinkToStyleSheet(node)) {
|
|
225
|
-
const href = getHrefAttr(node);
|
|
226
|
-
if (!isDataUrl_1(href)) {
|
|
227
|
-
styleBaseUrl = absolutizeUrl(href, baseUrl);
|
|
228
|
-
cssText = getCssFromCache(styleBaseUrl);
|
|
229
|
-
} else {
|
|
230
|
-
styleBaseUrl = baseUrl;
|
|
231
|
-
cssText = href.match(/,(.+)/)[1];
|
|
232
|
-
}
|
|
233
|
-
isUnfetched = cssText === undefined;
|
|
234
|
-
}
|
|
235
|
-
return {cssText, styleBaseUrl, isUnfetched};
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function isStyleElement(node) {
|
|
240
|
-
return node.nodeName && node.nodeName.toUpperCase() === 'STYLE';
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
var extractCssFromNode = makeExtractCssFromNode;
|
|
244
|
-
|
|
245
|
-
function makeCaptureNodeCss({extractCssFromNode, getBundledCssFromCssText, unfetchedToken}) {
|
|
246
|
-
return function captureNodeCss(node, baseUrl) {
|
|
247
|
-
const {styleBaseUrl, cssText, isUnfetched} = extractCssFromNode(node, baseUrl);
|
|
248
|
-
|
|
249
|
-
let unfetchedResources;
|
|
250
|
-
let bundledCss = '';
|
|
251
|
-
if (cssText) {
|
|
252
|
-
const {bundledCss: nestedCss, unfetchedResources: nestedUnfetched} = getBundledCssFromCssText(
|
|
253
|
-
cssText,
|
|
254
|
-
styleBaseUrl,
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
bundledCss += nestedCss;
|
|
258
|
-
unfetchedResources = new Set(nestedUnfetched);
|
|
259
|
-
} else if (isUnfetched) {
|
|
260
|
-
bundledCss += `${unfetchedToken}${styleBaseUrl}${unfetchedToken}`;
|
|
261
|
-
unfetchedResources = new Set([styleBaseUrl]);
|
|
262
|
-
}
|
|
263
|
-
return {bundledCss, unfetchedResources};
|
|
264
|
-
};
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
var captureNodeCss = makeCaptureNodeCss;
|
|
268
|
-
|
|
269
|
-
const NODE_TYPES = {
|
|
270
|
-
ELEMENT: 1,
|
|
271
|
-
TEXT: 3,
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
var nodeTypes = {NODE_TYPES};
|
|
275
|
-
|
|
276
|
-
const {NODE_TYPES: NODE_TYPES$1} = nodeTypes;
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
function makePrefetchAllCss(fetchCss) {
|
|
283
|
-
return async function prefetchAllCss(doc = document) {
|
|
284
|
-
const cssMap = {};
|
|
285
|
-
const start = Date.now();
|
|
286
|
-
const promises = [];
|
|
287
|
-
doFetchAllCssFromFrame(doc, cssMap, promises);
|
|
288
|
-
await Promise.all(promises);
|
|
289
|
-
console.log('[prefetchAllCss]', Date.now() - start);
|
|
290
|
-
|
|
291
|
-
return function fetchCssSync(url) {
|
|
292
|
-
return cssMap[url];
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
async function fetchNodeCss(node, baseUrl, cssMap) {
|
|
296
|
-
let cssText, resourceUrl;
|
|
297
|
-
if (isLinkToStyleSheet(node)) {
|
|
298
|
-
resourceUrl = absolutizeUrl_1(getHrefAttr(node), baseUrl);
|
|
299
|
-
cssText = await fetchCss(resourceUrl);
|
|
300
|
-
if (cssText !== undefined) {
|
|
301
|
-
cssMap[resourceUrl] = cssText;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
if (cssText) {
|
|
305
|
-
await fetchBundledCss(cssText, resourceUrl, cssMap);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
async function fetchBundledCss(cssText, resourceUrl, cssMap) {
|
|
310
|
-
try {
|
|
311
|
-
const styleSheet = parseCss_1(cssText);
|
|
312
|
-
const promises = [];
|
|
313
|
-
for (const rule of Array.from(styleSheet.cssRules)) {
|
|
314
|
-
if (rule instanceof CSSImportRule) {
|
|
315
|
-
promises.push(
|
|
316
|
-
(async () => {
|
|
317
|
-
const nestedUrl = absolutizeUrl_1(rule.href, resourceUrl);
|
|
318
|
-
const cssText = await fetchCss(nestedUrl);
|
|
319
|
-
cssMap[nestedUrl] = cssText;
|
|
320
|
-
if (cssText !== undefined) {
|
|
321
|
-
await fetchBundledCss(cssText, nestedUrl, cssMap);
|
|
322
|
-
}
|
|
323
|
-
})(),
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
await Promise.all(promises);
|
|
328
|
-
} catch (ex) {
|
|
329
|
-
console.log(`error during fetchBundledCss, resourceUrl=${resourceUrl}`, ex);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
function doFetchAllCssFromFrame(frameDoc, cssMap, promises) {
|
|
334
|
-
fetchAllCssFromNode(frameDoc.documentElement);
|
|
335
|
-
|
|
336
|
-
function fetchAllCssFromNode(node) {
|
|
337
|
-
promises.push(fetchNodeCss(node, frameDoc.location.href, cssMap));
|
|
338
|
-
|
|
339
|
-
switch (node.nodeType) {
|
|
340
|
-
case NODE_TYPES$1.ELEMENT: {
|
|
341
|
-
const tagName = node.tagName.toUpperCase();
|
|
342
|
-
if (tagName === 'IFRAME') {
|
|
343
|
-
return fetchAllCssFromIframe(node);
|
|
344
|
-
} else {
|
|
345
|
-
return fetchAllCssFromElement(node);
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
async function fetchAllCssFromElement(el) {
|
|
352
|
-
Array.prototype.map.call(el.childNodes, fetchAllCssFromNode);
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
async function fetchAllCssFromIframe(el) {
|
|
356
|
-
fetchAllCssFromElement(el);
|
|
357
|
-
try {
|
|
358
|
-
doFetchAllCssFromFrame(el.contentDocument, cssMap, promises);
|
|
359
|
-
} catch (ex) {
|
|
360
|
-
console.log(ex);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
var prefetchAllCss = makePrefetchAllCss;
|
|
368
|
-
|
|
369
|
-
const {NODE_TYPES: NODE_TYPES$2} = nodeTypes;
|
|
370
|
-
|
|
371
|
-
const API_VERSION = '1.1.0';
|
|
372
|
-
|
|
373
|
-
async function captureFrame(
|
|
374
|
-
{styleProps, rectProps, ignoredTagNames} = defaultDomProps,
|
|
375
|
-
doc = document,
|
|
376
|
-
addStats = false,
|
|
377
|
-
) {
|
|
378
|
-
const performance = {total: {}, prefetchCss: {}, doCaptureFrame: {}, waitForImages: {}};
|
|
379
|
-
function startTime(obj) {
|
|
380
|
-
obj.startTime = Date.now();
|
|
381
|
-
}
|
|
382
|
-
function endTime(obj) {
|
|
383
|
-
obj.endTime = Date.now();
|
|
384
|
-
obj.ellapsedTime = obj.endTime - obj.startTime;
|
|
385
|
-
}
|
|
386
|
-
const promises = [];
|
|
387
|
-
startTime(performance.total);
|
|
388
|
-
const unfetchedResources = new Set();
|
|
389
|
-
const iframeCors = [];
|
|
390
|
-
const iframeToken = '@@@@@';
|
|
391
|
-
const unfetchedToken = '#####';
|
|
392
|
-
const separator = '-----';
|
|
393
|
-
|
|
394
|
-
startTime(performance.prefetchCss);
|
|
395
|
-
const prefetchAllCss$$1 = prefetchAllCss(fetchCss(fetch));
|
|
396
|
-
const getCssFromCache = await prefetchAllCss$$1(doc);
|
|
397
|
-
endTime(performance.prefetchCss);
|
|
398
|
-
|
|
399
|
-
const getBundledCssFromCssText$$1 = getBundledCssFromCssText({
|
|
400
|
-
parseCss: parseCss_1,
|
|
401
|
-
CSSImportRule,
|
|
402
|
-
getCssFromCache,
|
|
403
|
-
absolutizeUrl: absolutizeUrl_1,
|
|
404
|
-
unfetchedToken,
|
|
405
|
-
});
|
|
406
|
-
const extractCssFromNode$$1 = extractCssFromNode({getCssFromCache, absolutizeUrl: absolutizeUrl_1});
|
|
407
|
-
const captureNodeCss$$1 = captureNodeCss({
|
|
408
|
-
extractCssFromNode: extractCssFromNode$$1,
|
|
409
|
-
getBundledCssFromCssText: getBundledCssFromCssText$$1,
|
|
410
|
-
unfetchedToken,
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
startTime(performance.doCaptureFrame);
|
|
414
|
-
const capturedFrame = doCaptureFrame(doc);
|
|
415
|
-
endTime(performance.doCaptureFrame);
|
|
416
|
-
|
|
417
|
-
startTime(performance.waitForImages);
|
|
418
|
-
await Promise.all(promises);
|
|
419
|
-
endTime(performance.waitForImages);
|
|
420
|
-
|
|
421
|
-
// Note: Change the API_VERSION when changing json structure.
|
|
422
|
-
capturedFrame.version = API_VERSION;
|
|
423
|
-
capturedFrame.scriptVersion = '7.1.3';
|
|
424
|
-
|
|
425
|
-
const iframePrefix = iframeCors.length ? `${iframeCors.join('\n')}\n` : '';
|
|
426
|
-
const unfetchedPrefix = unfetchedResources.size
|
|
427
|
-
? `${Array.from(unfetchedResources).join('\n')}\n`
|
|
428
|
-
: '';
|
|
429
|
-
const metaPrefix = JSON.stringify({
|
|
430
|
-
separator,
|
|
431
|
-
cssStartToken: unfetchedToken,
|
|
432
|
-
cssEndToken: unfetchedToken,
|
|
433
|
-
iframeStartToken: `"${iframeToken}`,
|
|
434
|
-
iframeEndToken: `${iframeToken}"`,
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
endTime(performance.total);
|
|
438
|
-
|
|
439
|
-
function stats() {
|
|
440
|
-
if (!addStats) {
|
|
441
|
-
return '';
|
|
442
|
-
}
|
|
443
|
-
return `\n${separator}\n${JSON.stringify(performance)}`;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
const ret = `${metaPrefix}\n${unfetchedPrefix}${separator}\n${iframePrefix}${separator}\n${JSON.stringify(
|
|
447
|
-
capturedFrame,
|
|
448
|
-
)}${stats()}`;
|
|
449
|
-
console.log('[captureFrame]', JSON.stringify(performance));
|
|
450
|
-
return ret;
|
|
451
|
-
|
|
452
|
-
function filter(x) {
|
|
453
|
-
return !!x;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
function notEmptyObj(obj) {
|
|
457
|
-
return Object.keys(obj).length ? obj : undefined;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
function captureTextNode(node) {
|
|
461
|
-
return {
|
|
462
|
-
tagName: '#text',
|
|
463
|
-
text: node.textContent,
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
function doCaptureFrame(frameDoc) {
|
|
468
|
-
const bgImages = new Set();
|
|
469
|
-
let bundledCss = '';
|
|
470
|
-
const ret = captureNode(frameDoc.documentElement);
|
|
471
|
-
ret.css = bundledCss;
|
|
472
|
-
promises.push(getImageSizes_1({bgImages}).then(images => (ret.images = images)));
|
|
473
|
-
return ret;
|
|
474
|
-
|
|
475
|
-
function captureNode(node) {
|
|
476
|
-
const {bundledCss: nodeCss, unfetchedResources: nodeUnfetched} = captureNodeCss$$1(
|
|
477
|
-
node,
|
|
478
|
-
frameDoc.location.href,
|
|
479
|
-
);
|
|
480
|
-
bundledCss += nodeCss;
|
|
481
|
-
if (nodeUnfetched) for (const elem of nodeUnfetched) unfetchedResources.add(elem);
|
|
482
|
-
|
|
483
|
-
switch (node.nodeType) {
|
|
484
|
-
case NODE_TYPES$2.TEXT: {
|
|
485
|
-
return captureTextNode(node);
|
|
486
|
-
}
|
|
487
|
-
case NODE_TYPES$2.ELEMENT: {
|
|
488
|
-
const tagName = node.tagName.toUpperCase();
|
|
489
|
-
if (tagName === 'IFRAME') {
|
|
490
|
-
return iframeToJSON(node);
|
|
491
|
-
} else {
|
|
492
|
-
return elementToJSON(node);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
default: {
|
|
496
|
-
return null;
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
function elementToJSON(el) {
|
|
502
|
-
const childNodes = Array.prototype.map.call(el.childNodes, captureNode).filter(filter);
|
|
503
|
-
|
|
504
|
-
const tagName = el.tagName.toUpperCase();
|
|
505
|
-
if (ignoredTagNames.indexOf(tagName) > -1) return null;
|
|
506
|
-
|
|
507
|
-
const computedStyle = window.getComputedStyle(el);
|
|
508
|
-
const boundingClientRect = el.getBoundingClientRect();
|
|
509
|
-
|
|
510
|
-
const style = {};
|
|
511
|
-
for (const p of styleProps) style[p] = computedStyle.getPropertyValue(p);
|
|
512
|
-
if (!style['border-width']) {
|
|
513
|
-
style['border-width'] = `${computedStyle.getPropertyValue(
|
|
514
|
-
'border-top-width',
|
|
515
|
-
)} ${computedStyle.getPropertyValue('border-right-width')} ${computedStyle.getPropertyValue(
|
|
516
|
-
'border-bottom-width',
|
|
517
|
-
)} ${computedStyle.getPropertyValue('border-left-width')}`;
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
const rect = {};
|
|
521
|
-
for (const p of rectProps) rect[p] = boundingClientRect[p];
|
|
522
|
-
|
|
523
|
-
const attributes = Array.from(el.attributes)
|
|
524
|
-
.map(a => ({key: a.name, value: a.value}))
|
|
525
|
-
.reduce((obj, attr) => {
|
|
526
|
-
obj[attr.key] = attr.value;
|
|
527
|
-
return obj;
|
|
528
|
-
}, {});
|
|
529
|
-
|
|
530
|
-
const bgImage = getBackgroundImageUrl_1(computedStyle.getPropertyValue('background-image'));
|
|
531
|
-
if (bgImage) {
|
|
532
|
-
bgImages.add(bgImage);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
return {
|
|
536
|
-
tagName,
|
|
537
|
-
style: notEmptyObj(style),
|
|
538
|
-
rect: notEmptyObj(rect),
|
|
539
|
-
attributes: notEmptyObj(attributes),
|
|
540
|
-
childNodes,
|
|
541
|
-
};
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
function iframeToJSON(el) {
|
|
545
|
-
const obj = elementToJSON(el);
|
|
546
|
-
let doc;
|
|
547
|
-
try {
|
|
548
|
-
doc = el.contentDocument;
|
|
549
|
-
} catch (ex) {
|
|
550
|
-
markFrameAsCors();
|
|
551
|
-
return obj;
|
|
552
|
-
}
|
|
553
|
-
try {
|
|
554
|
-
if (doc) {
|
|
555
|
-
obj.childNodes = [doCaptureFrame(el.contentDocument)];
|
|
556
|
-
} else {
|
|
557
|
-
markFrameAsCors();
|
|
558
|
-
}
|
|
559
|
-
} catch (ex) {
|
|
560
|
-
console.log('error in iframeToJSON', ex);
|
|
561
|
-
}
|
|
562
|
-
return obj;
|
|
563
|
-
|
|
564
|
-
function markFrameAsCors() {
|
|
565
|
-
const xpath = genXpath_1(el);
|
|
566
|
-
iframeCors.push(xpath);
|
|
567
|
-
obj.childNodes = [`${iframeToken}${xpath}${iframeToken}`];
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
var captureFrame_1 = captureFrame;
|
|
574
|
-
|
|
575
|
-
const EYES_NAME_SPACE = '__EYES__APPLITOOLS__';
|
|
576
|
-
|
|
577
|
-
function captureFrameAndPoll(...args) {
|
|
578
|
-
if (!window[EYES_NAME_SPACE]) {
|
|
579
|
-
window[EYES_NAME_SPACE] = {};
|
|
580
|
-
}
|
|
581
|
-
if (!window[EYES_NAME_SPACE].captureDomResult) {
|
|
582
|
-
window[EYES_NAME_SPACE].captureDomResult = {
|
|
583
|
-
status: 'WIP',
|
|
584
|
-
value: null,
|
|
585
|
-
error: null,
|
|
586
|
-
};
|
|
587
|
-
captureFrame_1(...args)
|
|
588
|
-
.then(r => ((resultObject.status = 'SUCCESS'), (resultObject.value = r)))
|
|
589
|
-
.catch(e => ((resultObject.status = 'ERROR'), (resultObject.error = e.message)));
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
const resultObject = window[EYES_NAME_SPACE].captureDomResult;
|
|
593
|
-
if (resultObject.status === 'SUCCESS') {
|
|
594
|
-
window[EYES_NAME_SPACE].captureDomResult = null;
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
return JSON.stringify(resultObject);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
var captureFrameAndPoll_1 = captureFrameAndPoll;
|
|
601
|
-
|
|
602
|
-
return captureFrameAndPoll_1;
|
|
603
|
-
|
|
604
|
-
}());
|
|
605
|
-
|
|
606
|
-
return captureDomAndPoll.apply(this, arguments);
|
|
607
|
-
}
|
|
608
|
-
SCRIPT
|
|
609
|
-
end
|
|
610
|
-
end
|
|
611
|
-
end
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
require 'css_parser'
|
|
3
|
-
|
|
4
|
-
module Applitools
|
|
5
|
-
module Selenium
|
|
6
|
-
class ExternalCssResources
|
|
7
|
-
include CssParser
|
|
8
|
-
def initialize(url, _base_url = nil)
|
|
9
|
-
@parser = CssParser::Parser.new(absolute_paths: true)
|
|
10
|
-
@parser.load_uri!(url)
|
|
11
|
-
@parser.compact!
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def flatten_rules
|
|
15
|
-
@flatten ||= flatten_hash(hash, 0)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def hash
|
|
19
|
-
@h ||= @parser.to_h
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def images
|
|
23
|
-
result = []
|
|
24
|
-
@parser.each_rule_set do |s|
|
|
25
|
-
s.expand_background_shorthand!
|
|
26
|
-
result.push(s) unless s.get_value('background-image').empty?
|
|
27
|
-
end
|
|
28
|
-
result
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|