@appsurify-testmap/rrweb-playwright-plugin 2.1.3-alpha.3 → 2.1.3-alpha.4
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 +29 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +29 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -13031,7 +13031,7 @@ class VisibilityManager {
|
|
|
13031
13031
|
}
|
|
13032
13032
|
}
|
|
13033
13033
|
}
|
|
13034
|
-
const version$1 = "2.1.3-alpha.
|
|
13034
|
+
const version$1 = "2.1.3-alpha.4";
|
|
13035
13035
|
let wrappedEmit;
|
|
13036
13036
|
let takeFullSnapshot$1;
|
|
13037
13037
|
let canvasManager;
|
|
@@ -13193,13 +13193,27 @@ function record(options = {}) {
|
|
|
13193
13193
|
}
|
|
13194
13194
|
return e2;
|
|
13195
13195
|
};
|
|
13196
|
+
let lastMetaHref = null;
|
|
13197
|
+
let navSnapshotInProgress = false;
|
|
13196
13198
|
wrappedEmit = (r2, isCheckout) => {
|
|
13197
|
-
var _a2;
|
|
13199
|
+
var _a2, _b;
|
|
13198
13200
|
const e2 = r2;
|
|
13199
13201
|
e2.timestamp = nowTimestamp();
|
|
13202
|
+
let navTriggeredFS = false;
|
|
13200
13203
|
if (((_a2 = mutationBuffers[0]) == null ? void 0 : _a2.isFrozen()) && e2.type !== EventType.FullSnapshot && !(e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.Mutation)) {
|
|
13201
13204
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
13202
13205
|
}
|
|
13206
|
+
if (!navSnapshotInProgress && e2.type !== EventType.Meta && e2.type !== EventType.FullSnapshot && lastMetaHref && window.location.href !== lastMetaHref) {
|
|
13207
|
+
navSnapshotInProgress = true;
|
|
13208
|
+
try {
|
|
13209
|
+
recentVisibilityChanges = 0;
|
|
13210
|
+
incrementalSnapshotCount = 0;
|
|
13211
|
+
navTriggeredFS = true;
|
|
13212
|
+
takeFullSnapshot$1(true);
|
|
13213
|
+
} finally {
|
|
13214
|
+
navSnapshotInProgress = false;
|
|
13215
|
+
}
|
|
13216
|
+
}
|
|
13203
13217
|
if (inEmittingFrame) {
|
|
13204
13218
|
emit == null ? void 0 : emit(eventProcessor(e2), isCheckout);
|
|
13205
13219
|
} else if (passEmitsToParent) {
|
|
@@ -13211,6 +13225,9 @@ function record(options = {}) {
|
|
|
13211
13225
|
};
|
|
13212
13226
|
window.parent.postMessage(message, "*");
|
|
13213
13227
|
}
|
|
13228
|
+
if (e2.type === EventType.Meta) {
|
|
13229
|
+
lastMetaHref = ((_b = e2.data) == null ? void 0 : _b.href) || window.location.href;
|
|
13230
|
+
}
|
|
13214
13231
|
if (e2.type === EventType.FullSnapshot) {
|
|
13215
13232
|
lastFullSnapshotEvent = e2;
|
|
13216
13233
|
incrementalSnapshotCount = 0;
|
|
@@ -13219,14 +13236,16 @@ function record(options = {}) {
|
|
|
13219
13236
|
return;
|
|
13220
13237
|
}
|
|
13221
13238
|
incrementalSnapshotCount++;
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
if (exceedVisibility) {
|
|
13227
|
-
|
|
13239
|
+
if (!navTriggeredFS) {
|
|
13240
|
+
const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
|
|
13241
|
+
const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
|
|
13242
|
+
const exceedVisibility = checkoutEveryNvm && recentVisibilityChanges >= checkoutEveryNvm;
|
|
13243
|
+
if (exceedCount || exceedTime || exceedVisibility) {
|
|
13244
|
+
if (exceedVisibility) {
|
|
13245
|
+
recentVisibilityChanges = 0;
|
|
13246
|
+
}
|
|
13247
|
+
takeFullSnapshot$1(true);
|
|
13228
13248
|
}
|
|
13229
|
-
takeFullSnapshot$1(true);
|
|
13230
13249
|
}
|
|
13231
13250
|
}
|
|
13232
13251
|
};
|
|
@@ -13712,5 +13731,5 @@ if (typeof module.exports == "object" && typeof exports == "object") {
|
|
|
13712
13731
|
return module.exports;
|
|
13713
13732
|
}))
|
|
13714
13733
|
//# sourceMappingURL=rrweb-plugin-sequential-id-record.umd.cjs.map
|
|
13715
|
-
`;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:N}),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 M=new Map;function
|
|
13734
|
+
`;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:N}),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 M=new Map;function T(t,e){M.set(t,e)}function k(t){return M.get(t)}var x=y.test.extend({browser:async({browser:t},e)=>{await e(t)},context:async({browser:t},e,n)=>{let s=await t.newContext(),r=I(t,n);T(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=k(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 d=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 d(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)}});x.beforeEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F7E2} TEST START] ${t.title}`)});x.afterEach(async({},t)=>{console.log(`[${Date.now()}] [\u{1F534} TEST END] ${t.title}`);let e=k(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});
|
|
13716
13735
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["src_exports","__export","test","__toCommonJS","import_test","import_os","import_path","import_fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","path","tmp","fs","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","os","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["src_exports","__export","test","__toCommonJS","import_test","import_os","import_path","import_fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","path","tmp","fs","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","os","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{test as D,expect as Q}from"@playwright/test";import v from"os";import h from"path";import u from"fs";var N="test-results/playwright/ui";function M(t,e){let n=h.dirname(t),s=h.join(n,`.${h.basename(t)}.tmp-${process.pid}-${Date.now()}`);u.mkdirSync(n,{recursive:!0}),u.writeFileSync(s,e,"utf-8"),u.renameSync(s,t)}function
|
|
1
|
+
import{test as D,expect as Q}from"@playwright/test";import v from"os";import h from"path";import u from"fs";var N="test-results/playwright/ui";function M(t,e){let n=h.dirname(t),s=h.join(n,`.${h.basename(t)}.tmp-${process.pid}-${Date.now()}`);u.mkdirSync(n,{recursive:!0}),u.writeFileSync(s,e,"utf-8"),u.renameSync(s,t)}function T(t){try{if(!u.existsSync(t))return[];let e=u.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:N,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`,d=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}};u.mkdirSync(n,{recursive:!0}),u.mkdirSync(h.dirname(d),{recursive:!0}),u.writeFileSync(d,JSON.stringify(p,null,2),"utf-8"),console.log(`[ui-coverage] Saved report to ${d}`);try{let a=h.join(n,"ui-coverage-aggregated.json"),l=T(a);l.push(p),M(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()??"",[d,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:d,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 k(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 x(t){await t.evaluate(()=>new Promise(e=>requestAnimationFrame(()=>e())))}var A={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(A).map(([t,e])=>[e,t]));var $=`(function (g, f) {
|
|
2
2
|
if ("object" == typeof exports && "object" == typeof module) {
|
|
3
3
|
module.exports = f();
|
|
4
4
|
} else if ("function" == typeof define && define.amd) {
|
|
@@ -13031,7 +13031,7 @@ class VisibilityManager {
|
|
|
13031
13031
|
}
|
|
13032
13032
|
}
|
|
13033
13033
|
}
|
|
13034
|
-
const version$1 = "2.1.3-alpha.
|
|
13034
|
+
const version$1 = "2.1.3-alpha.4";
|
|
13035
13035
|
let wrappedEmit;
|
|
13036
13036
|
let takeFullSnapshot$1;
|
|
13037
13037
|
let canvasManager;
|
|
@@ -13193,13 +13193,27 @@ function record(options = {}) {
|
|
|
13193
13193
|
}
|
|
13194
13194
|
return e2;
|
|
13195
13195
|
};
|
|
13196
|
+
let lastMetaHref = null;
|
|
13197
|
+
let navSnapshotInProgress = false;
|
|
13196
13198
|
wrappedEmit = (r2, isCheckout) => {
|
|
13197
|
-
var _a2;
|
|
13199
|
+
var _a2, _b;
|
|
13198
13200
|
const e2 = r2;
|
|
13199
13201
|
e2.timestamp = nowTimestamp();
|
|
13202
|
+
let navTriggeredFS = false;
|
|
13200
13203
|
if (((_a2 = mutationBuffers[0]) == null ? void 0 : _a2.isFrozen()) && e2.type !== EventType.FullSnapshot && !(e2.type === EventType.IncrementalSnapshot && e2.data.source === IncrementalSource.Mutation)) {
|
|
13201
13204
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
13202
13205
|
}
|
|
13206
|
+
if (!navSnapshotInProgress && e2.type !== EventType.Meta && e2.type !== EventType.FullSnapshot && lastMetaHref && window.location.href !== lastMetaHref) {
|
|
13207
|
+
navSnapshotInProgress = true;
|
|
13208
|
+
try {
|
|
13209
|
+
recentVisibilityChanges = 0;
|
|
13210
|
+
incrementalSnapshotCount = 0;
|
|
13211
|
+
navTriggeredFS = true;
|
|
13212
|
+
takeFullSnapshot$1(true);
|
|
13213
|
+
} finally {
|
|
13214
|
+
navSnapshotInProgress = false;
|
|
13215
|
+
}
|
|
13216
|
+
}
|
|
13203
13217
|
if (inEmittingFrame) {
|
|
13204
13218
|
emit == null ? void 0 : emit(eventProcessor(e2), isCheckout);
|
|
13205
13219
|
} else if (passEmitsToParent) {
|
|
@@ -13211,6 +13225,9 @@ function record(options = {}) {
|
|
|
13211
13225
|
};
|
|
13212
13226
|
window.parent.postMessage(message, "*");
|
|
13213
13227
|
}
|
|
13228
|
+
if (e2.type === EventType.Meta) {
|
|
13229
|
+
lastMetaHref = ((_b = e2.data) == null ? void 0 : _b.href) || window.location.href;
|
|
13230
|
+
}
|
|
13214
13231
|
if (e2.type === EventType.FullSnapshot) {
|
|
13215
13232
|
lastFullSnapshotEvent = e2;
|
|
13216
13233
|
incrementalSnapshotCount = 0;
|
|
@@ -13219,14 +13236,16 @@ function record(options = {}) {
|
|
|
13219
13236
|
return;
|
|
13220
13237
|
}
|
|
13221
13238
|
incrementalSnapshotCount++;
|
|
13222
|
-
|
|
13223
|
-
|
|
13224
|
-
|
|
13225
|
-
|
|
13226
|
-
if (exceedVisibility) {
|
|
13227
|
-
|
|
13239
|
+
if (!navTriggeredFS) {
|
|
13240
|
+
const exceedCount = checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
|
|
13241
|
+
const exceedTime = checkoutEveryNms && e2.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
|
|
13242
|
+
const exceedVisibility = checkoutEveryNvm && recentVisibilityChanges >= checkoutEveryNvm;
|
|
13243
|
+
if (exceedCount || exceedTime || exceedVisibility) {
|
|
13244
|
+
if (exceedVisibility) {
|
|
13245
|
+
recentVisibilityChanges = 0;
|
|
13246
|
+
}
|
|
13247
|
+
takeFullSnapshot$1(true);
|
|
13228
13248
|
}
|
|
13229
|
-
takeFullSnapshot$1(true);
|
|
13230
13249
|
}
|
|
13231
13250
|
}
|
|
13232
13251
|
};
|
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":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECnYzJ,IAAME,EAAqD,CAC9D,eAAgB,MAChB,iBAAkB,GAClB,UAAW,GACX,aAAc,GACd,aAAc,GACd,aAAc,GACd,iBAAkB,CAAE,SAAU,EAAK,EACnC,SAAU,CACR,UAAW,GACX,iBAAkB,CAChB,QAAS,GACT,UAAW,GACX,MAAO,GACP,YAAa,GACb,SAAU,GACV,MAAO,GACP,KAAM,GACN,WAAY,GACZ,SAAU,EACZ,EACA,OAAQ,IACR,MAAO,IACP,MAAO,OACP,OAAQ,MACR,WAAY,CACV,KAAM,OACN,SAAU,EACV,UAAW,GACX,YAAa,IACb,YAAa,EACf,CACF,EACA,iBAAkB,QAClB,YAAa,mBACb,qBAAsB,EAC1B,EAeaC,EAAN,KAAoB,CACjB,SAAwC,KACxC,KAAoB,KACpB,QACA,aAAe,EACf,OAA0B,CAAC,EAC3B,cACA,cAGF,CAAC,EACC,sBAAwB,UACxB,mBAAqB,UACtB,YAAc,GAErB,YAAYC,EAAwC,CAClD,KAAK,cAAgBC,EAAUH,EAAsBE,GAAW,CAAC,CAAC,EAClE,KAAK,QAAU,CACb,UAAYE,GAAU,KAAK,OAAO,KAAKA,CAAK,CAC9C,CACF,CAEQ,WAAWA,EAAsB,CACvC,GAAIA,EAAM,OAAS,GAAKA,EAAM,OAAS,EACrC,OAEF,IAAMC,EAAyB,CAC7B,GAAGD,CACL,EACA,KAAK,QAAQ,UAAUC,CAAO,CAChC,CAEA,MAAa,OAAOC,EAAY,CAC9B,KAAK,KAAOA,EAEZ,MAAM,KAAK,MAAM,cAAc,CAAC,QAASC,CAAe,CAAC,EACzD,MAAM,KAAK,MAAM,cAAc,CAAC,QAASC,CAAqB,CAAC,EAE/D,MAAM,KAAK,MAAM,eAAe,aAAeJ,GAAyB,CACtE,KAAK,WAAWA,CAAK,CACvB,CAAC,CAEH,CAEA,MAAa,OAAQ,CACnB,KAAK,SAAW,MAAM,KAAK,MAAM,eAAe,IACvC,OAAO,OAAO,MACtB,EACD,MAAM,KAAK,UAAU,SAAS,CAACK,EAAkBC,IAAa,CAC5D,IAAMC,EAAO,KAAK,MAAMD,CAAQ,EAC1BE,EAAU,CAAC,EACb,OAAO,+BACTA,EAAQ,KACN,OAAO,8BAA8B,4BAA4B,CAC/D,IAAK,IACP,CAAC,CACH,EAGF,OAAO,OAASH,EAAE,CAChB,KAAOL,GAAyB,CAE9B,OAAO,aAAaA,CAAK,CAC3B,EACA,QAASQ,EACT,GAAGD,CACL,CAAC,CACH,EAAG,KAAK,UAAU,KAAK,aAAa,CAAC,EAErC,KAAK,YAAc,MAAM,KAAK,UAAU,SAAUF,GAAqBA,EAAE,YAAY,CAAC,EACtF,KAAK,sBAAwB,MAAM,KAAK,UAAU,SAAUA,GAAqBA,EAAE,WAAW,CAAC,EAE/F,MAAM,KAAK,MAAM,CACnB,CAEA,MAAa,MAAO,CAClB,KAAK,YAAc,GACf,KAAK,UAAY,KAAK,MAAQ,CAAC,KAAK,KAAK,SAAS,IACpD,MAAM,KAAK,MAAM,EACjB,MAAM,KAAK,KAAK,SAAS,IAAM,CAC7B,OAAO,OAAS,IAClB,CAAC,EAEL,CAEA,MAAa,OAAQ,CACnB,KAAK,aAAe,EACpB,KAAK,OAAS,CAAC,EACf,MAAM,KAAK,KAAK,EAChB,KAAK,QAAU,CACb,UAAYL,GAAU,KAAK,OAAO,KAAKA,CAAK,CAC9C,CACF,CAEA,MAAa,OAAQ,CACnB,GAAI,CAAC,KAAK,SAAU,OACpB,IAAMS,EAA0C,CAAC,EACjD,QAAWC,KAAO,KAAK,cACrB,GAAI,CACF,MAAM,KAAK,SAAS,SAAS,CAACL,EAAkBK,IAAQ,CACtDL,EAAE,eAAeK,EAAI,IAAKA,EAAI,OAAO,CACvC,EAAGA,CAAG,CACR,MAAE,CACA,QAAQ,MAAM,IAAI,KAAK,IAAI,gDAAgDA,EAAI,KAAK,EACpFD,EAAa,KAAKC,CAAG,CACvB,CAEF,KAAK,cAAgBD,CACvB,CAEA,MAAa,eAAeE,EAAaC,EAAkC,CACzE,IAAMZ,EAAQ,CAAE,IAAAW,EAAK,QAAAC,CAAQ,EAE7B,GAAI,CAAC,KAAK,UAAY,CAAC,KAAK,YAAa,CACvC,QAAQ,MAAM,IAAI,KAAK,IAAI,2DAA2DD,GAAK,EAC3F,KAAK,cAAc,KAAKX,CAAK,EAC7B,OAGF,GAAI,CACF,MAAM,KAAK,SAAS,SAAS,CAAC,EAAkBU,IAAQ,CACtD,EAAE,eAAeA,EAAI,IAAKA,EAAI,OAAO,CACvC,EAAGV,CAAK,CACV,MAAE,CACA,KAAK,cAAc,KAAKA,CAAK,CAC/B,CAEF,CAEO,kBAA4B,CACjC,MAAO,CAAC,CAAC,KAAK,UAAY,KAAK,WACjC,CAEO,kBAA2B,CAChC,MAAO,mCAAmC,KAAK,uBACjD,CAEO,eAAwB,CAC7B,MAAO,4BAA4B,KAAK,qBAAuB,UAAY,KAAK,mBAAqB,KAAK,uBAC5G,CAEO,WAAsC,CAC3C,OAAO,KAAK,MACd,CAEO,WAAgC,CACrC,OAAQ,KAAK,UAA6C,MAC5D,CAEO,KAAKa,EAAsB,CAChC,KAAK,QAAUA,CACjB,CAEO,gBAAgBC,EAAe,CACpC,KAAK,aAAeA,CACtB,CAEF,EC7NA,IAAOC,EAAQC,ECDR,IAAMC,EAAe,IAAI,IAEzB,SAASC,EAAsBC,EAAaC,EAA2B,CAC5EH,EAAa,IAAIE,EAAKC,CAAG,CAC3B,CAEO,SAASC,EAAsBF,EAAyC,CAC7E,OAAOF,EAAa,IAAIE,CAAG,CAC7B,CJgBA,IAAMG,EAAOC,EAAK,OAAW,CAC3B,QAAS,MAAO,CAAE,QAAAC,CAAQ,EAAGC,IAAQ,CACnC,MAAMA,EAAID,CAAO,CACnB,EAEA,QAAS,MAAO,CAAE,QAAAA,CAAQ,EAAGC,EAAKC,IAAa,CAC7C,IAAMC,EAAU,MAAMH,EAAQ,WAAW,EACnCI,EAAiBC,EAAqBL,EAASE,CAAQ,EAC7DI,EAAsBJ,EAAS,OAAQE,CAAc,EACrD,MAAMH,EAAIE,CAAO,EACjB,MAAMA,EAAQ,MAAM,CACtB,EAEA,KAAM,MAAO,CAAE,KAAAI,CAAK,EAAGN,EAAKC,IAAa,CAIvC,IAAMM,EADWN,EAAS,QAAQ,IACH,SAAW,CAAC,EACrCO,EACJ,OAAOD,GAAkB,UAAY,kBAAmBA,EACpDA,EAAc,cACdE,EAIAC,EAAW,IAAID,EAAcD,CAAa,EAE1CL,EAAiBQ,EAAsBV,EAAS,MAAM,EACxDE,IACFA,EAAe,iBAAmBO,GAGpCA,EAAS,KAAK,CAEZ,UAAW,MAAOE,GAAU,CAC1BT,GAAgB,eAAe,KAAKS,CAAK,EACzC,MAAM,QAAQ,QAAQ,CACxB,CACF,CAAC,EACD,MAAMF,EAAS,OAAOJ,CAAI,EAG1BA,EAAK,GAAG,UAAW,MAAOO,GAAmC,CACvDA,EAAe,KAAK,IAAM,SAC9B,QAAQ,MAAM,IAAI,KAAK,IAAI,oBAAqBA,EAAe,KAAK,CAAC,CACvE,CAAC,EAEDP,EAAK,GAAG,OAAQ,SAAY,CAE5B,CAAC,EAEDA,EAAK,GAAG,mBAAoB,SAAY,CACtC,MAAMI,EAAS,MAAM,EACjBP,GAAgB,SAClBA,EAAe,OAAO,SAAW,CAC/B,cAAeO,EAAS,iBAAiB,EACzC,WAAYA,EAAS,cAAc,CACrC,EAEJ,CAAC,EACDJ,EAAK,GAAG,iBAAkB,SAAY,CAEtC,CAAC,EAEDA,EAAK,GAAG,QAAS,SAAY,CAC3B,MAAMI,EAAS,MAAM,CACvB,CAAC,EAGD,IAAMI,EAAoBb,EAAS,WAAW,KAAK,MAAI,EAEvDA,EAAS,WAAa,MAAOc,GAOvB,CAGJ,IAAMC,EAAkBf,EAAS,SAAS,IAAIc,EAAe,MAAM,EAYnE,GAXIC,EAAgB,SAAWA,GAAiB,SAAS,OAASf,EAAS,MACzE,MAAMS,EAAS,eAAeM,EAAgB,QAAS,CACrD,OAAQA,EAAgB,OACxB,SAAUA,EAAgB,SAC1B,SAAUA,EAAgB,SAC1B,MAAOA,EAAgB,MACvB,QAASA,EAAgB,QACzB,YAAaA,EAAgB,WAC/B,CAAC,EAGC,CAACV,EAAK,SAAS,EACjB,GAAI,CACF,MAAMW,EAAeX,CAAI,CAC3B,MAAE,CAA4B,CAEhC,MAAMQ,EAAkBC,CAAc,CACxC,EAGA,IAAMG,EAAkCjB,EAAS,yBAAyB,KAAK,MAAI,EAEnFA,EAAS,yBAA2B,SAAY,CAE1CS,GAAYA,EAAS,iBAAiB,IACxC,MAAMS,EAA6BT,EAAU,GAAG,EAChD,MAAMA,EAAS,KAAK,GAGtB,MAAMQ,EAAgC,CACxC,EAEA,MAAMlB,EAAIM,CAAI,CAGhB,CACF,CAAC,EAEDT,EAAK,WAAW,MAAO,CAAC,EAAGI,IAAa,CACtC,QAAQ,IAAI,IAAI,KAAK,IAAI,6BAAsBA,EAAS,OAAO,CAEjE,CAAC,EAEDJ,EAAK,UAAU,MAAO,CAAC,EAAGI,IAAa,CACrC,QAAQ,IAAI,IAAI,KAAK,IAAI,2BAAoBA,EAAS,OAAO,EAC7D,IAAME,EAAiBQ,EAAsBV,EAAS,MAAM,EAC5D,GAAI,CAACE,EAAgB,OAErBA,EAAe,KAAK,SAAWF,EAAS,SACxC,IAAMmB,EAAgB,CAClB,OAAQjB,GAAgB,OACxB,KAAMA,GAAgB,KACtB,QAASA,GAAgB,QACzB,KAAMA,GAAgB,KACtB,MAAOA,GAAgB,KAAK,MAC5B,eAAgB,MAAM,QAAQA,GAAgB,cAAc,EAAIA,GAAgB,eAAiB,CAAC,CACtG,EAIMI,EADWN,EAAS,QAAQ,IACH,SAAW,CAAC,EAE3CoB,EAAgBD,EAAeb,EAAc,eAAe,CAE9D,CAAC","names":["base","expect","os","path","fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","tmp","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
|
|
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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsurify-testmap/rrweb-playwright-plugin",
|
|
3
|
-
"version": "2.1.3-alpha.
|
|
3
|
+
"version": "2.1.3-alpha.4",
|
|
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": "^2.1.3-alpha.
|
|
44
|
-
"@appsurify-testmap/rrweb-snapshot": "^2.1.3-alpha.
|
|
45
|
-
"@appsurify-testmap/rrweb-types": "^2.1.3-alpha.
|
|
43
|
+
"@appsurify-testmap/rrweb": "^2.1.3-alpha.4",
|
|
44
|
+
"@appsurify-testmap/rrweb-snapshot": "^2.1.3-alpha.4",
|
|
45
|
+
"@appsurify-testmap/rrweb-types": "^2.1.3-alpha.4",
|
|
46
46
|
"@playwright/test": "^1.52.0",
|
|
47
47
|
"@types/node": "^24.10.0",
|
|
48
48
|
"puppeteer": "^24.9.0",
|