@skrillex1224/playwright-toolkit 2.1.201 → 2.1.203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3039,6 +3039,7 @@ var Captcha = {
3039
3039
  };
3040
3040
 
3041
3041
  // src/mutation.js
3042
+ import { createHash } from "node:crypto";
3042
3043
  import { v4 as uuidv42 } from "uuid";
3043
3044
  var logger10 = createInternalLogger("Mutation");
3044
3045
  var MUTATION_MONITOR_MODE = Object.freeze({
@@ -3245,82 +3246,138 @@ var Mutation = {
3245
3246
  if (text.length <= max) return text;
3246
3247
  return `${text.slice(0, max)}...`;
3247
3248
  };
3249
+ const normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
3250
+ const normalizeHtml = (value) => String(value || "").trim();
3251
+ const hashSnapshot = (value) => createHash("sha256").update(String(value || "")).digest("hex");
3248
3252
  const buildState = async () => {
3249
- return await page.evaluate(({ selectorList: selectorList2 }) => {
3250
- const normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
3251
- const tail = (value, max = 512) => {
3252
- const text = String(value || "");
3253
- if (text.length <= max) return text;
3254
- return text.slice(text.length - max);
3255
- };
3256
- const safeFrameId = (frameEl) => {
3257
- const id = String(frameEl?.id || "").trim();
3258
- if (id) return id;
3259
- const name = String(frameEl?.name || "").trim();
3260
- if (name) return name;
3261
- return "no-id";
3262
- };
3263
- const items = [];
3264
- selectorList2.forEach((selector) => {
3265
- let nodes = [];
3253
+ const items = [];
3254
+ const describeElement = async (elementHandle) => {
3255
+ return await elementHandle.evaluate((node) => {
3256
+ const tagName = String(node?.tagName || "").toUpperCase();
3257
+ return {
3258
+ tagName,
3259
+ id: String(node?.id || "").trim(),
3260
+ name: String(node?.getAttribute?.("name") || "").trim()
3261
+ };
3262
+ });
3263
+ };
3264
+ const readElementSnapshot = async (elementHandle) => {
3265
+ return await elementHandle.evaluate((node) => {
3266
+ const text = String(node?.innerText || node?.textContent || "");
3267
+ const html = String(node?.innerHTML || node?.outerHTML || "");
3268
+ return {
3269
+ text,
3270
+ html
3271
+ };
3272
+ });
3273
+ };
3274
+ const readFrameSnapshot = async (frame) => {
3275
+ return await frame.evaluate(() => {
3276
+ const root = document.documentElement || document.body;
3277
+ const text = String(root?.innerText || root?.textContent || "");
3278
+ const html = String(root?.innerHTML || "");
3279
+ return {
3280
+ text,
3281
+ html,
3282
+ url: window.location.href,
3283
+ readyState: document.readyState
3284
+ };
3285
+ });
3286
+ };
3287
+ for (const selector of selectorList) {
3288
+ let handles = [];
3289
+ try {
3290
+ handles = await page.locator(selector).elementHandles();
3291
+ } catch {
3292
+ continue;
3293
+ }
3294
+ for (let index = 0; index < handles.length; index += 1) {
3295
+ const handle = handles[index];
3266
3296
  try {
3267
- nodes = Array.from(document.querySelectorAll(selector));
3268
- } catch {
3269
- return;
3270
- }
3271
- nodes.forEach((node, index) => {
3272
- const isIframe = node?.tagName === "IFRAME";
3273
- let text = "";
3274
- let html = "";
3297
+ const descriptor = await describeElement(handle);
3298
+ const tagName = descriptor?.tagName || "";
3299
+ const isFrameElement = tagName === "IFRAME" || tagName === "FRAME";
3300
+ const nodeName = descriptor?.id || descriptor?.name || "no-id";
3275
3301
  let source = "main";
3276
3302
  let path2 = `${selector}[${index}]`;
3277
- if (isIframe) {
3303
+ let text = "";
3304
+ let html = "";
3305
+ let frameUrl = "";
3306
+ let readyState = "";
3307
+ if (isFrameElement) {
3278
3308
  source = "iframe";
3279
- path2 = `${selector}[${index}]::iframe(${safeFrameId(node)})`;
3280
- try {
3281
- const frameDoc = node.contentDocument;
3282
- const frameRoot = frameDoc?.body || frameDoc?.documentElement;
3283
- if (frameRoot) {
3284
- text = normalizeText(frameRoot.innerText || frameRoot.textContent || "");
3285
- html = normalizeText(frameRoot.innerHTML || "");
3309
+ path2 = `${selector}[${index}]::iframe(${nodeName})`;
3310
+ const frame = await handle.contentFrame();
3311
+ if (frame) {
3312
+ try {
3313
+ const frameSnapshot = await readFrameSnapshot(frame);
3314
+ text = normalizeText(frameSnapshot?.text || "");
3315
+ html = normalizeHtml(frameSnapshot?.html || "");
3316
+ frameUrl = String(frameSnapshot?.url || "").trim();
3317
+ readyState = String(frameSnapshot?.readyState || "").trim();
3318
+ } catch (error) {
3319
+ source = "iframe-unreadable";
3320
+ readyState = error?.name || "unreadable";
3286
3321
  }
3287
- } catch {
3322
+ } else {
3323
+ source = "iframe-detached";
3288
3324
  }
3289
3325
  } else {
3290
- text = normalizeText(node?.innerText || node?.textContent || "");
3291
- html = normalizeText(node?.innerHTML || node?.outerHTML || "");
3326
+ try {
3327
+ const elementSnapshot = await readElementSnapshot(handle);
3328
+ text = normalizeText(elementSnapshot?.text || "");
3329
+ html = normalizeHtml(elementSnapshot?.html || "");
3330
+ } catch (error) {
3331
+ source = "main-unreadable";
3332
+ readyState = error?.name || "unreadable";
3333
+ }
3292
3334
  }
3293
- const snapshot = text || html;
3335
+ const snapshot = `${text}
3336
+ <!--HTML-->
3337
+ ${html}`;
3294
3338
  items.push({
3295
3339
  selector,
3296
3340
  source,
3297
3341
  path: path2,
3298
3342
  text,
3299
3343
  html,
3344
+ frameUrl,
3345
+ readyState,
3300
3346
  snapshot
3301
3347
  });
3302
- });
3303
- });
3304
- const snapshotKey = items.map((item) => `${item.path}:${item.snapshot.length}:${tail(item.snapshot, 512)}`).join("||");
3305
- const summaryText = items.map((item) => item.snapshot || item.text).join("\n").trim();
3306
- const summaryHtml = items.map((item) => item.html).join("\n");
3307
- const hasMatched = items.length > 0;
3308
- const primary = items.length > 0 ? items[items.length - 1] : null;
3309
- return {
3310
- hasMatched,
3311
- snapshotKey,
3312
- text: summaryText,
3313
- html: summaryHtml,
3314
- snapshotLength: summaryText.length,
3315
- itemCount: items.length,
3316
- primaryPath: primary?.path || "",
3317
- mutationNodes: items.map((item) => ({
3318
- html: item.html,
3319
- text: item.snapshot || item.text,
3320
- mutationType: item.source
3321
- }))
3322
- };
3323
- }, { selectorList });
3348
+ } finally {
3349
+ await handle.dispose().catch(() => {
3350
+ });
3351
+ }
3352
+ }
3353
+ }
3354
+ const serializedSnapshot = items.map((item) => JSON.stringify({
3355
+ path: item.path,
3356
+ source: item.source,
3357
+ frameUrl: item.frameUrl,
3358
+ readyState: item.readyState,
3359
+ snapshot: item.snapshot
3360
+ })).join("||");
3361
+ const summaryText = items.map((item) => item.text).join("\n").trim();
3362
+ const summaryHtml = items.map((item) => item.html).join("\n");
3363
+ const hasMatched = items.length > 0;
3364
+ const primary = items.length > 0 ? items[items.length - 1] : null;
3365
+ return {
3366
+ hasMatched,
3367
+ snapshotKey: hashSnapshot(serializedSnapshot),
3368
+ text: summaryText,
3369
+ html: summaryHtml,
3370
+ snapshotLength: serializedSnapshot.length,
3371
+ itemCount: items.length,
3372
+ primaryPath: primary?.path || "",
3373
+ mutationNodes: items.map((item) => ({
3374
+ html: item.html,
3375
+ text: item.text,
3376
+ mutationType: item.source,
3377
+ frameUrl: item.frameUrl,
3378
+ readyState: item.readyState
3379
+ }))
3380
+ };
3324
3381
  };
3325
3382
  const invokeMutationCallback = async (context) => {
3326
3383
  if (!onMutation) return "__CONTINUE__";