@applitools/eyes-testcafe 2.0.0-beta.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +467 -0
  2. package/LICENSE +1 -1
  3. package/README.md +7 -531
  4. package/dist/api.js +51 -0
  5. package/dist/extract-environment.js +15 -0
  6. package/dist/index-legacy.js +5 -0
  7. package/dist/index.js +19 -0
  8. package/dist/legacy.js +225 -0
  9. package/dist/spec-driver.js +245 -0
  10. package/package.json +73 -76
  11. package/types/index-legacy.d.ts +2 -0
  12. package/types/index.d.ts +1833 -0
  13. package/dist/captureFrameAndPoll.js +0 -1468
  14. package/dist/captureFrameAndPollForIE.js +0 -12569
  15. package/index.js +0 -29
  16. package/lib/BordersAwareElementContentLocationProvider.js +0 -79
  17. package/lib/Eyes.js +0 -927
  18. package/lib/EyesFactory.js +0 -73
  19. package/lib/EyesTestCafe.js +0 -1270
  20. package/lib/EyesTestcafeUtils.js +0 -440
  21. package/lib/EyesVisualGrid.js +0 -345
  22. package/lib/ImageOrientationHandler.js +0 -31
  23. package/lib/JavascriptHandler.js +0 -20
  24. package/lib/TestCafeExecutor.js +0 -57
  25. package/lib/capture/EyesWebDriverScreenshot.js +0 -650
  26. package/lib/capture/EyesWebDriverScreenshotFactory.js +0 -32
  27. package/lib/capture/FirefoxScreenshotImageProvider.js +0 -63
  28. package/lib/capture/ImageProviderFactory.js +0 -38
  29. package/lib/capture/SafariScreenshotImageProvider.js +0 -254
  30. package/lib/capture/TakesScreenshotImageProvider.js +0 -35
  31. package/lib/errors/EyesDriverOperationError.js +0 -10
  32. package/lib/errors/NoFramesError.js +0 -7
  33. package/lib/fluent/AccessibilityRegionByElement.js +0 -46
  34. package/lib/fluent/AccessibilityRegionBySelector.js +0 -58
  35. package/lib/fluent/FloatingRegionByElement.js +0 -56
  36. package/lib/fluent/FloatingRegionBySelector.js +0 -63
  37. package/lib/fluent/FrameLocator.js +0 -110
  38. package/lib/fluent/IgnoreRegionByElement.js +0 -51
  39. package/lib/fluent/IgnoreRegionBySelector.js +0 -57
  40. package/lib/fluent/SelectorByElement.js +0 -37
  41. package/lib/fluent/SelectorByLocator.js +0 -47
  42. package/lib/fluent/Target.js +0 -17
  43. package/lib/fluent/TestcafeCheckSettings.js +0 -352
  44. package/lib/frames/Frame.js +0 -149
  45. package/lib/frames/FrameChain.js +0 -175
  46. package/lib/getCaptureDomScript.js +0 -14
  47. package/lib/hash.js +0 -15
  48. package/lib/isTestcafeSelector.js +0 -7
  49. package/lib/makeClientFunctionWrapper.js +0 -61
  50. package/lib/positioning/CssTranslatePositionMemento.js +0 -39
  51. package/lib/positioning/CssTranslatePositionProvider.js +0 -130
  52. package/lib/positioning/ElementPositionMemento.js +0 -36
  53. package/lib/positioning/ElementPositionProvider.js +0 -88
  54. package/lib/positioning/FirefoxRegionPositionCompensation.js +0 -45
  55. package/lib/positioning/ImageRotation.js +0 -22
  56. package/lib/positioning/OverflowAwareCssTranslatePositionProvider.js +0 -17
  57. package/lib/positioning/OverflowAwareScrollPositionProvider.js +0 -17
  58. package/lib/positioning/RegionPositionCompensationFactory.js +0 -37
  59. package/lib/positioning/SafariRegionPositionCompensation.js +0 -26
  60. package/lib/positioning/ScrollPositionMemento.js +0 -36
  61. package/lib/positioning/ScrollPositionProvider.js +0 -118
  62. package/lib/positioning/fixImageMarkPosition.js +0 -36
  63. package/lib/regionVisibility/MoveToRegionVisibilityStrategy.js +0 -55
  64. package/lib/regionVisibility/NopRegionVisibilityStrategy.js +0 -35
  65. package/lib/regionVisibility/RegionVisibilityStrategy.js +0 -30
  66. package/lib/runner/ClassicRunner.js +0 -31
  67. package/lib/runner/EyesRunner.js +0 -41
  68. package/lib/runner/TestResultContainer.js +0 -38
  69. package/lib/runner/TestResultsSummary.js +0 -112
  70. package/lib/runner/VisualGridRunner.js +0 -57
  71. package/lib/safeExecuteFunction.js +0 -28
  72. package/lib/wrappers/EyesTargetLocator.js +0 -329
  73. package/lib/wrappers/EyesWebDriver.js +0 -560
  74. package/lib/wrappers/EyesWebElement.js +0 -383
  75. package/lib/wrappers/EyesWebElementPromise.js +0 -68
