@appsurify-testmap/rrweb-playwright-plugin 3.1.1-alpha.2 → 3.2.0-alpha.1

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var O=Object.create;var f=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var D=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var U=(t,e)=>{for(var n in e)f(t,n,{get:e[n],enumerable:!0})},k=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of L(e))!F.call(t,r)&&r!==n&&f(t,r,{get:()=>e[r],enumerable:!(s=P(e,r))||s.enumerable});return t};var b=(t,e,n)=>(n=t!=null?O(D(t)):{},k(e||!t||!t.__esModule?f(n,"default",{value:t,enumerable:!0}):n,t)),z=t=>k(f({},"__esModule",{value:!0}),t);var Y={};U(Y,{expect:()=>y.expect,test:()=>$});module.exports=z(Y);var y=require("@playwright/test");var w=b(require("os")),p=b(require("path")),d=b(require("fs")),j="test-results/playwright/ui";function B(t,e){let n=p.default.dirname(t),s=p.default.join(n,`.${p.default.basename(t)}.tmp-${process.pid}-${Date.now()}`);d.default.mkdirSync(n,{recursive:!0}),d.default.writeFileSync(s,e,"utf-8"),d.default.renameSync(s,t)}function W(t){try{if(!d.default.existsSync(t))return[];let e=d.default.readFileSync(t,"utf-8").trim();if(!e)return[];let n=JSON.parse(e);return Array.isArray(n)?n:[]}catch{return[]}}function C(t,e){let n=e!==void 0?e:j,s=v(t.spec.name),r=v(t.test.suite?.title),i=v(t.test.title),o=t.browser.name,c=`${r?r+"-":""}${i}.json`,u=p.default.join(n,s,o,c),h={events:t.recorderEvents,metadata:{runner:t.runner,spec:t.spec,suite:t.test.suite,test:t.test,browser:t.browser}};d.default.mkdirSync(n,{recursive:!0}),d.default.mkdirSync(p.default.dirname(u),{recursive:!0}),d.default.writeFileSync(u,JSON.stringify(h,null,2),"utf-8"),console.log(`[ui-coverage] Saved report to ${u}`);try{let a=p.default.join(n,"ui-coverage-aggregated.json"),l=W(a);l.push(h),B(a,JSON.stringify(l,null,2)),console.log(`[ui-coverage] Updated aggregate: ${a}`)}catch(a){console.warn("[ui-coverage] Failed to update aggregate report:",a)}}function v(t){return(t??"").trim().replace(/[\s:/\\<>|"'?*]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function _(t,e){let n=t.browserType(),s=t.version(),r=n.name(),i=e.file,o=i.replace(process.cwd(),"").replace(/^[/\\]/,""),c=o.split(/[\\/]/).pop()??"",[u,h]=c.split(/\.(?=[^\\.]+$)/),a=e.titlePath.slice(1,-1),l=a.join(" > ")||"Root Suite";return{runner:{source:"playwright",type:"unknown",version:e.config.version,platform:w.default.platform(),arch:w.default.arch(),recorder:{scriptVersion:"unknown",libVersion:"unknown"}},spec:{name:c,relative:o,absolute:i,baseName:c,fileName:u,fileExtension:h,id:o},test:{suite:{id:a.join("::")||"root",invocationDetails:{absoluteFile:i,column:e.column??0,line:e.line??0,fileUrl:void 0,function:void 0,originalFile:void 0,relativeFile:o},pending:!1,root:a.length===0,title:l,type:"unknown"},id:e.testId,title:e.title,titlePath:e.titlePath.slice(1),fullTitle:e.titlePath.slice(1).join(" "),file:e.file,invocationDetails:{absoluteFile:i,column:e.column,line:e.line,fileUrl:"",relativeFile:o},state:e.status,duration:e.duration,pending:!1,sync:!1,timedOut:void 0,type:""},browser:{name:r,family:r,version:s,majorVersion:parseInt(s.split(".")[0],10),displayName:e.project.use?.channel?.toUpperCase?.()??r.charAt(0).toUpperCase()+r.slice(1),channel:e.project.use?.channel??"",path:n.executablePath()},recorderEvents:[]}}function S(t,e){let n={...t};for(let s in e){let r=e[s],i=t[s];r&&typeof r=="object"&&!Array.isArray(r)&&i&&typeof i=="object"&&!Array.isArray(i)?n[s]=S(i,r):r!==void 0&&(n[s]=r)}return n}async function I(t,e=500){let n=Date.now(),s=t.getEvents().length;return new Promise(r=>{let i=setInterval(()=>{let o=t.getEvents().length;(o===s||Date.now()-n>e)&&(clearInterval(i),r()),s=o},50)})}async function E(t){await t.evaluate(()=>new Promise(e=>requestAnimationFrame(()=>e())))}var H={i8:Int8Array,ui8:Uint8Array,ui8c:Uint8ClampedArray,i16:Int16Array,ui16:Uint16Array,i32:Int32Array,ui32:Uint32Array,f32:Float32Array,f64:Float64Array,bi64:BigInt64Array,bui64:BigUint64Array},Z=new Map(Object.entries(H).map(([t,e])=>[e,t]));var R=`(function (g, f) {if ("object" == typeof exports && "object" == typeof module) {module.exports = f();} else if ("function" == typeof define && define.amd) {define("rrweb", [], f);} else if ("object" == typeof exports) {exports["rrweb"] = f();} else {g["rrweb"] = f();}}(typeof self !== 'undefined' ? self : typeof globalThis !== 'undefined' ? globalThis : this, () => {var exports = {};var module = { exports };
1
+ "use strict";var O=Object.create;var f=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var L=Object.getPrototypeOf,F=Object.prototype.hasOwnProperty;var U=(t,e)=>{for(var n in e)f(t,n,{get:e[n],enumerable:!0})},k=(t,e,n,s)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of D(e))!F.call(t,r)&&r!==n&&f(t,r,{get:()=>e[r],enumerable:!(s=P(e,r))||s.enumerable});return t};var b=(t,e,n)=>(n=t!=null?O(L(t)):{},k(e||!t||!t.__esModule?f(n,"default",{value:t,enumerable:!0}):n,t)),z=t=>k(f({},"__esModule",{value:!0}),t);var Y={};U(Y,{expect:()=>y.expect,test:()=>$});module.exports=z(Y);var y=require("@playwright/test");var w=b(require("os")),p=b(require("path")),d=b(require("fs")),B="test-results/playwright/ui";function j(t,e){let n=p.default.dirname(t),s=p.default.join(n,`.${p.default.basename(t)}.tmp-${process.pid}-${Date.now()}`);d.default.mkdirSync(n,{recursive:!0}),d.default.writeFileSync(s,e,"utf-8"),d.default.renameSync(s,t)}function W(t){try{if(!d.default.existsSync(t))return[];let e=d.default.readFileSync(t,"utf-8").trim();if(!e)return[];let n=JSON.parse(e);return Array.isArray(n)?n:[]}catch{return[]}}function C(t,e){let n=e!==void 0?e:B,s=v(t.spec.name),r=v(t.test.suite?.title),i=v(t.test.title),o=t.browser.name,c=`${r?r+"-":""}${i}.json`,u=p.default.join(n,s,o,c),h={events:t.recorderEvents,metadata:{runner:t.runner,spec:t.spec,suite:t.test.suite,test:t.test,browser:t.browser}};d.default.mkdirSync(n,{recursive:!0}),d.default.mkdirSync(p.default.dirname(u),{recursive:!0}),d.default.writeFileSync(u,JSON.stringify(h,null,2),"utf-8"),console.log(`[ui-coverage] Saved report to ${u}`);try{let a=p.default.join(n,"ui-coverage-aggregated.json"),l=W(a);l.push(h),j(a,JSON.stringify(l,null,2)),console.log(`[ui-coverage] Updated aggregate: ${a}`)}catch(a){console.warn("[ui-coverage] Failed to update aggregate report:",a)}}function v(t){return(t??"").trim().replace(/[\s:/\\<>|"'?*]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function _(t,e){let n=t.browserType(),s=t.version(),r=n.name(),i=e.file,o=i.replace(process.cwd(),"").replace(/^[/\\]/,""),c=o.split(/[\\/]/).pop()??"",[u,h]=c.split(/\.(?=[^\\.]+$)/),a=e.titlePath.slice(1,-1),l=a.join(" > ")||"Root Suite";return{runner:{source:"playwright",type:"unknown",version:e.config.version,platform:w.default.platform(),arch:w.default.arch(),recorder:{scriptVersion:"unknown",libVersion:"unknown"}},spec:{name:c,relative:o,absolute:i,baseName:c,fileName:u,fileExtension:h,id:o},test:{suite:{id:a.join("::")||"root",invocationDetails:{absoluteFile:i,column:e.column??0,line:e.line??0,fileUrl:void 0,function:void 0,originalFile:void 0,relativeFile:o},pending:!1,root:a.length===0,title:l,type:"unknown"},id:e.testId,title:e.title,titlePath:e.titlePath.slice(1),fullTitle:e.titlePath.slice(1).join(" "),file:e.file,invocationDetails:{absoluteFile:i,column:e.column,line:e.line,fileUrl:"",relativeFile:o},state:e.status,duration:e.duration,pending:!1,sync:!1,timedOut:void 0,type:""},browser:{name:r,family:r,version:s,majorVersion:parseInt(s.split(".")[0],10),displayName:e.project.use?.channel?.toUpperCase?.()??r.charAt(0).toUpperCase()+r.slice(1),channel:e.project.use?.channel??"",path:n.executablePath()},recorderEvents:[]}}function S(t,e){let n={...t};for(let s in e){let r=e[s],i=t[s];r&&typeof r=="object"&&!Array.isArray(r)&&i&&typeof i=="object"&&!Array.isArray(i)?n[s]=S(i,r):r!==void 0&&(n[s]=r)}return n}async function E(t,e=500){let n=Date.now(),s=t.getEvents().length;return new Promise(r=>{let i=setInterval(()=>{let o=t.getEvents().length;(o===s||Date.now()-n>e)&&(clearInterval(i),r()),s=o},50)})}async function I(t){await t.evaluate(()=>new Promise(e=>requestAnimationFrame(()=>e())))}var H={i8:Int8Array,ui8:Uint8Array,ui8c:Uint8ClampedArray,i16:Int16Array,ui16:Uint16Array,i32:Int32Array,ui32:Uint32Array,f32:Float32Array,f64:Float64Array,bi64:BigInt64Array,bui64:BigUint64Array},Z=new Map(Object.entries(H).map(([t,e])=>[e,t]));var R=`(function (g, f) {if ("object" == typeof exports && "object" == typeof module) {module.exports = f();} else if ("function" == typeof define && define.amd) {define("rrweb", [], f);} else if ("object" == typeof exports) {exports["rrweb"] = f();} else {g["rrweb"] = f();}}(typeof self !== 'undefined' ? self : typeof globalThis !== 'undefined' ? globalThis : this, () => {var exports = {};var module = { exports };
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __defProps = Object.defineProperties;
@@ -981,7 +981,14 @@ const bt$1 = {
981
981
  source: "dom-dsl"
982
982
  };
983
983
  function P$1(r2) {
984
- return !!(/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2) || /^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2) && (/\\d/.test(r2) || /[A-Z]/.test(r2)) || /^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
984
+ if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
985
+ return true;
986
+ if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
987
+ const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
988
+ if (t2 && e2 || s2)
989
+ return true;
990
+ }
991
+ return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
985
992
  }
986
993
  const Q$1 = /* @__PURE__ */ new Set([
987
994
  "aria-labelledby",
@@ -1182,6 +1189,11 @@ const xt$1 = [
1182
1189
  /^(rtl|ltr):/,
1183
1190
  // === FIX 4: Group and peer variants ===
1184
1191
  /^(group|peer)(-hover|-focus|-active)?:/,
1192
+ // === Arbitrary pseudo-class/modifier variants (catch-all) ===
1193
+ // Matches any lowercase/hyphenated prefix followed by colon
1194
+ // e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
1195
+ // Must come AFTER semantic pattern checks to avoid false positives
1196
+ /^[a-z][a-z-]*:/,
1185
1197
  // === FIX 4: Tailwind utilities with fraction values ===
1186
1198
  /\\/([\\d.]+|full|auto|screen)$/,
1187
1199
  // /50, /100, /full, /auto, /screen
@@ -11752,7 +11764,14 @@ const bt = {
11752
11764
  source: "dom-dsl"
11753
11765
  };
11754
11766
  function P(r2) {
11755
- return !!(/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2) || /^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2) && (/\\d/.test(r2) || /[A-Z]/.test(r2)) || /^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
11767
+ if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
11768
+ return true;
11769
+ if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
11770
+ const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
11771
+ if (t2 && e2 || s2)
11772
+ return true;
11773
+ }
11774
+ return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
11756
11775
  }
11757
11776
  const Q = /* @__PURE__ */ new Set([
11758
11777
  "aria-labelledby",
@@ -11953,6 +11972,11 @@ const xt = [
11953
11972
  /^(rtl|ltr):/,
11954
11973
  // === FIX 4: Group and peer variants ===
11955
11974
  /^(group|peer)(-hover|-focus|-active)?:/,
11975
+ // === Arbitrary pseudo-class/modifier variants (catch-all) ===
11976
+ // Matches any lowercase/hyphenated prefix followed by colon
11977
+ // e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
11978
+ // Must come AFTER semantic pattern checks to avoid false positives
11979
+ /^[a-z][a-z-]*:/,
11956
11980
  // === FIX 4: Tailwind utilities with fraction values ===
11957
11981
  /\\/([\\d.]+|full|auto|screen)$/,
11958
11982
  // /50, /100, /full, /auto, /screen
@@ -13906,6 +13930,30 @@ class MutationBuffer {
13906
13930
  this.shadowDomManager.reset();
13907
13931
  this.canvasManager.reset();
13908
13932
  }
13933
+ /**
13934
+ * Clear all accumulated mutation data without emitting.
13935
+ * Used after freeze+debounce checkout \u2014 FullSnapshot already captured the state.
13936
+ */
13937
+ resetBuffers() {
13938
+ this.addedSet = /* @__PURE__ */ new Set();
13939
+ this.movedSet = /* @__PURE__ */ new Set();
13940
+ this.droppedSet = /* @__PURE__ */ new Set();
13941
+ this.removesSubTreeCache = /* @__PURE__ */ new Set();
13942
+ this.mapRemoves = [];
13943
+ this.movedMap = {};
13944
+ this.attributes = [];
13945
+ this.texts = [];
13946
+ this.attributeMap = /* @__PURE__ */ new WeakMap();
13947
+ this.removes = [];
13948
+ }
13949
+ /**
13950
+ * Clear frozen flag without triggering emit.
13951
+ * Used after freeze+debounce checkout \u2014 buffers already cleared by resetBuffers().
13952
+ */
13953
+ unsetFrozen() {
13954
+ this.frozen = false;
13955
+ this.canvasManager.unfreeze();
13956
+ }
13909
13957
  }
13910
13958
  function deepDelete(addsSet, n2) {
13911
13959
  addsSet.delete(n2);
@@ -16326,11 +16374,15 @@ class VisibilityManager {
16326
16374
  }
16327
16375
  flushBuffer() {
16328
16376
  var _a2;
16377
+ if (this.frozen || this.locked)
16378
+ return;
16329
16379
  if (this.buffer.size === 0)
16330
16380
  return;
16331
- (_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, this.buffer.size);
16332
- this.mutationCb({ mutations: Array.from(this.buffer.values()) });
16381
+ const mutations = Array.from(this.buffer.values());
16382
+ const count = mutations.length;
16333
16383
  this.buffer.clear();
16384
+ this.mutationCb({ mutations });
16385
+ (_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, count);
16334
16386
  }
16335
16387
  observe(el) {
16336
16388
  if (this.disabled)
@@ -16346,6 +16398,10 @@ class VisibilityManager {
16346
16398
  }
16347
16399
  freeze() {
16348
16400
  this.frozen = true;
16401
+ if (this.debounceTimer) {
16402
+ clearTimeout(this.debounceTimer);
16403
+ this.debounceTimer = null;
16404
+ }
16349
16405
  }
16350
16406
  unfreeze() {
16351
16407
  this.frozen = false;
@@ -16353,9 +16409,33 @@ class VisibilityManager {
16353
16409
  }
16354
16410
  lock() {
16355
16411
  this.locked = true;
16412
+ if (this.debounceTimer) {
16413
+ clearTimeout(this.debounceTimer);
16414
+ this.debounceTimer = null;
16415
+ }
16356
16416
  }
16357
16417
  unlock() {
16358
16418
  this.locked = false;
16419
+ this.buffer.clear();
16420
+ if (this.debounceTimer) {
16421
+ clearTimeout(this.debounceTimer);
16422
+ this.debounceTimer = null;
16423
+ }
16424
+ if (!this.disabled && this.elements.size > 0) {
16425
+ this.previousState = computeVisibility(this.elements, /* @__PURE__ */ new Map(), {
16426
+ root: this.root,
16427
+ threshold: this.threshold,
16428
+ sensitivity: this.sensitivity,
16429
+ rootMargin: this.rootMargin
16430
+ });
16431
+ }
16432
+ }
16433
+ /**
16434
+ * Clear frozen flag without triggering flush.
16435
+ * Used after freeze+debounce checkout \u2014 buffer already cleared by unlock().
16436
+ */
16437
+ unsetFrozen() {
16438
+ this.frozen = false;
16359
16439
  }
16360
16440
  reset() {
16361
16441
  this.elements.clear();
@@ -16458,7 +16538,7 @@ class ProcessedNodeManager {
16458
16538
  destroy() {
16459
16539
  }
16460
16540
  }
16461
- const version$1 = "3.1.1-alpha.2";
16541
+ const version$1 = "3.1.1-alpha.3";
16462
16542
  let wrappedEmit;
16463
16543
  let takeFullSnapshot$1;
16464
16544
  let canvasManager;
@@ -16512,6 +16592,7 @@ function record(options = {}) {
16512
16592
  checkoutEveryNms,
16513
16593
  checkoutEveryNth,
16514
16594
  checkoutEveryNvm,
16595
+ checkoutDebounce,
16515
16596
  blockClass = "rr-block",
16516
16597
  blockSelector = null,
16517
16598
  ignoreClass = "rr-ignore",
@@ -16606,6 +16687,10 @@ function record(options = {}) {
16606
16687
  let lastFullSnapshotEvent;
16607
16688
  let incrementalSnapshotCount = 0;
16608
16689
  let visibilityMutationCount = 0;
16690
+ let checkoutId = 0;
16691
+ let checkoutPending = false;
16692
+ let checkoutDebounceTimer = null;
16693
+ let checkoutFreezeTimestamp = null;
16609
16694
  const eventProcessor = (e2) => {
16610
16695
  for (const plugin3 of plugins || []) {
16611
16696
  if (plugin3.eventProcessor) {
@@ -16618,11 +16703,25 @@ function record(options = {}) {
16618
16703
  }
16619
16704
  return e2;
16620
16705
  };
16706
+ const executeCheckout = () => {
16707
+ checkoutDebounceTimer = null;
16708
+ checkoutPending = false;
16709
+ checkoutFreezeTimestamp = null;
16710
+ takeFullSnapshot$1(true);
16711
+ mutationBuffers.forEach((buf) => {
16712
+ buf.resetBuffers();
16713
+ buf.unsetFrozen();
16714
+ });
16715
+ if (visibilityManager) {
16716
+ visibilityManager.unsetFrozen();
16717
+ }
16718
+ };
16621
16719
  wrappedEmit = (r2, isCheckout) => {
16622
16720
  var _a2;
16623
16721
  const e2 = r2;
16624
16722
  e2.timestamp = nowTimestamp();
16625
- if (((_a2 = mutationBuffers[0]) == null ? void 0 : _a2.isFrozen()) && e2.type !== EventType.FullSnapshot && !(e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.Mutation)) {
16723
+ e2.checkoutId = checkoutId;
16724
+ if (((_a2 = mutationBuffers[0]) == null ? void 0 : _a2.isFrozen()) && !checkoutPending && e2.type !== EventType.FullSnapshot && !(e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.Mutation)) {
16626
16725
  mutationBuffers.forEach((buf) => buf.unfreeze());
16627
16726
  visibilityManager == null ? void 0 : visibilityManager.unfreeze();
16628
16727
  }
@@ -16649,7 +16748,29 @@ function record(options = {}) {
16649
16748
  const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
16650
16749
  const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
16651
16750
  if (exceedCount || exceedTime) {
16652
- takeFullSnapshot$1(true);
16751
+ if (checkoutDebounce) {
16752
+ if (!checkoutPending) {
16753
+ checkoutPending = true;
16754
+ checkoutFreezeTimestamp = nowTimestamp();
16755
+ mutationBuffers.forEach((buf) => buf.freeze());
16756
+ visibilityManager == null ? void 0 : visibilityManager.freeze();
16757
+ }
16758
+ if (checkoutDebounceTimer) {
16759
+ clearTimeout(checkoutDebounceTimer);
16760
+ }
16761
+ const frozenDuration = nowTimestamp() - checkoutFreezeTimestamp;
16762
+ const maxFreeze = checkoutDebounce * 3;
16763
+ if (frozenDuration >= maxFreeze) {
16764
+ executeCheckout();
16765
+ } else {
16766
+ checkoutDebounceTimer = setTimeout(
16767
+ () => executeCheckout(),
16768
+ checkoutDebounce
16769
+ );
16770
+ }
16771
+ } else {
16772
+ takeFullSnapshot$1(true);
16773
+ }
16653
16774
  }
16654
16775
  }
16655
16776
  }
@@ -16759,8 +16880,30 @@ function record(options = {}) {
16759
16880
  notifyActivity: checkoutEveryNvm != null ? (count) => {
16760
16881
  visibilityMutationCount += count;
16761
16882
  if (visibilityMutationCount >= checkoutEveryNvm) {
16762
- takeFullSnapshot$1(true);
16763
16883
  visibilityMutationCount = 0;
16884
+ if (checkoutDebounce) {
16885
+ if (!checkoutPending) {
16886
+ checkoutPending = true;
16887
+ checkoutFreezeTimestamp = nowTimestamp();
16888
+ mutationBuffers.forEach((buf) => buf.freeze());
16889
+ visibilityManager == null ? void 0 : visibilityManager.freeze();
16890
+ }
16891
+ if (checkoutDebounceTimer) {
16892
+ clearTimeout(checkoutDebounceTimer);
16893
+ }
16894
+ const frozenDuration = nowTimestamp() - checkoutFreezeTimestamp;
16895
+ const maxFreeze = checkoutDebounce * 3;
16896
+ if (frozenDuration >= maxFreeze) {
16897
+ executeCheckout();
16898
+ } else {
16899
+ checkoutDebounceTimer = setTimeout(
16900
+ () => executeCheckout(),
16901
+ checkoutDebounce
16902
+ );
16903
+ }
16904
+ } else {
16905
+ takeFullSnapshot$1(true);
16906
+ }
16764
16907
  }
16765
16908
  } : void 0
16766
16909
  });
@@ -16769,6 +16912,7 @@ function record(options = {}) {
16769
16912
  if (!recordDOM) {
16770
16913
  return;
16771
16914
  }
16915
+ checkoutId++;
16772
16916
  wrappedEmit(
16773
16917
  {
16774
16918
  type: EventType.Meta,
@@ -17040,6 +17184,10 @@ function record(options = {}) {
17040
17184
  );
17041
17185
  }
17042
17186
  return () => {
17187
+ if (checkoutDebounceTimer) {
17188
+ clearTimeout(checkoutDebounceTimer);
17189
+ checkoutDebounceTimer = null;
17190
+ }
17043
17191
  flushCustomEventQueue$1();
17044
17192
  handlers.forEach((h) => h());
17045
17193
  processedNodeManager.destroy();
@@ -17154,5 +17302,5 @@ exports.globalSequentialId = globalSequentialId;
17154
17302
  return module.exports;
17155
17303
  }))
17156
17304
  //# sourceMappingURL=rrweb-plugin-sequential-id-record.umd.cjs.map
17157
- `;var K={slimDOMOptions:"all",inlineStylesheet:!0,recordDOM:!0,recordCanvas:!0,collectFonts:!0,inlineImages:!0,maskInputOptions:{password:!0},sampling:{mousemove:!1,mouseInteraction:{MouseUp:!1,MouseDown:!1,Click:!0,ContextMenu:!0,DblClick:!0,Focus:!0,Blur:!0,TouchStart:!1,TouchEnd:!1},scroll:100,media:100,input:"last",canvas:"all",visibility:{mode:"none",debounce:0,threshold:.5,sensitivity:.05,rafThrottle:10}},flushCustomEvent:"after",recordAfter:"DOMContentLoaded",userTriggeredOnInput:!0},m=class{recordFn=null;page=null;context;eventCounter=0;events=[];recordOptions;pendingEvents=[];recorderScriptVersion="unknown";recorderLibVersion="unknown";isRecording=!1;constructor(e){this.recordOptions=S(K,e??{}),this.context={pushEvent:n=>this.events.push(n)}}handleEmit(e){if(e.type===0||e.type===1)return;let n={...e};this.context.pushEvent(n)}async inject(e){this.page=e,await this.page?.addInitScript({content:R}),await this.page?.addInitScript({content:A}),await this.page?.exposeFunction("handleEmit",n=>{this.handleEmit(n)})}async start(){this.recordFn=await this.page?.evaluateHandle(()=>window.rrweb?.record),await this.recordFn?.evaluate((e,n)=>{let s=JSON.parse(n),r=[];window.rrwebPluginSequentialIdRecord&&r.push(window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({key:"id"})),window.stopFn=e({emit:i=>{window.handleEmit?.(i)},plugins:r,...s})},JSON.stringify(this.recordOptions)),this.isRecording=await this.recordFn?.evaluate(e=>e.isRecording()),this.recorderScriptVersion=await this.recordFn?.evaluate(e=>e.getVersion()),await this.flush()}async stop(){this.isRecording=!1,this.recordFn&&this.page&&!this.page.isClosed()&&(await this.flush(),await this.page.evaluate(()=>{window.stopFn=null}))}async reset(){this.eventCounter=0,this.events=[],await this.stop(),this.context={pushEvent:e=>this.events.push(e)}}async flush(){if(!this.recordFn)return;let e=[];for(let n of this.pendingEvents)try{await this.recordFn.evaluate((s,r)=>{s.addCustomEvent(r.tag,r.payload)},n)}catch{console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${n.tag}`),e.push(n)}this.pendingEvents=e}async addCustomEvent(e,n){let s={tag:e,payload:n};if(!this.recordFn||!this.isRecording){console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${e}`),this.pendingEvents.push(s);return}try{await this.recordFn.evaluate((r,i)=>{r.addCustomEvent(i.tag,i.payload)},s)}catch{this.pendingEvents.push(s)}}isRecordingReady(){return!!this.recordFn&&this.isRecording}getScriptVersion(){return`@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`}getLibVersion(){return`@appsurify-testmap/rrweb:${this.recorderLibVersion!=="unknown"?this.recorderLibVersion:this.recorderScriptVersion}`}getEvents(){return this.events}getMirror(){return this.recordFn?.mirror}bind(e){this.context=e}setEventCounter(e){this.eventCounter=e}};var g=m;var T=new Map;function M(t,e){T.set(t,e)}function x(t){return T.get(t)}var $=y.test.extend({browser:async({browser:t},e)=>{await e(t)},context:async({browser:t},e,n)=>{let s=await t.newContext(),r=_(t,n);M(n.testId,r),await e(s),await s.close()},page:async({page:t},e,n)=>{let r=n.project.use.testmap??{},i=typeof r=="object"&&"recordingOpts"in r?r.recordingOpts:g,o=new g(i),c=x(n.testId);c&&(c.recorderInstance=o),o.bind({pushEvent:async a=>{c?.recorderEvents.push(a),await Promise.resolve()}}),await o.inject(t),t.on("console",async a=>{a.type()!=="debug"&&console.debug(`[${Date.now()}] [page] console`,a.text())}),t.on("load",async()=>{}),t.on("domcontentloaded",async()=>{await o.start(),c?.runner&&(c.runner.recorder={scriptVersion:o.getScriptVersion(),libVersion:o.getLibVersion()})}),t.on("framenavigated",async()=>{}),t.on("close",async()=>{await o.flush()});let u=n._onStepEnd.bind(void 0);n._onStepEnd=async a=>{let l=n._stepMap.get(a.stepId);if(l.apiName&&l?.location.file===n.file&&await o.addCustomEvent(l.apiName,{stepId:l.stepId,category:l.category,location:l.location,title:l.title,apiName:l.apiName,endWallTime:l.endWallTime}),!t.isClosed())try{await E(t)}catch{}await u(a)};let h=n._onDidFinishTestFunction.bind(void 0);n._onDidFinishTestFunction=async()=>{o&&o.isRecordingReady()&&(await I(o,500),await o.stop()),await h()},await e(t)}});$.beforeEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F7E2} TEST START] ${t.title}`)});$.afterEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F534} TEST END] ${t.title}`);let e=x(t.testId);if(!e)return;e.test.duration=t.duration;let n={runner:e?.runner,spec:e?.spec,browser:e?.browser,test:e?.test,suite:e?.test.suite,recorderEvents:Array.isArray(e?.recorderEvents)?e?.recorderEvents:[]},r=t.project.use.testmap??{};C(n,r.outputReportDir)});0&&(module.exports={expect,test});
17305
+ `;var K={slimDOMOptions:"all",inlineStylesheet:!0,recordDOM:!0,recordCanvas:!0,collectFonts:!0,inlineImages:!0,maskInputOptions:{password:!0},sampling:{mousemove:!1,mouseInteraction:{MouseUp:!1,MouseDown:!1,Click:!0,ContextMenu:!0,DblClick:!0,Focus:!0,Blur:!0,TouchStart:!1,TouchEnd:!1},scroll:100,media:100,input:"last",canvas:"all",visibility:{mode:"none",debounce:0,threshold:.5,sensitivity:.05,rafThrottle:10}},flushCustomEvent:"after",recordAfter:"DOMContentLoaded",userTriggeredOnInput:!0},m=class{recordFn=null;page=null;context;eventCounter=0;events=[];recordOptions;pendingEvents=[];recorderScriptVersion="unknown";recorderLibVersion="unknown";isRecording=!1;constructor(e){this.recordOptions=S(K,e??{}),this.context={pushEvent:n=>this.events.push(n)}}handleEmit(e){if(e.type===0||e.type===1)return;let n={...e};this.context.pushEvent(n)}async inject(e){this.page=e,await this.page?.addInitScript({content:R}),await this.page?.addInitScript({content:A}),await this.page?.exposeFunction("handleEmit",n=>{this.handleEmit(n)})}async start(){this.recordFn=await this.page?.evaluateHandle(()=>window.rrweb?.record),await this.recordFn?.evaluate((e,n)=>{let s=JSON.parse(n),r=[];window.rrwebPluginSequentialIdRecord&&r.push(window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({key:"id"})),window.stopFn=e({emit:i=>{window.handleEmit?.(i)},plugins:r,...s})},JSON.stringify(this.recordOptions)),this.isRecording=await this.recordFn?.evaluate(e=>e.isRecording()),this.recorderScriptVersion=await this.recordFn?.evaluate(e=>e.getVersion()),await this.flush()}async stop(){this.isRecording=!1,this.recordFn&&this.page&&!this.page.isClosed()&&(await this.flush(),await this.page.evaluate(()=>{window.stopFn=null}))}async reset(){this.eventCounter=0,this.events=[],await this.stop(),this.context={pushEvent:e=>this.events.push(e)}}async flush(){if(!this.recordFn)return;let e=[];for(let n of this.pendingEvents)try{await this.recordFn.evaluate((s,r)=>{s.addCustomEvent(r.tag,r.payload)},n)}catch{console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${n.tag}`),e.push(n)}this.pendingEvents=e}async addCustomEvent(e,n){let s={tag:e,payload:n};if(!this.recordFn||!this.isRecording){console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${e}`),this.pendingEvents.push(s);return}try{await this.recordFn.evaluate((r,i)=>{r.addCustomEvent(i.tag,i.payload)},s)}catch{this.pendingEvents.push(s)}}isRecordingReady(){return!!this.recordFn&&this.isRecording}getScriptVersion(){return`@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`}getLibVersion(){return`@appsurify-testmap/rrweb:${this.recorderLibVersion!=="unknown"?this.recorderLibVersion:this.recorderScriptVersion}`}getEvents(){return this.events}getMirror(){return this.recordFn?.mirror}bind(e){this.context=e}setEventCounter(e){this.eventCounter=e}};var g=m;var T=new Map;function M(t,e){T.set(t,e)}function x(t){return T.get(t)}var $=y.test.extend({browser:async({browser:t},e)=>{await e(t)},context:async({browser:t},e,n)=>{let s=await t.newContext(),r=_(t,n);M(n.testId,r),await e(s),await s.close()},page:async({page:t},e,n)=>{let r=n.project.use.testmap??{},i=typeof r=="object"&&"recordingOpts"in r?r.recordingOpts:g,o=new g(i),c=x(n.testId);c&&(c.recorderInstance=o),o.bind({pushEvent:async a=>{c?.recorderEvents.push(a),await Promise.resolve()}}),await o.inject(t),t.on("console",async a=>{a.type()!=="debug"&&console.debug(`[${Date.now()}] [page] console`,a.text())}),t.on("load",async()=>{}),t.on("domcontentloaded",async()=>{await o.start(),c?.runner&&(c.runner.recorder={scriptVersion:o.getScriptVersion(),libVersion:o.getLibVersion()})}),t.on("framenavigated",async()=>{}),t.on("close",async()=>{await o.flush()});let u=n._onStepEnd.bind(void 0);n._onStepEnd=async a=>{let l=n._stepMap.get(a.stepId);if(l.apiName&&l?.location.file===n.file&&await o.addCustomEvent(l.apiName,{stepId:l.stepId,category:l.category,location:l.location,title:l.title,apiName:l.apiName,endWallTime:l.endWallTime}),!t.isClosed())try{await I(t)}catch{}await u(a)};let h=n._onDidFinishTestFunction.bind(void 0);n._onDidFinishTestFunction=async()=>{o&&o.isRecordingReady()&&(await E(o,500),await o.stop()),await h()},await e(t)}});$.beforeEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F7E2} TEST START] ${t.title}`)});$.afterEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F534} TEST END] ${t.title}`);let e=x(t.testId);if(!e)return;e.test.duration=t.duration;let n={runner:e?.runner,spec:e?.spec,browser:e?.browser,test:e?.test,suite:e?.test.suite,recorderEvents:Array.isArray(e?.recorderEvents)?e?.recorderEvents:[]},r=t.project.use.testmap??{};C(n,r.outputReportDir)});0&&(module.exports={expect,test});
17158
17306
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["src_exports","__export","test","__toCommonJS","import_test","import_os","import_path","import_fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","path","tmp","fs","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","os","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["src_exports","__export","test","__toCommonJS","import_test","import_os","import_path","import_fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","path","tmp","fs","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","os","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import{test as D,expect as X}from"@playwright/test";import v from"os";import h from"path";import d from"fs";var A="test-results/playwright/ui";function T(t,e){let n=h.dirname(t),s=h.join(n,`.${h.basename(t)}.tmp-${process.pid}-${Date.now()}`);d.mkdirSync(n,{recursive:!0}),d.writeFileSync(s,e,"utf-8"),d.renameSync(s,t)}function M(t){try{if(!d.existsSync(t))return[];let e=d.readFileSync(t,"utf-8").trim();if(!e)return[];let n=JSON.parse(e);return Array.isArray(n)?n:[]}catch{return[]}}function w(t,e){let n=e!==void 0?e:A,s=g(t.spec.name),r=g(t.test.suite?.title),i=g(t.test.title),o=t.browser.name,c=`${r?r+"-":""}${i}.json`,u=h.join(n,s,o,c),p={events:t.recorderEvents,metadata:{runner:t.runner,spec:t.spec,suite:t.test.suite,test:t.test,browser:t.browser}};d.mkdirSync(n,{recursive:!0}),d.mkdirSync(h.dirname(u),{recursive:!0}),d.writeFileSync(u,JSON.stringify(p,null,2),"utf-8"),console.log(`[ui-coverage] Saved report to ${u}`);try{let a=h.join(n,"ui-coverage-aggregated.json"),l=M(a);l.push(p),T(a,JSON.stringify(l,null,2)),console.log(`[ui-coverage] Updated aggregate: ${a}`)}catch(a){console.warn("[ui-coverage] Failed to update aggregate report:",a)}}function g(t){return(t??"").trim().replace(/[\s:/\\<>|"'?*]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function S(t,e){let n=t.browserType(),s=t.version(),r=n.name(),i=e.file,o=i.replace(process.cwd(),"").replace(/^[/\\]/,""),c=o.split(/[\\/]/).pop()??"",[u,p]=c.split(/\.(?=[^\\.]+$)/),a=e.titlePath.slice(1,-1),l=a.join(" > ")||"Root Suite";return{runner:{source:"playwright",type:"unknown",version:e.config.version,platform:v.platform(),arch:v.arch(),recorder:{scriptVersion:"unknown",libVersion:"unknown"}},spec:{name:c,relative:o,absolute:i,baseName:c,fileName:u,fileExtension:p,id:o},test:{suite:{id:a.join("::")||"root",invocationDetails:{absoluteFile:i,column:e.column??0,line:e.line??0,fileUrl:void 0,function:void 0,originalFile:void 0,relativeFile:o},pending:!1,root:a.length===0,title:l,type:"unknown"},id:e.testId,title:e.title,titlePath:e.titlePath.slice(1),fullTitle:e.titlePath.slice(1).join(" "),file:e.file,invocationDetails:{absoluteFile:i,column:e.column,line:e.line,fileUrl:"",relativeFile:o},state:e.status,duration:e.duration,pending:!1,sync:!1,timedOut:void 0,type:""},browser:{name:r,family:r,version:s,majorVersion:parseInt(s.split(".")[0],10),displayName:e.project.use?.channel?.toUpperCase?.()??r.charAt(0).toUpperCase()+r.slice(1),channel:e.project.use?.channel??"",path:n.executablePath()},recorderEvents:[]}}function y(t,e){let n={...t};for(let s in e){let r=e[s],i=t[s];r&&typeof r=="object"&&!Array.isArray(r)&&i&&typeof i=="object"&&!Array.isArray(i)?n[s]=y(i,r):r!==void 0&&(n[s]=r)}return n}async function x(t,e=500){let n=Date.now(),s=t.getEvents().length;return new Promise(r=>{let i=setInterval(()=>{let o=t.getEvents().length;(o===s||Date.now()-n>e)&&(clearInterval(i),r()),s=o},50)})}async function $(t){await t.evaluate(()=>new Promise(e=>requestAnimationFrame(()=>e())))}var N={i8:Int8Array,ui8:Uint8Array,ui8c:Uint8ClampedArray,i16:Int16Array,ui16:Uint16Array,i32:Int32Array,ui32:Uint32Array,f32:Float32Array,f64:Float64Array,bi64:BigInt64Array,bui64:BigUint64Array},j=new Map(Object.entries(N).map(([t,e])=>[e,t]));var k=`(function (g, f) {if ("object" == typeof exports && "object" == typeof module) {module.exports = f();} else if ("function" == typeof define && define.amd) {define("rrweb", [], f);} else if ("object" == typeof exports) {exports["rrweb"] = f();} else {g["rrweb"] = f();}}(typeof self !== 'undefined' ? self : typeof globalThis !== 'undefined' ? globalThis : this, () => {var exports = {};var module = { exports };
1
+ import{test as L,expect as X}from"@playwright/test";import v from"os";import h from"path";import d from"fs";var A="test-results/playwright/ui";function T(t,e){let n=h.dirname(t),s=h.join(n,`.${h.basename(t)}.tmp-${process.pid}-${Date.now()}`);d.mkdirSync(n,{recursive:!0}),d.writeFileSync(s,e,"utf-8"),d.renameSync(s,t)}function M(t){try{if(!d.existsSync(t))return[];let e=d.readFileSync(t,"utf-8").trim();if(!e)return[];let n=JSON.parse(e);return Array.isArray(n)?n:[]}catch{return[]}}function w(t,e){let n=e!==void 0?e:A,s=g(t.spec.name),r=g(t.test.suite?.title),i=g(t.test.title),o=t.browser.name,c=`${r?r+"-":""}${i}.json`,u=h.join(n,s,o,c),p={events:t.recorderEvents,metadata:{runner:t.runner,spec:t.spec,suite:t.test.suite,test:t.test,browser:t.browser}};d.mkdirSync(n,{recursive:!0}),d.mkdirSync(h.dirname(u),{recursive:!0}),d.writeFileSync(u,JSON.stringify(p,null,2),"utf-8"),console.log(`[ui-coverage] Saved report to ${u}`);try{let a=h.join(n,"ui-coverage-aggregated.json"),l=M(a);l.push(p),T(a,JSON.stringify(l,null,2)),console.log(`[ui-coverage] Updated aggregate: ${a}`)}catch(a){console.warn("[ui-coverage] Failed to update aggregate report:",a)}}function g(t){return(t??"").trim().replace(/[\s:/\\<>|"'?*]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function S(t,e){let n=t.browserType(),s=t.version(),r=n.name(),i=e.file,o=i.replace(process.cwd(),"").replace(/^[/\\]/,""),c=o.split(/[\\/]/).pop()??"",[u,p]=c.split(/\.(?=[^\\.]+$)/),a=e.titlePath.slice(1,-1),l=a.join(" > ")||"Root Suite";return{runner:{source:"playwright",type:"unknown",version:e.config.version,platform:v.platform(),arch:v.arch(),recorder:{scriptVersion:"unknown",libVersion:"unknown"}},spec:{name:c,relative:o,absolute:i,baseName:c,fileName:u,fileExtension:p,id:o},test:{suite:{id:a.join("::")||"root",invocationDetails:{absoluteFile:i,column:e.column??0,line:e.line??0,fileUrl:void 0,function:void 0,originalFile:void 0,relativeFile:o},pending:!1,root:a.length===0,title:l,type:"unknown"},id:e.testId,title:e.title,titlePath:e.titlePath.slice(1),fullTitle:e.titlePath.slice(1).join(" "),file:e.file,invocationDetails:{absoluteFile:i,column:e.column,line:e.line,fileUrl:"",relativeFile:o},state:e.status,duration:e.duration,pending:!1,sync:!1,timedOut:void 0,type:""},browser:{name:r,family:r,version:s,majorVersion:parseInt(s.split(".")[0],10),displayName:e.project.use?.channel?.toUpperCase?.()??r.charAt(0).toUpperCase()+r.slice(1),channel:e.project.use?.channel??"",path:n.executablePath()},recorderEvents:[]}}function y(t,e){let n={...t};for(let s in e){let r=e[s],i=t[s];r&&typeof r=="object"&&!Array.isArray(r)&&i&&typeof i=="object"&&!Array.isArray(i)?n[s]=y(i,r):r!==void 0&&(n[s]=r)}return n}async function x(t,e=500){let n=Date.now(),s=t.getEvents().length;return new Promise(r=>{let i=setInterval(()=>{let o=t.getEvents().length;(o===s||Date.now()-n>e)&&(clearInterval(i),r()),s=o},50)})}async function $(t){await t.evaluate(()=>new Promise(e=>requestAnimationFrame(()=>e())))}var N={i8:Int8Array,ui8:Uint8Array,ui8c:Uint8ClampedArray,i16:Int16Array,ui16:Uint16Array,i32:Int32Array,ui32:Uint32Array,f32:Float32Array,f64:Float64Array,bi64:BigInt64Array,bui64:BigUint64Array},B=new Map(Object.entries(N).map(([t,e])=>[e,t]));var k=`(function (g, f) {if ("object" == typeof exports && "object" == typeof module) {module.exports = f();} else if ("function" == typeof define && define.amd) {define("rrweb", [], f);} else if ("object" == typeof exports) {exports["rrweb"] = f();} else {g["rrweb"] = f();}}(typeof self !== 'undefined' ? self : typeof globalThis !== 'undefined' ? globalThis : this, () => {var exports = {};var module = { exports };
2
2
  "use strict";
3
3
  var __defProp = Object.defineProperty;
4
4
  var __defProps = Object.defineProperties;
@@ -981,7 +981,14 @@ const bt$1 = {
981
981
  source: "dom-dsl"
982
982
  };
983
983
  function P$1(r2) {
984
- return !!(/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2) || /^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2) && (/\\d/.test(r2) || /[A-Z]/.test(r2)) || /^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
984
+ if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
985
+ return true;
986
+ if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
987
+ const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
988
+ if (t2 && e2 || s2)
989
+ return true;
990
+ }
991
+ return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
985
992
  }
986
993
  const Q$1 = /* @__PURE__ */ new Set([
987
994
  "aria-labelledby",
@@ -1182,6 +1189,11 @@ const xt$1 = [
1182
1189
  /^(rtl|ltr):/,
1183
1190
  // === FIX 4: Group and peer variants ===
1184
1191
  /^(group|peer)(-hover|-focus|-active)?:/,
1192
+ // === Arbitrary pseudo-class/modifier variants (catch-all) ===
1193
+ // Matches any lowercase/hyphenated prefix followed by colon
1194
+ // e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
1195
+ // Must come AFTER semantic pattern checks to avoid false positives
1196
+ /^[a-z][a-z-]*:/,
1185
1197
  // === FIX 4: Tailwind utilities with fraction values ===
1186
1198
  /\\/([\\d.]+|full|auto|screen)$/,
1187
1199
  // /50, /100, /full, /auto, /screen
@@ -11752,7 +11764,14 @@ const bt = {
11752
11764
  source: "dom-dsl"
11753
11765
  };
11754
11766
  function P(r2) {
11755
- return !!(/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2) || /^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2) && (/\\d/.test(r2) || /[A-Z]/.test(r2)) || /^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
11767
+ if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
11768
+ return true;
11769
+ if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
11770
+ const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
11771
+ if (t2 && e2 || s2)
11772
+ return true;
11773
+ }
11774
+ return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
11756
11775
  }
11757
11776
  const Q = /* @__PURE__ */ new Set([
11758
11777
  "aria-labelledby",
@@ -11953,6 +11972,11 @@ const xt = [
11953
11972
  /^(rtl|ltr):/,
11954
11973
  // === FIX 4: Group and peer variants ===
11955
11974
  /^(group|peer)(-hover|-focus|-active)?:/,
11975
+ // === Arbitrary pseudo-class/modifier variants (catch-all) ===
11976
+ // Matches any lowercase/hyphenated prefix followed by colon
11977
+ // e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
11978
+ // Must come AFTER semantic pattern checks to avoid false positives
11979
+ /^[a-z][a-z-]*:/,
11956
11980
  // === FIX 4: Tailwind utilities with fraction values ===
11957
11981
  /\\/([\\d.]+|full|auto|screen)$/,
11958
11982
  // /50, /100, /full, /auto, /screen
@@ -13906,6 +13930,30 @@ class MutationBuffer {
13906
13930
  this.shadowDomManager.reset();
13907
13931
  this.canvasManager.reset();
13908
13932
  }
13933
+ /**
13934
+ * Clear all accumulated mutation data without emitting.
13935
+ * Used after freeze+debounce checkout \u2014 FullSnapshot already captured the state.
13936
+ */
13937
+ resetBuffers() {
13938
+ this.addedSet = /* @__PURE__ */ new Set();
13939
+ this.movedSet = /* @__PURE__ */ new Set();
13940
+ this.droppedSet = /* @__PURE__ */ new Set();
13941
+ this.removesSubTreeCache = /* @__PURE__ */ new Set();
13942
+ this.mapRemoves = [];
13943
+ this.movedMap = {};
13944
+ this.attributes = [];
13945
+ this.texts = [];
13946
+ this.attributeMap = /* @__PURE__ */ new WeakMap();
13947
+ this.removes = [];
13948
+ }
13949
+ /**
13950
+ * Clear frozen flag without triggering emit.
13951
+ * Used after freeze+debounce checkout \u2014 buffers already cleared by resetBuffers().
13952
+ */
13953
+ unsetFrozen() {
13954
+ this.frozen = false;
13955
+ this.canvasManager.unfreeze();
13956
+ }
13909
13957
  }
13910
13958
  function deepDelete(addsSet, n2) {
13911
13959
  addsSet.delete(n2);
@@ -16326,11 +16374,15 @@ class VisibilityManager {
16326
16374
  }
16327
16375
  flushBuffer() {
16328
16376
  var _a2;
16377
+ if (this.frozen || this.locked)
16378
+ return;
16329
16379
  if (this.buffer.size === 0)
16330
16380
  return;
16331
- (_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, this.buffer.size);
16332
- this.mutationCb({ mutations: Array.from(this.buffer.values()) });
16381
+ const mutations = Array.from(this.buffer.values());
16382
+ const count = mutations.length;
16333
16383
  this.buffer.clear();
16384
+ this.mutationCb({ mutations });
16385
+ (_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, count);
16334
16386
  }
16335
16387
  observe(el) {
16336
16388
  if (this.disabled)
@@ -16346,6 +16398,10 @@ class VisibilityManager {
16346
16398
  }
16347
16399
  freeze() {
16348
16400
  this.frozen = true;
16401
+ if (this.debounceTimer) {
16402
+ clearTimeout(this.debounceTimer);
16403
+ this.debounceTimer = null;
16404
+ }
16349
16405
  }
16350
16406
  unfreeze() {
16351
16407
  this.frozen = false;
@@ -16353,9 +16409,33 @@ class VisibilityManager {
16353
16409
  }
16354
16410
  lock() {
16355
16411
  this.locked = true;
16412
+ if (this.debounceTimer) {
16413
+ clearTimeout(this.debounceTimer);
16414
+ this.debounceTimer = null;
16415
+ }
16356
16416
  }
16357
16417
  unlock() {
16358
16418
  this.locked = false;
16419
+ this.buffer.clear();
16420
+ if (this.debounceTimer) {
16421
+ clearTimeout(this.debounceTimer);
16422
+ this.debounceTimer = null;
16423
+ }
16424
+ if (!this.disabled && this.elements.size > 0) {
16425
+ this.previousState = computeVisibility(this.elements, /* @__PURE__ */ new Map(), {
16426
+ root: this.root,
16427
+ threshold: this.threshold,
16428
+ sensitivity: this.sensitivity,
16429
+ rootMargin: this.rootMargin
16430
+ });
16431
+ }
16432
+ }
16433
+ /**
16434
+ * Clear frozen flag without triggering flush.
16435
+ * Used after freeze+debounce checkout \u2014 buffer already cleared by unlock().
16436
+ */
16437
+ unsetFrozen() {
16438
+ this.frozen = false;
16359
16439
  }
16360
16440
  reset() {
16361
16441
  this.elements.clear();
@@ -16458,7 +16538,7 @@ class ProcessedNodeManager {
16458
16538
  destroy() {
16459
16539
  }
16460
16540
  }
16461
- const version$1 = "3.1.1-alpha.2";
16541
+ const version$1 = "3.1.1-alpha.3";
16462
16542
  let wrappedEmit;
16463
16543
  let takeFullSnapshot$1;
16464
16544
  let canvasManager;
@@ -16512,6 +16592,7 @@ function record(options = {}) {
16512
16592
  checkoutEveryNms,
16513
16593
  checkoutEveryNth,
16514
16594
  checkoutEveryNvm,
16595
+ checkoutDebounce,
16515
16596
  blockClass = "rr-block",
16516
16597
  blockSelector = null,
16517
16598
  ignoreClass = "rr-ignore",
@@ -16606,6 +16687,10 @@ function record(options = {}) {
16606
16687
  let lastFullSnapshotEvent;
16607
16688
  let incrementalSnapshotCount = 0;
16608
16689
  let visibilityMutationCount = 0;
16690
+ let checkoutId = 0;
16691
+ let checkoutPending = false;
16692
+ let checkoutDebounceTimer = null;
16693
+ let checkoutFreezeTimestamp = null;
16609
16694
  const eventProcessor = (e2) => {
16610
16695
  for (const plugin3 of plugins || []) {
16611
16696
  if (plugin3.eventProcessor) {
@@ -16618,11 +16703,25 @@ function record(options = {}) {
16618
16703
  }
16619
16704
  return e2;
16620
16705
  };
16706
+ const executeCheckout = () => {
16707
+ checkoutDebounceTimer = null;
16708
+ checkoutPending = false;
16709
+ checkoutFreezeTimestamp = null;
16710
+ takeFullSnapshot$1(true);
16711
+ mutationBuffers.forEach((buf) => {
16712
+ buf.resetBuffers();
16713
+ buf.unsetFrozen();
16714
+ });
16715
+ if (visibilityManager) {
16716
+ visibilityManager.unsetFrozen();
16717
+ }
16718
+ };
16621
16719
  wrappedEmit = (r2, isCheckout) => {
16622
16720
  var _a2;
16623
16721
  const e2 = r2;
16624
16722
  e2.timestamp = nowTimestamp();
16625
- if (((_a2 = mutationBuffers[0]) == null ? void 0 : _a2.isFrozen()) && e2.type !== EventType.FullSnapshot && !(e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.Mutation)) {
16723
+ e2.checkoutId = checkoutId;
16724
+ if (((_a2 = mutationBuffers[0]) == null ? void 0 : _a2.isFrozen()) && !checkoutPending && e2.type !== EventType.FullSnapshot && !(e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.Mutation)) {
16626
16725
  mutationBuffers.forEach((buf) => buf.unfreeze());
16627
16726
  visibilityManager == null ? void 0 : visibilityManager.unfreeze();
16628
16727
  }
@@ -16649,7 +16748,29 @@ function record(options = {}) {
16649
16748
  const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
16650
16749
  const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
16651
16750
  if (exceedCount || exceedTime) {
16652
- takeFullSnapshot$1(true);
16751
+ if (checkoutDebounce) {
16752
+ if (!checkoutPending) {
16753
+ checkoutPending = true;
16754
+ checkoutFreezeTimestamp = nowTimestamp();
16755
+ mutationBuffers.forEach((buf) => buf.freeze());
16756
+ visibilityManager == null ? void 0 : visibilityManager.freeze();
16757
+ }
16758
+ if (checkoutDebounceTimer) {
16759
+ clearTimeout(checkoutDebounceTimer);
16760
+ }
16761
+ const frozenDuration = nowTimestamp() - checkoutFreezeTimestamp;
16762
+ const maxFreeze = checkoutDebounce * 3;
16763
+ if (frozenDuration >= maxFreeze) {
16764
+ executeCheckout();
16765
+ } else {
16766
+ checkoutDebounceTimer = setTimeout(
16767
+ () => executeCheckout(),
16768
+ checkoutDebounce
16769
+ );
16770
+ }
16771
+ } else {
16772
+ takeFullSnapshot$1(true);
16773
+ }
16653
16774
  }
16654
16775
  }
16655
16776
  }
@@ -16759,8 +16880,30 @@ function record(options = {}) {
16759
16880
  notifyActivity: checkoutEveryNvm != null ? (count) => {
16760
16881
  visibilityMutationCount += count;
16761
16882
  if (visibilityMutationCount >= checkoutEveryNvm) {
16762
- takeFullSnapshot$1(true);
16763
16883
  visibilityMutationCount = 0;
16884
+ if (checkoutDebounce) {
16885
+ if (!checkoutPending) {
16886
+ checkoutPending = true;
16887
+ checkoutFreezeTimestamp = nowTimestamp();
16888
+ mutationBuffers.forEach((buf) => buf.freeze());
16889
+ visibilityManager == null ? void 0 : visibilityManager.freeze();
16890
+ }
16891
+ if (checkoutDebounceTimer) {
16892
+ clearTimeout(checkoutDebounceTimer);
16893
+ }
16894
+ const frozenDuration = nowTimestamp() - checkoutFreezeTimestamp;
16895
+ const maxFreeze = checkoutDebounce * 3;
16896
+ if (frozenDuration >= maxFreeze) {
16897
+ executeCheckout();
16898
+ } else {
16899
+ checkoutDebounceTimer = setTimeout(
16900
+ () => executeCheckout(),
16901
+ checkoutDebounce
16902
+ );
16903
+ }
16904
+ } else {
16905
+ takeFullSnapshot$1(true);
16906
+ }
16764
16907
  }
16765
16908
  } : void 0
16766
16909
  });
@@ -16769,6 +16912,7 @@ function record(options = {}) {
16769
16912
  if (!recordDOM) {
16770
16913
  return;
16771
16914
  }
16915
+ checkoutId++;
16772
16916
  wrappedEmit(
16773
16917
  {
16774
16918
  type: EventType.Meta,
@@ -17040,6 +17184,10 @@ function record(options = {}) {
17040
17184
  );
17041
17185
  }
17042
17186
  return () => {
17187
+ if (checkoutDebounceTimer) {
17188
+ clearTimeout(checkoutDebounceTimer);
17189
+ checkoutDebounceTimer = null;
17190
+ }
17043
17191
  flushCustomEventQueue$1();
17044
17192
  handlers.forEach((h) => h());
17045
17193
  processedNodeManager.destroy();
@@ -17154,5 +17302,5 @@ exports.globalSequentialId = globalSequentialId;
17154
17302
  return module.exports;
17155
17303
  }))
17156
17304
  //# sourceMappingURL=rrweb-plugin-sequential-id-record.umd.cjs.map
17157
- `;var L={slimDOMOptions:"all",inlineStylesheet:!0,recordDOM:!0,recordCanvas:!0,collectFonts:!0,inlineImages:!0,maskInputOptions:{password:!0},sampling:{mousemove:!1,mouseInteraction:{MouseUp:!1,MouseDown:!1,Click:!0,ContextMenu:!0,DblClick:!0,Focus:!0,Blur:!0,TouchStart:!1,TouchEnd:!1},scroll:100,media:100,input:"last",canvas:"all",visibility:{mode:"none",debounce:0,threshold:.5,sensitivity:.05,rafThrottle:10}},flushCustomEvent:"after",recordAfter:"DOMContentLoaded",userTriggeredOnInput:!0},f=class{recordFn=null;page=null;context;eventCounter=0;events=[];recordOptions;pendingEvents=[];recorderScriptVersion="unknown";recorderLibVersion="unknown";isRecording=!1;constructor(e){this.recordOptions=y(L,e??{}),this.context={pushEvent:n=>this.events.push(n)}}handleEmit(e){if(e.type===0||e.type===1)return;let n={...e};this.context.pushEvent(n)}async inject(e){this.page=e,await this.page?.addInitScript({content:k}),await this.page?.addInitScript({content:C}),await this.page?.exposeFunction("handleEmit",n=>{this.handleEmit(n)})}async start(){this.recordFn=await this.page?.evaluateHandle(()=>window.rrweb?.record),await this.recordFn?.evaluate((e,n)=>{let s=JSON.parse(n),r=[];window.rrwebPluginSequentialIdRecord&&r.push(window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({key:"id"})),window.stopFn=e({emit:i=>{window.handleEmit?.(i)},plugins:r,...s})},JSON.stringify(this.recordOptions)),this.isRecording=await this.recordFn?.evaluate(e=>e.isRecording()),this.recorderScriptVersion=await this.recordFn?.evaluate(e=>e.getVersion()),await this.flush()}async stop(){this.isRecording=!1,this.recordFn&&this.page&&!this.page.isClosed()&&(await this.flush(),await this.page.evaluate(()=>{window.stopFn=null}))}async reset(){this.eventCounter=0,this.events=[],await this.stop(),this.context={pushEvent:e=>this.events.push(e)}}async flush(){if(!this.recordFn)return;let e=[];for(let n of this.pendingEvents)try{await this.recordFn.evaluate((s,r)=>{s.addCustomEvent(r.tag,r.payload)},n)}catch{console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${n.tag}`),e.push(n)}this.pendingEvents=e}async addCustomEvent(e,n){let s={tag:e,payload:n};if(!this.recordFn||!this.isRecording){console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${e}`),this.pendingEvents.push(s);return}try{await this.recordFn.evaluate((r,i)=>{r.addCustomEvent(i.tag,i.payload)},s)}catch{this.pendingEvents.push(s)}}isRecordingReady(){return!!this.recordFn&&this.isRecording}getScriptVersion(){return`@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`}getLibVersion(){return`@appsurify-testmap/rrweb:${this.recorderLibVersion!=="unknown"?this.recorderLibVersion:this.recorderScriptVersion}`}getEvents(){return this.events}getMirror(){return this.recordFn?.mirror}bind(e){this.context=e}setEventCounter(e){this.eventCounter=e}};var m=f;var _=new Map;function I(t,e){_.set(t,e)}function b(t){return _.get(t)}var E=D.extend({browser:async({browser:t},e)=>{await e(t)},context:async({browser:t},e,n)=>{let s=await t.newContext(),r=S(t,n);I(n.testId,r),await e(s),await s.close()},page:async({page:t},e,n)=>{let r=n.project.use.testmap??{},i=typeof r=="object"&&"recordingOpts"in r?r.recordingOpts:m,o=new m(i),c=b(n.testId);c&&(c.recorderInstance=o),o.bind({pushEvent:async a=>{c?.recorderEvents.push(a),await Promise.resolve()}}),await o.inject(t),t.on("console",async a=>{a.type()!=="debug"&&console.debug(`[${Date.now()}] [page] console`,a.text())}),t.on("load",async()=>{}),t.on("domcontentloaded",async()=>{await o.start(),c?.runner&&(c.runner.recorder={scriptVersion:o.getScriptVersion(),libVersion:o.getLibVersion()})}),t.on("framenavigated",async()=>{}),t.on("close",async()=>{await o.flush()});let u=n._onStepEnd.bind(void 0);n._onStepEnd=async a=>{let l=n._stepMap.get(a.stepId);if(l.apiName&&l?.location.file===n.file&&await o.addCustomEvent(l.apiName,{stepId:l.stepId,category:l.category,location:l.location,title:l.title,apiName:l.apiName,endWallTime:l.endWallTime}),!t.isClosed())try{await $(t)}catch{}await u(a)};let p=n._onDidFinishTestFunction.bind(void 0);n._onDidFinishTestFunction=async()=>{o&&o.isRecordingReady()&&(await x(o,500),await o.stop()),await p()},await e(t)}});E.beforeEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F7E2} TEST START] ${t.title}`)});E.afterEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F534} TEST END] ${t.title}`);let e=b(t.testId);if(!e)return;e.test.duration=t.duration;let n={runner:e?.runner,spec:e?.spec,browser:e?.browser,test:e?.test,suite:e?.test.suite,recorderEvents:Array.isArray(e?.recorderEvents)?e?.recorderEvents:[]},r=t.project.use.testmap??{};w(n,r.outputReportDir)});export{X as expect,E as test};
17305
+ `;var D={slimDOMOptions:"all",inlineStylesheet:!0,recordDOM:!0,recordCanvas:!0,collectFonts:!0,inlineImages:!0,maskInputOptions:{password:!0},sampling:{mousemove:!1,mouseInteraction:{MouseUp:!1,MouseDown:!1,Click:!0,ContextMenu:!0,DblClick:!0,Focus:!0,Blur:!0,TouchStart:!1,TouchEnd:!1},scroll:100,media:100,input:"last",canvas:"all",visibility:{mode:"none",debounce:0,threshold:.5,sensitivity:.05,rafThrottle:10}},flushCustomEvent:"after",recordAfter:"DOMContentLoaded",userTriggeredOnInput:!0},f=class{recordFn=null;page=null;context;eventCounter=0;events=[];recordOptions;pendingEvents=[];recorderScriptVersion="unknown";recorderLibVersion="unknown";isRecording=!1;constructor(e){this.recordOptions=y(D,e??{}),this.context={pushEvent:n=>this.events.push(n)}}handleEmit(e){if(e.type===0||e.type===1)return;let n={...e};this.context.pushEvent(n)}async inject(e){this.page=e,await this.page?.addInitScript({content:k}),await this.page?.addInitScript({content:C}),await this.page?.exposeFunction("handleEmit",n=>{this.handleEmit(n)})}async start(){this.recordFn=await this.page?.evaluateHandle(()=>window.rrweb?.record),await this.recordFn?.evaluate((e,n)=>{let s=JSON.parse(n),r=[];window.rrwebPluginSequentialIdRecord&&r.push(window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({key:"id"})),window.stopFn=e({emit:i=>{window.handleEmit?.(i)},plugins:r,...s})},JSON.stringify(this.recordOptions)),this.isRecording=await this.recordFn?.evaluate(e=>e.isRecording()),this.recorderScriptVersion=await this.recordFn?.evaluate(e=>e.getVersion()),await this.flush()}async stop(){this.isRecording=!1,this.recordFn&&this.page&&!this.page.isClosed()&&(await this.flush(),await this.page.evaluate(()=>{window.stopFn=null}))}async reset(){this.eventCounter=0,this.events=[],await this.stop(),this.context={pushEvent:e=>this.events.push(e)}}async flush(){if(!this.recordFn)return;let e=[];for(let n of this.pendingEvents)try{await this.recordFn.evaluate((s,r)=>{s.addCustomEvent(r.tag,r.payload)},n)}catch{console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${n.tag}`),e.push(n)}this.pendingEvents=e}async addCustomEvent(e,n){let s={tag:e,payload:n};if(!this.recordFn||!this.isRecording){console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${e}`),this.pendingEvents.push(s);return}try{await this.recordFn.evaluate((r,i)=>{r.addCustomEvent(i.tag,i.payload)},s)}catch{this.pendingEvents.push(s)}}isRecordingReady(){return!!this.recordFn&&this.isRecording}getScriptVersion(){return`@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`}getLibVersion(){return`@appsurify-testmap/rrweb:${this.recorderLibVersion!=="unknown"?this.recorderLibVersion:this.recorderScriptVersion}`}getEvents(){return this.events}getMirror(){return this.recordFn?.mirror}bind(e){this.context=e}setEventCounter(e){this.eventCounter=e}};var m=f;var _=new Map;function E(t,e){_.set(t,e)}function b(t){return _.get(t)}var I=L.extend({browser:async({browser:t},e)=>{await e(t)},context:async({browser:t},e,n)=>{let s=await t.newContext(),r=S(t,n);E(n.testId,r),await e(s),await s.close()},page:async({page:t},e,n)=>{let r=n.project.use.testmap??{},i=typeof r=="object"&&"recordingOpts"in r?r.recordingOpts:m,o=new m(i),c=b(n.testId);c&&(c.recorderInstance=o),o.bind({pushEvent:async a=>{c?.recorderEvents.push(a),await Promise.resolve()}}),await o.inject(t),t.on("console",async a=>{a.type()!=="debug"&&console.debug(`[${Date.now()}] [page] console`,a.text())}),t.on("load",async()=>{}),t.on("domcontentloaded",async()=>{await o.start(),c?.runner&&(c.runner.recorder={scriptVersion:o.getScriptVersion(),libVersion:o.getLibVersion()})}),t.on("framenavigated",async()=>{}),t.on("close",async()=>{await o.flush()});let u=n._onStepEnd.bind(void 0);n._onStepEnd=async a=>{let l=n._stepMap.get(a.stepId);if(l.apiName&&l?.location.file===n.file&&await o.addCustomEvent(l.apiName,{stepId:l.stepId,category:l.category,location:l.location,title:l.title,apiName:l.apiName,endWallTime:l.endWallTime}),!t.isClosed())try{await $(t)}catch{}await u(a)};let p=n._onDidFinishTestFunction.bind(void 0);n._onDidFinishTestFunction=async()=>{o&&o.isRecordingReady()&&(await x(o,500),await o.stop()),await p()},await e(t)}});I.beforeEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F7E2} TEST START] ${t.title}`)});I.afterEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F534} TEST END] ${t.title}`);let e=b(t.testId);if(!e)return;e.test.duration=t.duration;let n={runner:e?.runner,spec:e?.spec,browser:e?.browser,test:e?.test,suite:e?.test.suite,recorderEvents:Array.isArray(e?.recorderEvents)?e?.recorderEvents:[]},r=t.project.use.testmap??{};w(n,r.outputReportDir)});export{X as expect,I as test};
17158
17306
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["base","expect","os","path","fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","tmp","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECnYzJ,IAAME,EAAqD,CAC9D,eAAgB,MAChB,iBAAkB,GAClB,UAAW,GACX,aAAc,GACd,aAAc,GACd,aAAc,GACd,iBAAkB,CAAE,SAAU,EAAK,EACnC,SAAU,CACR,UAAW,GACX,iBAAkB,CAChB,QAAS,GACT,UAAW,GACX,MAAO,GACP,YAAa,GACb,SAAU,GACV,MAAO,GACP,KAAM,GACN,WAAY,GACZ,SAAU,EACZ,EACA,OAAQ,IACR,MAAO,IACP,MAAO,OACP,OAAQ,MACR,WAAY,CACV,KAAM,OACN,SAAU,EACV,UAAW,GACX,YAAa,IACb,YAAa,EACf,CACF,EACA,iBAAkB,QAClB,YAAa,mBACb,qBAAsB,EAC1B,EAeaC,EAAN,KAAoB,CACjB,SAAwC,KACxC,KAAoB,KACpB,QACA,aAAe,EACf,OAA0B,CAAC,EAC3B,cACA,cAGF,CAAC,EACC,sBAAwB,UACxB,mBAAqB,UACtB,YAAc,GAErB,YAAYC,EAAwC,CAClD,KAAK,cAAgBC,EAAUH,EAAsBE,GAAW,CAAC,CAAC,EAClE,KAAK,QAAU,CACb,UAAYE,GAAU,KAAK,OAAO,KAAKA,CAAK,CAC9C,CACF,CAEQ,WAAWA,EAAsB,CACvC,GAAIA,EAAM,OAAS,GAAKA,EAAM,OAAS,EACrC,OAEF,IAAMC,EAAyB,CAC7B,GAAGD,CACL,EACA,KAAK,QAAQ,UAAUC,CAAO,CAChC,CAEA,MAAa,OAAOC,EAAY,CAC9B,KAAK,KAAOA,EAEZ,MAAM,KAAK,MAAM,cAAc,CAAC,QAASC,CAAe,CAAC,EACzD,MAAM,KAAK,MAAM,cAAc,CAAC,QAASC,CAAqB,CAAC,EAE/D,MAAM,KAAK,MAAM,eAAe,aAAeJ,GAAyB,CACtE,KAAK,WAAWA,CAAK,CACvB,CAAC,CAEH,CAEA,MAAa,OAAQ,CACnB,KAAK,SAAW,MAAM,KAAK,MAAM,eAAe,IACvC,OAAO,OAAO,MACtB,EACD,MAAM,KAAK,UAAU,SAAS,CAACK,EAAkBC,IAAa,CAC5D,IAAMC,EAAO,KAAK,MAAMD,CAAQ,EAC1BE,EAAU,CAAC,EACb,OAAO,+BACTA,EAAQ,KACN,OAAO,8BAA8B,4BAA4B,CAC/D,IAAK,IACP,CAAC,CACH,EAGF,OAAO,OAASH,EAAE,CAChB,KAAOL,GAAyB,CAE9B,OAAO,aAAaA,CAAK,CAC3B,EACA,QAASQ,EACT,GAAGD,CACL,CAAC,CACH,EAAG,KAAK,UAAU,KAAK,aAAa,CAAC,EAErC,KAAK,YAAc,MAAM,KAAK,UAAU,SAAUF,GAAqBA,EAAE,YAAY,CAAC,EACtF,KAAK,sBAAwB,MAAM,KAAK,UAAU,SAAUA,GAAqBA,EAAE,WAAW,CAAC,EAE/F,MAAM,KAAK,MAAM,CACnB,CAEA,MAAa,MAAO,CAClB,KAAK,YAAc,GACf,KAAK,UAAY,KAAK,MAAQ,CAAC,KAAK,KAAK,SAAS,IACpD,MAAM,KAAK,MAAM,EACjB,MAAM,KAAK,KAAK,SAAS,IAAM,CAC7B,OAAO,OAAS,IAClB,CAAC,EAEL,CAEA,MAAa,OAAQ,CACnB,KAAK,aAAe,EACpB,KAAK,OAAS,CAAC,EACf,MAAM,KAAK,KAAK,EAChB,KAAK,QAAU,CACb,UAAYL,GAAU,KAAK,OAAO,KAAKA,CAAK,CAC9C,CACF,CAEA,MAAa,OAAQ,CACnB,GAAI,CAAC,KAAK,SAAU,OACpB,IAAMS,EAA0C,CAAC,EACjD,QAAWC,KAAO,KAAK,cACrB,GAAI,CACF,MAAM,KAAK,SAAS,SAAS,CAACL,EAAkBK,IAAQ,CACtDL,EAAE,eAAeK,EAAI,IAAKA,EAAI,OAAO,CACvC,EAAGA,CAAG,CACR,MAAE,CACA,QAAQ,MAAM,IAAI,KAAK,IAAI,gDAAgDA,EAAI,KAAK,EACpFD,EAAa,KAAKC,CAAG,CACvB,CAEF,KAAK,cAAgBD,CACvB,CAEA,MAAa,eAAeE,EAAaC,EAAkC,CACzE,IAAMZ,EAAQ,CAAE,IAAAW,EAAK,QAAAC,CAAQ,EAE7B,GAAI,CAAC,KAAK,UAAY,CAAC,KAAK,YAAa,CACvC,QAAQ,MAAM,IAAI,KAAK,IAAI,2DAA2DD,GAAK,EAC3F,KAAK,cAAc,KAAKX,CAAK,EAC7B,OAGF,GAAI,CACF,MAAM,KAAK,SAAS,SAAS,CAAC,EAAkBU,IAAQ,CACtD,EAAE,eAAeA,EAAI,IAAKA,EAAI,OAAO,CACvC,EAAGV,CAAK,CACV,MAAE,CACA,KAAK,cAAc,KAAKA,CAAK,CAC/B,CAEF,CAEO,kBAA4B,CACjC,MAAO,CAAC,CAAC,KAAK,UAAY,KAAK,WACjC,CAEO,kBAA2B,CAChC,MAAO,mCAAmC,KAAK,uBACjD,CAEO,eAAwB,CAC7B,MAAO,4BAA4B,KAAK,qBAAuB,UAAY,KAAK,mBAAqB,KAAK,uBAC5G,CAEO,WAAsC,CAC3C,OAAO,KAAK,MACd,CAEO,WAAgC,CACrC,OAAQ,KAAK,UAA6C,MAC5D,CAEO,KAAKa,EAAsB,CAChC,KAAK,QAAUA,CACjB,CAEO,gBAAgBC,EAAe,CACpC,KAAK,aAAeA,CACtB,CAEF,EC7NA,IAAOC,EAAQC,ECDR,IAAMC,EAAe,IAAI,IAEzB,SAASC,EAAsBC,EAAaC,EAA2B,CAC5EH,EAAa,IAAIE,EAAKC,CAAG,CAC3B,CAEO,SAASC,EAAsBF,EAAyC,CAC7E,OAAOF,EAAa,IAAIE,CAAG,CAC7B,CJgBA,IAAMG,EAAOC,EAAK,OAAW,CAC3B,QAAS,MAAO,CAAE,QAAAC,CAAQ,EAAGC,IAAQ,CACnC,MAAMA,EAAID,CAAO,CACnB,EAEA,QAAS,MAAO,CAAE,QAAAA,CAAQ,EAAGC,EAAKC,IAAa,CAC7C,IAAMC,EAAU,MAAMH,EAAQ,WAAW,EACnCI,EAAiBC,EAAqBL,EAASE,CAAQ,EAC7DI,EAAsBJ,EAAS,OAAQE,CAAc,EACrD,MAAMH,EAAIE,CAAO,EACjB,MAAMA,EAAQ,MAAM,CACtB,EAEA,KAAM,MAAO,CAAE,KAAAI,CAAK,EAAGN,EAAKC,IAAa,CAIvC,IAAMM,EADWN,EAAS,QAAQ,IACH,SAAW,CAAC,EACrCO,EACJ,OAAOD,GAAkB,UAAY,kBAAmBA,EACpDA,EAAc,cACdE,EAIAC,EAAW,IAAID,EAAcD,CAAa,EAE1CL,EAAiBQ,EAAsBV,EAAS,MAAM,EACxDE,IACFA,EAAe,iBAAmBO,GAGpCA,EAAS,KAAK,CAEZ,UAAW,MAAOE,GAAU,CAC1BT,GAAgB,eAAe,KAAKS,CAAK,EACzC,MAAM,QAAQ,QAAQ,CACxB,CACF,CAAC,EACD,MAAMF,EAAS,OAAOJ,CAAI,EAG1BA,EAAK,GAAG,UAAW,MAAOO,GAAmC,CACvDA,EAAe,KAAK,IAAM,SAC9B,QAAQ,MAAM,IAAI,KAAK,IAAI,oBAAqBA,EAAe,KAAK,CAAC,CACvE,CAAC,EAEDP,EAAK,GAAG,OAAQ,SAAY,CAE5B,CAAC,EAEDA,EAAK,GAAG,mBAAoB,SAAY,CACtC,MAAMI,EAAS,MAAM,EACjBP,GAAgB,SAClBA,EAAe,OAAO,SAAW,CAC/B,cAAeO,EAAS,iBAAiB,EACzC,WAAYA,EAAS,cAAc,CACrC,EAEJ,CAAC,EACDJ,EAAK,GAAG,iBAAkB,SAAY,CAEtC,CAAC,EAEDA,EAAK,GAAG,QAAS,SAAY,CAC3B,MAAMI,EAAS,MAAM,CACvB,CAAC,EAGD,IAAMI,EAAoBb,EAAS,WAAW,KAAK,MAAI,EAEvDA,EAAS,WAAa,MAAOc,GAOvB,CAGJ,IAAMC,EAAkBf,EAAS,SAAS,IAAIc,EAAe,MAAM,EAYnE,GAXIC,EAAgB,SAAWA,GAAiB,SAAS,OAASf,EAAS,MACzE,MAAMS,EAAS,eAAeM,EAAgB,QAAS,CACrD,OAAQA,EAAgB,OACxB,SAAUA,EAAgB,SAC1B,SAAUA,EAAgB,SAC1B,MAAOA,EAAgB,MACvB,QAASA,EAAgB,QACzB,YAAaA,EAAgB,WAC/B,CAAC,EAGC,CAACV,EAAK,SAAS,EACjB,GAAI,CACF,MAAMW,EAAeX,CAAI,CAC3B,MAAE,CAA4B,CAEhC,MAAMQ,EAAkBC,CAAc,CACxC,EAGA,IAAMG,EAAkCjB,EAAS,yBAAyB,KAAK,MAAI,EAEnFA,EAAS,yBAA2B,SAAY,CAE1CS,GAAYA,EAAS,iBAAiB,IACxC,MAAMS,EAA6BT,EAAU,GAAG,EAChD,MAAMA,EAAS,KAAK,GAGtB,MAAMQ,EAAgC,CACxC,EAEA,MAAMlB,EAAIM,CAAI,CAGhB,CACF,CAAC,EAEDT,EAAK,WAAW,MAAO,CAAC,EAAGI,IAAa,CACtC,QAAQ,IAAI,IAAI,KAAK,IAAI,6BAAsBA,EAAS,OAAO,CAEjE,CAAC,EAEDJ,EAAK,UAAU,MAAO,CAAC,EAAGI,IAAa,CACrC,QAAQ,IAAI,IAAI,KAAK,IAAI,2BAAoBA,EAAS,OAAO,EAC7D,IAAME,EAAiBQ,EAAsBV,EAAS,MAAM,EAC5D,GAAI,CAACE,EAAgB,OAErBA,EAAe,KAAK,SAAWF,EAAS,SACxC,IAAMmB,EAAgB,CAClB,OAAQjB,GAAgB,OACxB,KAAMA,GAAgB,KACtB,QAASA,GAAgB,QACzB,KAAMA,GAAgB,KACtB,MAAOA,GAAgB,KAAK,MAC5B,eAAgB,MAAM,QAAQA,GAAgB,cAAc,EAAIA,GAAgB,eAAiB,CAAC,CACtG,EAIMI,EADWN,EAAS,QAAQ,IACH,SAAW,CAAC,EAE3CoB,EAAgBD,EAAeb,EAAc,eAAe,CAE9D,CAAC","names":["base","expect","os","path","fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","tmp","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appsurify-testmap/rrweb-playwright-plugin",
3
- "version": "3.1.1-alpha.2",
3
+ "version": "3.2.0-alpha.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -40,9 +40,9 @@
40
40
  "@playwright/test": ">=1.50.0"
41
41
  },
42
42
  "devDependencies": {
43
- "@appsurify-testmap/rrweb": "^3.1.1-alpha.2",
44
- "@appsurify-testmap/rrweb-snapshot": "^3.1.1-alpha.2",
45
- "@appsurify-testmap/rrweb-types": "^3.1.1-alpha.2",
43
+ "@appsurify-testmap/rrweb": "^3.2.0-alpha.1",
44
+ "@appsurify-testmap/rrweb-snapshot": "^3.2.0-alpha.1",
45
+ "@appsurify-testmap/rrweb-types": "^3.2.0-alpha.1",
46
46
  "@playwright/test": "^1.52.0",
47
47
  "@types/node": "^24.10.0",
48
48
  "puppeteer": "^24.9.0",