@applitools/eyes-browser 1.5.19 → 1.5.20

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.5.20](https://github.com/Applitools-Dev/sdk/compare/js/eyes-browser@1.5.19...js/eyes-browser@1.5.20) (2026-01-11)
4
+
5
+
6
+ ### Dependencies
7
+
8
+ * @applitools/driver bumped to 1.24.4
9
+ #### Bug Fixes
10
+
11
+ * scrolling element fallback logic | FLD-3959 ([#3442](https://github.com/Applitools-Dev/sdk/issues/3442)) ([36348b4](https://github.com/Applitools-Dev/sdk/commit/36348b46e6a127c99d4ccfa58bf386a8e414fb40))
12
+ * @applitools/dom-snapshot bumped to 4.15.5
13
+
14
+ * @applitools/dom-capture bumped to 11.6.8
15
+ #### Bug Fixes
16
+
17
+ * added support for `font-style` attribute | AD-12435 ([#3458](https://github.com/Applitools-Dev/sdk/issues/3458)) ([f121c2a](https://github.com/Applitools-Dev/sdk/commit/f121c2acdea9285b8b53846466dcb4e2c97820e4))
18
+ * @applitools/nml-client bumped to 1.11.14
19
+ #### Bug Fixes
20
+
21
+ * nml broker retry mechanism | FLD-3968 FLD-3963 FLD-3950 ([#3430](https://github.com/Applitools-Dev/sdk/issues/3430)) ([42617e0](https://github.com/Applitools-Dev/sdk/commit/42617e021f43a89f8a8f2cb914f489ac8d215714))
22
+
23
+
24
+
25
+ * @applitools/core bumped to 4.54.2
26
+ #### Bug Fixes
27
+
28
+ * per-API key heartbeat management | FLD-3889 ([#3406](https://github.com/Applitools-Dev/sdk/issues/3406)) ([5d7f380](https://github.com/Applitools-Dev/sdk/commit/5d7f38037f17006dcc923c4a3dc925e8dded25d8))
29
+ * preserve response body in broker handler ([e1bec23](https://github.com/Applitools-Dev/sdk/commit/e1bec23eabf8e8b73db7ec7cd2febb054047f7a7))
30
+
31
+
32
+
33
+ * @applitools/spec-driver-webdriver bumped to 1.5.4
34
+
35
+ * @applitools/spec-driver-selenium bumped to 1.7.10
36
+
37
+ * @applitools/spec-driver-puppeteer bumped to 1.6.10
38
+
39
+ * @applitools/screenshoter bumped to 3.12.11
40
+
41
+ * @applitools/core-base bumped to 1.31.1
42
+ #### Bug Fixes
43
+
44
+ * per-API key heartbeat management | FLD-3889 ([#3406](https://github.com/Applitools-Dev/sdk/issues/3406)) ([5d7f380](https://github.com/Applitools-Dev/sdk/commit/5d7f38037f17006dcc923c4a3dc925e8dded25d8))
45
+ * @applitools/ec-client bumped to 1.12.16
46
+
47
+ * @applitools/eyes bumped to 1.36.20
48
+
49
+
3
50
  ## [1.5.19](https://github.com/Applitools-Dev/sdk/compare/js/eyes-browser@1.5.18...js/eyes-browser@1.5.19) (2025-12-28)
4
51
 
5
52
 
package/dist/index.js CHANGED
@@ -22142,13 +22142,12 @@ var require_requests = __commonJS({
22142
22142
  logger.log('Request "openEyes" called with settings', settings);
22143
22143
  const account = await getAccountInfoWithCache({ settings });
22144
22144
  if (account.processKeepaliveIntervalSec) {
22145
- settings.processId = heartbeat.acquire({
22145
+ heartbeat.acquire({
22146
22146
  eyesServerUrl: settings.eyesServerUrl,
22147
22147
  apiKey: settings.apiKey,
22148
22148
  proxy: settings.proxy,
22149
22149
  useDnsCache: settings.useDnsCache,
22150
22150
  agentId: settings.agentId,
22151
- processId: settings.processId,
22152
22151
  interval: (_a = utils34.general.getEnvValue("HEARTBEAT_INTERVAL", "number")) !== null && _a !== void 0 ? _a : account.processKeepaliveIntervalSec * 1e3
22153
22152
  });
22154
22153
  }
@@ -22694,7 +22693,6 @@ var require_requests = __commonJS({
22694
22693
  proxy: settings.proxy,
22695
22694
  useDnsCache: settings.useDnsCache,
22696
22695
  agentId: settings.agentId,
22697
- processId: settings.processId,
22698
22696
  interval: (_a = utils34.general.getEnvValue("HEARTBEAT_INTERVAL", "number")) !== null && _a !== void 0 ? _a : account.processKeepaliveIntervalSec * 1e3
22699
22697
  });
22700
22698
  }
@@ -66388,7 +66386,7 @@ var require_check_and_close = __commonJS({
66388
66386
  if (signal.aborted) {
66389
66387
  throw new Error('Command "checkAndClose" was aborted');
66390
66388
  }
66391
- return requests.checkAndClose({ target, settings, logger }).finally(done).finally(() => heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.release());
66389
+ return requests.checkAndClose({ target, settings, logger }).finally(done).finally(() => heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.release(requests.test.eyesServer.apiKey));
66392
66390
  };
66393
66391
  }
66394
66392
  exports.makeCheckAndClose = makeCheckAndClose;
@@ -66442,7 +66440,7 @@ var require_close = __commonJS({
66442
66440
  return async function close({ settings, logger = mainLogger } = {}) {
66443
66441
  logger = logger.extend(mainLogger, { tags: [`close-base-${utils34.general.shortid()}`] });
66444
66442
  logger.log('Command "close" is called with settings', settings);
66445
- void requests.close({ settings, logger }).finally(done).finally(() => heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.release());
66443
+ void requests.close({ settings, logger }).finally(done).finally(() => heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.release(requests.test.eyesServer.apiKey));
66446
66444
  };
66447
66445
  }
66448
66446
  exports.makeClose = makeClose;
@@ -66497,7 +66495,7 @@ var require_abort = __commonJS({
66497
66495
  logger = logger.extend(mainLogger, { tags: [`abort-base-${utils34.general.shortid()}`] });
66498
66496
  logger.log('Command "abort" is called with settings', settings);
66499
66497
  controller.abort();
66500
- void requests.abort({ settings, logger }).finally(done).finally(() => heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.release());
66498
+ void requests.abort({ settings, logger }).finally(done).finally(() => heartbeat === null || heartbeat === void 0 ? void 0 : heartbeat.release(requests.test.eyesServer.apiKey));
66501
66499
  };
66502
66500
  }
66503
66501
  exports.makeAbort = makeAbort;
@@ -66785,7 +66783,7 @@ var require_open_eyes = __commonJS({
66785
66783
  if (!throttle) {
66786
66784
  throttle = (0, throttle_1.getThrottle)(settings.sessionConcurrency);
66787
66785
  }
66788
- (_a = settings.processId) !== null && _a !== void 0 ? _a : settings.processId = heartbeat.processId;
66786
+ (_a = settings.processId) !== null && _a !== void 0 ? _a : settings.processId = heartbeat.getOrCreateProcessId(settings.apiKey);
66789
66787
  settings.agentId = `${defaultAgentId} ${settings.agentId ? `[${settings.agentId}]` : ""}`.trim();
66790
66788
  logger.log('Command "openEyes" is called with settings', settings);
66791
66789
  return new Promise((resolve, reject) => {
@@ -67325,74 +67323,107 @@ var require_heartbeat = __commonJS({
67325
67323
  return result;
67326
67324
  };
67327
67325
  Object.defineProperty(exports, "__esModule", { value: true });
67328
- exports.makeHeartbeat = void 0;
67326
+ exports.makeHeartbeat = exports.clearAllHeartbeats = void 0;
67329
67327
  var utils34 = __importStar(require_browser3());
67330
- var processId = utils34.general.guid();
67331
- var isRunning = false;
67332
- var intervalId;
67333
- var refCount = 0;
67328
+ var heartbeats = /* @__PURE__ */ new Map();
67329
+ function clearAllHeartbeats() {
67330
+ for (const [apiKey, state] of heartbeats) {
67331
+ if (state.intervalId) {
67332
+ clearInterval(state.intervalId);
67333
+ }
67334
+ heartbeats.delete(apiKey);
67335
+ }
67336
+ }
67337
+ exports.clearAllHeartbeats = clearAllHeartbeats;
67334
67338
  function makeHeartbeat({ requests, logger: mainLogger }) {
67335
67339
  const logger = mainLogger.extend(mainLogger, { tags: [`heartbeat-base-${utils34.general.shortid()}`] });
67336
- function stopHeartbeats() {
67337
- logger.log("Stopping heartbeats");
67338
- if (intervalId) {
67339
- clearInterval(intervalId);
67340
- intervalId = void 0;
67341
- isRunning = false;
67342
- processId = utils34.general.guid();
67343
- logger.log("Generated new processId after expiration:", processId);
67344
- }
67345
- }
67346
- async function startHeartbeats(settings) {
67347
- await requests.sendHeartbeat({ settings: { ...settings, processId }, logger }).catch((error) => {
67340
+ function stopHeartbeats(apiKey) {
67341
+ const state = heartbeats.get(apiKey);
67342
+ if (!state)
67343
+ return;
67344
+ logger.log("Stopping heartbeats for apiKey:", apiKey);
67345
+ if (state.intervalId) {
67346
+ clearInterval(state.intervalId);
67347
+ }
67348
+ heartbeats.delete(apiKey);
67349
+ logger.log("Heartbeat removed for apiKey:", apiKey);
67350
+ }
67351
+ async function startHeartbeats(apiKey, settings) {
67352
+ const state = heartbeats.get(apiKey);
67353
+ if (!state)
67354
+ return;
67355
+ await requests.sendHeartbeat({ settings: { ...settings, processId: state.processId }, logger }).catch((error) => {
67348
67356
  logger.error("Failed to send heartbeat:", error);
67349
67357
  });
67350
- intervalId = setIntervalBrowser(async () => {
67358
+ if (!heartbeats.has(apiKey)) {
67359
+ logger.log("Heartbeat state was removed during initial heartbeat for apiKey:", apiKey);
67360
+ return;
67361
+ }
67362
+ state.intervalId = setIntervalBrowser(async () => {
67363
+ const currentState = heartbeats.get(apiKey);
67364
+ if (!currentState) {
67365
+ if (state.intervalId) {
67366
+ clearInterval(state.intervalId);
67367
+ logger.log("Cleared orphaned heartbeat interval for apiKey:", apiKey);
67368
+ }
67369
+ return;
67370
+ }
67351
67371
  try {
67352
- await requests.sendHeartbeat({ settings: { ...settings, processId }, logger });
67372
+ await requests.sendHeartbeat({ settings: { ...settings, processId: currentState.processId }, logger });
67353
67373
  } catch (error) {
67354
67374
  if (error.message === "This process is expired. All its sessions were abandoned") {
67355
- logger.log("Heartbeat process expired on server");
67356
- stopHeartbeats();
67375
+ logger.log("Heartbeat process expired on server for apiKey:", apiKey);
67376
+ stopHeartbeats(apiKey);
67357
67377
  }
67358
67378
  }
67359
67379
  }, settings.interval);
67360
- intervalId.unref();
67380
+ state.intervalId.unref();
67381
+ }
67382
+ function getOrCreateProcessId(apiKey) {
67383
+ let state = heartbeats.get(apiKey);
67384
+ if (state)
67385
+ return state.processId;
67386
+ const processId = utils34.general.guid();
67387
+ state = {
67388
+ processId,
67389
+ intervalId: void 0,
67390
+ refCount: 0
67391
+ };
67392
+ heartbeats.set(apiKey, state);
67393
+ logger.log("Created processId for apiKey:", apiKey, "processId:", processId);
67394
+ return processId;
67361
67395
  }
67362
67396
  function acquire(settings) {
67363
- refCount++;
67364
- logger.log("Heartbeat acquired, refCount:", refCount);
67365
- if (!isRunning) {
67366
- if (settings.processId && settings.processId === processId) {
67367
- logger.log("Starting heartbeats with provided processId:", processId);
67368
- } else if (!settings.processId || settings.processId !== processId) {
67369
- if (settings.processId && settings.processId !== processId) {
67370
- logger.log("Provided processId differs from current, using current processId:", processId);
67371
- } else {
67372
- processId = utils34.general.guid();
67373
- logger.log("Starting heartbeats with new processId:", processId);
67374
- }
67375
- }
67376
- isRunning = true;
67377
- void startHeartbeats(settings).catch((error) => {
67397
+ const apiKey = settings.apiKey;
67398
+ const state = heartbeats.get(apiKey);
67399
+ if (!state) {
67400
+ throw new Error("Heartbeat state not found. getOrCreateProcessId must be called before acquire.");
67401
+ }
67402
+ const shouldStartHeartbeat = state.refCount === 0;
67403
+ state.refCount++;
67404
+ logger.log("Heartbeat acquired for apiKey:", apiKey, "refCount:", state.refCount);
67405
+ if (shouldStartHeartbeat) {
67406
+ logger.log("Starting heartbeats for apiKey:", apiKey, "with processId:", state.processId);
67407
+ void startHeartbeats(apiKey, settings).catch((error) => {
67378
67408
  logger.error("Failed to start heartbeats:", error);
67379
67409
  });
67380
67410
  }
67381
- return processId;
67411
+ return state.processId;
67382
67412
  }
67383
- function release() {
67384
- if (refCount > 0) {
67385
- refCount--;
67386
- logger.log("Heartbeat released, refCount:", refCount);
67387
- if (refCount === 0) {
67388
- stopHeartbeats();
67389
- }
67413
+ function release(apiKey) {
67414
+ const state = heartbeats.get(apiKey);
67415
+ if (!state) {
67416
+ logger.log("Heartbeat release called for unknown apiKey:", apiKey);
67417
+ return;
67418
+ }
67419
+ state.refCount--;
67420
+ logger.log("Heartbeat released for apiKey:", apiKey, "refCount:", state.refCount);
67421
+ if (state.refCount === 0) {
67422
+ stopHeartbeats(apiKey);
67390
67423
  }
67391
67424
  }
67392
67425
  return {
67393
- get processId() {
67394
- return processId;
67395
- },
67426
+ getOrCreateProcessId,
67396
67427
  acquire,
67397
67428
  release
67398
67429
  };
@@ -69998,6 +70029,10 @@ var require_context = __commonJS({
69998
70029
  this.logger.log(`Using dynamic default scrolling element - "${selector}"`);
69999
70030
  }
70000
70031
  this._scrollingElement = await this.element({ type: "css", selector });
70032
+ if (!this._scrollingElement) {
70033
+ this.logger.warn(`Scrolling element "${selector}" not found, trying with xpath selector`);
70034
+ this._scrollingElement = await this.element({ type: "xpath", selector: `//${selector}` });
70035
+ }
70001
70036
  } else {
70002
70037
  this._scrollingElement = await this.element({ type: "xpath", selector: '//*[@scrollable="true"]' });
70003
70038
  }
@@ -72398,13 +72433,13 @@ var require_get_target = __commonJS({
72398
72433
  const isScrollable = await element.isScrollable();
72399
72434
  returnRegion = isScrollable ? null : await element.getRegion();
72400
72435
  scrollingElement = isScrollable ? element : await elementContext.getScrollingElement();
72401
- scrollingMode = scrollingMode === "css" && !await scrollingElement.isRoot() ? "mixed+" : scrollingMode;
72436
+ scrollingMode = scrollingMode === "css" && scrollingElement && !await scrollingElement.isRoot() ? "mixed+" : scrollingMode;
72402
72437
  } else {
72403
72438
  scrollingElement = await context.getScrollingElement();
72404
72439
  returnRegion = await element.getRegion();
72405
72440
  }
72406
72441
  const scroller = makeScroller({ element: scrollingElement, scrollingMode, logger });
72407
- if (returnRegion && !environment.isNative && !await scrollingElement.isRoot()) {
72442
+ if (returnRegion && !environment.isNative && scrollingElement && !await scrollingElement.isRoot()) {
72408
72443
  const scrollerOffset = await scroller.getScrollOffset();
72409
72444
  returnRegion = utils34.geometry.offset(returnRegion, scrollerOffset);
72410
72445
  }
@@ -73877,7 +73912,7 @@ var require_captureDomPollCjs = __commonJS({
73877
73912
  }
73878
73913
  });
73879
73914
  t3.isAccessibleFrame = y.default;
73880
- var w = { EYES_NAMESPACE: "__EYES__APPLITOOLS__", DOM_CAPTURE_KEY: "domCaptureResult", NODE_TYPES: { ELEMENT: 1, TEXT: 3, DOCUMENT_FRAGMENT: 11 }, DEFAULT_STYLE_PROPS: ["background-repeat", "background-origin", "background-position", "background-color", "background-image", "background-size", "border-width", "border-color", "border-style", "color", "display", "font-size", "font-weight", "font-family", "line-height", "margin", "opacity", "overflow", "padding", "visibility", "text-align", "position", "border-radius", "z-index", "pointer-events", "cursor"], DEFAULT_RECT_PROPS: ["width", "height", "top", "left"], DEFAULT_IGNORED_TAG_NAMES: ["HEAD", "SCRIPT"] };
73915
+ var w = { EYES_NAMESPACE: "__EYES__APPLITOOLS__", DOM_CAPTURE_KEY: "domCaptureResult", NODE_TYPES: { ELEMENT: 1, TEXT: 3, DOCUMENT_FRAGMENT: 11 }, DEFAULT_STYLE_PROPS: ["background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "border-color", "border-radius", "border-style", "border-width", "color", "cursor", "display", "font-family", "font-size", "font-weight", "font-style", "line-height", "margin", "opacity", "overflow", "padding", "pointer-events", "position", "text-align", "visibility", "z-index"], DEFAULT_RECT_PROPS: ["width", "height", "top", "left"], DEFAULT_IGNORED_TAG_NAMES: ["HEAD", "SCRIPT"] };
73881
73916
  const E = /url\((?!['"]?:)['"]?([^'")]*)['"]?\)/;
73882
73917
  const { NODE_TYPES: C } = w;
73883
73918
  function T(e4) {
@@ -74127,7 +74162,7 @@ ${l2}`}`, { bundledCss: i2, unfetchedResources: u2 };
74127
74162
  return d4 && (N3.shadowRoot = d4), N3;
74128
74163
  }
74129
74164
  }(t4);
74130
- d2(i2.doCaptureDoc), l2(i2.waitForImages), await Promise.all(f2), d2(i2.waitForImages), N2.version = "1.3.0", N2.scriptVersion = "11.6.7";
74165
+ d2(i2.doCaptureDoc), l2(i2.waitForImages), await Promise.all(f2), d2(i2.waitForImages), N2.version = "1.3.0", N2.scriptVersion = "11.6.8";
74131
74166
  const S2 = h2.length ? `${h2.join("\n")}
74132
74167
  ` : "", A2 = m2.size ? `${Array.from(m2).join("\n")}
74133
74168
  ` : "", _2 = JSON.stringify({ separator: y2, cssStartToken: g2, cssEndToken: g2, iframeStartToken: `"${p2}`, iframeEndToken: `${p2}"` });
@@ -74281,7 +74316,7 @@ var require_pollResultCjs = __commonJS({
74281
74316
  }
74282
74317
  });
74283
74318
  t4.isAccessibleFrame = m.default;
74284
- const { poll: _ } = t4, { EYES_NAMESPACE: y, DOM_CAPTURE_KEY: b } = { EYES_NAMESPACE: "__EYES__APPLITOOLS__", DOM_CAPTURE_KEY: "domCaptureResult", NODE_TYPES: { ELEMENT: 1, TEXT: 3, DOCUMENT_FRAGMENT: 11 }, DEFAULT_STYLE_PROPS: ["background-repeat", "background-origin", "background-position", "background-color", "background-image", "background-size", "border-width", "border-color", "border-style", "color", "display", "font-size", "font-weight", "font-family", "line-height", "margin", "opacity", "overflow", "padding", "visibility", "text-align", "position", "border-radius", "z-index", "pointer-events", "cursor"], DEFAULT_RECT_PROPS: ["width", "height", "top", "left"], DEFAULT_IGNORED_TAG_NAMES: ["HEAD", "SCRIPT"] };
74319
+ const { poll: _ } = t4, { EYES_NAMESPACE: y, DOM_CAPTURE_KEY: b } = { EYES_NAMESPACE: "__EYES__APPLITOOLS__", DOM_CAPTURE_KEY: "domCaptureResult", NODE_TYPES: { ELEMENT: 1, TEXT: 3, DOCUMENT_FRAGMENT: 11 }, DEFAULT_STYLE_PROPS: ["background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "border-color", "border-radius", "border-style", "border-width", "color", "cursor", "display", "font-family", "font-size", "font-weight", "font-style", "line-height", "margin", "opacity", "overflow", "padding", "pointer-events", "position", "text-align", "visibility", "z-index"], DEFAULT_RECT_PROPS: ["width", "height", "top", "left"], DEFAULT_IGNORED_TAG_NAMES: ["HEAD", "SCRIPT"] };
74285
74320
  return function(t5) {
74286
74321
  return t5 && t5.__esModule && Object.prototype.hasOwnProperty.call(t5, "default") ? t5.default : t5;
74287
74322
  }(function(t5) {
@@ -80606,7 +80641,7 @@ var require_captureDomPollForIE = __commonJS({
80606
80641
  return this.delegate = { iterator: L2(e5), resultName: r4, nextLoc: n4 }, "next" === this.method && (this.arg = t4), g2;
80607
80642
  } }, e4;
80608
80643
  }
80609
- s0.EYES_NAMESPACE = "__EYES__APPLITOOLS__", s0.DOM_CAPTURE_KEY = "domCaptureResult", s0.NODE_TYPES = { ELEMENT: 1, TEXT: 3, DOCUMENT_FRAGMENT: 11 }, s0.DEFAULT_STYLE_PROPS = ["background-repeat", "background-origin", "background-position", "background-color", "background-image", "background-size", "border-width", "border-color", "border-style", "color", "display", "font-size", "font-weight", "font-family", "line-height", "margin", "opacity", "overflow", "padding", "visibility", "text-align", "position", "border-radius", "z-index", "pointer-events", "cursor"], s0.DEFAULT_RECT_PROPS = ["width", "height", "top", "left"], s0.DEFAULT_IGNORED_TAG_NAMES = ["HEAD", "SCRIPT"];
80644
+ s0.EYES_NAMESPACE = "__EYES__APPLITOOLS__", s0.DOM_CAPTURE_KEY = "domCaptureResult", s0.NODE_TYPES = { ELEMENT: 1, TEXT: 3, DOCUMENT_FRAGMENT: 11 }, s0.DEFAULT_STYLE_PROPS = ["background-color", "background-image", "background-origin", "background-position", "background-repeat", "background-size", "border-color", "border-radius", "border-style", "border-width", "color", "cursor", "display", "font-family", "font-size", "font-weight", "font-style", "line-height", "margin", "opacity", "overflow", "padding", "pointer-events", "position", "text-align", "visibility", "z-index"], s0.DEFAULT_RECT_PROPS = ["width", "height", "top", "left"], s0.DEFAULT_IGNORED_TAG_NAMES = ["HEAD", "SCRIPT"];
80610
80645
  var v0 = /url\((?!['"]?:)['"]?([^'")]*)['"]?\)/, g0 = function(t4) {
80611
80646
  return new Promise(function(e4) {
80612
80647
  setTimeout(e4, t4);
@@ -81008,7 +81043,7 @@ var require_captureDomPollForIE = __commonJS({
81008
81043
  case 23:
81009
81044
  return I2 = e5.sent, A2(w2.prefetchCss), L2 = N0({ parseCss: U0, CSSImportRule, getCssFromCache: I2, absolutizeUrl: L0, unfetchedToken: R2 }), j2 = B0({ getCssFromCache: I2, absolutizeUrl: L0 }), k2 = z0({ extractCssFromNode: j2, getBundledCssFromCssText: L2, unfetchedToken: R2 }), E2(w2.doCaptureDoc), C2 = V2(i3), A2(w2.doCaptureDoc), E2(w2.waitForImages), e5.next = 34, Promise.all(S2);
81010
81045
  case 34:
81011
- return A2(w2.waitForImages), C2.version = "1.3.0", C2.scriptVersion = "11.6.7", M2 = x2.length ? x2.join("\n") + "\n" : "", N2 = O2.size ? Array.from(O2).join("\n") + "\n" : "", U2 = JSON.stringify({ separator: _2, cssStartToken: R2, cssEndToken: R2, iframeStartToken: '"' + T2, iframeEndToken: T2 + '"' }), A2(w2.total), F2 = U2 + "\n" + N2 + _2 + "\n" + M2 + _2 + "\n" + JSON.stringify(C2) + D2(), console.log("[captureFrame]", JSON.stringify(w2)), e5.abrupt("return", F2);
81046
+ return A2(w2.waitForImages), C2.version = "1.3.0", C2.scriptVersion = "11.6.8", M2 = x2.length ? x2.join("\n") + "\n" : "", N2 = O2.size ? Array.from(O2).join("\n") + "\n" : "", U2 = JSON.stringify({ separator: _2, cssStartToken: R2, cssEndToken: R2, iframeStartToken: '"' + T2, iframeEndToken: T2 + '"' }), A2(w2.total), F2 = U2 + "\n" + N2 + _2 + "\n" + M2 + _2 + "\n" + JSON.stringify(C2) + D2(), console.log("[captureFrame]", JSON.stringify(w2)), e5.abrupt("return", F2);
81012
81047
  case 44:
81013
81048
  case "end":
81014
81049
  return e5.stop();
@@ -87350,6 +87385,21 @@ var require_req_broker = __commonJS({
87350
87385
  exports.makeReqBroker = void 0;
87351
87386
  var req_1 = __importStar((init_dist(), __toCommonJS(dist_exports)));
87352
87387
  var utils34 = __importStar(require_browser3());
87388
+ function isInvalidBrokerMessage(result) {
87389
+ try {
87390
+ const parsedResult = JSON.parse(result);
87391
+ if (Array.isArray(parsedResult) && parsedResult.length === 0)
87392
+ return true;
87393
+ if (parsedResult && typeof parsedResult === "object" && !Array.isArray(parsedResult)) {
87394
+ const { payload } = parsedResult;
87395
+ if (Array.isArray(payload) && payload.length === 0)
87396
+ return true;
87397
+ }
87398
+ return false;
87399
+ } catch {
87400
+ return true;
87401
+ }
87402
+ }
87353
87403
  function makeReqBroker({ settings, logger }) {
87354
87404
  return (0, req_1.makeReq)({
87355
87405
  method: "POST",
@@ -87387,34 +87437,83 @@ var require_req_broker = __commonJS({
87387
87437
  }
87388
87438
  };
87389
87439
  }
87440
+ function makeBufferingFetch() {
87441
+ return async (input, init) => {
87442
+ const response = await (0, req_1.default)(input, init);
87443
+ const bufferedBody = await response.text();
87444
+ const bufferedResponse = new req_1.Response(bufferedBody, {
87445
+ status: response.status,
87446
+ statusText: response.statusText,
87447
+ headers: response.headers
87448
+ });
87449
+ bufferedResponse.text = async () => bufferedBody;
87450
+ bufferedResponse.json = async () => JSON.parse(bufferedBody);
87451
+ const originalClone = bufferedResponse.clone.bind(bufferedResponse);
87452
+ bufferedResponse.clone = () => {
87453
+ const cloned = originalClone();
87454
+ cloned.text = async () => bufferedBody;
87455
+ cloned.json = async () => JSON.parse(bufferedBody);
87456
+ return cloned;
87457
+ };
87458
+ return bufferedResponse;
87459
+ };
87460
+ }
87390
87461
  function handleLongRequests({ req: req2, logger: defaultLogger }) {
87391
87462
  return {
87392
87463
  async afterResponse({ request, response, options }) {
87464
+ var _a;
87393
87465
  if (response.status === 200) {
87466
+ let attemptCount = 0;
87467
+ const MAX_ATTEMPTS = 1500;
87468
+ const logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : defaultLogger;
87469
+ const bufferingFetch = makeBufferingFetch();
87394
87470
  return req2(request.url + "-response", {
87395
87471
  proxy: options === null || options === void 0 ? void 0 : options.proxy,
87396
- retry: {
87397
- // 1500 attempts x 200 ms = 5 minutes
87398
- limit: 1500,
87399
- timeout: 200,
87400
- statuses: [404]
87401
- },
87472
+ fetch: bufferingFetch,
87473
+ retry: [
87474
+ {
87475
+ // 1500 attempts x 200 ms = 5 minutes
87476
+ limit: MAX_ATTEMPTS,
87477
+ timeout: 200,
87478
+ statuses: [404]
87479
+ },
87480
+ {
87481
+ limit: MAX_ATTEMPTS,
87482
+ timeout: 200,
87483
+ validate: async ({ response: response2 }) => {
87484
+ if (!response2 || response2.status !== 200)
87485
+ return false;
87486
+ try {
87487
+ const body = await response2.clone().text();
87488
+ const isInvalid = isInvalidBrokerMessage(body);
87489
+ if (isInvalid) {
87490
+ logger === null || logger === void 0 ? void 0 : logger.log(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" received empty response, retrying (attempt ${attemptCount + 1}/${MAX_ATTEMPTS})`);
87491
+ }
87492
+ return isInvalid;
87493
+ } catch (error) {
87494
+ return false;
87495
+ }
87496
+ }
87497
+ }
87498
+ ],
87402
87499
  hooks: [
87403
87500
  {
87404
87501
  beforeRequest({ request: request2, options: beforeOptions }) {
87405
- var _a;
87406
- const logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : defaultLogger;
87407
- logger === null || logger === void 0 ? void 0 : logger.log(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" will be sent to the address "[${request2.method}]${request2.url}" with body`, beforeOptions === null || beforeOptions === void 0 ? void 0 : beforeOptions.body);
87502
+ attemptCount++;
87503
+ logger === null || logger === void 0 ? void 0 : logger.log(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" attempt #${attemptCount}/${MAX_ATTEMPTS} will be sent to the address "[${request2.method}]${request2.url}" with body`, beforeOptions === null || beforeOptions === void 0 ? void 0 : beforeOptions.body);
87408
87504
  },
87409
87505
  async afterResponse({ request: request2, response: response2 }) {
87410
- var _a;
87411
- const logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : defaultLogger;
87412
- logger === null || logger === void 0 ? void 0 : logger.log(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" that was sent to the address "[${request2.method}]${request2.url}" respond with ${response2.statusText}(${response2.status})`, response2.status !== 200 ? `and body ${JSON.stringify(await response2.clone().text())}` : "");
87506
+ try {
87507
+ const body = await response2.clone().text();
87508
+ logger === null || logger === void 0 ? void 0 : logger.log(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" attempt #${attemptCount}/${MAX_ATTEMPTS} that was sent to the address "[${request2.method}]${request2.url}" respond with ${response2.statusText}(${response2.status}) with body ${JSON.stringify(body)}`);
87509
+ } catch (error) {
87510
+ logger === null || logger === void 0 ? void 0 : logger.log(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" attempt #${attemptCount}/${MAX_ATTEMPTS} that was sent to the address "[${request2.method}]${request2.url}" respond with ${response2.statusText}(${response2.status})`);
87511
+ }
87413
87512
  },
87414
87513
  afterError({ request: request2, error }) {
87415
- var _a;
87416
- const logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : defaultLogger;
87417
- logger === null || logger === void 0 ? void 0 : logger.error(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" that was sent to the address "[${request2.method}]${request2.url}" failed with error`, error);
87514
+ var _a2;
87515
+ const logger2 = (_a2 = options === null || options === void 0 ? void 0 : options.logger) !== null && _a2 !== void 0 ? _a2 : defaultLogger;
87516
+ logger2 === null || logger2 === void 0 ? void 0 : logger2.error(`Broker polling request "${options === null || options === void 0 ? void 0 : options.name}" attempt #${attemptCount}/${MAX_ATTEMPTS} that was sent to the address "[${request2.method}]${request2.url}" failed with error`, error);
87418
87517
  }
87419
87518
  }
87420
87519
  ]
@@ -87428,19 +87527,21 @@ var require_req_broker = __commonJS({
87428
87527
  async afterResponse({ response }) {
87429
87528
  if (response.status !== 200) {
87430
87529
  throw new Error(`Something went wrong when communicating with the mobile application, please try running your test again (error code: ${response.status})`);
87431
- } else {
87432
- const body = await response.text();
87433
- const result = JSON.parse(body);
87434
- if (result === null || result === void 0 ? void 0 : result.payload) {
87435
- const error = utils34.types.isArray(result.payload) ? result.payload.find((payload) => payload.error) : result.payload.error;
87436
- if (error) {
87437
- const nmlError = new Error(`There was a problem when interacting with the mobile application. The provided error message was "${error.message}" and had a stack trace of "${error.stack}"`);
87438
- nmlError.nextPath = result.nextPath;
87439
- throw nmlError;
87440
- }
87530
+ }
87531
+ const body = await response.clone().text();
87532
+ if (!body) {
87533
+ return response;
87534
+ }
87535
+ const result = JSON.parse(body);
87536
+ if (result === null || result === void 0 ? void 0 : result.payload) {
87537
+ const error = utils34.types.isArray(result.payload) ? result.payload.find((payload) => payload.error) : result.payload.error;
87538
+ if (error) {
87539
+ const nmlError = new Error(`There was a problem when interacting with the mobile application. The provided error message was "${error.message}" and had a stack trace of "${error.stack}"`);
87540
+ nmlError.nextPath = result.nextPath;
87541
+ throw nmlError;
87441
87542
  }
87442
- return { response, body };
87443
87543
  }
87544
+ return response;
87444
87545
  }
87445
87546
  };
87446
87547
  }
@@ -87629,7 +87730,7 @@ var require_requests2 = __commonJS({
87629
87730
  brokerUrl = result.nextPath;
87630
87731
  }
87631
87732
  async function takeScreenshots({ settings: settings2, logger = mainLogger }) {
87632
- var _a, _b;
87733
+ var _a;
87633
87734
  logger = logger.extend(mainLogger, { tags: [`nml-request-${utils34.general.shortid()}`] });
87634
87735
  logger.log('Request "takeScreenshots" called with settings', settings2);
87635
87736
  const { localEnvironment, renderEnvironments, environmentSettings } = await (0, get_environments_info_1.getNMLEnvironmentsInfo)({
@@ -87662,31 +87763,33 @@ var require_requests2 = __commonJS({
87662
87763
  let screenshots;
87663
87764
  if (Number(result.protocolVersion) >= 2) {
87664
87765
  logger.log(`Request "takeScreenshots" was performed on applitools lib v${result.nmlVersion} through protocol v${result.protocolVersion} on device`, result.payload.debugInfo);
87665
- if ((_b = result.payload.result) === null || _b === void 0 ? void 0 : _b.some((res) => res.error)) {
87666
- const errors = result.payload.result.filter((res) => res.error);
87667
- let errMessage = "There were problems in taking screenshots for";
87668
- if (localEnvironment) {
87669
- errMessage += ` local environment ${JSON.stringify(localEnvironment)}:
87670
- `;
87671
- errMessage += ` ${JSON.stringify(errors)}`;
87672
- } else {
87673
- errMessage += " environments:";
87674
- errMessage += `
87675
- ${errors.map((err, index) => `Environment ${JSON.stringify(renderEnvironments[index])}: ${JSON.stringify(err)}`).join("\n ")}`;
87766
+ if (localEnvironment) {
87767
+ if (result.payload.result[0].error) {
87768
+ throw new Error(`There was a problem in taking screenshot for local environment ${JSON.stringify(localEnvironment)}. The provided error message was "${result.payload.result[0].error.message}" and had a stack trace of "${result.payload.result[0].error.stack}"`);
87676
87769
  }
87677
- throw new Error(errMessage);
87770
+ screenshots = [
87771
+ {
87772
+ image: result.payload.result[0].result.screenshotUrl,
87773
+ calculateRegions: result.payload.result[0].result.selectorRegions,
87774
+ dom: result.payload.result[0].result.dom,
87775
+ environment: localEnvironment
87776
+ }
87777
+ ];
87778
+ } else {
87779
+ screenshots = renderEnvironments.map((environment, index) => {
87780
+ if (result.payload.result[index].error) {
87781
+ throw new Error(`There was a problem in taking screenshot for environment ${JSON.stringify(environment)}. The provided error message was "${result.payload.result[index].error.message}" and had a stack trace of "${result.payload.result[index].error.stack}"`);
87782
+ }
87783
+ return {
87784
+ image: result.payload.result[index].result.screenshotUrl,
87785
+ calculateRegions: result.payload.result[index].result.selectorRegions,
87786
+ dom: result.payload.result[index].result.dom,
87787
+ environment
87788
+ };
87789
+ });
87678
87790
  }
87679
- screenshots = renderEnvironments.map((environment, index) => {
87680
- return {
87681
- image: result.payload.result[index].result.screenshotUrl,
87682
- calculateRegions: result.payload.result[index].result.selectorRegions,
87683
- dom: result.payload.result[index].result.dom,
87684
- environment: localEnvironment || environment
87685
- };
87686
- });
87687
- if (localEnvironment && renderEnvironments.length > 1) {
87688
- logger.warn(`Local environment detected with ${renderEnvironments.length} rendered environment(s). Using local environment ${JSON.stringify(localEnvironment)} and ignoring rendered environments: ${JSON.stringify(renderEnvironments)}. Note - this warning shouldn't appear in normal usage.`);
87689
- screenshots = [screenshots[0]];
87791
+ if (localEnvironment && renderEnvironments.length > 0) {
87792
+ logger.warn(`Local environment detected with ${renderEnvironments.length} rendered environment(s). Using local environment and ignoring rendered environments: ${JSON.stringify(renderEnvironments)}. Note - this warning shouldn't appear in normal usage.`);
87690
87793
  }
87691
87794
  } else {
87692
87795
  screenshots = localEnvironment ? [
@@ -95610,7 +95713,7 @@ creating temp style for access.`), r3 = Zh(e3);
95610
95713
  function B2(e3) {
95611
95714
  return n4.defaultView && n4.defaultView.frameElement && n4.defaultView.frameElement.getAttribute(e3);
95612
95715
  }
95613
- }(t3).then((e3) => (h2.log("processPage end"), e3.scriptVersion = "4.15.4", e3));
95716
+ }(t3).then((e3) => (h2.log("processPage end"), e3.scriptVersion = "4.15.5", e3));
95614
95717
  }, window[x], "domSnapshotResult");
95615
95718
  return function(e3) {
95616
95719
  try {
@@ -116713,6 +116816,34 @@ var require_chrome_emulation_devices = __commonJS({
116713
116816
  capabilities: ["touch", "mobile"]
116714
116817
  }
116715
116818
  },
116819
+ "Galaxy S25": {
116820
+ portrait: {
116821
+ height: 780,
116822
+ width: 360
116823
+ },
116824
+ landscape: {
116825
+ height: 360,
116826
+ width: 780
116827
+ },
116828
+ metadata: {
116829
+ pixelRatio: 3,
116830
+ capabilities: ["touch", "mobile"]
116831
+ }
116832
+ },
116833
+ "Galaxy S25 Ultra": {
116834
+ portrait: {
116835
+ height: 824,
116836
+ width: 384
116837
+ },
116838
+ landscape: {
116839
+ height: 384,
116840
+ width: 824
116841
+ },
116842
+ metadata: {
116843
+ pixelRatio: 3.75,
116844
+ capabilities: ["touch", "mobile"]
116845
+ }
116846
+ },
116716
116847
  "Laptop with touch": {
116717
116848
  portrait: {
116718
116849
  height: 1280,
@@ -117231,6 +117362,20 @@ var require_chrome_emulation_devices = __commonJS({
117231
117362
  capabilities: ["touch", "mobile"]
117232
117363
  }
117233
117364
  },
117365
+ "Pixel 9": {
117366
+ portrait: {
117367
+ height: 840,
117368
+ width: 390
117369
+ },
117370
+ landscape: {
117371
+ height: 390,
117372
+ width: 840
117373
+ },
117374
+ metadata: {
117375
+ pixelRatio: 2.75,
117376
+ capabilities: ["touch", "mobile"]
117377
+ }
117378
+ },
117234
117379
  "iPad 7th Gen": {
117235
117380
  portrait: {
117236
117381
  height: 1080,
@@ -120982,7 +121127,7 @@ var require_package3 = __commonJS({
120982
121127
  "../core/package.json"(exports, module) {
120983
121128
  module.exports = {
120984
121129
  name: "@applitools/core",
120985
- version: "4.54.1",
121130
+ version: "4.54.2",
120986
121131
  homepage: "https://applitools.com",
120987
121132
  bugs: {
120988
121133
  url: "https://github.com/applitools/eyes.sdk.javascript1/issues"
@@ -127898,7 +128043,7 @@ var require_package4 = __commonJS({
127898
128043
  "../eyes/package.json"(exports, module) {
127899
128044
  module.exports = {
127900
128045
  name: "@applitools/eyes",
127901
- version: "1.36.19",
128046
+ version: "1.36.20",
127902
128047
  keywords: [
127903
128048
  "applitools",
127904
128049
  "eyes",
@@ -128091,12 +128236,15 @@ var DeviceNameEnum = /* @__PURE__ */ ((DeviceNameEnum2) => {
128091
128236
  DeviceNameEnum2["Galaxy_Tab_A8"] = "Galaxy Tab A8";
128092
128237
  DeviceNameEnum2["Galaxy_S23"] = "Galaxy S23";
128093
128238
  DeviceNameEnum2["Galaxy_S23_Ultra"] = "Galaxy S23 Ultra";
128239
+ DeviceNameEnum2["Galaxy_S25"] = "Galaxy S25";
128240
+ DeviceNameEnum2["Galaxy_S25_Ultra"] = "Galaxy S25 Ultra";
128094
128241
  DeviceNameEnum2["Galaxy_A52s"] = "Galaxy A52s";
128095
128242
  DeviceNameEnum2["Pixel_3"] = "Pixel 3";
128096
128243
  DeviceNameEnum2["Pixel_3_XL"] = "Pixel 3 XL";
128097
128244
  DeviceNameEnum2["Pixel_4"] = "Pixel 4";
128098
128245
  DeviceNameEnum2["Pixel_4_XL"] = "Pixel 4 XL";
128099
128246
  DeviceNameEnum2["Pixel_5"] = "Pixel 5";
128247
+ DeviceNameEnum2["Pixel_9"] = "Pixel 9";
128100
128248
  DeviceNameEnum2["iPad_7th_Gen"] = "iPad 7th Gen";
128101
128249
  DeviceNameEnum2["OnePlus_7T"] = "OnePlus 7T";
128102
128250
  DeviceNameEnum2["OnePlus_7T_Pro"] = "OnePlus 7T Pro";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@applitools/eyes-browser",
3
- "version": "1.5.19",
3
+ "version": "1.5.20",
4
4
  "keywords": [
5
5
  "applitools",
6
6
  "browser",
@@ -48,7 +48,7 @@
48
48
  "test": "run --top-level mocha './test/**/*.spec.ts'"
49
49
  },
50
50
  "dependencies": {
51
- "@applitools/eyes": "1.36.19"
51
+ "@applitools/eyes": "1.36.20"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^12.20.55",
@@ -78,12 +78,15 @@ export declare enum DeviceNameEnum {
78
78
  Galaxy_Tab_A8 = "Galaxy Tab A8",
79
79
  Galaxy_S23 = "Galaxy S23",
80
80
  Galaxy_S23_Ultra = "Galaxy S23 Ultra",
81
+ Galaxy_S25 = "Galaxy S25",
82
+ Galaxy_S25_Ultra = "Galaxy S25 Ultra",
81
83
  Galaxy_A52s = "Galaxy A52s",
82
84
  Pixel_3 = "Pixel 3",
83
85
  Pixel_3_XL = "Pixel 3 XL",
84
86
  Pixel_4 = "Pixel 4",
85
87
  Pixel_4_XL = "Pixel 4 XL",
86
88
  Pixel_5 = "Pixel 5",
89
+ Pixel_9 = "Pixel 9",
87
90
  iPad_7th_Gen = "iPad 7th Gen",
88
91
  OnePlus_7T = "OnePlus 7T",
89
92
  OnePlus_7T_Pro = "OnePlus 7T Pro",