@dev-blinq/cucumber_client 1.0.1596-dev → 1.0.1598-dev

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.
@@ -154,7 +154,9 @@ export class PublishService {
154
154
  this.TOKEN = TOKEN;
155
155
  }
156
156
  async saveScenario({ scenario, featureName, override, branch, isEditing, projectId }) {
157
- const url = path.join(`${getRunsServiceBaseURL()}`, "..", "workspace/publish-recording");
157
+ const runsURL = getRunsServiceBaseURL();
158
+ const workspaceURL = runsURL.replace("/runs", "/workspace");
159
+ const url = `${workspaceURL}/publish-recording`;
158
160
  const result = await axiosClient({
159
161
  url,
160
162
  method: "POST",
@@ -214,9 +216,8 @@ export class PublishService {
214
216
  export class RemoteBrowserService extends EventEmitter {
215
217
  CDP_CONNECT_URL;
216
218
  context;
217
- // stableTabId, Page Info
218
219
  pages = new Map();
219
- _selectedPageId = null; // This will be a stableTabId
220
+ _selectedPageId = null;
220
221
  constructor({ CDP_CONNECT_URL, context }) {
221
222
  super();
222
223
  this.CDP_CONNECT_URL = CDP_CONNECT_URL;
@@ -228,15 +229,46 @@ export class RemoteBrowserService extends EventEmitter {
228
229
  const timestamp = new Date().toISOString();
229
230
  console.log(`[${timestamp}] [RemoteBrowserService] ${message}`, data ? JSON.stringify(data, null, 2) : "");
230
231
  }
232
+ // Simplified: Get the ID directly from the page
233
+ async getCdpTargetId(page) {
234
+ try {
235
+ const cdpSession = await page.context().newCDPSession(page);
236
+ const { targetInfo } = await cdpSession.send("Target.getTargetInfo");
237
+ await cdpSession.detach();
238
+ if (targetInfo && targetInfo.targetId) {
239
+ this.log("✅ Found CDP ID by session", { id: targetInfo.targetId, url: page.url() });
240
+ return targetInfo.targetId;
241
+ }
242
+ throw new Error("Target.getTargetInfo did not return a targetId");
243
+ }
244
+ catch (error) {
245
+ this.log("❌ Error getting CDP ID by session", { url: page.url(), error });
246
+ return null;
247
+ }
248
+ }
249
+ async getDebugURLs() {
250
+ const url = `${this.CDP_CONNECT_URL}/json?t=${Date.now()}`; // Cache-busting
251
+ try {
252
+ const response = await fetch(url, { cache: "no-store" });
253
+ if (!response.ok) {
254
+ this.log("❌ Failed to fetch debug URLs", { status: response.status });
255
+ throw new Error("Error while fetching debug URL");
256
+ }
257
+ return await response.json();
258
+ }
259
+ catch (error) {
260
+ this.log("❌ Exception while fetching debug URLs", { error });
261
+ return [];
262
+ }
263
+ }
231
264
  async initializeListeners() {
232
265
  this.log("📡 Initializing listeners");
233
266
  this.context.on("page", async (page) => {
234
267
  const stableTabId = uuidv4();
235
268
  this.log("🆕 New page event triggered", { stableTabId, url: page.url() });
236
- this.pages.set(stableTabId, { page, cdpTargetId: null });
237
- const cdpTargetId = await this.findCdpTargetId(page);
269
+ const cdpTargetId = await this.getCdpTargetId(page);
270
+ this.pages.set(stableTabId, { page, cdpTargetId });
238
271
  if (cdpTargetId) {
239
- this.pages.get(stableTabId).cdpTargetId = cdpTargetId;
240
272
  this.log("✅ Page mapped to CDP ID", { stableTabId, cdpTargetId });
241
273
  }
242
274
  else {
@@ -246,115 +278,37 @@ export class RemoteBrowserService extends EventEmitter {
246
278
  this._selectedPageId = stableTabId;
247
279
  }
248
280
  await this.syncState();
249
- page.on("load", async () => {
250
- this.log("🔄 Page load event", { stableTabId, url: page.url() });
251
- const newCdpId = await this.findCdpTargetId(page);
252
- const pageInfo = this.pages.get(stableTabId);
253
- if (pageInfo && newCdpId && pageInfo.cdpTargetId !== newCdpId) {
254
- this.log("🔄 CDP Target ID changed on navigation", {
255
- stableTabId,
256
- old: pageInfo.cdpTargetId,
257
- new: newCdpId,
258
- });
259
- pageInfo.cdpTargetId = newCdpId;
260
- }
261
- await this.syncState();
262
- });
281
+ page.on("load", () => this.syncState());
282
+ page.on("framenavigated", () => this.syncState());
263
283
  page.on("close", async () => {
264
- this.log("🗑️ Page close event", { stableTabId, url: page.url() });
284
+ this.log("🗑️ Page close event", { stableTabId });
265
285
  this.pages.delete(stableTabId);
266
- this.log("✅ Page removed from internal map", {
267
- stableTabId,
268
- remaining: this.pages.size,
269
- });
270
286
  if (this._selectedPageId === stableTabId) {
271
- const firstPage = Array.from(this.pages.keys())[0];
272
- this._selectedPageId = firstPage || null;
273
- this.log("🔄 Selected page changed after close", {
274
- oldSelectedId: stableTabId,
275
- newSelectedId: this._selectedPageId,
276
- });
287
+ this._selectedPageId = this.pages.size > 0 ? Array.from(this.pages.keys())[0] : null;
288
+ this.log("🔄 Selected page changed after close", { newSelectedId: this._selectedPageId });
277
289
  }
278
290
  await this.syncState();
279
291
  });
280
- page.on("framenavigated", async (frame) => {
281
- this.log("🔄 Frame navigated event", { stableTabId, url: frame.url() });
282
- await this.syncState();
283
- });
284
292
  });
293
+ // Initialize with existing pages
285
294
  const existingPages = this.context.pages();
286
295
  this.log("📄 Found existing pages", { count: existingPages.length });
287
296
  for (const page of existingPages) {
288
297
  const stableTabId = uuidv4();
289
- const cdpTargetId = await this.findCdpTargetId(page);
298
+ const cdpTargetId = await this.getCdpTargetId(page);
290
299
  this.pages.set(stableTabId, { page, cdpTargetId });
291
- this.log("✅ Existing page added to map", {
292
- stableTabId,
293
- cdpTargetId,
294
- url: page.url(),
295
- });
300
+ this.log("✅ Existing page added to map", { stableTabId, cdpTargetId, url: page.url() });
296
301
  }
297
302
  if (this.pages.size > 0 && !this._selectedPageId) {
298
303
  this._selectedPageId = Array.from(this.pages.keys())[0];
299
- this.log("🎯 Initial selected page set", { selectedPageId: this._selectedPageId });
300
304
  }
301
305
  await this.syncState();
302
306
  }
303
- async findCdpTargetId(page) {
304
- try {
305
- // This is the most direct and reliable way to get the ID
306
- const cdpSession = await page.context().newCDPSession(page);
307
- const { targetInfo } = await cdpSession.send("Target.getTargetInfo");
308
- await cdpSession.detach();
309
- if (targetInfo && targetInfo.targetId) {
310
- this.log("🎭 Target info", targetInfo);
311
- this.log("✅ Found CDP ID by session", { id: targetInfo.targetId, url: page.url() });
312
- return targetInfo.targetId;
313
- }
314
- else {
315
- throw new Error("Target.getTargetInfo did not return a targetId");
316
- }
317
- }
318
- catch (cdpError) {
319
- // If the session fails, fall back to a simple URL match
320
- this.log("⚠️ CDP session failed, trying URL match as fallback...", { url: page.url(), cdpError });
321
- try {
322
- const debugData = await this.getDebugURLs(); // This now has the cache-busting fix
323
- const match = debugData.find((p) => p.type === "page" && p.url === page.url());
324
- if (match) {
325
- this.log("✅ Found CDP ID by exact URL as fallback", { id: match.id, url: page.url() });
326
- return match.id;
327
- }
328
- }
329
- catch (fetchError) {
330
- this.log("❌ Error in fallback getDebugURLs", { fetchError });
331
- }
332
- }
333
- this.log("❌ No match found for page", { url: page.url() });
334
- return null;
335
- }
336
- async getDebugURLs() {
337
- const url = `${this.CDP_CONNECT_URL}/json?_=${Date.now()}`; // Cache-busting query param
338
- try {
339
- const response = await fetch(url, { cache: "no-store" });
340
- if (!response.ok) {
341
- throw new Error("Error while fetching debug URL");
342
- }
343
- return await response.json();
344
- }
345
- catch (error) {
346
- this.log("❌ Exception while fetching debug URLs", { error });
347
- return [];
348
- }
349
- }
350
307
  async syncState() {
351
308
  try {
352
309
  this.log("🔄 Starting state sync");
353
310
  const state = await this.getState();
354
- this.log("✅ State sync complete", {
355
- pagesCount: state.pages.length,
356
- selectedPageId: state.selectedPageId,
357
- });
311
+ this.log("✅ State sync complete", { pagesCount: state.pages.length, selectedPageId: state.selectedPageId });
358
312
  this.emit("BrowserService.stateSync", state);
359
313
  }
360
314
  catch (error) {
@@ -363,38 +317,36 @@ export class RemoteBrowserService extends EventEmitter {
363
317
  }
364
318
  async getState() {
365
319
  this.log("📊 Getting current state");
320
+ // Get the *live* list of debuggable pages
366
321
  const debugData = await this.getDebugURLs();
367
- this.log("📊 Debug data for state", debugData);
322
+ const debugMap = new Map(debugData.map((d) => [d.id, d]));
368
323
  const pagesData = [];
369
324
  for (const [stableTabId, pageInfo] of this.pages.entries()) {
370
- let currentCdpId = pageInfo.cdpTargetId;
371
- let debugInfo = debugData.find((d) => d.id === currentCdpId);
372
- this.log("🔍 debugInfo ", debugInfo);
373
- if (!debugInfo) {
374
- this.log("⚠️ Re-finding CDP ID for", { stableTabId });
375
- const newCdpId = await this.findCdpTargetId(pageInfo.page);
376
- if (newCdpId) {
377
- pageInfo.cdpTargetId = newCdpId;
378
- debugInfo = debugData.find((d) => d.id === newCdpId);
379
- this.log("🔍 Updated debugInfo after re-finding CDP ID", debugInfo);
380
- this.log("✅ Re-found CDP ID", { stableTabId, newCdpId });
381
- }
382
- }
383
325
  try {
326
+ // Re-verify the CDP ID in case it changed
327
+ const currentCdpId = await this.getCdpTargetId(pageInfo.page);
328
+ if (currentCdpId && pageInfo.cdpTargetId !== currentCdpId) {
329
+ this.log("🔄 CDP ID changed", { stableTabId, old: pageInfo.cdpTargetId, new: currentCdpId });
330
+ pageInfo.cdpTargetId = currentCdpId;
331
+ }
332
+ // Get the debug info from the live map
333
+ const debugInfo = currentCdpId ? debugMap.get(currentCdpId) : undefined;
384
334
  pagesData.push({
385
- id: stableTabId, // Use the STABLE ID
335
+ id: stableTabId,
386
336
  title: await pageInfo.page.title(),
387
337
  url: pageInfo.page.url(),
388
- wsDebuggerUrl: debugInfo?.webSocketDebuggerUrl || "", // Get the *current* ws url
338
+ wsDebuggerUrl: debugInfo?.webSocketDebuggerUrl || "",
389
339
  });
390
340
  }
391
341
  catch (error) {
342
+ // This likely means the page was closed during the loop
392
343
  this.log("❌ Error getting page data (page might be closed)", { stableTabId });
344
+ this.pages.delete(stableTabId); // Clean up dead page
393
345
  }
394
346
  }
347
+ // Ensure selectedPageId is valid
395
348
  if (this._selectedPageId && !this.pages.has(this._selectedPageId)) {
396
- this._selectedPageId = this.pages.size > 0 ? Array.from(this.pages.keys())[0] : null;
397
- this.log("🔄 Corrected selectedPageId", { new: this._selectedPageId });
349
+ this._selectedPageId = pagesData.length > 0 ? pagesData[0].id : null;
398
350
  }
399
351
  const state = {
400
352
  pages: pagesData,
@@ -406,10 +358,11 @@ export class RemoteBrowserService extends EventEmitter {
406
358
  async createTab(url = "about:blank") {
407
359
  try {
408
360
  this.log("🆕 Creating new tab", { url });
409
- const page = await this.context.newPage(); // This will trigger the 'page' event
361
+ const page = await this.context.newPage(); // Triggers 'page' event
410
362
  if (url !== "about:blank") {
411
363
  await page.goto(url, { waitUntil: "domcontentloaded" });
412
364
  }
365
+ // Find the stableTabId that was just created by the 'page' event
413
366
  for (const [stableTabId, pageInfo] of this.pages.entries()) {
414
367
  if (pageInfo.page === page) {
415
368
  this._selectedPageId = stableTabId;
@@ -428,7 +381,7 @@ export class RemoteBrowserService extends EventEmitter {
428
381
  this.log("🗑️ Closing tab", { stableTabId });
429
382
  const pageInfo = this.pages.get(stableTabId);
430
383
  if (pageInfo) {
431
- await pageInfo.page.close(); // This will trigger the 'close' event
384
+ await pageInfo.page.close(); // Triggers 'close' event
432
385
  }
433
386
  else {
434
387
  this.log("⚠️ Page not found for closing", { stableTabId });
@@ -458,462 +411,16 @@ export class RemoteBrowserService extends EventEmitter {
458
411
  }
459
412
  getSelectedPage() {
460
413
  const pageInfo = this._selectedPageId ? this.pages.get(this._selectedPageId) : null;
461
- this.log("🔍 Getting selected page", {
462
- selectedPageId: this._selectedPageId,
463
- found: !!pageInfo,
464
- url: pageInfo?.page.url(),
465
- });
466
414
  return pageInfo?.page || null;
467
415
  }
468
416
  destroy() {
469
417
  this.log("💥 Destroying RemoteBrowserService");
470
- // Remove all listeners *this* instance has registered
471
- // This stops it from listening to context/page events
472
418
  this.context.removeAllListeners("page");
473
- for (const [stableId, pageInfo] of this.pages.entries()) {
474
- pageInfo.page.removeAllListeners("load");
475
- pageInfo.page.removeAllListeners("close");
476
- pageInfo.page.removeAllListeners("framenavigated");
419
+ for (const [, pageInfo] of this.pages.entries()) {
420
+ pageInfo.page.removeAllListeners();
477
421
  }
478
- // Clear internal maps
479
422
  this.pages.clear();
480
423
  this._selectedPageId = null;
481
- // Remove all listeners *on this* emitter
482
424
  this.removeAllListeners();
483
425
  }
484
426
  }
485
- // export class RemoteBrowserService extends EventEmitter {
486
- // private CDP_CONNECT_URL: string;
487
- // private context: BrowserContext;
488
- // private pages: Map<string, Page> = new Map();
489
- // private _selectedPageId: string | null = null;
490
- // constructor({ CDP_CONNECT_URL, context }: { CDP_CONNECT_URL: string; context: BrowserContext }) {
491
- // super();
492
- // this.CDP_CONNECT_URL = CDP_CONNECT_URL;
493
- // this.context = context;
494
- // this.log("🚀 RemoteBrowserService initialized", { CDP_CONNECT_URL });
495
- // this.initializeListeners();
496
- // }
497
- // private log(message: string, data?: any) {
498
- // const timestamp = new Date().toISOString();
499
- // console.log(`[${timestamp}] [RemoteBrowserService] ${message}`, data ? JSON.stringify(data, null, 2) : "");
500
- // }
501
- // private async initializeListeners() {
502
- // this.log("📡 Initializing listeners");
503
- // // Listen for new pages
504
- // this.context.on("page", async (page) => {
505
- // this.log("🆕 New page event triggered", { url: page.url() });
506
- // const id = await this.getPageId(page);
507
- // this.log("🔍 Got page ID from CDP", { id, url: page.url() });
508
- // if (id) {
509
- // this.pages.set(id, page);
510
- // this.log("✅ Page added to internal map", {
511
- // id,
512
- // url: page.url(),
513
- // totalPages: this.pages.size,
514
- // allPageIds: Array.from(this.pages.keys()),
515
- // });
516
- // await this.syncState();
517
- // } else {
518
- // this.log("❌ Failed to get page ID, page not added to map", { url: page.url() });
519
- // }
520
- // // Listen for page updates
521
- // page.on("load", async () => {
522
- // this.log("🔄 Page load event", { id, url: page.url() });
523
- // await this.syncState();
524
- // });
525
- // page.on("close", async () => {
526
- // this.log("🗑️ Page close event", { id, url: page.url() });
527
- // if (id) {
528
- // this.pages.delete(id);
529
- // this.log("✅ Page removed from internal map", {
530
- // id,
531
- // remainingPages: this.pages.size,
532
- // allPageIds: Array.from(this.pages.keys()),
533
- // });
534
- // if (this._selectedPageId === id) {
535
- // const firstPage = Array.from(this.pages.keys())[0];
536
- // this._selectedPageId = firstPage || null;
537
- // this.log("🔄 Selected page changed after close", {
538
- // oldSelectedId: id,
539
- // newSelectedId: this._selectedPageId,
540
- // });
541
- // }
542
- // await this.syncState();
543
- // }
544
- // });
545
- // });
546
- // // Initialize with existing pages
547
- // const existingPages = this.context.pages();
548
- // this.log("📄 Found existing pages", { count: existingPages.length });
549
- // for (const page of existingPages) {
550
- // const id = await this.getPageId(page);
551
- // this.log("🔍 Processing existing page", { id, url: page.url() });
552
- // if (id) {
553
- // this.pages.set(id, page);
554
- // this.log("✅ Existing page added to map", {
555
- // id,
556
- // url: page.url(),
557
- // totalPages: this.pages.size,
558
- // });
559
- // }
560
- // }
561
- // // Set initial selected page
562
- // if (this.pages.size > 0 && !this._selectedPageId) {
563
- // this._selectedPageId = Array.from(this.pages.keys())[0];
564
- // this.log("🎯 Initial selected page set", { selectedPageId: this._selectedPageId });
565
- // }
566
- // this.log("✅ Initialization complete", {
567
- // totalPages: this.pages.size,
568
- // selectedPageId: this._selectedPageId,
569
- // allPageIds: Array.from(this.pages.keys()),
570
- // });
571
- // await this.syncState();
572
- // }
573
- // private async getPageId(page: Page): Promise<string | null> {
574
- // try {
575
- // const pageUrl = page.url();
576
- // this.log("🔍 Getting page ID", { pageUrl });
577
- // // Fetch debug data from /json endpoint (more reliable for matching)
578
- // const debugData = await this.getDebugURLs();
579
- // this.log("📊 CDP debug data received", {
580
- // totalPages: debugData.length,
581
- // pages: debugData.map((p) => ({ id: p.id, type: p.type, url: p.url })),
582
- // });
583
- // // Exact URL match
584
- // for (const pageData of debugData) {
585
- // if (pageData.type === "page" && pageData.url === pageUrl) {
586
- // this.log("✅ Found exact URL match in /json", {
587
- // id: pageData.id,
588
- // url: pageUrl,
589
- // });
590
- // return pageData.id;
591
- // }
592
- // }
593
- // this.log("⚠️ No exact match found, trying normalized URLs", { pageUrl });
594
- // // Normalized URL match
595
- // const normalizeUrl = (url: string) => {
596
- // try {
597
- // const u = new URL(url);
598
- // const normalized = u.hostname.replace(/^www\./, "") + u.pathname + u.search;
599
- // return normalized;
600
- // } catch {
601
- // return url;
602
- // }
603
- // };
604
- // const normalizedPageUrl = normalizeUrl(pageUrl);
605
- // for (const pageData of debugData) {
606
- // if (pageData.type === "page") {
607
- // const normalizedDebugUrl = normalizeUrl(pageData.url);
608
- // if (normalizedDebugUrl === normalizedPageUrl) {
609
- // this.log("✅ Found normalized URL match in /json", {
610
- // id: pageData.id,
611
- // pageUrl: normalizedPageUrl,
612
- // debugUrl: normalizedDebugUrl,
613
- // });
614
- // return pageData.id;
615
- // }
616
- // }
617
- // }
618
- // // If still not found, try CDP session as fallback
619
- // this.log("⚠️ Not found in /json, trying CDP Target.getTargetInfo", { pageUrl });
620
- // try {
621
- // const cdpSession = await page.context().newCDPSession(page);
622
- // const { targetInfo } = await cdpSession.send("Target.getTargetInfo");
623
- // await cdpSession.detach();
624
- // if (targetInfo && targetInfo.targetId) {
625
- // // Verify this target ID exists in debug data
626
- // const targetExists = debugData.some((d) => d.id === targetInfo.targetId);
627
- // if (targetExists) {
628
- // this.log("✅ Got target ID from CDP session and verified in /json", {
629
- // targetId: targetInfo.targetId,
630
- // url: pageUrl,
631
- // });
632
- // return targetInfo.targetId;
633
- // } else {
634
- // this.log("⚠️ Target ID from CDP session not found in /json (ID mismatch)", {
635
- // cdpTargetId: targetInfo.targetId,
636
- // availableIds: debugData.map((d) => d.id),
637
- // });
638
- // }
639
- // }
640
- // } catch (cdpError) {
641
- // this.log("⚠️ Failed to get target ID from CDP session", {
642
- // error: cdpError instanceof Error ? cdpError.message : String(cdpError),
643
- // });
644
- // }
645
- // this.log("❌ No match found for page", {
646
- // pageUrl,
647
- // normalizedPageUrl,
648
- // availablePages: debugData.filter((p) => p.type === "page").map((p) => p.url),
649
- // });
650
- // return null;
651
- // } catch (error) {
652
- // this.log("❌ Error getting page ID", {
653
- // error: error instanceof Error ? error.message : String(error),
654
- // stack: error instanceof Error ? error.stack : undefined,
655
- // });
656
- // return null;
657
- // }
658
- // }
659
- // private async getDebugURLs(): Promise<DebugPageInfo[]> {
660
- // const url = `${this.CDP_CONNECT_URL}/json`;
661
- // this.log("📡 Fetching debug URLs", { url });
662
- // try {
663
- // const response = await fetch(url);
664
- // if (!response.ok) {
665
- // this.log("❌ Failed to fetch debug URLs", {
666
- // status: response.status,
667
- // statusText: response.statusText,
668
- // });
669
- // throw new Error("Error while fetching debug URL");
670
- // }
671
- // const data = await response.json();
672
- // this.log("✅ Debug URLs fetched successfully", {
673
- // count: data.length,
674
- // pages: data.map((p: any) => ({ id: p.id, type: p.type, url: p.url })),
675
- // });
676
- // return data;
677
- // } catch (error) {
678
- // this.log("❌ Exception while fetching debug URLs", {
679
- // error: error instanceof Error ? error.message : String(error),
680
- // });
681
- // throw error;
682
- // }
683
- // }
684
- // private async syncState() {
685
- // try {
686
- // this.log("🔄 Starting state sync");
687
- // const state = await this.getState();
688
- // this.log("✅ State sync complete", {
689
- // pagesCount: state.pages.length,
690
- // selectedPageId: state.selectedPageId,
691
- // pages: state.pages.map((p) => ({ id: p.id, title: p.title, url: p.url })),
692
- // });
693
- // this.emit("BrowserService.stateSync", state);
694
- // } catch (error) {
695
- // this.log("❌ Error syncing state", {
696
- // error: error instanceof Error ? error.message : String(error),
697
- // stack: error instanceof Error ? error.stack : undefined,
698
- // });
699
- // }
700
- // }
701
- // async getState(): Promise<BrowserState> {
702
- // this.log("📊 Getting current state", {
703
- // internalPagesCount: this.pages.size,
704
- // internalPageIds: Array.from(this.pages.keys()),
705
- // selectedPageId: this._selectedPageId,
706
- // });
707
- // const debugData = await this.getDebugURLs();
708
- // this.log("📊 Debug data for state", {
709
- // debugPagesCount: debugData.length,
710
- // debugPages: debugData.map((p) => ({ id: p.id, type: p.type, url: p.url })),
711
- // });
712
- // const pagesData: PageData[] = [];
713
- // const updatedPages = new Map<string, Page>();
714
- // const matchedDebugIds = new Set<string>(); // Track which CDP IDs we've already matched
715
- // let updatedSelectedPageId = this._selectedPageId;
716
- // for (const [oldId, page] of this.pages.entries()) {
717
- // this.log("🔍 Processing page from internal map", {
718
- // oldId,
719
- // url: page.url(),
720
- // });
721
- // // Try to find by old ID first (most common case - ID hasn't changed)
722
- // let debugInfo = debugData.find((d) => d.id === oldId && !matchedDebugIds.has(d.id));
723
- // // Fallback: Try to find by URL (page ID may have changed)
724
- // if (!debugInfo) {
725
- // this.log("⚠️ Page ID not found in CDP, attempting to match by URL", {
726
- // oldId,
727
- // pageUrl: page.url(),
728
- // });
729
- // debugInfo = debugData.find((d) => d.type === "page" && d.url === page.url() && !matchedDebugIds.has(d.id));
730
- // if (debugInfo) {
731
- // this.log("✅ Found page by URL match, updating ID", {
732
- // oldId,
733
- // newId: debugInfo.id,
734
- // url: page.url(),
735
- // });
736
- // // Update selected page ID if this was the selected page and ID changed
737
- // if (oldId === this._selectedPageId) {
738
- // updatedSelectedPageId = debugInfo.id;
739
- // this.log("🔄 Updated selected page ID", {
740
- // oldId,
741
- // newId: debugInfo.id,
742
- // });
743
- // }
744
- // }
745
- // } else {
746
- // this.log("✅ Found matching debug info by ID", {
747
- // id: debugInfo.id,
748
- // debugUrl: debugInfo.url,
749
- // pageUrl: page.url(),
750
- // });
751
- // }
752
- // if (debugInfo) {
753
- // // Mark this CDP ID as matched to avoid duplicate matches
754
- // matchedDebugIds.add(debugInfo.id);
755
- // try {
756
- // const pageData = {
757
- // id: debugInfo.id,
758
- // title: await page.title(),
759
- // url: page.url(),
760
- // wsDebuggerUrl: debugInfo.webSocketDebuggerUrl || "",
761
- // };
762
- // pagesData.push(pageData);
763
- // updatedPages.set(debugInfo.id, page);
764
- // this.log("✅ Page added to state", pageData);
765
- // } catch (error) {
766
- // this.log("❌ Error getting page data", {
767
- // id: oldId,
768
- // error: error instanceof Error ? error.message : String(error),
769
- // });
770
- // }
771
- // } else {
772
- // this.log("⚠️ No matching debug info found by ID or URL", {
773
- // oldId,
774
- // pageUrl: page.url(),
775
- // availableDebugIds: debugData.map((d) => d.id),
776
- // availableDebugUrls: debugData.map((d) => d.url),
777
- // alreadyMatched: Array.from(matchedDebugIds),
778
- // });
779
- // }
780
- // }
781
- // // Update the internal pages map with current CDP IDs
782
- // if (updatedPages.size !== this.pages.size || updatedSelectedPageId !== this._selectedPageId) {
783
- // this.log("🔄 Updating internal state with new CDP IDs", {
784
- // oldPagesCount: this.pages.size,
785
- // newPagesCount: updatedPages.size,
786
- // oldSelectedId: this._selectedPageId,
787
- // newSelectedId: updatedSelectedPageId,
788
- // });
789
- // this.pages = updatedPages;
790
- // this._selectedPageId = updatedSelectedPageId;
791
- // }
792
- // const state = {
793
- // pages: pagesData,
794
- // selectedPageId: this._selectedPageId,
795
- // };
796
- // this.log("📦 Final state", state);
797
- // return state;
798
- // }
799
- // async createTab(url: string = "about:blank"): Promise<void> {
800
- // try {
801
- // this.log("🆕 Creating new tab", { url });
802
- // const page = await this.context.newPage();
803
- // this.log("✅ New page created by Playwright", { url: page.url() });
804
- // if (typeof url === "string" && url !== "about:blank") {
805
- // this.log("🌐 Navigating to URL", { url });
806
- // await page.goto(url, { waitUntil: "domcontentloaded" });
807
- // this.log("✅ Navigation complete", { finalUrl: page.url() });
808
- // }
809
- // // Wait longer for CDP to register and stabilize the page
810
- // this.log("⏳ Waiting for CDP registration and stabilization...");
811
- // await new Promise((resolve) => setTimeout(resolve, 1000)); // Increased to 1 second
812
- // // Try multiple times to get a stable page ID
813
- // let id: string | null = null;
814
- // let attempts = 0;
815
- // const maxAttempts = 5;
816
- // while (!id && attempts < maxAttempts) {
817
- // attempts++;
818
- // this.log(`🔍 Attempt ${attempts}/${maxAttempts} to get page ID`);
819
- // id = await this.getPageId(page);
820
- // if (!id) {
821
- // this.log(`⏳ Page ID not found, waiting 500ms before retry...`);
822
- // await new Promise((resolve) => setTimeout(resolve, 500));
823
- // }
824
- // }
825
- // this.log("🔍 Retrieved page ID after retries", {
826
- // id,
827
- // url: page.url(),
828
- // attempts,
829
- // });
830
- // if (id) {
831
- // this.pages.set(id, page);
832
- // this._selectedPageId = id;
833
- // this.log("✅ Tab created successfully", {
834
- // id,
835
- // url: page.url(),
836
- // totalPages: this.pages.size,
837
- // allPageIds: Array.from(this.pages.keys()),
838
- // selectedPageId: this._selectedPageId,
839
- // });
840
- // } else {
841
- // this.log("❌ Failed to get page ID for new tab after all retries", {
842
- // url: page.url(),
843
- // attempts,
844
- // });
845
- // // Try to get debug data to see what's available
846
- // const debugData = await this.getDebugURLs();
847
- // this.log("🔍 Current CDP state after failed ID retrieval", {
848
- // debugPages: debugData.map((p) => ({ id: p.id, url: p.url, type: p.type })),
849
- // });
850
- // }
851
- // await this.syncState();
852
- // } catch (error) {
853
- // this.log("❌ Error creating tab", {
854
- // url,
855
- // error: error instanceof Error ? error.message : String(error),
856
- // stack: error instanceof Error ? error.stack : undefined,
857
- // });
858
- // throw error;
859
- // }
860
- // }
861
- // async closeTab(pageId: string): Promise<void> {
862
- // try {
863
- // this.log("🗑️ Closing tab", { pageId });
864
- // const page = this.pages.get(pageId);
865
- // if (page) {
866
- // this.log("✅ Found page to close", { pageId, url: page.url() });
867
- // await page.close();
868
- // this.log("✅ Page closed successfully", { pageId });
869
- // } else {
870
- // this.log("⚠️ Page not found", {
871
- // pageId,
872
- // availablePageIds: Array.from(this.pages.keys()),
873
- // });
874
- // }
875
- // } catch (error) {
876
- // this.log("❌ Error closing tab", {
877
- // pageId,
878
- // error: error instanceof Error ? error.message : String(error),
879
- // });
880
- // throw error;
881
- // }
882
- // }
883
- // async selectTab(pageId: string): Promise<void> {
884
- // try {
885
- // this.log("🎯 Selecting tab", { pageId });
886
- // const page = this.pages.get(pageId);
887
- // if (page) {
888
- // this._selectedPageId = pageId;
889
- // await page.bringToFront();
890
- // this.log("✅ Tab selected successfully", {
891
- // pageId,
892
- // url: page.url(),
893
- // selectedPageId: this._selectedPageId,
894
- // });
895
- // await this.syncState();
896
- // } else {
897
- // this.log("⚠️ Page not found for selection", {
898
- // pageId,
899
- // availablePageIds: Array.from(this.pages.keys()),
900
- // });
901
- // }
902
- // } catch (error) {
903
- // this.log("❌ Error selecting tab", {
904
- // pageId,
905
- // error: error instanceof Error ? error.message : String(error),
906
- // });
907
- // throw error;
908
- // }
909
- // }
910
- // getSelectedPage(): Page | null {
911
- // const page = this._selectedPageId ? this.pages.get(this._selectedPageId) || null : null;
912
- // this.log("🔍 Getting selected page", {
913
- // selectedPageId: this._selectedPageId,
914
- // found: !!page,
915
- // url: page?.url(),
916
- // });
917
- // return page;
918
- // }
919
- // }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1596-dev",
3
+ "version": "1.0.1598-dev",
4
4
  "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",