@checksum-ai/runtime 1.1.33 → 1.1.35

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/checksumlib.js CHANGED
@@ -9714,9 +9714,6 @@
9714
9714
  this.restoreNodeAttributes(node2, removedAttributes);
9715
9715
  const result2 = await this.getElementWindowPlaywright(node2).$(selector);
9716
9716
  if (result2 !== node2) {
9717
- console.log(
9718
- `Selector ${selector} is not valid, trying to generate new one`
9719
- );
9720
9717
  ({ selector, locator } = await this.safeGetSelectorAndLocator(
9721
9718
  nodeHTML
9722
9719
  ));
@@ -29390,8 +29387,9 @@
29390
29387
  var SessionReplayer = class {
29391
29388
  constructor(config = {}) {
29392
29389
  this.events = [];
29393
- this.castedEvents = [];
29390
+ this.numberOfCastedEvents = 0;
29394
29391
  this.isLive = true;
29392
+ this.liveEvents = [];
29395
29393
  // private currentTraveledTimestamp: number = undefined;
29396
29394
  this.currentTraveledNumberOfEvents = void 0;
29397
29395
  this.config = {
@@ -29420,8 +29418,8 @@
29420
29418
  this.events = [...this.events, ...sortedNewEvents];
29421
29419
  const promise = new Promise((resolve2) => {
29422
29420
  this.onEventCast = (event) => {
29423
- this.castedEvents.push(event);
29424
- if (this.castedEvents.length === this.events.length) {
29421
+ this.numberOfCastedEvents++;
29422
+ if (this.numberOfCastedEvents === this.events.length) {
29425
29423
  this.onEventCast = void 0;
29426
29424
  resolve2();
29427
29425
  }
@@ -29438,6 +29436,20 @@
29438
29436
  this.getOriginalTimestamp = /* @__PURE__ */ __name((event) => {
29439
29437
  return event.originalTimestamp ?? event.timestamp;
29440
29438
  }, "getOriginalTimestamp");
29439
+ this.trimEventsToLastCheckout = /* @__PURE__ */ __name((events) => {
29440
+ const lastCheckoutEventIndex = events.reduce(
29441
+ (lastCheckoutEventIndex2, event, index2) => {
29442
+ return event.isCheckout && event.type === EventType.Meta ? index2 : lastCheckoutEventIndex2;
29443
+ },
29444
+ void 0
29445
+ );
29446
+ let trimmedEvents = events;
29447
+ if (lastCheckoutEventIndex !== void 0) {
29448
+ trimmedEvents = events.slice(lastCheckoutEventIndex);
29449
+ }
29450
+ const castedEvents = lastCheckoutEventIndex !== void 0 ? this.liveEvents.slice(0, lastCheckoutEventIndex) : [];
29451
+ return { trimmedEvents, castedEvents, lastCheckoutEventIndex };
29452
+ }, "trimEventsToLastCheckout");
29441
29453
  this.getNodeById = /* @__PURE__ */ __name((id) => {
29442
29454
  return this.replayer.getMirror().getNode(id);
29443
29455
  }, "getNodeById");
@@ -29445,36 +29457,49 @@
29445
29457
  return this.replayer.getMirror().getMeta(node2);
29446
29458
  }, "getMeta");
29447
29459
  this.config = { ...this.config, ...config };
29460
+ this.goBackWithEvents = this.goBackWithEvents_native;
29448
29461
  }
29449
29462
  static {
29450
29463
  __name(this, "SessionReplayer");
29451
29464
  }
29452
- start(options) {
29453
- this.startOptions = options;
29454
- const {
29455
- firstEventTimestamp,
29456
- speed = 8,
29457
- useTimestampCompression = true
29458
- } = options;
29465
+ makeReplayerConfig(live, { speed = 8 } = {}) {
29459
29466
  const playerConfig = {
29460
29467
  mouseTail: false,
29461
29468
  pauseAnimation: false,
29462
29469
  speed,
29463
29470
  triggerFocus: true,
29464
29471
  UNSAFE_replayCanvas: true,
29465
- liveMode: true,
29472
+ liveMode: live,
29466
29473
  showDebug: false,
29467
- skipInactive: true
29474
+ skipInactive: true,
29475
+ inactivePeriodThreshold: 100
29468
29476
  };
29469
29477
  if (this.config.root) {
29470
29478
  playerConfig.root = this.config.root;
29471
29479
  }
29472
- this.replayer = new Replayer([], playerConfig);
29480
+ return playerConfig;
29481
+ }
29482
+ makeReplayer(events, live, { speed = 8 } = {}) {
29483
+ this.replayer = new Replayer(
29484
+ events,
29485
+ this.makeReplayerConfig(live, { speed })
29486
+ );
29473
29487
  if (this.config.enableInteract) {
29474
29488
  this.replayer.enableInteract();
29475
29489
  } else {
29476
29490
  this.replayer.disableInteract();
29477
29491
  }
29492
+ }
29493
+ start(options, castedEvents = []) {
29494
+ this.startOptions = options;
29495
+ const {
29496
+ firstEventTimestamp,
29497
+ speed = 8,
29498
+ useTimestampCompression = true
29499
+ } = options;
29500
+ this.events = castedEvents;
29501
+ this.numberOfCastedEvents = castedEvents.length;
29502
+ this.makeReplayer([], true, { speed });
29478
29503
  this.useTimestampCompression = useTimestampCompression;
29479
29504
  this.replayer.startLive(
29480
29505
  this.useTimestampCompression ? Date.now() : firstEventTimestamp
@@ -29485,20 +29510,23 @@
29485
29510
  }
29486
29511
  });
29487
29512
  }
29488
- getCurrentReplayPoint() {
29489
- return this.isLive ? this.events.length : this.currentTraveledNumberOfEvents;
29490
- }
29491
- // private beforeGoBack() {
29492
- // if (this.isLive) {
29493
- // this.liveEvents = this.events;
29494
- // }
29495
- // this.stop();
29496
- // this.events = [];
29497
- // this.castedEvents = [];
29498
- // this.start(this.startOptions);
29499
- // this.isLive = false;
29500
- // }
29501
- async goBackWithEvents(getEvents2, { sleepAfter = 1e3 }) {
29513
+ async goLive(sleepAfter = 1e3) {
29514
+ if (this.isLive) {
29515
+ return;
29516
+ }
29517
+ this.stop();
29518
+ this.currentTraveledNumberOfEvents = void 0;
29519
+ const { trimmedEvents, castedEvents } = this.trimEventsToLastCheckout(
29520
+ this.liveEvents
29521
+ );
29522
+ this.start(this.startOptions, castedEvents);
29523
+ this.isLive = true;
29524
+ await this.fastForward(trimmedEvents);
29525
+ if (sleepAfter) {
29526
+ await (0, import_await_sleep3.default)(sleepAfter);
29527
+ }
29528
+ }
29529
+ async goBackWithEvents_native(getEvents2, { sleepAfter = 1e3 }) {
29502
29530
  if (this.isLive) {
29503
29531
  this.liveEvents = this.events;
29504
29532
  }
@@ -29506,38 +29534,65 @@
29506
29534
  if (events.length === this.currentTraveledNumberOfEvents) {
29507
29535
  return;
29508
29536
  }
29509
- const lastCheckoutEventIndex = events.reduce(
29510
- (lastCheckoutEventIndex2, event, index2) => {
29511
- return event.isCheckout && event.type === EventType.Meta ? index2 : lastCheckoutEventIndex2;
29512
- },
29513
- void 0
29514
- );
29515
- if (lastCheckoutEventIndex !== void 0) {
29516
- console.log(
29517
- "lastCheckoutEventIndex:",
29518
- lastCheckoutEventIndex,
29519
- "number of events to render:",
29520
- events.length - lastCheckoutEventIndex
29521
- );
29522
- events.splice(lastCheckoutEventIndex);
29523
- }
29524
29537
  this.stop();
29525
29538
  this.events = [];
29526
- this.castedEvents = [];
29527
- this.start(this.startOptions);
29539
+ this.numberOfCastedEvents = 0;
29528
29540
  this.isLive = false;
29529
29541
  this.currentTraveledNumberOfEvents = events.length;
29530
- await this.fastForward(events, true);
29542
+ const { trimmedEvents } = this.trimEventsToLastCheckout(events);
29543
+ this.makeReplayer(trimmedEvents, false, { speed: 360 });
29544
+ this.replayer.play(trimmedEvents[trimmedEvents.length - 1].timestamp);
29531
29545
  if (sleepAfter) {
29532
29546
  await (0, import_await_sleep3.default)(sleepAfter);
29533
29547
  }
29534
29548
  }
29535
- async goBackToReplayPoint(replayPoint, {
29536
- sleepAfter = 1e3
29537
- } = {}) {
29538
- return this.goBackWithEvents(() => this.liveEvents.slice(0, replayPoint), {
29539
- sleepAfter
29540
- });
29549
+ async goBackWithEvents_native2(getEvents2, { sleepAfter = 1e3 }) {
29550
+ try {
29551
+ const events = getEvents2();
29552
+ const targetTimestamp = events[events.length - 1]?.timestamp ?? 0;
29553
+ const getTimeForPause = /* @__PURE__ */ __name(() => {
29554
+ return targetTimestamp - (this.events[0].timestamp ?? 0);
29555
+ }, "getTimeForPause");
29556
+ if (!this.isLive && targetTimestamp <= this.events[this.events.length - 1].timestamp) {
29557
+ const timeForPause2 = getTimeForPause();
29558
+ this.replayer.pause(timeForPause2);
29559
+ return;
29560
+ }
29561
+ if (this.isLive) {
29562
+ this.liveEvents = this.events;
29563
+ }
29564
+ this.stop();
29565
+ this.events = this.liveEvents;
29566
+ this.numberOfCastedEvents = this.liveEvents.length;
29567
+ this.isLive = false;
29568
+ this.makeReplayer(this.events, false, { speed: 360 });
29569
+ const timeForPause = getTimeForPause();
29570
+ this.replayer.pause(timeForPause);
29571
+ } finally {
29572
+ if (sleepAfter) {
29573
+ await (0, import_await_sleep3.default)(sleepAfter);
29574
+ }
29575
+ }
29576
+ }
29577
+ async goBackWithEvents_FFwd(getEvents2, { sleepAfter = 1e3 }) {
29578
+ if (this.isLive) {
29579
+ this.liveEvents = this.events;
29580
+ }
29581
+ const events = getEvents2();
29582
+ if (events.length === this.currentTraveledNumberOfEvents) {
29583
+ return;
29584
+ }
29585
+ this.currentTraveledNumberOfEvents = events.length;
29586
+ this.stop();
29587
+ const { trimmedEvents, castedEvents } = this.trimEventsToLastCheckout(
29588
+ this.liveEvents
29589
+ );
29590
+ this.start(this.startOptions, castedEvents);
29591
+ this.isLive = false;
29592
+ await this.fastForward(trimmedEvents, true);
29593
+ if (sleepAfter) {
29594
+ await (0, import_await_sleep3.default)(sleepAfter);
29595
+ }
29541
29596
  }
29542
29597
  async goBack(timestamp, {
29543
29598
  sleepAfter = 1e3,
@@ -29577,28 +29632,24 @@
29577
29632
  sleepAfter
29578
29633
  });
29579
29634
  }
29580
- async goLive(sleepAfter = 1e3) {
29581
- if (this.isLive) {
29582
- return;
29583
- }
29584
- this.stop();
29585
- this.currentTraveledNumberOfEvents = void 0;
29586
- this.events = [];
29587
- this.castedEvents = [];
29588
- this.start(this.startOptions);
29589
- this.isLive = true;
29590
- await this.fastForward(this.liveEvents);
29591
- if (sleepAfter) {
29592
- await (0, import_await_sleep3.default)(sleepAfter);
29593
- }
29594
- }
29595
- getLastEventTimestamps() {
29596
- const lastEvent = this.events[this.events.length - 1];
29635
+ async getLastEventTimestamps(snapshot2 = false) {
29636
+ const lastEvent = snapshot2 ? await this.findLastFullSnapshotEvent() : this.events[this.events.length - 1];
29597
29637
  return {
29598
29638
  timestamp: lastEvent?.timestamp,
29599
29639
  originalTimestamp: lastEvent?.originalTimestamp
29600
29640
  };
29601
29641
  }
29642
+ async findLastFullSnapshotEvent() {
29643
+ const event = this.events.reduce((snapshotEvent, event2) => {
29644
+ return event2.type === EventType.FullSnapshot ? event2 : snapshotEvent;
29645
+ }, void 0);
29646
+ if (event) {
29647
+ return event;
29648
+ }
29649
+ console.log("waiting for full snapshot event...");
29650
+ await (0, import_await_sleep3.default)(1e3);
29651
+ return this.findLastFullSnapshotEvent();
29652
+ }
29602
29653
  };
29603
29654
 
29604
29655
  // ../browser-lib/src/session-record-replay/events-streamer.ts
@@ -31533,7 +31584,8 @@
31533
31584
  clear = true,
31534
31585
  shouldFlipHighlightTextOutsideViewport = true,
31535
31586
  pointerEvents,
31536
- classNames = []
31587
+ classNames = [],
31588
+ renderDocument
31537
31589
  } = {}) {
31538
31590
  if (clear) {
31539
31591
  this.clearHighlights();
@@ -31541,16 +31593,30 @@
31541
31593
  if (!element) {
31542
31594
  return;
31543
31595
  }
31544
- const elementDocument = element.ownerDocument;
31596
+ const iframeOffset = { left: 0, top: 0, right: 0, bottom: 0 };
31597
+ if (renderDocument !== element.ownerDocument) {
31598
+ let iframe = element.ownerDocument.defaultView?.frameElement;
31599
+ while (iframe) {
31600
+ const iframeRect = iframe.getBoundingClientRect();
31601
+ iframeOffset.left += iframeRect.left;
31602
+ iframeOffset.top += iframeRect.top;
31603
+ iframe = iframe.ownerDocument.defaultView?.frameElement;
31604
+ }
31605
+ }
31606
+ const elementDocument = renderDocument ?? element.ownerDocument;
31545
31607
  const isFixed = isAncestorOrSelfFixed(element);
31546
- const rect = element.getBoundingClientRect();
31608
+ const elementBoundingBox = element.getBoundingClientRect();
31609
+ const elementPositionWithOffset = {
31610
+ top: elementBoundingBox.top + iframeOffset.top,
31611
+ left: elementBoundingBox.left + iframeOffset.left
31612
+ };
31547
31613
  const newElement = elementDocument.createElement("div");
31548
31614
  newElement.style.outline = "2px dashed rgba(255,0,0,.75)";
31549
31615
  newElement.style.position = isFixed ? "fixed" : "absolute";
31550
- newElement.style.left = rect.left + "px";
31551
- newElement.style.top = rect.top + "px";
31552
- newElement.style.width = rect.right - rect.left + "px";
31553
- newElement.style.height = rect.bottom - rect.top + "px";
31616
+ newElement.style.left = elementPositionWithOffset.left + "px";
31617
+ newElement.style.top = elementPositionWithOffset.top + "px";
31618
+ newElement.style.width = elementBoundingBox.width + "px";
31619
+ newElement.style.height = elementBoundingBox.height + "px";
31554
31620
  newElement.style.pointerEvents = pointerEvents ?? "none";
31555
31621
  newElement.style.zIndex = "2147483647";
31556
31622
  newElement.className = ["checksum-dom-cache-ignore", ...classNames].join(
@@ -31586,7 +31652,7 @@
31586
31652
  );
31587
31653
  hoverTextEl.innerText = text;
31588
31654
  hoverTextEl.style.fontSize = "12px";
31589
- hoverTextEl.style.width = textWidthType === "rect" ? `${rect.width}px` : "auto";
31655
+ hoverTextEl.style.width = textWidthType === "rect" ? `${elementBoundingBox.width}px` : "auto";
31590
31656
  hoverTextEl.style.background = "#000000a1";
31591
31657
  hoverTextEl.style.color = "white";
31592
31658
  hoverTextEl.style.padding = "5px";
@@ -31594,9 +31660,9 @@
31594
31660
  hoverTextEl.style.pointerEvents = "none";
31595
31661
  hoverTextEl.style.userSelect = "none";
31596
31662
  if (textPosition === "above") {
31597
- hoverTextEl.style.bottom = `${rect.height}px`;
31663
+ hoverTextEl.style.bottom = `${elementBoundingBox.height}px`;
31598
31664
  } else if (textPosition === "below") {
31599
- hoverTextEl.style.top = `${rect.height}px`;
31665
+ hoverTextEl.style.top = `${elementBoundingBox.height}px`;
31600
31666
  }
31601
31667
  this.mergeStyle(hoverTextEl, textStyle);
31602
31668
  newElement.appendChild(hoverTextEl);
@@ -31614,17 +31680,17 @@
31614
31680
  elementDocument.body.appendChild(newElement);
31615
31681
  if (textPosition === "above" && getHeightOfCroppedElementAboveViewport(hoverTextEl) > 0) {
31616
31682
  hoverTextEl.style.bottom = "initial";
31617
- hoverTextEl.style.top = `${rect.height}px`;
31683
+ hoverTextEl.style.top = `${elementBoundingBox.height}px`;
31618
31684
  } else if (textPosition === "below" && getHeightsOfCroppedElementBelowViewport(hoverTextEl) > 0) {
31619
31685
  hoverTextEl.style.top = "initial";
31620
- hoverTextEl.style.bottom = `${rect.height}px`;
31686
+ hoverTextEl.style.bottom = `${elementBoundingBox.height}px`;
31621
31687
  }
31622
31688
  this.lastHighlights.push(newElement);
31623
31689
  if (shouldFlipHighlightTextOutsideViewport) {
31624
31690
  this.flipHighlightTextPositionOutsideViewport(
31625
31691
  hoverTextEl,
31626
31692
  textPosition,
31627
- rect.height
31693
+ elementBoundingBox.height
31628
31694
  );
31629
31695
  }
31630
31696
  }
@@ -34231,7 +34297,7 @@
34231
34297
  return;
34232
34298
  }
34233
34299
  }
34234
- if (target instanceof this.defaultView.HTMLIFrameElement) {
34300
+ if (isNodeInstanceOf(target, "HTMLIFrameElement")) {
34235
34301
  this.handleSubDocument(
34236
34302
  target.contentDocument,
34237
34303
  target.contentDocument.defaultView
@@ -34241,10 +34307,11 @@
34241
34307
  if (this.subDocumentInspector) {
34242
34308
  this.stopSubDocumentInspector(true);
34243
34309
  }
34244
- if (!(target instanceof this.defaultView.Element)) {
34310
+ if (!isNodeInstanceOf(target, "HTMLElement")) {
34245
34311
  return;
34246
34312
  }
34247
- if (target === this.hoveredElement || target.matches(".element-inspector-ignore")) {
34313
+ const targetElement = target;
34314
+ if (targetElement === this.hoveredElement || targetElement.matches(".element-inspector-ignore")) {
34248
34315
  return;
34249
34316
  }
34250
34317
  elementHighlighter.clearHighlights();
@@ -34254,14 +34321,15 @@
34254
34321
  });
34255
34322
  }
34256
34323
  const { locator, selector, parentFramesSelectors } = await this.playwrightElementSelectorGenerator.getSelectorAndLocator(
34257
- target
34324
+ targetElement
34258
34325
  );
34259
- elementHighlighter.highlightElement(target, {
34326
+ elementHighlighter.highlightElement(targetElement, {
34260
34327
  text: locator.replace("frameLocator('iframe').", ""),
34261
34328
  textPosition: "below",
34262
34329
  textWidthType: "auto",
34263
34330
  pointerEvents: "none",
34264
- classNames: ["element-inspector-ignore"]
34331
+ classNames: ["element-inspector-ignore"],
34332
+ renderDocument: this.defaultView.top.document
34265
34333
  });
34266
34334
  const elementByLocator = await this.playwrightElementSelectorGenerator.selector(
34267
34335
  selector,
@@ -34272,10 +34340,11 @@
34272
34340
  // highlightStyle: { outlineColor: "blue" },
34273
34341
  clear: false,
34274
34342
  pointerEvents: "none",
34275
- classNames: ["element-inspector-ignore"]
34343
+ classNames: ["element-inspector-ignore"],
34344
+ renderDocument: this.defaultView.top.document
34276
34345
  });
34277
34346
  }
34278
- this.hoveredElement = target;
34347
+ this.hoveredElement = targetElement;
34279
34348
  this.hoveredElementSelection = { locator, selector, parentFramesSelectors };
34280
34349
  this.wasHoveredElementSelected = false;
34281
34350
  target.addEventListener("click", this.onClick, {
@@ -34431,16 +34500,14 @@ ${data.locator}`
34431
34500
  }
34432
34501
  this.sessionRecorder.addCustomEvent("assertion" /* Assertion */, {
34433
34502
  matcher: `toHaveText("${result2}")`,
34434
- locator: data.locator,
34435
- thought: `Element should have text: ${result2}`
34503
+ locator: data.locator
34436
34504
  });
34437
34505
  }, "toHaveTextHandler");
34438
34506
  this.toBeVisibleHandler = /* @__PURE__ */ __name(() => (messageEvent) => {
34439
34507
  const data = messageEvent?.data?.data;
34440
34508
  this.sessionRecorder.addCustomEvent("assertion" /* Assertion */, {
34441
34509
  matcher: `toBeVisible()`,
34442
- locator: data.locator,
34443
- thought: `Element ${data.locator} should be visible`
34510
+ locator: data.locator
34444
34511
  });
34445
34512
  }, "toBeVisibleHandler");
34446
34513
  this.sessionRecorder = sessionRecorder;
@@ -35517,8 +35584,8 @@ ${data.locator}`
35517
35584
  goLive() {
35518
35585
  return this.sessionReplayer.goLive();
35519
35586
  }
35520
- getLastEventTimestamps() {
35521
- return this.sessionReplayer.getLastEventTimestamps();
35587
+ getLastEventTimestamps(snapshot2 = false) {
35588
+ return this.sessionReplayer.getLastEventTimestamps(snapshot2);
35522
35589
  }
35523
35590
  };
35524
35591