@appsurify-testmap/rrweb-playwright-plugin 3.1.1-alpha.2 → 3.1.1-alpha.3
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 +27 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +27 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -981,7 +981,14 @@ const bt$1 = {
|
|
|
981
981
|
source: "dom-dsl"
|
|
982
982
|
};
|
|
983
983
|
function P$1(r2) {
|
|
984
|
-
|
|
984
|
+
if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
|
|
985
|
+
return true;
|
|
986
|
+
if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
|
|
987
|
+
const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
|
|
988
|
+
if (t2 && e2 || s2)
|
|
989
|
+
return true;
|
|
990
|
+
}
|
|
991
|
+
return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
|
|
985
992
|
}
|
|
986
993
|
const Q$1 = /* @__PURE__ */ new Set([
|
|
987
994
|
"aria-labelledby",
|
|
@@ -1182,6 +1189,11 @@ const xt$1 = [
|
|
|
1182
1189
|
/^(rtl|ltr):/,
|
|
1183
1190
|
// === FIX 4: Group and peer variants ===
|
|
1184
1191
|
/^(group|peer)(-hover|-focus|-active)?:/,
|
|
1192
|
+
// === Arbitrary pseudo-class/modifier variants (catch-all) ===
|
|
1193
|
+
// Matches any lowercase/hyphenated prefix followed by colon
|
|
1194
|
+
// e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
|
|
1195
|
+
// Must come AFTER semantic pattern checks to avoid false positives
|
|
1196
|
+
/^[a-z][a-z-]*:/,
|
|
1185
1197
|
// === FIX 4: Tailwind utilities with fraction values ===
|
|
1186
1198
|
/\\/([\\d.]+|full|auto|screen)$/,
|
|
1187
1199
|
// /50, /100, /full, /auto, /screen
|
|
@@ -11752,7 +11764,14 @@ const bt = {
|
|
|
11752
11764
|
source: "dom-dsl"
|
|
11753
11765
|
};
|
|
11754
11766
|
function P(r2) {
|
|
11755
|
-
|
|
11767
|
+
if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
|
|
11768
|
+
return true;
|
|
11769
|
+
if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
|
|
11770
|
+
const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
|
|
11771
|
+
if (t2 && e2 || s2)
|
|
11772
|
+
return true;
|
|
11773
|
+
}
|
|
11774
|
+
return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
|
|
11756
11775
|
}
|
|
11757
11776
|
const Q = /* @__PURE__ */ new Set([
|
|
11758
11777
|
"aria-labelledby",
|
|
@@ -11953,6 +11972,11 @@ const xt = [
|
|
|
11953
11972
|
/^(rtl|ltr):/,
|
|
11954
11973
|
// === FIX 4: Group and peer variants ===
|
|
11955
11974
|
/^(group|peer)(-hover|-focus|-active)?:/,
|
|
11975
|
+
// === Arbitrary pseudo-class/modifier variants (catch-all) ===
|
|
11976
|
+
// Matches any lowercase/hyphenated prefix followed by colon
|
|
11977
|
+
// e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
|
|
11978
|
+
// Must come AFTER semantic pattern checks to avoid false positives
|
|
11979
|
+
/^[a-z][a-z-]*:/,
|
|
11956
11980
|
// === FIX 4: Tailwind utilities with fraction values ===
|
|
11957
11981
|
/\\/([\\d.]+|full|auto|screen)$/,
|
|
11958
11982
|
// /50, /100, /full, /auto, /screen
|
|
@@ -16458,7 +16482,7 @@ class ProcessedNodeManager {
|
|
|
16458
16482
|
destroy() {
|
|
16459
16483
|
}
|
|
16460
16484
|
}
|
|
16461
|
-
const version$1 = "3.1.1-alpha.
|
|
16485
|
+
const version$1 = "3.1.1-alpha.3";
|
|
16462
16486
|
let wrappedEmit;
|
|
16463
16487
|
let takeFullSnapshot$1;
|
|
16464
16488
|
let canvasManager;
|
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
|
@@ -981,7 +981,14 @@ const bt$1 = {
|
|
|
981
981
|
source: "dom-dsl"
|
|
982
982
|
};
|
|
983
983
|
function P$1(r2) {
|
|
984
|
-
|
|
984
|
+
if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
|
|
985
|
+
return true;
|
|
986
|
+
if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
|
|
987
|
+
const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
|
|
988
|
+
if (t2 && e2 || s2)
|
|
989
|
+
return true;
|
|
990
|
+
}
|
|
991
|
+
return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
|
|
985
992
|
}
|
|
986
993
|
const Q$1 = /* @__PURE__ */ new Set([
|
|
987
994
|
"aria-labelledby",
|
|
@@ -1182,6 +1189,11 @@ const xt$1 = [
|
|
|
1182
1189
|
/^(rtl|ltr):/,
|
|
1183
1190
|
// === FIX 4: Group and peer variants ===
|
|
1184
1191
|
/^(group|peer)(-hover|-focus|-active)?:/,
|
|
1192
|
+
// === Arbitrary pseudo-class/modifier variants (catch-all) ===
|
|
1193
|
+
// Matches any lowercase/hyphenated prefix followed by colon
|
|
1194
|
+
// e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
|
|
1195
|
+
// Must come AFTER semantic pattern checks to avoid false positives
|
|
1196
|
+
/^[a-z][a-z-]*:/,
|
|
1185
1197
|
// === FIX 4: Tailwind utilities with fraction values ===
|
|
1186
1198
|
/\\/([\\d.]+|full|auto|screen)$/,
|
|
1187
1199
|
// /50, /100, /full, /auto, /screen
|
|
@@ -11752,7 +11764,14 @@ const bt = {
|
|
|
11752
11764
|
source: "dom-dsl"
|
|
11753
11765
|
};
|
|
11754
11766
|
function P(r2) {
|
|
11755
|
-
|
|
11767
|
+
if (/^[a-z]+-\\d+$/i.test(r2) || /^[a-z]+(-[a-z]+)+-\\d+$/i.test(r2) || /^[a-z]+(_[a-z]+)*_\\d+$/i.test(r2) || /^\\d+$/.test(r2) || /^:[a-z0-9]+:$/i.test(r2) || /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(r2))
|
|
11768
|
+
return true;
|
|
11769
|
+
if (/^[a-z]{1,3}[A-Za-z0-9]{8,}$/.test(r2)) {
|
|
11770
|
+
const t2 = /\\d/.test(r2), e2 = /[A-Z]/.test(r2), s2 = r2.length >= 20;
|
|
11771
|
+
if (t2 && e2 || s2)
|
|
11772
|
+
return true;
|
|
11773
|
+
}
|
|
11774
|
+
return !!(/^radix-/.test(r2) || /^mui-\\d+$/.test(r2));
|
|
11756
11775
|
}
|
|
11757
11776
|
const Q = /* @__PURE__ */ new Set([
|
|
11758
11777
|
"aria-labelledby",
|
|
@@ -11953,6 +11972,11 @@ const xt = [
|
|
|
11953
11972
|
/^(rtl|ltr):/,
|
|
11954
11973
|
// === FIX 4: Group and peer variants ===
|
|
11955
11974
|
/^(group|peer)(-hover|-focus|-active)?:/,
|
|
11975
|
+
// === Arbitrary pseudo-class/modifier variants (catch-all) ===
|
|
11976
|
+
// Matches any lowercase/hyphenated prefix followed by colon
|
|
11977
|
+
// e.g., file:bg-transparent, placeholder:text-gray, invalid:border-red, accept:text-primary
|
|
11978
|
+
// Must come AFTER semantic pattern checks to avoid false positives
|
|
11979
|
+
/^[a-z][a-z-]*:/,
|
|
11956
11980
|
// === FIX 4: Tailwind utilities with fraction values ===
|
|
11957
11981
|
/\\/([\\d.]+|full|auto|screen)$/,
|
|
11958
11982
|
// /50, /100, /full, /auto, /screen
|
|
@@ -16458,7 +16482,7 @@ class ProcessedNodeManager {
|
|
|
16458
16482
|
destroy() {
|
|
16459
16483
|
}
|
|
16460
16484
|
}
|
|
16461
|
-
const version$1 = "3.1.1-alpha.
|
|
16485
|
+
const version$1 = "3.1.1-alpha.3";
|
|
16462
16486
|
let wrappedEmit;
|
|
16463
16487
|
let takeFullSnapshot$1;
|
|
16464
16488
|
let canvasManager;
|
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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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["base","expect","os","path","fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","tmp","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/utils.ts","../src/recorder/RRWebRecorder.ts","../src/recorder/index.ts","../src/runtime.ts"],"sourcesContent":["import {\n test as base,\n expect,\n} from '@playwright/test';\nimport type {\n ConsoleMessage,\n} from '@playwright/test';\nimport RRWebRecorder from './recorder';\nimport defaultRecordOptions from './recorder';\n\nimport {\n createTestrunContext,\n saveRRWebReport,\n waitForNextRAF,\n waitForRecorderStabilization,\n} from './utils';\nimport {\n getCurrentTestContext,\n setCurrentTestContext,\n} from './runtime';\n\nimport type {\n TestmapConfig\n} from './types';\n\n\nconst test = base.extend<{}>({\n browser: async ({ browser }, use) => {\n await use(browser);\n },\n\n context: async ({ browser }, use, testInfo) => {\n const context = await browser.newContext();\n const testRunContext = createTestrunContext(browser, testInfo);\n setCurrentTestContext(testInfo.testId, testRunContext);\n await use(context);\n await context.close();\n },\n\n page: async ({ page }, use, testInfo) => {\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n const recordingOpts =\n typeof testmapConfig === 'object' && 'recordingOpts' in testmapConfig\n ? testmapConfig.recordingOpts\n : defaultRecordOptions;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n // @ts-ignore\n const recorder = new RRWebRecorder(recordingOpts);\n\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (testRunContext) {\n testRunContext.recorderInstance = recorder;\n }\n\n recorder.bind({\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n pushEvent: async (event) => {\n testRunContext?.recorderEvents.push(event);\n await Promise.resolve();\n },\n });\n await recorder.inject(page);\n\n // eslint-disable-next-line @typescript-eslint/require-await\n page.on('console', async (consoleMessage: ConsoleMessage) => {\n if (consoleMessage.type() === 'debug') return;\n console.debug(`[${Date.now()}] [page] console`, consoleMessage.text());\n });\n\n page.on('load', async () => {\n /* empty */\n });\n\n page.on('domcontentloaded', async () => {\n await recorder.start();\n if (testRunContext?.runner) {\n testRunContext.runner.recorder = {\n scriptVersion: recorder.getScriptVersion(),\n libVersion: recorder.getLibVersion(),\n };\n }\n });\n page.on('framenavigated', async () => {\n /* empty */\n });\n\n page.on('close', async () => {\n await recorder.flush();\n });\n\n // @ts-ignore\n const originalonStepEnd = testInfo._onStepEnd.bind(this);\n // @ts-ignore\n testInfo._onStepEnd = async (stepEndPayload: {\n testId: string;\n stepId: string;\n wallTime: number;\n error?: unknown;\n suggestedRebaseline?: string;\n annotations: { type: string, description?: string }[];\n }) => {\n\n // @ts-ignore\n const currentStepInfo = testInfo._stepMap.get(stepEndPayload.stepId);\n if (currentStepInfo.apiName && currentStepInfo?.location.file === testInfo.file) {\n await recorder.addCustomEvent(currentStepInfo.apiName, {\n stepId: currentStepInfo.stepId,\n category: currentStepInfo.category,\n location: currentStepInfo.location,\n title: currentStepInfo.title,\n apiName: currentStepInfo.apiName,\n endWallTime: currentStepInfo.endWallTime,\n });\n\n }\n if (!page.isClosed()) {\n try {\n await waitForNextRAF(page);\n } catch (error) { /* empty */ }\n }\n await originalonStepEnd(stepEndPayload);\n };\n\n // @ts-ignore\n const originalonDidFinishTestFunction = testInfo._onDidFinishTestFunction.bind(this);\n // @ts-ignore\n testInfo._onDidFinishTestFunction = async () => {\n\n if (recorder && recorder.isRecordingReady()) {\n await waitForRecorderStabilization(recorder, 500);\n await recorder.stop();\n }\n\n await originalonDidFinishTestFunction();\n }\n\n await use(page);\n\n\n },\n});\n\ntest.beforeEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🟢 TEST START] ${testInfo.title}`);\n\n});\n\ntest.afterEach(async ({}, testInfo) => {\n console.log(`[${Date.now()}] [🔴 TEST END] ${testInfo.title}`);\n const testRunContext = getCurrentTestContext(testInfo.testId);\n if (!testRunContext) return;\n\n testRunContext.test.duration = testInfo.duration;\n const testRunResult = {\n runner: testRunContext?.runner,\n spec: testRunContext?.spec,\n browser: testRunContext?.browser,\n test: testRunContext?.test,\n suite: testRunContext?.test.suite,\n recorderEvents: Array.isArray(testRunContext?.recorderEvents) ? testRunContext?.recorderEvents : []\n }\n\n type ExtendedUse = typeof testInfo.project.use & { testmap?: TestmapConfig };\n const pwConfig = testInfo.project.use as ExtendedUse;\n const testmapConfig = pwConfig.testmap ?? {};\n\n saveRRWebReport(testRunResult, testmapConfig.outputReportDir)\n\n});\n\nexport { test, expect };\n\n","import os from 'os';\nimport path from 'path';\nimport fs from 'fs';\nimport { Browser, Page, Frame, TestInfo } from '@playwright/test';\nimport type { RecorderEvent } from './recorder/types';\nimport type { TestRunContext, TestRunResult, SerializedValue } from './types';\nimport RRWebRecorder from \"./recorder\";\n\nconst defaultOutputReportDir = 'test-results/playwright/ui';\n\nfunction writeFileAtomic(filePath: string, data: string) {\n const dir = path.dirname(filePath);\n const tmp = path.join(dir, `.${path.basename(filePath)}.tmp-${process.pid}-${Date.now()}`);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(tmp, data, 'utf-8');\n fs.renameSync(tmp, filePath);\n}\n\nfunction readJsonArraySafe(filePath: string): unknown[] {\n try {\n if (!fs.existsSync(filePath)) return [];\n const text = fs.readFileSync(filePath, 'utf-8').trim();\n if (!text) return [];\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const parsed = JSON.parse(text);\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\nexport function saveRRWebReport(testRunResult: TestRunResult, outputReportDir?: string) {\n const reportDir = outputReportDir !== undefined ? outputReportDir : defaultOutputReportDir;\n const specName = sanitizeFileNamePart(testRunResult.spec.name);\n const suiteTitle = sanitizeFileNamePart(testRunResult.test.suite?.title);\n const testTitle = sanitizeFileNamePart(testRunResult.test.title);\n const browserName = testRunResult.browser.name;\n\n const jsonFileNameRaw = `${suiteTitle ? suiteTitle + '-' : ''}${testTitle}.json`;\n const jsonFilePathRaw = path.join(reportDir, specName, browserName, jsonFileNameRaw);\n const reportRaw = {\n events: testRunResult.recorderEvents,\n metadata: {\n runner: testRunResult.runner,\n spec: testRunResult.spec,\n suite: testRunResult.test.suite,\n test: testRunResult.test,\n browser: testRunResult.browser,\n }\n };\n fs.mkdirSync(reportDir, { recursive: true });\n fs.mkdirSync(path.dirname(jsonFilePathRaw), { recursive: true });\n fs.writeFileSync(jsonFilePathRaw, JSON.stringify(reportRaw, null, 2), 'utf-8');\n console.log(`[ui-coverage] Saved report to ${jsonFilePathRaw}`);\n\n try {\n const aggregatePath = path.join(reportDir, \"ui-coverage-aggregated.json\");\n const current = readJsonArraySafe(aggregatePath);\n current.push(reportRaw);\n writeFileAtomic(aggregatePath, JSON.stringify(current, null, 2));\n console.log(`[ui-coverage] Updated aggregate: ${aggregatePath}`);\n } catch (e) {\n console.warn('[ui-coverage] Failed to update aggregate report:', e);\n }\n}\n\nexport function sanitizeFileNamePart(name: string | undefined): string {\n return (name ?? '')\n .trim()\n .replace(/[\\s:/\\\\<>|\"'?*]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '');\n}\n\nexport function createTestrunContext(browser: Browser, testInfo: TestInfo): TestRunContext {\n const browserType = browser.browserType();\n const version = browser.version();\n const family = browserType.name();\n\n const absolute = testInfo.file;\n const relative = absolute.replace(process.cwd(), '').replace(/^[/\\\\]/, '');\n const baseName = relative.split(/[\\\\/]/).pop() ?? '';\n const [fileName, fileExtension] = baseName.split(/\\.(?=[^\\\\.]+$)/);\n\n const suiteTitlePath = testInfo.titlePath.slice(1, -1); // всё кроме последнего (сам тест)\n const suiteTitle = suiteTitlePath.join(' > ') || 'Root Suite';\n\n const testRunContext: TestRunContext = {\n runner: {\n source: 'playwright',\n type: 'unknown',\n version: testInfo.config.version,\n platform: os.platform(),\n arch: os.arch(),\n recorder: {\n scriptVersion: 'unknown',\n libVersion: 'unknown'\n }\n\n },\n spec: {\n name: baseName,\n relative,\n absolute,\n baseName,\n fileName,\n fileExtension,\n id: relative,\n },\n test: {\n suite: {\n id: suiteTitlePath.join('::') || 'root',\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column ?? 0,\n line: testInfo.line ?? 0,\n fileUrl: undefined,\n function: undefined,\n originalFile: undefined,\n relativeFile: relative,\n },\n pending: false,\n root: suiteTitlePath.length === 0,\n title: suiteTitle,\n type: \"unknown\"\n },\n id: testInfo.testId,\n title: testInfo.title,\n titlePath: testInfo.titlePath.slice(1),\n fullTitle: testInfo.titlePath.slice(1).join(' '),\n file: testInfo.file,\n invocationDetails: {\n absoluteFile: absolute,\n column: testInfo.column,\n line: testInfo.line,\n fileUrl: '',\n relativeFile: relative,\n },\n state: testInfo.status,\n duration: testInfo.duration,\n pending: false,\n sync: false,\n timedOut: undefined,\n type: ''\n },\n browser: {\n name: family,\n family,\n version,\n majorVersion: parseInt(version.split('.')[0], 10),\n displayName: testInfo.project.use?.channel?.toUpperCase?.() ?? family.charAt(0).toUpperCase() + family.slice(1),\n channel: testInfo.project.use?.channel ?? '',\n path: browserType.executablePath(),\n },\n recorderEvents: [] as RecorderEvent[],\n };\n return testRunContext\n}\n\nexport function deepMerge<T>(target: T, source: Partial<T>): T {\n const result = { ...target };\n\n for (const key in source) {\n const sourceValue = source[key];\n const targetValue = target[key];\n\n if (\n sourceValue &&\n typeof sourceValue === 'object' &&\n !Array.isArray(sourceValue) &&\n targetValue &&\n typeof targetValue === 'object' &&\n !Array.isArray(targetValue)\n ) {\n result[key] = deepMerge(targetValue, sourceValue);\n } else if (sourceValue !== undefined) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n result[key] = sourceValue as unknown;\n }\n }\n\n return result;\n}\n\nexport async function waitForRecorderStabilization(recorder: RRWebRecorder, timeout = 500) {\n const start = Date.now();\n let lastCount = recorder.getEvents().length;\n\n return new Promise<void>((resolve) => {\n const interval = setInterval(() => {\n const currentCount = recorder.getEvents().length;\n if (currentCount === lastCount || Date.now() - start > timeout) {\n clearInterval(interval);\n resolve();\n }\n lastCount = currentCount;\n }, 50);\n });\n}\n\nexport async function waitForNextRAF(page: Page) {\n await page.evaluate(() => new Promise<void>((r) => requestAnimationFrame(() => r())));\n}\n\nexport async function waitForRAF(\n pageOrFrame: Page | Frame,\n) {\n return await pageOrFrame.evaluate(() => {\n return new Promise((resolve) => {\n requestAnimationFrame(() => {\n requestAnimationFrame(resolve);\n });\n });\n });\n}\n\nexport function parseSerializedValue(value: SerializedValue, handles: any[] | undefined): any {\n return innerParseSerializedValue(value, handles, new Map(), []);\n}\n\nfunction innerParseSerializedValue(value: SerializedValue, handles: any[] | undefined, refs: Map<number, object>, accessChain: Array<string | number>): any {\n if (value.ref !== undefined)\n return refs.get(value.ref);\n if (value.n !== undefined)\n return value.n;\n if (value.s !== undefined)\n return value.s;\n if (value.b !== undefined)\n return value.b;\n if (value.v !== undefined) {\n if (value.v === 'undefined')\n return undefined;\n if (value.v === 'null')\n return null;\n if (value.v === 'NaN')\n return NaN;\n if (value.v === 'Infinity')\n return Infinity;\n if (value.v === '-Infinity')\n return -Infinity;\n if (value.v === '-0')\n return -0;\n }\n if (value.d !== undefined)\n return new Date(value.d);\n if (value.u !== undefined)\n return new URL(value.u);\n if (value.bi !== undefined)\n return BigInt(value.bi);\n if (value.e !== undefined) {\n const error = new Error(value.e.m);\n error.name = value.e.n;\n error.stack = value.e.s;\n return error;\n }\n if (value.r !== undefined)\n return new RegExp(value.r.p, value.r.f);\n if (value.ta !== undefined) {\n const ctor = typedArrayKindToConstructor[value.ta.k] as any;\n return new ctor(value.ta.b.buffer, value.ta.b.byteOffset, value.ta.b.length / ctor.BYTES_PER_ELEMENT);\n }\n\n if (value.a !== undefined) {\n const result: any[] = [];\n refs.set(value.id!, result);\n for (let i = 0; i < value.a.length; i++)\n result.push(innerParseSerializedValue(value.a[i], handles, refs, [...accessChain, i]));\n return result;\n }\n if (value.o !== undefined) {\n const result: any = {};\n refs.set(value.id!, result);\n for (const { k, v } of value.o)\n result[k] = innerParseSerializedValue(v, handles, refs, [...accessChain, k]);\n return result;\n }\n if (value.h !== undefined) {\n if (handles === undefined)\n throw new Error('Unexpected handle');\n return handles[value.h];\n }\n throw new Error(`Attempting to deserialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nexport type HandleOrValue = { h: number } | { fallThrough: any };\ntype VisitorInfo = {\n visited: Map<object, number>;\n lastId: number;\n};\n\nexport function serializeValue(value: any, handleSerializer: (value: any) => HandleOrValue): SerializedValue {\n return innerSerializeValue(value, handleSerializer, { lastId: 0, visited: new Map() }, []);\n}\n\nfunction innerSerializeValue(value: any, handleSerializer: (value: any) => HandleOrValue, visitorInfo: VisitorInfo, accessChain: Array<string | number>): SerializedValue {\n const handle = handleSerializer(value);\n if ('fallThrough' in handle)\n value = handle.fallThrough;\n else\n return handle;\n\n if (typeof value === 'symbol')\n return { v: 'undefined' };\n if (Object.is(value, undefined))\n return { v: 'undefined' };\n if (Object.is(value, null))\n return { v: 'null' };\n if (Object.is(value, NaN))\n return { v: 'NaN' };\n if (Object.is(value, Infinity))\n return { v: 'Infinity' };\n if (Object.is(value, -Infinity))\n return { v: '-Infinity' };\n if (Object.is(value, -0))\n return { v: '-0' };\n if (typeof value === 'boolean')\n return { b: value };\n if (typeof value === 'number')\n return { n: value };\n if (typeof value === 'string')\n return { s: value };\n if (typeof value === 'bigint')\n return { bi: value.toString() };\n if (isError(value))\n return { e: { n: value.name, m: value.message, s: value.stack || '' } };\n if (isDate(value))\n return { d: value.toJSON() };\n if (isURL(value))\n return { u: value.toJSON() };\n if (isRegExp(value))\n return { r: { p: value.source, f: value.flags } };\n\n const typedArrayKind = constructorToTypedArrayKind.get(value.constructor);\n if (typedArrayKind)\n return { ta: { b: Buffer.from(value.buffer, value.byteOffset, value.byteLength), k: typedArrayKind } };\n\n const id = visitorInfo.visited.get(value);\n if (id)\n return { ref: id };\n\n if (Array.isArray(value)) {\n const a = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (let i = 0; i < value.length; ++i)\n a.push(innerSerializeValue(value[i], handleSerializer, visitorInfo, [...accessChain, i]));\n return { a, id };\n }\n if (typeof value === 'object') {\n const o: { k: string, v: SerializedValue }[] = [];\n const id = ++visitorInfo.lastId;\n visitorInfo.visited.set(value, id);\n for (const name of Object.keys(value))\n o.push({ k: name, v: innerSerializeValue(value[name], handleSerializer, visitorInfo, [...accessChain, name]) });\n return { o, id };\n }\n throw new Error(`Attempting to serialize unexpected value${accessChainToDisplayString(accessChain)}: ${value}`);\n}\n\nfunction accessChainToDisplayString(accessChain: Array<string | number>): string {\n const chainString = accessChain.map((accessor, i) => {\n if (typeof accessor === 'string')\n return i ? `.${accessor}` : accessor;\n return `[${accessor}]`;\n }).join('');\n\n return chainString.length > 0 ? ` at position \"${chainString}\"` : '';\n}\n\nfunction isRegExp(obj: any): obj is RegExp {\n return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';\n}\n\nfunction isDate(obj: any): obj is Date {\n return obj instanceof Date || Object.prototype.toString.call(obj) === '[object Date]';\n}\n\nfunction isURL(obj: any): obj is URL {\n return obj instanceof URL || Object.prototype.toString.call(obj) === '[object URL]';\n}\n\nfunction isError(obj: any): obj is Error {\n const proto = obj ? Object.getPrototypeOf(obj) : null;\n return obj instanceof Error || proto?.name === 'Error' || (proto && isError(proto));\n}\n\n\ntype TypedArrayKind = NonNullable<SerializedValue['ta']>['k'];\nconst typedArrayKindToConstructor: Record<TypedArrayKind, Function> = {\n i8: Int8Array,\n ui8: Uint8Array,\n ui8c: Uint8ClampedArray,\n i16: Int16Array,\n ui16: Uint16Array,\n i32: Int32Array,\n ui32: Uint32Array,\n f32: Float32Array,\n f64: Float64Array,\n bi64: BigInt64Array,\n bui64: BigUint64Array,\n};\n\nconst constructorToTypedArrayKind: Map<Function, TypedArrayKind> = new Map(Object.entries(typedArrayKindToConstructor).map(([k, v]) => [v, k as TypedArrayKind]));\n","import type { recordOptions } from '@appsurify-testmap/rrweb';\nimport { record } from '@appsurify-testmap/rrweb';\nimport type { Mirror } from '@appsurify-testmap/rrweb-snapshot';\nimport type { Page, JSHandle } from '@playwright/test';\nimport type { RecorderContext, RecorderEvent } from './types';\nimport type { eventWithTime, RecordPlugin } from '@appsurify-testmap/rrweb-types';\nimport { deepMerge } from '../utils';\n\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrSrc from './releases/rrweb-record.umd.cjs.src';\n// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-ignore\nimport rrPluginSrc from './releases/rrweb-plugin-sequential-id-record.umd.cjs.src';\n\n\nexport const defaultRecordOptions: recordOptions<RecorderEvent> = {\n slimDOMOptions: 'all',\n inlineStylesheet: true,\n recordDOM: true,\n recordCanvas: true,\n collectFonts: true,\n inlineImages: true,\n maskInputOptions: { password: true },\n sampling: {\n mousemove: false,\n mouseInteraction: {\n MouseUp: false,\n MouseDown: false,\n Click: true,\n ContextMenu: true,\n DblClick: true,\n Focus: true,\n Blur: true,\n TouchStart: false,\n TouchEnd: false,\n },\n scroll: 100,\n media: 100,\n input: 'last',\n canvas: 'all',\n visibility: {\n mode: 'none',\n debounce: 0,\n threshold: 0.5,\n sensitivity: 0.05,\n rafThrottle: 10\n }\n },\n flushCustomEvent: 'after',\n recordAfter: 'DOMContentLoaded',\n userTriggeredOnInput: true,\n}\n\ndeclare global {\n interface Window {\n rrweb?: {\n record?: typeof record;\n },\n stopFn: (() => void) | undefined | null,\n handleEmit: (event: RecorderEvent) => void,\n rrwebPluginSequentialIdRecord?: {\n getRecordSequentialIdPlugin: (options?: Partial<{key: string, getId?: () => number}>) => RecordPlugin;\n }\n }\n}\n\nexport class RRWebRecorder {\n private recordFn: JSHandle | null | undefined = null;\n private page: Page | null = null;\n private context: RecorderContext;\n private eventCounter = 0;\n private events: RecorderEvent[] = [];\n private recordOptions?: recordOptions<RecorderEvent>;\n private pendingEvents: {\n tag: string;\n payload: Record<string, unknown>;\n }[] = [];\n private recorderScriptVersion = 'unknown';\n private recorderLibVersion = 'unknown';\n public isRecording = false;\n\n constructor(options?: recordOptions<RecorderEvent>) {\n this.recordOptions = deepMerge(defaultRecordOptions, options ?? {});\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n private handleEmit(event: RecorderEvent) {\n if (event.type === 0 || event.type === 1) {\n return;\n }\n const rrEvent: RecorderEvent = {\n ...event,\n };\n this.context.pushEvent(rrEvent);\n }\n\n public async inject(page: Page) {\n this.page = page\n\n await this.page?.addInitScript({content: rrSrc as string});\n await this.page?.addInitScript({content: rrPluginSrc as string});\n\n await this.page?.exposeFunction('handleEmit', (event: RecorderEvent) => {\n this.handleEmit(event);\n });\n\n }\n\n public async start() {\n this.recordFn = await this.page?.evaluateHandle(() => {\n return window.rrweb?.record;\n });\n await this.recordFn?.evaluate((r: typeof record, optsJson) => {\n const opts = JSON.parse(optsJson) as recordOptions<RecorderEvent>;\n const plugins = [];\n if (window.rrwebPluginSequentialIdRecord) {\n plugins.push(\n window.rrwebPluginSequentialIdRecord.getRecordSequentialIdPlugin({\n key: 'id',\n })\n )\n }\n\n window.stopFn = r({\n emit: (event: RecorderEvent) => {\n // console.info(`[${event.timestamp}] [rrweb-recorder] ${event.type} ${event.data?.source} ${event.data?.href}`)\n window.handleEmit?.(event);\n },\n plugins: plugins,\n ...opts,\n })\n }, JSON.stringify(this.recordOptions));\n\n this.isRecording = await this.recordFn?.evaluate((r: typeof record) => r.isRecording()) as boolean;\n this.recorderScriptVersion = await this.recordFn?.evaluate((r: typeof record) => r.getVersion()) as string;\n\n await this.flush();\n }\n\n public async stop() {\n this.isRecording = false;\n if (this.recordFn && this.page && !this.page.isClosed()) {\n await this.flush();\n await this.page.evaluate(() => {\n window.stopFn = null;\n });\n }\n }\n\n public async reset() {\n this.eventCounter = 0;\n this.events = [];\n await this.stop();\n this.context = {\n pushEvent: (event) => this.events.push(event),\n };\n }\n\n public async flush() {\n if (!this.recordFn) return;\n const stillPending: typeof this.pendingEvents = [];\n for (const evt of this.pendingEvents) {\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, evt);\n } catch (error) {\n console.debug(`[${Date.now()}] [recorder] flush failed for custom event: ${evt.tag}`);\n stillPending.push(evt);\n }\n }\n this.pendingEvents = stillPending;\n }\n\n public async addCustomEvent(tag: string, payload: Record<string, unknown>) {\n const event = { tag, payload };\n\n if (!this.recordFn || !this.isRecording) {\n console.debug(`[${Date.now()}] [recorder] queued custom event (recorder not ready): ${tag}`);\n this.pendingEvents.push(event);\n return;\n }\n\n try {\n await this.recordFn.evaluate((r: typeof record, evt) => {\n r.addCustomEvent(evt.tag, evt.payload)\n }, event);\n } catch (error) {\n this.pendingEvents.push(event);\n }\n\n }\n\n public isRecordingReady(): boolean {\n return !!this.recordFn && this.isRecording;\n }\n\n public getScriptVersion(): string {\n return `@appsurify-testmap/rrweb-record:${this.recorderScriptVersion}`;\n }\n\n public getLibVersion(): string {\n return `@appsurify-testmap/rrweb:${this.recorderLibVersion !== 'unknown' ? this.recorderLibVersion : this.recorderScriptVersion}`;\n }\n\n public getEvents(): readonly RecorderEvent[] {\n return this.events;\n }\n\n public getMirror(): Mirror | undefined {\n return (this.recordFn as unknown as { mirror?: Mirror })?.mirror;\n }\n\n public bind(ctx: RecorderContext) {\n this.context = ctx;\n }\n\n public setEventCounter(value: number) {\n this.eventCounter = value;\n }\n\n}\n","import { RRWebRecorder } from './RRWebRecorder';\n\n\nexport default RRWebRecorder;\n","import type { TestRunContext } from './types';\n\nexport const testContexts = new Map<string, TestRunContext>();\n\nexport function setCurrentTestContext(key: string, ctx: TestRunContext): void {\n testContexts.set(key, ctx);\n}\n\nexport function getCurrentTestContext(key: string): TestRunContext | undefined {\n return testContexts.get(key);\n}\n\nexport function clearTestContext(key: string): void {\n testContexts.delete(key);\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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","names":["base","expect","os","path","fs","defaultOutputReportDir","writeFileAtomic","filePath","data","dir","tmp","readJsonArraySafe","text","parsed","saveRRWebReport","testRunResult","outputReportDir","reportDir","specName","sanitizeFileNamePart","suiteTitle","testTitle","browserName","jsonFileNameRaw","jsonFilePathRaw","reportRaw","aggregatePath","current","e","name","createTestrunContext","browser","testInfo","browserType","version","family","absolute","relative","baseName","fileName","fileExtension","suiteTitlePath","deepMerge","target","source","result","key","sourceValue","targetValue","waitForRecorderStabilization","recorder","timeout","start","lastCount","resolve","interval","currentCount","waitForNextRAF","page","r","typedArrayKindToConstructor","constructorToTypedArrayKind","k","v","defaultRecordOptions","RRWebRecorder","options","deepMerge","event","rrEvent","page","rrweb_record_umd_cjs_default","rrweb_plugin_sequential_id_record_umd_cjs_default","r","optsJson","opts","plugins","stillPending","evt","tag","payload","ctx","value","recorder_default","RRWebRecorder","testContexts","setCurrentTestContext","key","ctx","getCurrentTestContext","test","base","browser","use","testInfo","context","testRunContext","createTestrunContext","setCurrentTestContext","page","testmapConfig","recordingOpts","recorder_default","recorder","getCurrentTestContext","event","consoleMessage","originalonStepEnd","stepEndPayload","currentStepInfo","waitForNextRAF","originalonDidFinishTestFunction","waitForRecorderStabilization","testRunResult","saveRRWebReport"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsurify-testmap/rrweb-playwright-plugin",
|
|
3
|
-
"version": "3.1.1-alpha.
|
|
3
|
+
"version": "3.1.1-alpha.3",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"@playwright/test": ">=1.50.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@appsurify-testmap/rrweb": "^3.1.1-alpha.
|
|
44
|
-
"@appsurify-testmap/rrweb-snapshot": "^3.1.1-alpha.
|
|
45
|
-
"@appsurify-testmap/rrweb-types": "^3.1.1-alpha.
|
|
43
|
+
"@appsurify-testmap/rrweb": "^3.1.1-alpha.3",
|
|
44
|
+
"@appsurify-testmap/rrweb-snapshot": "^3.1.1-alpha.3",
|
|
45
|
+
"@appsurify-testmap/rrweb-types": "^3.1.1-alpha.3",
|
|
46
46
|
"@playwright/test": "^1.52.0",
|
|
47
47
|
"@types/node": "^24.10.0",
|
|
48
48
|
"puppeteer": "^24.9.0",
|