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