@@ -1,1270 +0,0 @@
1
- 'use strict'
2
-
3
- const {DomCapture} = require('@applitools/dom-utils')
4
-
5
- const {
6
- SimplePropertyHandler,
7
- CoordinatesType,
8
- Region,
9
- Location,
10
- RectangleSize,
11
- UserAgent,
12
- ArgumentGuard,
13
- TypeUtils,
14
- StitchMode,
15
- } = require('@applitools/eyes-common')
16
-
17
- const {
18
- FullPageCaptureAlgorithm,
19
- FixedScaleProviderFactory,
20
- NullScaleProvider,
21
- RegionProvider,
22
- NullRegionProvider,
23
- ContextBasedScaleProviderFactory,
24
- ScaleProviderIdentityFactory,
25
- NullCutProvider,
26
- MatchResult,
27
- EyesJsBrowserUtils,
28
- } = require('@applitools/eyes-sdk-core')
29
- const getCaptureDomScript = require('./getCaptureDomScript')
30
-
31
- const {ClassicRunner} = require('./runner/ClassicRunner')
32
- const {ImageProviderFactory} = require('./capture/ImageProviderFactory')
33
- const {EyesWebDriverScreenshotFactory} = require('./capture/EyesWebDriverScreenshotFactory')
34
- const {FrameChain} = require('./frames/FrameChain')
35
- const {EyesTargetLocator} = require('./wrappers/EyesTargetLocator')
36
- const {EyesTestcafeUtils} = require('./EyesTestcafeUtils')
37
- const {EyesWebElement} = require('./wrappers/EyesWebElement')
38
- const {EyesWebDriverScreenshot} = require('./capture/EyesWebDriverScreenshot')
39
- const {
40
- RegionPositionCompensationFactory,
41
- } = require('./positioning/RegionPositionCompensationFactory')
42
- const {ScrollPositionProvider} = require('./positioning/ScrollPositionProvider')
43
- const {ElementPositionProvider} = require('./positioning/ElementPositionProvider')
44
- const {CssTranslatePositionProvider} = require('./positioning/CssTranslatePositionProvider')
45
- const {Eyes} = require('./Eyes')
46
- const GEN_XPATH_SCRIPT = `function genXpath(el) {
47
- if (!el.ownerDocument) return ''; // this is the document node
48
- let xpath = '',
49
- currEl = el,
50
- doc = el.ownerDocument,
51
- frameElement = doc.defaultView.frameElement,
52
- index;
53
- while (currEl !== doc) {
54
- index = window.Array.prototype.filter.call(currEl.parentNode.childNodes, node => node.tagName === currEl.tagName).indexOf(currEl) + 1
55
- xpath = currEl.tagName + '[' + index + ']/' + xpath;
56
- currEl = currEl.parentNode;
57
- }
58
- if (frameElement) {
59
- xpath = genXpath(frameElement) + ',' + xpath;
60
- }
61
- return xpath.replace(/\\/$/, '');
62
- }`
63
-
64
- const ELEMENTS_BY_XPATH_SCRIPT = `xpath => {
65
- const iterator = document.evaluate(xpath, document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
66
- const items = [];
67
- let item = iterator.iterateNext();
68
- while (item) {
69
- items.push(item);
70
- item = iterator.iterateNext();
71
- }
72
- return items;
73
- }`
74
-
75
- /**
76
- * The main API gateway for the SDK.
77
- *
78
- * @ignore
79
- */
80
- class EyesTestCafe extends Eyes {
81
- /** @var {Logger} EyesTestCafe#_logger */
82
- /** @var {Configuration} EyesTestCafe#_configuration */
83
-
84
- /**
85
- * Creates a new (possibly disabled) Eyes instance that interacts with the Eyes Server at the specified url.
86
- *
87
- * @param {string} [serverUrl] - The Eyes server URL.
88
- * @param {boolean} [isDisabled=false] - Set {@code true} to disable Applitools Eyes and use the WebDriver directly.
89
- * @param {ClassicRunner} [runner] - Set shared ClassicRunner if you want to group results.
90
- */
91
- constructor(serverUrl, isDisabled, runner = new ClassicRunner()) {
92
- super(serverUrl, isDisabled, runner)
93
-
94
- /** @type {boolean} */
95
- this._checkFrameOrElement = false
96
-
97
- /** @type {Location} */
98
- this._imageLocation = undefined
99
-
100
- /** @type {UserAgent} */
101
- this._userAgent = undefined
102
- /** @type {ImageProvider} */
103
- this._imageProvider = undefined
104
- /** @type {RegionPositionCompensation} */
105
- this._regionPositionCompensation = undefined
106
-
107
- /** @type {EyesWebElement|WebElement} */
108
- this._targetElement = undefined
109
- /** @type {PositionMemento} */
110
- this._positionMemento = undefined
111
- /** @type {Region} */
112
- this._effectiveViewport = Region.EMPTY
113
- /** @type {EyesWebDriverScreenshotFactory} */
114
- this._screenshotFactory = undefined
115
- }
116
-
117
- /**
118
- * @inheritDoc
119
- */
120
- async open(driver, appName, testName, viewportSize, sessionType) {
121
- if (this.getIsDisabled()) {
122
- this._logger.verbose('Ignored')
123
- return driver
124
- }
125
-
126
- ArgumentGuard.notNull(driver, 'driver')
127
-
128
- // noinspection NonBlockStatementBodyJS
129
- if (appName) this._configuration.setAppName(appName)
130
- // noinspection NonBlockStatementBodyJS
131
- if (testName) this._configuration.setTestName(testName)
132
- // noinspection NonBlockStatementBodyJS
133
- if (viewportSize) this._configuration.setViewportSize(viewportSize)
134
- // noinspection NonBlockStatementBodyJS
135
- if (sessionType) this._configuration.setSessionType(sessionType)
136
-
137
- ArgumentGuard.notNull(this._configuration.getAppName(), 'appName')
138
- ArgumentGuard.notNull(this._configuration.getTestName(), 'testName')
139
-
140
- this._initDriver(driver)
141
-
142
- this._screenshotFactory = new EyesWebDriverScreenshotFactory(this._logger, this._driver)
143
-
144
- const uaString = await this._driver.getUserAgent()
145
- if (uaString) {
146
- this._userAgent = UserAgent.parseUserAgentString(uaString, true)
147
- }
148
-
149
- this._imageProvider = ImageProviderFactory.getImageProvider(
150
- this._userAgent,
151
- this,
152
- this._logger,
153
- this._driver,
154
- )
155
- this._regionPositionCompensation = RegionPositionCompensationFactory.getRegionPositionCompensation(
156
- this._userAgent,
157
- this,
158
- this._logger,
159
- )
160
-
161
- await this.openBase(
162
- this._configuration.getAppName(),
163
- this._configuration.getTestName(),
164
- this._configuration.getViewportSize(),
165
- this._configuration.getSessionType(),
166
- )
167
-
168
- this._devicePixelRatio = Eyes.UNKNOWN_DEVICE_PIXEL_RATIO
169
-
170
- this._driver.setRotation(this._rotation)
171
- return this._driver
172
- }
173
-
174
- /**
175
- * @private
176
- * @return {PositionProvider}
177
- */
178
- _createPositionProvider(scrollRootElement = this._scrollRootElement) {
179
- // Setting the correct position provider.
180
- this._logger.verbose(
181
- 'initializing position provider. stitchMode:',
182
- this._configuration.getStitchMode(),
183
- )
184
-
185
- switch (this._configuration.getStitchMode()) {
186
- case StitchMode.CSS:
187
- return new CssTranslatePositionProvider(this._logger, this._jsExecutor, scrollRootElement)
188
- default:
189
- return new ScrollPositionProvider(this._logger, this._jsExecutor, scrollRootElement)
190
- }
191
- }
192
-
193
- /**
194
- * Perform visual validation
195
- *
196
- * @param {string} name - A name to be associated with the match
197
- * @param {TestcafeCheckSettings} checkSettings - Target instance which describes whether we want a window/region/frame
198
- * @return {Promise<TestResults>} - A promise which is resolved when the validation is finished.
199
- */
200
- async testWindow(name, checkSettings) {
201
- const originalCheckWindowBase = this.checkWindowBase
202
- try {
203
- this.checkWindowBase = this.checkSingleWindowBase
204
-
205
- return await this.check(name, checkSettings)
206
- } finally {
207
- this.checkWindowBase = originalCheckWindowBase
208
- }
209
- }
210
-
211
- // noinspection FunctionWithMoreThanThreeNegationsJS
212
- /**
213
- * @inheritDoc
214
- */
215
- async check(name, checkSettings) {
216
- if (this._configuration.getIsDisabled()) {
217
- this._logger.log(`check('${name}', ${checkSettings}): Ignored`)
218
- return new MatchResult()
219
- }
220
-
221
- ArgumentGuard.notNull(checkSettings, 'checkSettings')
222
- ArgumentGuard.isValidState(this._isOpen, 'Eyes not open')
223
-
224
- if (TypeUtils.isNotNull(name)) {
225
- checkSettings.withName(name)
226
- } else {
227
- name = checkSettings.getName()
228
- }
229
-
230
- this._logger.verbose(`check(${checkSettings}) - begin`)
231
- this._stitchContent = checkSettings.getStitchContent()
232
- const targetRegion = checkSettings.getTargetRegion()
233
- this._scrollRootElement = this._getScrollRootElementFromCheckSettings(checkSettings)
234
-
235
- this._currentFramePositionProvider = null
236
- this.setPositionProvider(this._createPositionProvider())
237
- this._originalFC = this._driver.getFrameChain().clone()
238
-
239
- // const validationInfo = this.fireValidationWillStartEvent(name);
240
-
241
- // if (!(await EyesTestcafeUtils.isMobileDevice(this._driver))) {
242
- this._logger.verbose(`URL: ${await this._driver.getCurrentUrl()}`)
243
- // }
244
-
245
- const switchedToFrameCount = await this._switchToFrame(checkSettings)
246
-
247
- this._regionToCheck = null
248
-
249
- let result = null
250
-
251
- const switchTo = this._driver.switchTo()
252
- let originalFC = null
253
-
254
- if (targetRegion) {
255
- this._logger.verbose('have target region')
256
- originalFC = await this._tryHideScrollbars()
257
- this._imageLocation = targetRegion.getLocation()
258
- const source = await this._driver.getCurrentUrl()
259
- result = await this.checkWindowBase(
260
- new RegionProvider(targetRegion),
261
- name,
262
- false,
263
- checkSettings,
264
- source,
265
- )
266
- } else if (checkSettings) {
267
- let targetElement = checkSettings.getTargetElement()
268
-
269
- const targetSelector = checkSettings.getTargetSelector()
270
- if (!targetElement && targetSelector) {
271
- targetElement = this._driver.findElement(targetSelector)
272
- }
273
-
274
- if (targetElement) {
275
- this._logger.verbose('have target element')
276
- originalFC = await this._tryHideScrollbars()
277
- this._targetElement = new EyesWebElement(this._logger, this._driver, targetElement)
278
- if (this._stitchContent) {
279
- result = await this._checkElement(undefined, name, checkSettings)
280
- } else {
281
- result = await this._checkRegionByElement(name, checkSettings)
282
- }
283
- this._targetElement = null
284
- } else if (checkSettings.getFrameChain().length > 0) {
285
- this._logger.verbose('have frame chain')
286
- originalFC = await this._tryHideScrollbars()
287
- if (this._stitchContent) {
288
- result = await this._checkFullFrameOrElement(name, checkSettings)
289
- } else {
290
- result = await this._checkFrameFluent(name, checkSettings)
291
- }
292
- } else {
293
- this._logger.verbose('default case')
294
- // if (!(await EyesTestcafeUtils.isMobileDevice(this._driver))) {
295
- // required to prevent cut line on the last stitched part of the page on some browsers (like firefox).
296
- await switchTo.defaultContent()
297
- originalFC = await this._tryHideScrollbars()
298
- const scrollRootElement = this.getScrollRootElement()
299
- this._currentFramePositionProvider = this._createPositionProvider(scrollRootElement)
300
- // }
301
- const source = await this._driver.getCurrentUrl()
302
- result = await this.checkWindowBase(
303
- new NullRegionProvider(),
304
- name,
305
- false,
306
- checkSettings,
307
- source,
308
- )
309
- await switchTo.frames(this._originalFC)
310
- }
311
- }
312
-
313
- if (!result) {
314
- result = new MatchResult()
315
- }
316
-
317
- await this._switchToParentFrame(switchedToFrameCount)
318
-
319
- if (this._positionMemento) {
320
- await this._positionProviderHandler.get().restoreState(this._positionMemento)
321
- this._positionMemento = null
322
- }
323
-
324
- await switchTo.resetScroll()
325
-
326
- if (originalFC) {
327
- await this._tryRestoreScrollbars(originalFC)
328
- }
329
-
330
- await this._trySwitchToFrames(switchTo, this._originalFC)
331
-
332
- this._stitchContent = false
333
- this._imageLocation = null
334
-
335
- this._logger.verbose('check - done!')
336
- return result
337
- }
338
-
339
- /**
340
- * @private
341
- * @param {EyesTargetLocator} switchTo
342
- * @param {FrameChain} frames
343
- * @return {Promise}
344
- */
345
- async _trySwitchToFrames(switchTo, frames) {
346
- // if (await EyesTestcafeUtils.isMobileDevice(this._driver)) {
347
- // return;
348
- // }
349
-
350
- try {
351
- await switchTo.frames(frames)
352
- } catch (err) {
353
- this._logger.log(`WARNING: Failed to switch to original frame chain! ${err}`)
354
- }
355
- }
356
-
357
- /**
358
- * @private
359
- * @return {Promise<MatchResult>}
360
- */
361
- async _checkFrameFluent(name, checkSettings) {
362
- const frameChain = this._driver.getFrameChain().clone()
363
- const targetFrame = frameChain.pop()
364
- this._targetElement = targetFrame.getReference()
365
-
366
- await this._driver.switchTo().framesDoScroll(frameChain)
367
- const result = await this._checkRegionByElement(name, checkSettings)
368
- this._targetElement = null
369
- return result
370
- }
371
-
372
- /**
373
- * @private
374
- * @return {Promise<number>}
375
- */
376
- async _switchToParentFrame(switchedToFrameCount) {
377
- if (switchedToFrameCount > 0) {
378
- await this._driver.switchTo().parentFrame()
379
- return this._switchToParentFrame(switchedToFrameCount - 1)
380
- }
381
-
382
- return switchedToFrameCount
383
- }
384
-
385
- /**
386
- * @private
387
- * @param {TestcafeCheckSettings} checkSettings
388
- * @return {Promise<number>}
389
- */
390
- async _switchToFrame(checkSettings) {
391
- if (!checkSettings) {
392
- return 0
393
- }
394
-
395
- const frameChain = checkSettings.getFrameChain()
396
- let switchedToFrameCount = 0
397
- for (const frameLocator of frameChain) {
398
- if (await this._switchToFrameLocator(frameLocator)) {
399
- switchedToFrameCount += 1
400
- }
401
- }
402
- return switchedToFrameCount
403
- }
404
-
405
- /**
406
- * @private
407
- * @param {FrameLocator} frameTarget
408
- * @return {Promise<boolean>}
409
- */
410
- async _switchToFrameLocator(frameTarget) {
411
- const switchTo = this._driver.switchTo()
412
-
413
- if (frameTarget.getFrameIndex()) {
414
- await switchTo.frame(frameTarget.getFrameIndex())
415
- await this._updateFrameScrollRoot(frameTarget)
416
- return true
417
- }
418
-
419
- if (frameTarget.getFrameNameOrId()) {
420
- await switchTo.frame(frameTarget.getFrameNameOrId())
421
- await this._updateFrameScrollRoot(frameTarget)
422
- return true
423
- }
424
-
425
- if (frameTarget.getFrameElement()) {
426
- await switchTo.frame(frameTarget.getFrameElement())
427
- await this._updateFrameScrollRoot(frameTarget)
428
- return true
429
- }
430
-
431
- if (frameTarget.getFrameSelector()) {
432
- const frameElement = this._driver.findElement(frameTarget.getFrameSelector())
433
- if (frameElement) {
434
- await switchTo.frame(frameElement)
435
- await this._updateFrameScrollRoot(frameTarget)
436
- return true
437
- }
438
- }
439
-
440
- return false
441
- }
442
-
443
- /**
444
- * @private
445
- * @param {FrameLocator} frameTarget
446
- */
447
- async _updateFrameScrollRoot(frameTarget) {
448
- const rootElement = await this._getScrollRootElementFromCheckSettings(frameTarget)
449
- const frame = this._driver.getFrameChain().peek()
450
- frame.setScrollRootElement(rootElement)
451
- }
452
-
453
- /**
454
- * @private
455
- * @return {Promise<MatchResult>}
456
- */
457
- async _checkFullFrameOrElement(name, checkSettings) {
458
- const self = this
459
- this._checkFrameOrElement = true
460
- this._logger.verbose('checkFullFrameOrElement()')
461
-
462
- /**
463
- * @private
464
- * @type {RegionProvider}
465
- */
466
- const RegionProviderImpl = class RegionProviderImpl extends RegionProvider {
467
- // noinspection JSUnusedGlobalSymbols
468
- /** @inheritDoc */
469
- async getRegion() {
470
- const region = await self._getFullFrameOrElementRegion()
471
- self._imageLocation = region.getLocation()
472
- return region
473
- }
474
- }
475
-
476
- const source = await this._driver.getCurrentUrl()
477
- const result = await this.checkWindowBase(
478
- new RegionProviderImpl(),
479
- name,
480
- false,
481
- checkSettings,
482
- source,
483
- )
484
- this._checkFrameOrElement = false
485
- return result
486
- }
487
-
488
- /**
489
- * @private
490
- * @return {Promise<Region>}
491
- */
492
- async _getFullFrameOrElementRegion() {
493
- if (this._checkFrameOrElement) {
494
- const fc = await this._ensureFrameVisible()
495
-
496
- // FIXME - Scaling should be handled in a single place instead
497
- const scaleProviderFactory = await this._updateScalingParams()
498
-
499
- const screenshotImage = await this._imageProvider.getImage()
500
-
501
- await this._debugScreenshotsProvider.save(screenshotImage, 'checkFullFrameOrElement')
502
-
503
- scaleProviderFactory.getScaleProvider(screenshotImage.getWidth())
504
-
505
- const switchTo = this._driver.switchTo()
506
- await switchTo.frames(fc)
507
-
508
- const screenshot = await EyesWebDriverScreenshot.fromScreenshotType(
509
- this._logger,
510
- this._driver,
511
- screenshotImage,
512
- )
513
- this._logger.verbose('replacing regionToCheck')
514
- this.setRegionToCheck(screenshot.getFrameWindow())
515
- }
516
-
517
- return Region.EMPTY
518
- }
519
-
520
- /**
521
- * @private
522
- * @return {Promise<FrameChain>}
523
- */
524
- async _ensureFrameVisible() {
525
- this._logger.verbose('scrollRootElement_:', this._scrollRootElement)
526
- const originalFC = this._driver.getFrameChain().clone()
527
- const fc = this._driver.getFrameChain().clone()
528
- await this._driver.executeScript('window.scrollTo(0,0);')
529
-
530
- while (fc.size() > 0) {
531
- this._logger.verbose(`fc.Count: ${fc.size()}`)
532
- // driver.getRemoteWebDriver().switchTo().parentFrame();
533
- await EyesTargetLocator.tryParentFrame(this._driver.getRemoteWebDriver().switchTo(), fc)
534
- await this._driver.executeScript('window.scrollTo(0,0);')
535
- const prevFrame = fc.pop()
536
- const frame = fc.peek()
537
- let scrollRootElement = null
538
- if (fc.size() === this._originalFC.size()) {
539
- this._logger.verbose('PositionProvider:', this._positionProviderHandler.get())
540
- this._positionMemento = await this._positionProviderHandler.get().getState()
541
- scrollRootElement = this._scrollRootElement
542
- } else {
543
- if (frame != null) {
544
- scrollRootElement = await frame.getForceScrollRootElement(this._driver)
545
- }
546
- if (scrollRootElement == null) {
547
- scrollRootElement = this._driver.findElement('html')
548
- }
549
- }
550
- this._logger.verbose('scrollRootElement:', scrollRootElement)
551
-
552
- const positionProvider = this._getElementPositionProvider(scrollRootElement)
553
- await positionProvider.setPosition(prevFrame.getLocation())
554
-
555
- const reg = new Region(Location.ZERO, prevFrame.getInnerSize())
556
- this._effectiveViewport.intersect(reg)
557
- }
558
- await this._driver.switchTo().frames(originalFC)
559
- return originalFC
560
- }
561
-
562
- /**
563
- * @private
564
- * @param {WebElement} element
565
- * @return {Promise}
566
- */
567
- async _ensureElementVisible(element) {
568
- if (this._targetElement == null || !this.getScrollToRegion()) {
569
- // No element? we must be checking the window.
570
- return
571
- }
572
-
573
- // if (await EyesTestcafeUtils.isMobileDevice(this._driver)) {
574
- // this._logger.log("NATIVE context identified, skipping 'ensure element visible'");
575
- // return;
576
- // }
577
-
578
- const originalFC = this._driver.getFrameChain().clone()
579
- const switchTo = this._driver.switchTo()
580
-
581
- const eyesWebElement = new EyesWebElement(this._logger, this._driver, element)
582
- let elementBounds = await eyesWebElement.getBounds()
583
-
584
- const currentFrameOffset = originalFC.getCurrentFrameOffset()
585
- elementBounds = elementBounds.offset(currentFrameOffset.getX(), currentFrameOffset.getY())
586
-
587
- const viewportBounds = await this._getViewportScrollBounds()
588
-
589
- this._logger.verbose(`viewportBounds: ${viewportBounds} ; elementBounds: ${elementBounds}`)
590
-
591
- if (!viewportBounds.contains(elementBounds)) {
592
- await this._ensureFrameVisible()
593
-
594
- const rect = await eyesWebElement.getRect()
595
- const elementLocation = new Location(rect)
596
-
597
- let scrollRootElement
598
- if (
599
- originalFC.size() > 0 &&
600
- !(await EyesWebElement.equals(element, originalFC.peek().getReference()))
601
- ) {
602
- await switchTo.frames(originalFC)
603
- scrollRootElement = await this._driver.findElement('html')
604
- } else {
605
- scrollRootElement = this._scrollRootElement
606
- }
607
-
608
- const positionProvider = this._getElementPositionProvider(scrollRootElement)
609
- await positionProvider.setPosition(elementLocation)
610
- }
611
- }
612
-
613
- /**
614
- * @private
615
- * @return {Promise<Region>}
616
- */
617
- async _getViewportScrollBounds() {
618
- if (!this.getScrollToRegion()) {
619
- this._logger.log('WARNING: no region visibility strategy! returning an empty region!')
620
- return Region.EMPTY
621
- }
622
-
623
- const originalFrameChain = this._driver.getFrameChain().clone()
624
- const switchTo = this._driver.switchTo()
625
- await switchTo.frames(this._originalFC)
626
- const spp = new ScrollPositionProvider(this._logger, this._jsExecutor, this._scrollRootElement)
627
- let location = null
628
- try {
629
- location = await spp.getCurrentPosition()
630
- } catch (err) {
631
- this._logger.log(`WARNING: ${err}`)
632
- this._logger.log('Assuming position is 0,0')
633
- location = new Location(Location.ZERO)
634
- }
635
-
636
- const size = await this.getViewportSize()
637
- const viewportBounds = new Region(location, size)
638
- await switchTo.frames(originalFrameChain)
639
- return viewportBounds
640
- }
641
-
642
- /**
643
- * @private
644
- * @return {Promise<MatchResult>}
645
- */
646
- async _checkRegionByElement(name, checkSettings) {
647
- const self = this
648
-
649
- /**
650
- * @private
651
- * @type {RegionProvider}
652
- */
653
- const RegionProviderImpl = class RegionProviderImpl extends RegionProvider {
654
- // noinspection JSUnusedGlobalSymbols
655
- /** @inheritDoc */
656
- async getRegion() {
657
- const rect = await self._targetElement.getRect()
658
- // noinspection JSSuspiciousNameCombination
659
- const region = new Region(
660
- Math.ceil(rect.x),
661
- Math.ceil(rect.y),
662
- rect.width,
663
- rect.height,
664
- CoordinatesType.CONTEXT_RELATIVE,
665
- )
666
- self._imageLocation = region.getLocation()
667
- return region
668
- }
669
- }
670
-
671
- const source = await this._driver.getCurrentUrl()
672
- const result = await this.checkWindowBase(
673
- new RegionProviderImpl(),
674
- name,
675
- false,
676
- checkSettings,
677
- source,
678
- )
679
- this._logger.verbose('Done! trying to scroll back to original position...')
680
- return result
681
- }
682
-
683
- /**
684
- * @private
685
- * @return {Promise<MatchResult>}
686
- */
687
- async _checkElement(eyesElement = this._targetElement, name, checkSettings) {
688
- this._regionToCheck = null
689
- const scrollRootElement = await this.getCurrentFrameScrollRootElement()
690
- const positionProvider = this._createPositionProvider(scrollRootElement)
691
- const originalPositionMemento = await positionProvider.getState()
692
-
693
- await this._ensureElementVisible(this._targetElement)
694
-
695
- let result
696
- let originalOverflow
697
- const rect = await eyesElement.getRect()
698
-
699
- try {
700
- this._checkFrameOrElement = true
701
-
702
- const displayStyle = await eyesElement.getComputedStyle('display')
703
-
704
- if (this._configuration.getHideScrollbars()) {
705
- originalOverflow = await eyesElement.getOverflow()
706
- await eyesElement.setOverflow('hidden')
707
- }
708
-
709
- const sizeAndBorders = await eyesElement.getSizeAndBorders()
710
-
711
- if (
712
- displayStyle !== 'inline' &&
713
- sizeAndBorders.height <= this._effectiveViewport.getHeight() &&
714
- sizeAndBorders.width <= this._effectiveViewport.getWidth()
715
- ) {
716
- this._elementPositionProvider = new ElementPositionProvider(
717
- this._logger,
718
- this._driver,
719
- eyesElement,
720
- )
721
- } else {
722
- this._elementPositionProvider = null
723
- }
724
-
725
- const elementRegion = new Region(
726
- rect.x + sizeAndBorders.left,
727
- rect.y + sizeAndBorders.top,
728
- sizeAndBorders.width,
729
- sizeAndBorders.height,
730
- CoordinatesType.SCREENSHOT_AS_IS,
731
- )
732
-
733
- this._logger.verbose('Element region:', elementRegion)
734
-
735
- this._regionToCheck = elementRegion
736
-
737
- if (!this._effectiveViewport.isSizeEmpty()) {
738
- this._regionToCheck.intersect(this._effectiveViewport)
739
- }
740
-
741
- this._imageLocation = this._regionToCheck.getLocation()
742
- const source = await this._driver.getCurrentUrl()
743
- result = await this.checkWindowBase(
744
- new NullRegionProvider(),
745
- name,
746
- false,
747
- checkSettings,
748
- source,
749
- )
750
- } finally {
751
- if (originalOverflow) {
752
- await eyesElement.setOverflow(originalOverflow)
753
- }
754
-
755
- this._checkFrameOrElement = false
756
-
757
- await positionProvider.restoreState(originalPositionMemento)
758
- this._regionToCheck = null
759
- this._elementPositionProvider = null
760
- this._imageLocation = null
761
- }
762
-
763
- return result
764
- }
765
-
766
- /**
767
- * Updates the state of scaling related parameters.
768
- *
769
- * @protected
770
- * @return {Promise<ScaleProviderFactory>}
771
- */
772
- async _updateScalingParams() {
773
- // Update the scaling params only if we haven't done so yet, and the user hasn't set anything else manually.
774
- if (
775
- this._devicePixelRatio === Eyes.UNKNOWN_DEVICE_PIXEL_RATIO &&
776
- this._scaleProviderHandler.get() instanceof NullScaleProvider
777
- ) {
778
- let factory
779
- this._logger.verbose('Trying to extract device pixel ratio...')
780
-
781
- try {
782
- this._devicePixelRatio = await EyesTestcafeUtils.getDevicePixelRatio(this._jsExecutor)
783
- } catch (err) {
784
- this._logger.verbose('Failed to extract device pixel ratio! Using default.', err)
785
- this._devicePixelRatio = Eyes.DEFAULT_DEVICE_PIXEL_RATIO
786
- }
787
- this._logger.verbose(`Device pixel ratio: ${this._devicePixelRatio}`)
788
-
789
- this._logger.verbose('Setting scale provider...')
790
- try {
791
- factory = await this._getScaleProviderFactory()
792
- } catch (err) {
793
- this._logger.verbose('Failed to set ContextBasedScaleProvider.', err)
794
- this._logger.verbose('Using FixedScaleProvider instead...')
795
- factory = new FixedScaleProviderFactory(
796
- 1 / this._devicePixelRatio,
797
- this._scaleProviderHandler,
798
- )
799
- }
800
-
801
- this._logger.verbose('Done!')
802
- return factory
803
- }
804
-
805
- // If we already have a scale provider set, we'll just use it, and pass a mock as provider handler.
806
- const nullProvider = new SimplePropertyHandler()
807
- return new ScaleProviderIdentityFactory(this._scaleProviderHandler.get(), nullProvider)
808
- }
809
-
810
- /**
811
- * @private
812
- * @return {Promise<ScaleProviderFactory>}
813
- */
814
- async _getScaleProviderFactory() {
815
- const element = await this._driver.findElement('html')
816
- const entireSize = await EyesTestcafeUtils.getEntireElementSize(this._jsExecutor, element)
817
-
818
- return new ContextBasedScaleProviderFactory(
819
- this._logger,
820
- entireSize,
821
- this._viewportSizeHandler.get(),
822
- this._devicePixelRatio,
823
- false,
824
- this._scaleProviderHandler,
825
- )
826
- }
827
-
828
- /**
829
- * @param {boolean} [throwEx]
830
- * @return {Promise<TestResults>}
831
- */
832
- async close(throwEx = true) {
833
- const results = await Eyes.prototype.close.call(this, throwEx)
834
-
835
- if (this._runner) {
836
- this._runner._allTestResult.push(results)
837
- }
838
-
839
- return results
840
- }
841
-
842
- /**
843
- * @inheritDoc
844
- */
845
- async getViewportSize() {
846
- let viewportSize = this._viewportSizeHandler.get()
847
- if (!viewportSize) {
848
- viewportSize = await this._driver.getDefaultContentViewportSize()
849
- }
850
-
851
- return viewportSize
852
- }
853
-
854
- /**
855
- * @inheritDoc
856
- */
857
- async tryCaptureDom() {
858
- try {
859
- this._logger.verbose('Getting window DOM...')
860
- const captureDomScript = await getCaptureDomScript({
861
- webDriver: this._driver,
862
- logger: this._logger,
863
- })
864
- return await DomCapture.getFullWindowDom(
865
- this._logger,
866
- this._driver,
867
- undefined,
868
- undefined,
869
- captureDomScript,
870
- )
871
- } catch (err) {
872
- this._logger.log(`Error capturing DOM of the page: ${JSON.stringify(err)}`)
873
- return ''
874
- }
875
- }
876
-
877
- /**
878
- * @private
879
- * @return {Promise<FrameChain>}
880
- */
881
- async _tryHideScrollbars() {
882
- // if (await EyesTestcafeUtils.isMobileDevice(this._driver)) {
883
- // return new FrameChain(this._logger);
884
- // }
885
-
886
- if (
887
- this._configuration.getHideScrollbars() ||
888
- (this._configuration.getStitchMode() === StitchMode.CSS && this._stitchContent)
889
- ) {
890
- const originalFC = this._driver.getFrameChain().clone()
891
- const fc = this._driver.getFrameChain().clone()
892
- let frame = fc.peek()
893
-
894
- if (fc.size() > 0) {
895
- while (fc.size() > 0) {
896
- this._logger.verbose(`fc.Count = ${fc.size()}`)
897
-
898
- if (this._stitchContent || fc.size() !== originalFC.size()) {
899
- if (frame === null) {
900
- this._logger.verbose('hiding scrollbars of element (1)')
901
- await EyesTestcafeUtils.setOverflow(this._driver, 'hidden', this._scrollRootElement)
902
- } else {
903
- await frame.hideScrollbars(this._driver)
904
- }
905
- }
906
-
907
- await this._driver.switchTo().parentFrame()
908
- fc.pop()
909
- frame = fc.peek()
910
- }
911
- } else {
912
- this._logger.verbose('hiding scrollbars of element (2)')
913
- this._originalOverflow = await EyesTestcafeUtils.setOverflow(
914
- this._driver,
915
- 'hidden',
916
- this._scrollRootElement,
917
- )
918
- }
919
-
920
- this._logger.verbose('switching back to original frame')
921
- await this._driver.switchTo().frames(originalFC)
922
- this._logger.verbose('done hiding scrollbars.')
923
- return originalFC
924
- }
925
-
926
- return new FrameChain(this._logger)
927
- }
928
-
929
- /**
930
- * @inheritDoc
931
- */
932
- async getImageLocation() {
933
- if (this._imageLocation) {
934
- return this._imageLocation
935
- }
936
-
937
- return Location.ZERO
938
- }
939
-
940
- /**
941
- * @private
942
- * @param {FrameChain} frameChain
943
- * @return {Promise}
944
- */
945
- async _tryRestoreScrollbars(frameChain) {
946
- // if (await EyesTestcafeUtils.isMobileDevice(this._driver)) {
947
- // return;
948
- // }
949
-
950
- if (
951
- this._configuration.getHideScrollbars() ||
952
- (this._configuration.getStitchMode() === StitchMode.CSS && this._stitchContent)
953
- ) {
954
- await this._driver.switchTo().frames(frameChain)
955
- const originalFC = frameChain.clone()
956
- const fc = frameChain.clone()
957
- if (fc.size() > 0) {
958
- while (fc.size() > 0) {
959
- const frame = fc.pop()
960
- await frame.returnToOriginalOverflow(this._driver)
961
- await EyesTargetLocator.tryParentFrame(this._driver.getRemoteWebDriver().switchTo(), fc)
962
- }
963
- } else {
964
- this._logger.verbose('returning overflow of element to its original value')
965
- await EyesTestcafeUtils.setOverflow(
966
- this._driver,
967
- this._originalOverflow,
968
- this._scrollRootElement,
969
- )
970
- }
971
- await this._driver.switchTo().frames(originalFC)
972
- this._logger.verbose('done restoring scrollbars.')
973
- } else {
974
- this._logger.verbose('no need to restore scrollbars.')
975
- }
976
- this._driver.getFrameChain().clear()
977
- }
978
-
979
- /*
980
- /**
981
- * @protected
982
- * @return {Promise}
983
- * /
984
- _afterMatchWindow() {
985
- if (this.hideScrollbars) {
986
- try {
987
- EyesTestcafeUtils.setOverflow(this.driver, this.originalOverflow);
988
- } catch (EyesDriverOperationException e) {
989
- // Bummer, but we'll continue with the screenshot anyway :)
990
- logger.log("WARNING: Failed to revert overflow! Error: " + e.getMessage());
991
- }
992
- }
993
- }
994
- */
995
-
996
- /**
997
- * Gets scroll root element.
998
- *
999
- * @override
1000
- * @return {Promise<WebElement>} the scroll root element
1001
- */
1002
- getScrollRootElement() {
1003
- if (this._scrollRootElement == null) {
1004
- this._scrollRootElement = this._driver.findElement('html')
1005
- }
1006
- return this._scrollRootElement
1007
- }
1008
-
1009
- async _scanPage() {
1010
- this._logger.verbose('scanPage started')
1011
- await EyesJsBrowserUtils.scanPage(this._driver)
1012
- this._logger.verbose('scanPage - done!')
1013
- }
1014
-
1015
- /**
1016
- * @private
1017
- * @param {TestcafeCheckSettings} scrollRootElementContainer
1018
- * @return {WebElement}
1019
- */
1020
- _getScrollRootElementFromCheckSettings(scrollRootElementContainer) {
1021
- // if (!EyesTestcafeUtils.isMobileDevice(driver)) {
1022
- if (scrollRootElementContainer) {
1023
- let scrollRootElement = scrollRootElementContainer.getScrollRootElement()
1024
-
1025
- if (!scrollRootElement) {
1026
- const scrollRootSelector = scrollRootElementContainer.getScrollRootSelector()
1027
- if (scrollRootSelector) {
1028
- scrollRootElement = this._driver.findElement(scrollRootSelector)
1029
- }
1030
- }
1031
-
1032
- if (scrollRootElement) {
1033
- return scrollRootElement
1034
- }
1035
- }
1036
- // }
1037
-
1038
- return this._driver.findElement('html')
1039
- }
1040
-
1041
- // noinspection JSUnusedGlobalSymbols
1042
- /**
1043
- * @param {EyesWebElement} scrollRootElement
1044
- * @return {PositionProvider}
1045
- */
1046
- _getElementPositionProvider(scrollRootElement) {
1047
- let positionProvider = scrollRootElement.getPositionProvider()
1048
- if (positionProvider == null) {
1049
- positionProvider = this._createPositionProvider(scrollRootElement)
1050
- scrollRootElement.setPositionProvider(positionProvider)
1051
- }
1052
-
1053
- this._logger.verbose('position provider:', positionProvider)
1054
- this._currentFramePositionProvider = positionProvider
1055
- return positionProvider
1056
- }
1057
-
1058
- // noinspection JSUnusedGlobalSymbols
1059
- /**
1060
- * @protected
1061
- * @inheritDoc
1062
- */
1063
- async getScreenshot() {
1064
- this._logger.verbose('enter()')
1065
-
1066
- const scaleProviderFactory = await this._updateScalingParams()
1067
-
1068
- const originalFrameChain = this._driver.getFrameChain().clone()
1069
- const switchTo = this._driver.switchTo()
1070
- await switchTo.frames(this._originalFC)
1071
-
1072
- const positionProvider = this.getPositionProvider()
1073
- let originalPosition = null
1074
- if (positionProvider) {
1075
- // !EyesTestcafeUtils.isMobileDevice(this.driver)
1076
- originalPosition = await positionProvider.getState()
1077
- }
1078
- await switchTo.frames(originalFrameChain)
1079
-
1080
- const scrollRootElement = await this.getCurrentFrameScrollRootElement()
1081
- const originProvider = new ScrollPositionProvider(
1082
- this._logger,
1083
- this._jsExecutor,
1084
- scrollRootElement,
1085
- )
1086
-
1087
- const algo = new FullPageCaptureAlgorithm(
1088
- this._logger,
1089
- this._regionPositionCompensation,
1090
- this._configuration.getWaitBeforeScreenshots(),
1091
- this._debugScreenshotsProvider,
1092
- this._screenshotFactory,
1093
- originProvider,
1094
- scaleProviderFactory,
1095
- this._cutProviderHandler.get(),
1096
- this._configuration.getStitchOverlap(),
1097
- this._imageProvider,
1098
- true,
1099
- )
1100
-
1101
- // TODO
1102
- // maybe we can just do later active elemnt.focus() ? check
1103
- // I think maybe frame stuff changes the active element
1104
- // so that is why I saved the xpath etc..
1105
- let activeElementXpath = null
1106
- if (this._configuration.getHideCaret()) {
1107
- try {
1108
- activeElementXpath = await this._driver.executeScript(
1109
- `document.activeElement && document.activeElement.blur();
1110
- return (${GEN_XPATH_SCRIPT})(document.activeElement);`,
1111
- )
1112
- } catch (err) {
1113
- this._logger.verbose(`WARNING: Cannot hide caret! ${err}`)
1114
- }
1115
- }
1116
-
1117
- let result
1118
- if (this._checkFrameOrElement) {
1119
- this._logger.verbose('Check frame/element requested')
1120
-
1121
- // if (!EyesTestcafeUtils.isMobileDevice(this.driver)) {
1122
- await switchTo.frames(originalFrameChain)
1123
- // }
1124
-
1125
- let entireFrameOrElement
1126
- if (!this._elementPositionProvider) {
1127
- const scrollRootElement2 = await this._driver.findElement('html')
1128
- const elemPositionProvider = this._getElementPositionProvider(scrollRootElement2)
1129
- await this._markElementForLayoutRCA(elemPositionProvider)
1130
- entireFrameOrElement = await algo.getStitchedRegion(
1131
- this._regionToCheck,
1132
- null,
1133
- elemPositionProvider,
1134
- )
1135
- } else {
1136
- await this._markElementForLayoutRCA(this._elementPositionProvider)
1137
- entireFrameOrElement = await algo.getStitchedRegion(
1138
- this._regionToCheck,
1139
- null,
1140
- this._elementPositionProvider,
1141
- )
1142
- }
1143
-
1144
- this._logger.verbose('Building screenshot object...')
1145
- const size = new RectangleSize(
1146
- entireFrameOrElement.getWidth(),
1147
- entireFrameOrElement.getHeight(),
1148
- )
1149
- result = await EyesWebDriverScreenshot.fromFrameSize(
1150
- this._logger,
1151
- this._driver,
1152
- entireFrameOrElement,
1153
- size,
1154
- )
1155
- } else if (this._configuration.getForceFullPageScreenshot() || this._stitchContent) {
1156
- this._logger.verbose('Full page screenshot requested.')
1157
-
1158
- // Save the current frame path.
1159
- const originalFramePosition =
1160
- originalFrameChain.size() > 0
1161
- ? originalFrameChain.getDefaultContentScrollPosition()
1162
- : new Location(Location.ZERO)
1163
-
1164
- await switchTo.frames(this._originalFC)
1165
- const eyesScrollRootElement = new EyesWebElement(
1166
- this._logger,
1167
- this._driver,
1168
- this._scrollRootElement,
1169
- )
1170
-
1171
- const rect = await eyesScrollRootElement.getRect()
1172
- const sizeAndBorders = await eyesScrollRootElement.getSizeAndBorders()
1173
- const region = new Region(
1174
- rect.x + sizeAndBorders.left,
1175
- rect.y + sizeAndBorders.top,
1176
- sizeAndBorders.width,
1177
- sizeAndBorders.height,
1178
- )
1179
-
1180
- await this._markElementForLayoutRCA(null)
1181
-
1182
- const fullPageImage = await algo.getStitchedRegion(
1183
- region,
1184
- null,
1185
- this._positionProviderHandler.get(),
1186
- )
1187
-
1188
- await switchTo.frames(originalFrameChain)
1189
-
1190
- result = await EyesWebDriverScreenshot.fromScreenshotType(
1191
- this._logger,
1192
- this._driver,
1193
- fullPageImage,
1194
- null,
1195
- originalFramePosition,
1196
- )
1197
- } else {
1198
- await this._ensureElementVisible(this._targetElement)
1199
-
1200
- this._logger.verbose('Screenshot requested...')
1201
- let screenshotImage = await this._imageProvider.getImage()
1202
- await this._debugScreenshotsProvider.save(screenshotImage, 'original')
1203
-
1204
- const scaleProvider = scaleProviderFactory.getScaleProvider(screenshotImage.getWidth())
1205
- if (scaleProvider.getScaleRatio() !== 1) {
1206
- this._logger.verbose('scaling...')
1207
- screenshotImage = await screenshotImage.scale(scaleProvider.getScaleRatio())
1208
- await this._debugScreenshotsProvider.save(screenshotImage, 'scaled')
1209
- }
1210
-
1211
- const cutProvider = this._cutProviderHandler.get()
1212
- if (!(cutProvider instanceof NullCutProvider)) {
1213
- this._logger.verbose('cutting...')
1214
- screenshotImage = await cutProvider.cut(screenshotImage)
1215
- await this._debugScreenshotsProvider.save(screenshotImage, 'cut')
1216
- }
1217
-
1218
- this._logger.verbose('Creating screenshot object...')
1219
- result = await EyesWebDriverScreenshot.fromScreenshotType(
1220
- this._logger,
1221
- this._driver,
1222
- screenshotImage,
1223
- )
1224
- }
1225
-
1226
- if (this._configuration.getHideCaret() && activeElementXpath != null) {
1227
- try {
1228
- await this._driver.executeScript(
1229
- `const activeElement = (${ELEMENTS_BY_XPATH_SCRIPT})(arguments[0]); activeElement[0].focus();`,
1230
- activeElementXpath,
1231
- )
1232
- } catch (err) {
1233
- this._logger.verbose(
1234
- `WARNING: Could not return focus to active element! ${JSON.stringify(err)}`,
1235
- )
1236
- }
1237
- }
1238
-
1239
- await switchTo.frames(this._originalFC)
1240
- if (positionProvider) {
1241
- await positionProvider.restoreState(originalPosition)
1242
- }
1243
- await switchTo.frames(originalFrameChain)
1244
-
1245
- this._logger.verbose('Done!')
1246
- return result
1247
- }
1248
-
1249
- /**
1250
- * @private
1251
- * @param {PositionProvider} elemPositionProvider
1252
- */
1253
- async _markElementForLayoutRCA(elemPositionProvider) {
1254
- const positionProvider = elemPositionProvider || this.getPositionProvider()
1255
- const scrolledElement = await positionProvider.getScrolledElement()
1256
-
1257
- if (scrolledElement) {
1258
- try {
1259
- await this._jsExecutor.executeScript(
1260
- "arguments[0].setAttribute('data-applitools-scroll','true');",
1261
- scrolledElement,
1262
- )
1263
- } catch (err) {
1264
- this._logger.verbose("Can't set data attribute for element", err)
1265
- }
1266
- }
1267
- }
1268
- }
1269
-
1270
- exports.EyesTestCafe = EyesTestCafe