@appsurify-testmap/rrweb-playwright-plugin 3.1.1-alpha.3 → 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 +131 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
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
|
|
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;
|
|
@@ -13930,6 +13930,30 @@ class MutationBuffer {
|
|
|
13930
13930
|
this.shadowDomManager.reset();
|
|
13931
13931
|
this.canvasManager.reset();
|
|
13932
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
|
+
}
|
|
13933
13957
|
}
|
|
13934
13958
|
function deepDelete(addsSet, n2) {
|
|
13935
13959
|
addsSet.delete(n2);
|
|
@@ -16350,11 +16374,15 @@ class VisibilityManager {
|
|
|
16350
16374
|
}
|
|
16351
16375
|
flushBuffer() {
|
|
16352
16376
|
var _a2;
|
|
16377
|
+
if (this.frozen || this.locked)
|
|
16378
|
+
return;
|
|
16353
16379
|
if (this.buffer.size === 0)
|
|
16354
16380
|
return;
|
|
16355
|
-
|
|
16356
|
-
|
|
16381
|
+
const mutations = Array.from(this.buffer.values());
|
|
16382
|
+
const count = mutations.length;
|
|
16357
16383
|
this.buffer.clear();
|
|
16384
|
+
this.mutationCb({ mutations });
|
|
16385
|
+
(_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, count);
|
|
16358
16386
|
}
|
|
16359
16387
|
observe(el) {
|
|
16360
16388
|
if (this.disabled)
|
|
@@ -16370,6 +16398,10 @@ class VisibilityManager {
|
|
|
16370
16398
|
}
|
|
16371
16399
|
freeze() {
|
|
16372
16400
|
this.frozen = true;
|
|
16401
|
+
if (this.debounceTimer) {
|
|
16402
|
+
clearTimeout(this.debounceTimer);
|
|
16403
|
+
this.debounceTimer = null;
|
|
16404
|
+
}
|
|
16373
16405
|
}
|
|
16374
16406
|
unfreeze() {
|
|
16375
16407
|
this.frozen = false;
|
|
@@ -16377,9 +16409,33 @@ class VisibilityManager {
|
|
|
16377
16409
|
}
|
|
16378
16410
|
lock() {
|
|
16379
16411
|
this.locked = true;
|
|
16412
|
+
if (this.debounceTimer) {
|
|
16413
|
+
clearTimeout(this.debounceTimer);
|
|
16414
|
+
this.debounceTimer = null;
|
|
16415
|
+
}
|
|
16380
16416
|
}
|
|
16381
16417
|
unlock() {
|
|
16382
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;
|
|
16383
16439
|
}
|
|
16384
16440
|
reset() {
|
|
16385
16441
|
this.elements.clear();
|
|
@@ -16536,6 +16592,7 @@ function record(options = {}) {
|
|
|
16536
16592
|
checkoutEveryNms,
|
|
16537
16593
|
checkoutEveryNth,
|
|
16538
16594
|
checkoutEveryNvm,
|
|
16595
|
+
checkoutDebounce,
|
|
16539
16596
|
blockClass = "rr-block",
|
|
16540
16597
|
blockSelector = null,
|
|
16541
16598
|
ignoreClass = "rr-ignore",
|
|
@@ -16630,6 +16687,10 @@ function record(options = {}) {
|
|
|
16630
16687
|
let lastFullSnapshotEvent;
|
|
16631
16688
|
let incrementalSnapshotCount = 0;
|
|
16632
16689
|
let visibilityMutationCount = 0;
|
|
16690
|
+
let checkoutId = 0;
|
|
16691
|
+
let checkoutPending = false;
|
|
16692
|
+
let checkoutDebounceTimer = null;
|
|
16693
|
+
let checkoutFreezeTimestamp = null;
|
|
16633
16694
|
const eventProcessor = (e2) => {
|
|
16634
16695
|
for (const plugin3 of plugins || []) {
|
|
16635
16696
|
if (plugin3.eventProcessor) {
|
|
@@ -16642,11 +16703,25 @@ function record(options = {}) {
|
|
|
16642
16703
|
}
|
|
16643
16704
|
return e2;
|
|
16644
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
|
+
};
|
|
16645
16719
|
wrappedEmit = (r2, isCheckout) => {
|
|
16646
16720
|
var _a2;
|
|
16647
16721
|
const e2 = r2;
|
|
16648
16722
|
e2.timestamp = nowTimestamp();
|
|
16649
|
-
|
|
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)) {
|
|
16650
16725
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
16651
16726
|
visibilityManager == null ? void 0 : visibilityManager.unfreeze();
|
|
16652
16727
|
}
|
|
@@ -16673,7 +16748,29 @@ function record(options = {}) {
|
|
|
16673
16748
|
const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
|
|
16674
16749
|
const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
|
|
16675
16750
|
if (exceedCount || exceedTime) {
|
|
16676
|
-
|
|
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
|
+
}
|
|
16677
16774
|
}
|
|
16678
16775
|
}
|
|
16679
16776
|
}
|
|
@@ -16783,8 +16880,30 @@ function record(options = {}) {
|
|
|
16783
16880
|
notifyActivity: checkoutEveryNvm != null ? (count) => {
|
|
16784
16881
|
visibilityMutationCount += count;
|
|
16785
16882
|
if (visibilityMutationCount >= checkoutEveryNvm) {
|
|
16786
|
-
takeFullSnapshot$1(true);
|
|
16787
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
|
+
}
|
|
16788
16907
|
}
|
|
16789
16908
|
} : void 0
|
|
16790
16909
|
});
|
|
@@ -16793,6 +16912,7 @@ function record(options = {}) {
|
|
|
16793
16912
|
if (!recordDOM) {
|
|
16794
16913
|
return;
|
|
16795
16914
|
}
|
|
16915
|
+
checkoutId++;
|
|
16796
16916
|
wrappedEmit(
|
|
16797
16917
|
{
|
|
16798
16918
|
type: EventType.Meta,
|
|
@@ -17064,6 +17184,10 @@ function record(options = {}) {
|
|
|
17064
17184
|
);
|
|
17065
17185
|
}
|
|
17066
17186
|
return () => {
|
|
17187
|
+
if (checkoutDebounceTimer) {
|
|
17188
|
+
clearTimeout(checkoutDebounceTimer);
|
|
17189
|
+
checkoutDebounceTimer = null;
|
|
17190
|
+
}
|
|
17067
17191
|
flushCustomEventQueue$1();
|
|
17068
17192
|
handlers.forEach((h) => h());
|
|
17069
17193
|
processedNodeManager.destroy();
|
|
@@ -17178,5 +17302,5 @@ exports.globalSequentialId = globalSequentialId;
|
|
|
17178
17302
|
return module.exports;
|
|
17179
17303
|
}))
|
|
17180
17304
|
//# sourceMappingURL=rrweb-plugin-sequential-id-record.umd.cjs.map
|
|
17181
|
-
`;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
|
|
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});
|
|
17182
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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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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,EAAO,EAAAC,KAAK,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":["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":"0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,8BAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAGO,4BCHP,IAAAC,EAAe,iBACfC,EAAiB,mBACjBC,EAAe,iBAMTC,EAAyB,6BAE/B,SAASC,EAAgBC,EAAkBC,EAAc,CACvD,IAAMC,EAAM,EAAAC,QAAK,QAAQH,CAAQ,EAC3BI,EAAM,EAAAD,QAAK,KAAKD,EAAK,IAAI,EAAAC,QAAK,SAASH,CAAQ,SAAS,QAAQ,OAAO,KAAK,IAAI,GAAG,EACzF,EAAAK,QAAG,UAAUH,EAAK,CAAE,UAAW,EAAK,CAAC,EACrC,EAAAG,QAAG,cAAcD,EAAKH,EAAM,OAAO,EACnC,EAAAI,QAAG,WAAWD,EAAKJ,CAAQ,CAC7B,CAEA,SAASM,EAAkBN,EAA6B,CACtD,GAAI,CACF,GAAI,CAAC,EAAAK,QAAG,WAAWL,CAAQ,EAAG,MAAO,CAAC,EACtC,IAAMO,EAAO,EAAAF,QAAG,aAAaL,EAAU,OAAO,EAAE,KAAK,EACrD,GAAI,CAACO,EAAM,MAAO,CAAC,EAEnB,IAAMC,EAAS,KAAK,MAAMD,CAAI,EAC9B,OAAO,MAAM,QAAQC,CAAM,EAAIA,EAAS,CAAC,CAC3C,MAAE,CACA,MAAO,CAAC,CACV,CACF,CAEO,SAASC,EAAgBC,EAA8BC,EAA0B,CACtF,IAAMC,EAAYD,IAAoB,OAAYA,EAAkBb,EAC9De,EAAWC,EAAqBJ,EAAc,KAAK,IAAI,EACvDK,EAAaD,EAAqBJ,EAAc,KAAK,OAAO,KAAK,EACjEM,EAAYF,EAAqBJ,EAAc,KAAK,KAAK,EACzDO,EAAcP,EAAc,QAAQ,KAEpCQ,EAAkB,GAAGH,EAAaA,EAAa,IAAM,KAAKC,SAC1DG,EAAkB,EAAAhB,QAAK,KAAKS,EAAWC,EAAUI,EAAaC,CAAe,EAC7EE,EAAY,CAChB,OAAQV,EAAc,eACtB,SAAU,CACR,OAAQA,EAAc,OACtB,KAAMA,EAAc,KACpB,MAAOA,EAAc,KAAK,MAC1B,KAAMA,EAAc,KACpB,QAASA,EAAc,OACzB,CACF,EACA,EAAAL,QAAG,UAAUO,EAAW,CAAE,UAAW,EAAK,CAAC,EAC3C,EAAAP,QAAG,UAAU,EAAAF,QAAK,QAAQgB,CAAe,EAAG,CAAE,UAAW,EAAK,CAAC,EAC/D,EAAAd,QAAG,cAAcc,EAAiB,KAAK,UAAUC,EAAW,KAAM,CAAC,EAAG,OAAO,EAC7E,QAAQ,IAAI,iCAAiCD,GAAiB,EAE9D,GAAI,CACF,IAAME,EAAgB,EAAAlB,QAAK,KAAKS,EAAW,6BAA6B,EAClEU,EAAUhB,EAAkBe,CAAa,EAC/CC,EAAQ,KAAKF,CAAS,EACtBrB,EAAgBsB,EAAe,KAAK,UAAUC,EAAS,KAAM,CAAC,CAAC,EAC/D,QAAQ,IAAI,oCAAoCD,GAAe,CACjE,OAASE,EAAP,CACA,QAAQ,KAAK,mDAAoDA,CAAC,CACpE,CACF,CAEO,SAAST,EAAqBU,EAAkC,CACrE,OAAQA,GAAQ,IACb,KAAK,EACL,QAAQ,oBAAqB,GAAG,EAChC,QAAQ,MAAO,GAAG,EAClB,QAAQ,SAAU,EAAE,CACzB,CAEO,SAASC,EAAqBC,EAAkBC,EAAoC,CACzF,IAAMC,EAAcF,EAAQ,YAAY,EAClCG,EAAUH,EAAQ,QAAQ,EAC1BI,EAASF,EAAY,KAAK,EAE1BG,EAAWJ,EAAS,KACpBK,EAAWD,EAAS,QAAQ,QAAQ,IAAI,EAAG,EAAE,EAAE,QAAQ,SAAU,EAAE,EACnEE,EAAWD,EAAS,MAAM,OAAO,EAAE,IAAI,GAAK,GAC5C,CAACE,EAAUC,CAAa,EAAIF,EAAS,MAAM,gBAAgB,EAE3DG,EAAiBT,EAAS,UAAU,MAAM,EAAG,EAAE,EAC/CZ,EAAaqB,EAAe,KAAK,KAAK,GAAK,aAuEjD,MArEuC,CACrC,OAAQ,CACN,OAAQ,aACR,KAAM,UACN,QAAST,EAAS,OAAO,QACzB,SAAU,EAAAU,QAAG,SAAS,EACtB,KAAM,EAAAA,QAAG,KAAK,EACd,SAAU,CACR,cAAe,UACf,WAAY,SACd,CAEF,EACA,KAAM,CACJ,KAAMJ,EACN,SAAAD,EACA,SAAAD,EACA,SAAAE,EACA,SAAAC,EACA,cAAAC,EACA,GAAIH,CACN,EACA,KAAM,CACJ,MAAO,CACL,GAAII,EAAe,KAAK,IAAI,GAAK,OACjC,kBAAmB,CACjB,aAAcL,EACd,OAAQJ,EAAS,QAAU,EAC3B,KAAMA,EAAS,MAAQ,EACvB,QAAS,OACT,SAAU,OACV,aAAc,OACd,aAAcK,CAChB,EACA,QAAS,GACT,KAAMI,EAAe,SAAW,EAChC,MAAOrB,EACP,KAAM,SACR,EACA,GAAIY,EAAS,OACb,MAAOA,EAAS,MAChB,UAAWA,EAAS,UAAU,MAAM,CAAC,EACrC,UAAWA,EAAS,UAAU,MAAM,CAAC,EAAE,KAAK,GAAG,EAC/C,KAAMA,EAAS,KACf,kBAAmB,CACjB,aAAcI,EACd,OAAQJ,EAAS,OACjB,KAAMA,EAAS,KACf,QAAS,GACT,aAAcK,CAChB,EACA,MAAOL,EAAS,OAChB,SAAUA,EAAS,SACnB,QAAS,GACT,KAAM,GACN,SAAU,OACV,KAAM,EACR,EACA,QAAS,CACP,KAAMG,EACN,OAAAA,EACA,QAAAD,EACA,aAAc,SAASA,EAAQ,MAAM,GAAG,EAAE,CAAC,EAAG,EAAE,EAChD,YAAaF,EAAS,QAAQ,KAAK,SAAS,cAAc,GAAKG,EAAO,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAO,MAAM,CAAC,EAC9G,QAASH,EAAS,QAAQ,KAAK,SAAW,GAC1C,KAAMC,EAAY,eAAe,CACnC,EACA,eAAgB,CAAC,CACnB,CAEF,CAEO,SAASU,EAAaC,EAAWC,EAAuB,CAC7D,IAAMC,EAAS,CAAE,GAAGF,CAAO,EAE3B,QAAWG,KAAOF,EAAQ,CACxB,IAAMG,EAAcH,EAAOE,CAAG,EACxBE,EAAcL,EAAOG,CAAG,EAG5BC,GACA,OAAOA,GAAgB,UACvB,CAAC,MAAM,QAAQA,CAAW,GAC1BC,GACA,OAAOA,GAAgB,UACvB,CAAC,MAAM,QAAQA,CAAW,EAE1BH,EAAOC,CAAG,EAAIJ,EAAUM,EAAaD,CAAW,EACvCA,IAAgB,SAGzBF,EAAOC,CAAG,EAAIC,GAIlB,OAAOF,CACT,CAEA,eAAsBI,EAA6BC,EAAyBC,EAAU,IAAK,CACzF,IAAMC,EAAQ,KAAK,IAAI,EACnBC,EAAYH,EAAS,UAAU,EAAE,OAErC,OAAO,IAAI,QAAeI,GAAY,CACpC,IAAMC,EAAW,YAAY,IAAM,CACjC,IAAMC,EAAeN,EAAS,UAAU,EAAE,QACtCM,IAAiBH,GAAa,KAAK,IAAI,EAAID,EAAQD,KACrD,cAAcI,CAAQ,EACtBD,EAAQ,GAEVD,EAAYG,CACd,EAAG,EAAE,CACP,CAAC,CACH,CAEA,eAAsBC,EAAeC,EAAY,CAC/C,MAAMA,EAAK,SAAS,IAAM,IAAI,QAAeC,GAAM,sBAAsB,IAAMA,EAAE,CAAC,CAAC,CAAC,CACtF,CA0LA,IAAMC,EAAgE,CACpE,GAAI,UACJ,IAAK,WACL,KAAM,kBACN,IAAK,WACL,KAAM,YACN,IAAK,WACL,KAAM,YACN,IAAK,aACL,IAAK,aACL,KAAM,cACN,MAAO,cACT,EAEMC,EAA6D,IAAI,IAAI,OAAO,QAAQD,CAA2B,EAAE,IAAI,CAAC,CAACE,EAAGC,CAAC,IAAM,CAACA,EAAGD,CAAmB,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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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
|
|
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;
|
|
@@ -13930,6 +13930,30 @@ class MutationBuffer {
|
|
|
13930
13930
|
this.shadowDomManager.reset();
|
|
13931
13931
|
this.canvasManager.reset();
|
|
13932
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
|
+
}
|
|
13933
13957
|
}
|
|
13934
13958
|
function deepDelete(addsSet, n2) {
|
|
13935
13959
|
addsSet.delete(n2);
|
|
@@ -16350,11 +16374,15 @@ class VisibilityManager {
|
|
|
16350
16374
|
}
|
|
16351
16375
|
flushBuffer() {
|
|
16352
16376
|
var _a2;
|
|
16377
|
+
if (this.frozen || this.locked)
|
|
16378
|
+
return;
|
|
16353
16379
|
if (this.buffer.size === 0)
|
|
16354
16380
|
return;
|
|
16355
|
-
|
|
16356
|
-
|
|
16381
|
+
const mutations = Array.from(this.buffer.values());
|
|
16382
|
+
const count = mutations.length;
|
|
16357
16383
|
this.buffer.clear();
|
|
16384
|
+
this.mutationCb({ mutations });
|
|
16385
|
+
(_a2 = this.notifyActivity) == null ? void 0 : _a2.call(this, count);
|
|
16358
16386
|
}
|
|
16359
16387
|
observe(el) {
|
|
16360
16388
|
if (this.disabled)
|
|
@@ -16370,6 +16398,10 @@ class VisibilityManager {
|
|
|
16370
16398
|
}
|
|
16371
16399
|
freeze() {
|
|
16372
16400
|
this.frozen = true;
|
|
16401
|
+
if (this.debounceTimer) {
|
|
16402
|
+
clearTimeout(this.debounceTimer);
|
|
16403
|
+
this.debounceTimer = null;
|
|
16404
|
+
}
|
|
16373
16405
|
}
|
|
16374
16406
|
unfreeze() {
|
|
16375
16407
|
this.frozen = false;
|
|
@@ -16377,9 +16409,33 @@ class VisibilityManager {
|
|
|
16377
16409
|
}
|
|
16378
16410
|
lock() {
|
|
16379
16411
|
this.locked = true;
|
|
16412
|
+
if (this.debounceTimer) {
|
|
16413
|
+
clearTimeout(this.debounceTimer);
|
|
16414
|
+
this.debounceTimer = null;
|
|
16415
|
+
}
|
|
16380
16416
|
}
|
|
16381
16417
|
unlock() {
|
|
16382
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;
|
|
16383
16439
|
}
|
|
16384
16440
|
reset() {
|
|
16385
16441
|
this.elements.clear();
|
|
@@ -16536,6 +16592,7 @@ function record(options = {}) {
|
|
|
16536
16592
|
checkoutEveryNms,
|
|
16537
16593
|
checkoutEveryNth,
|
|
16538
16594
|
checkoutEveryNvm,
|
|
16595
|
+
checkoutDebounce,
|
|
16539
16596
|
blockClass = "rr-block",
|
|
16540
16597
|
blockSelector = null,
|
|
16541
16598
|
ignoreClass = "rr-ignore",
|
|
@@ -16630,6 +16687,10 @@ function record(options = {}) {
|
|
|
16630
16687
|
let lastFullSnapshotEvent;
|
|
16631
16688
|
let incrementalSnapshotCount = 0;
|
|
16632
16689
|
let visibilityMutationCount = 0;
|
|
16690
|
+
let checkoutId = 0;
|
|
16691
|
+
let checkoutPending = false;
|
|
16692
|
+
let checkoutDebounceTimer = null;
|
|
16693
|
+
let checkoutFreezeTimestamp = null;
|
|
16633
16694
|
const eventProcessor = (e2) => {
|
|
16634
16695
|
for (const plugin3 of plugins || []) {
|
|
16635
16696
|
if (plugin3.eventProcessor) {
|
|
@@ -16642,11 +16703,25 @@ function record(options = {}) {
|
|
|
16642
16703
|
}
|
|
16643
16704
|
return e2;
|
|
16644
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
|
+
};
|
|
16645
16719
|
wrappedEmit = (r2, isCheckout) => {
|
|
16646
16720
|
var _a2;
|
|
16647
16721
|
const e2 = r2;
|
|
16648
16722
|
e2.timestamp = nowTimestamp();
|
|
16649
|
-
|
|
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)) {
|
|
16650
16725
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
16651
16726
|
visibilityManager == null ? void 0 : visibilityManager.unfreeze();
|
|
16652
16727
|
}
|
|
@@ -16673,7 +16748,29 @@ function record(options = {}) {
|
|
|
16673
16748
|
const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
|
|
16674
16749
|
const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
|
|
16675
16750
|
if (exceedCount || exceedTime) {
|
|
16676
|
-
|
|
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
|
+
}
|
|
16677
16774
|
}
|
|
16678
16775
|
}
|
|
16679
16776
|
}
|
|
@@ -16783,8 +16880,30 @@ function record(options = {}) {
|
|
|
16783
16880
|
notifyActivity: checkoutEveryNvm != null ? (count) => {
|
|
16784
16881
|
visibilityMutationCount += count;
|
|
16785
16882
|
if (visibilityMutationCount >= checkoutEveryNvm) {
|
|
16786
|
-
takeFullSnapshot$1(true);
|
|
16787
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
|
+
}
|
|
16788
16907
|
}
|
|
16789
16908
|
} : void 0
|
|
16790
16909
|
});
|
|
@@ -16793,6 +16912,7 @@ function record(options = {}) {
|
|
|
16793
16912
|
if (!recordDOM) {
|
|
16794
16913
|
return;
|
|
16795
16914
|
}
|
|
16915
|
+
checkoutId++;
|
|
16796
16916
|
wrappedEmit(
|
|
16797
16917
|
{
|
|
16798
16918
|
type: EventType.Meta,
|
|
@@ -17064,6 +17184,10 @@ function record(options = {}) {
|
|
|
17064
17184
|
);
|
|
17065
17185
|
}
|
|
17066
17186
|
return () => {
|
|
17187
|
+
if (checkoutDebounceTimer) {
|
|
17188
|
+
clearTimeout(checkoutDebounceTimer);
|
|
17189
|
+
checkoutDebounceTimer = null;
|
|
17190
|
+
}
|
|
17067
17191
|
flushCustomEventQueue$1();
|
|
17068
17192
|
handlers.forEach((h) => h());
|
|
17069
17193
|
processedNodeManager.destroy();
|
|
@@ -17178,5 +17302,5 @@ exports.globalSequentialId = globalSequentialId;
|
|
|
17178
17302
|
return module.exports;
|
|
17179
17303
|
}))
|
|
17180
17304
|
//# sourceMappingURL=rrweb-plugin-sequential-id-record.umd.cjs.map
|
|
17181
|
-
`;var
|
|
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};
|
|
17182
17306
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.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":"AAAA,OACE,QAAQA,EACR,UAAAC,MACK,mBCHP,OAAOC,MAAQ,KACf,OAAOC,MAAU,OACjB,OAAOC,MAAQ,KAMf,IAAMC,EAAyB,6BAE/B,SAASC,EAAgBC,EAAkBC,EAAc,CACvD,IAAMC,EAAMN,EAAK,QAAQI,CAAQ,EAC3BG,EAAMP,EAAK,KAAKM,EAAK,IAAIN,EAAK,SAASI,CAAQ,SAAS,QAAQ,OAAO,KAAK,IAAI,GAAG,EACzFH,EAAG,UAAUK,EAAK,CAAE,UAAW,EAAK,CAAC,EACrCL,EAAG,cAAcM,EAAKF,EAAM,OAAO,EACnCJ,EAAG,WAAWM,EAAKH,CAAQ,CAC7B,CAEA,SAASI,EAAkBJ,EAA6B,CACtD,GAAI,CACF,GAAI,CAACH,EAAG,WAAWG,CAAQ,EAAG,MAAO,CAAC,EACtC,IAAMK,EAAOR,EAAG,aAAaG,EAAU,OAAO,EAAE,KAAK,EACrD,GAAI,CAACK,EAAM,MAAO,CAAC,EAEnB,IAAMC,EAAS,KAAK,MAAMD,CAAI,EAC9B,OAAO,MAAM,QAAQC,CAAM,EAAIA,EAAS,CAAC,CAC3C,MAAE,CACA,MAAO,CAAC,CACV,CACF,CAEO,SAASC,EAAgBC,EAA8BC,EAA0B,CACtF,IAAMC,EAAYD,IAAoB,OAAYA,EAAkBX,EAC9Da,EAAWC,EAAqBJ,EAAc,KAAK,IAAI,EACvDK,EAAaD,EAAqBJ,EAAc,KAAK,OAAO,KAAK,EACjEM,EAAYF,EAAqBJ,EAAc,KAAK,KAAK,EACzDO,EAAcP,EAAc,QAAQ,KAEpCQ,EAAkB,GAAGH,EAAaA,EAAa,IAAM,KAAKC,SAC1DG,EAAkBrB,EAAK,KAAKc,EAAWC,EAAUI,EAAaC,CAAe,EAC7EE,EAAY,CAChB,OAAQV,EAAc,eACtB,SAAU,CACR,OAAQA,EAAc,OACtB,KAAMA,EAAc,KACpB,MAAOA,EAAc,KAAK,MAC1B,KAAMA,EAAc,KACpB,QAASA,EAAc,OACzB,CACF,EACAX,EAAG,UAAUa,EAAW,CAAE,UAAW,EAAK,CAAC,EAC3Cb,EAAG,UAAUD,EAAK,QAAQqB,CAAe,EAAG,CAAE,UAAW,EAAK,CAAC,EAC/DpB,EAAG,cAAcoB,EAAiB,KAAK,UAAUC,EAAW,KAAM,CAAC,EAAG,OAAO,EAC7E,QAAQ,IAAI,iCAAiCD,GAAiB,EAE9D,GAAI,CACF,IAAME,EAAgBvB,EAAK,KAAKc,EAAW,6BAA6B,EAClEU,EAAUhB,EAAkBe,CAAa,EAC/CC,EAAQ,KAAKF,CAAS,EACtBnB,EAAgBoB,EAAe,KAAK,UAAUC,EAAS,KAAM,CAAC,CAAC,EAC/D,QAAQ,IAAI,oCAAoCD,GAAe,CACjE,OAASE,EAAP,CACA,QAAQ,KAAK,mDAAoDA,CAAC,CACpE,CACF,CAEO,SAAST,EAAqBU,EAAkC,CACrE,OAAQA,GAAQ,IACb,KAAK,EACL,QAAQ,oBAAqB,GAAG,EAChC,QAAQ,MAAO,GAAG,EAClB,QAAQ,SAAU,EAAE,CACzB,CAEO,SAASC,EAAqBC,EAAkBC,EAAoC,CACzF,IAAMC,EAAcF,EAAQ,YAAY,EAClCG,EAAUH,EAAQ,QAAQ,EAC1BI,EAASF,EAAY,KAAK,EAE1BG,EAAWJ,EAAS,KACpBK,EAAWD,EAAS,QAAQ,QAAQ,IAAI,EAAG,EAAE,EAAE,QAAQ,SAAU,EAAE,EACnEE,EAAWD,EAAS,MAAM,OAAO,EAAE,IAAI,GAAK,GAC5C,CAACE,EAAUC,CAAa,EAAIF,EAAS,MAAM,gBAAgB,EAE3DG,EAAiBT,EAAS,UAAU,MAAM,EAAG,EAAE,EAC/CZ,EAAaqB,EAAe,KAAK,KAAK,GAAK,aAuEjD,MArEuC,CACrC,OAAQ,CACN,OAAQ,aACR,KAAM,UACN,QAAST,EAAS,OAAO,QACzB,SAAU9B,EAAG,SAAS,EACtB,KAAMA,EAAG,KAAK,EACd,SAAU,CACR,cAAe,UACf,WAAY,SACd,CAEF,EACA,KAAM,CACJ,KAAMoC,EACN,SAAAD,EACA,SAAAD,EACA,SAAAE,EACA,SAAAC,EACA,cAAAC,EACA,GAAIH,CACN,EACA,KAAM,CACJ,MAAO,CACL,GAAII,EAAe,KAAK,IAAI,GAAK,OACjC,kBAAmB,CACjB,aAAcL,EACd,OAAQJ,EAAS,QAAU,EAC3B,KAAMA,EAAS,MAAQ,EACvB,QAAS,OACT,SAAU,OACV,aAAc,OACd,aAAcK,CAChB,EACA,QAAS,GACT,KAAMI,EAAe,SAAW,EAChC,MAAOrB,EACP,KAAM,SACR,EACA,GAAIY,EAAS,OACb,MAAOA,EAAS,MAChB,UAAWA,EAAS,UAAU,MAAM,CAAC,EACrC,UAAWA,EAAS,UAAU,MAAM,CAAC,EAAE,KAAK,GAAG,EAC/C,KAAMA,EAAS,KACf,kBAAmB,CACjB,aAAcI,EACd,OAAQJ,EAAS,OACjB,KAAMA,EAAS,KACf,QAAS,GACT,aAAcK,CAChB,EACA,MAAOL,EAAS,OAChB,SAAUA,EAAS,SACnB,QAAS,GACT,KAAM,GACN,SAAU,OACV,KAAM,EACR,EACA,QAAS,CACP,KAAMG,EACN,OAAAA,EACA,QAAAD,EACA,aAAc,SAASA,EAAQ,MAAM,GAAG,EAAE,CAAC,EAAG,EAAE,EAChD,YAAaF,EAAS,QAAQ,KAAK,SAAS,cAAc,GAAKG,EAAO,OAAO,CAAC,EAAE,YAAY,EAAIA,EAAO,MAAM,CAAC,EAC9G,QAASH,EAAS,QAAQ,KAAK,SAAW,GAC1C,KAAMC,EAAY,eAAe,CACnC,EACA,eAAgB,CAAC,CACnB,CAEF,CAEO,SAASS,EAAaC,EAAWC,EAAuB,CAC7D,IAAMC,EAAS,CAAE,GAAGF,CAAO,EAE3B,QAAWG,KAAOF,EAAQ,CACxB,IAAMG,EAAcH,EAAOE,CAAG,EACxBE,EAAcL,EAAOG,CAAG,EAG5BC,GACA,OAAOA,GAAgB,UACvB,CAAC,MAAM,QAAQA,CAAW,GAC1BC,GACA,OAAOA,GAAgB,UACvB,CAAC,MAAM,QAAQA,CAAW,EAE1BH,EAAOC,CAAG,EAAIJ,EAAUM,EAAaD,CAAW,EACvCA,IAAgB,SAGzBF,EAAOC,CAAG,EAAIC,GAIlB,OAAOF,CACT,CAEA,eAAsBI,EAA6BC,EAAyBC,EAAU,IAAK,CACzF,IAAMC,EAAQ,KAAK,IAAI,EACnBC,EAAYH,EAAS,UAAU,EAAE,OAErC,OAAO,IAAI,QAAeI,GAAY,CACpC,IAAMC,EAAW,YAAY,IAAM,CACjC,IAAMC,EAAeN,EAAS,UAAU,EAAE,QACtCM,IAAiBH,GAAa,KAAK,IAAI,EAAID,EAAQD,KACrD,cAAcI,CAAQ,EACtBD,EAAQ,GAEVD,EAAYG,CACd,EAAG,EAAE,CACP,CAAC,CACH,CAEA,eAAsBC,EAAeC,EAAY,CAC/C,MAAMA,EAAK,SAAS,IAAM,IAAI,QAAeC,GAAM,sBAAsB,IAAMA,EAAE,CAAC,CAAC,CAAC,CACtF,CA0LA,IAAMC,EAAgE,CACpE,GAAI,UACJ,IAAK,WACL,KAAM,kBACN,IAAK,WACL,KAAM,YACN,IAAK,WACL,KAAM,YACN,IAAK,aACL,IAAK,aACL,KAAM,cACN,MAAO,cACT,EAEMC,EAA6D,IAAI,IAAI,OAAO,QAAQD,CAA2B,EAAE,IAAI,CAAC,CAACE,EAAGC,CAAC,IAAM,CAACA,EAAGD,CAAmB,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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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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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsurify-testmap/rrweb-playwright-plugin",
|
|
3
|
-
"version": "3.
|
|
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.
|
|
44
|
-
"@appsurify-testmap/rrweb-snapshot": "^3.
|
|
45
|
-
"@appsurify-testmap/rrweb-types": "^3.
|
|
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",
|