@dev-blinq/cucumber_client 1.0.1598-dev โ†’ 1.0.1599-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.
@@ -218,10 +218,12 @@ export class RemoteBrowserService extends EventEmitter {
218
218
  context;
219
219
  pages = new Map();
220
220
  _selectedPageId = null;
221
+ wsUrlBase; // Store the base URL
221
222
  constructor({ CDP_CONNECT_URL, context }) {
222
223
  super();
223
224
  this.CDP_CONNECT_URL = CDP_CONNECT_URL;
224
225
  this.context = context;
226
+ this.wsUrlBase = this.CDP_CONNECT_URL.replace(/^http/, "ws") + "/devtools/page/";
225
227
  this.log("๐Ÿš€ RemoteBrowserService initialized", { CDP_CONNECT_URL });
226
228
  this.initializeListeners();
227
229
  }
@@ -229,9 +231,16 @@ export class RemoteBrowserService extends EventEmitter {
229
231
  const timestamp = new Date().toISOString();
230
232
  console.log(`[${timestamp}] [RemoteBrowserService] ${message}`, data ? JSON.stringify(data, null, 2) : "");
231
233
  }
232
- // Simplified: Get the ID directly from the page
234
+ /**
235
+ * Gets the CDP Target ID for a page *directly* from the page.
236
+ * This is the only reliable method during restarts.
237
+ */
233
238
  async getCdpTargetId(page) {
234
239
  try {
240
+ if (page.isClosed()) {
241
+ this.log("โš ๏ธ Attempted to get CDP ID from a closed page");
242
+ return null;
243
+ }
235
244
  const cdpSession = await page.context().newCDPSession(page);
236
245
  const { targetInfo } = await cdpSession.send("Target.getTargetInfo");
237
246
  await cdpSession.detach();
@@ -246,38 +255,27 @@ export class RemoteBrowserService extends EventEmitter {
246
255
  return null;
247
256
  }
248
257
  }
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
- }
264
258
  async initializeListeners() {
265
259
  this.log("๐Ÿ“ก Initializing listeners");
266
260
  this.context.on("page", async (page) => {
267
261
  const stableTabId = uuidv4();
268
262
  this.log("๐Ÿ†• New page event triggered", { stableTabId, url: page.url() });
263
+ // We get the ID immediately, but it might be null if the page is too new
269
264
  const cdpTargetId = await this.getCdpTargetId(page);
270
265
  this.pages.set(stableTabId, { page, cdpTargetId });
271
266
  if (cdpTargetId) {
272
267
  this.log("โœ… Page mapped to CDP ID", { stableTabId, cdpTargetId });
273
268
  }
274
269
  else {
275
- this.log("โš ๏ธ Could not find CDP ID for new page", { stableTabId });
270
+ this.log("โš ๏ธ Could not find CDP ID for new page yet", { stableTabId });
276
271
  }
277
- if (this.pages.size === 1) {
272
+ if (!this._selectedPageId) {
273
+ // Select the first page that opens
278
274
  this._selectedPageId = stableTabId;
275
+ this.log("๐ŸŽฏ Initial selected page set", { selectedPageId: this._selectedPageId });
279
276
  }
280
277
  await this.syncState();
278
+ // Add listeners
281
279
  page.on("load", () => this.syncState());
282
280
  page.on("framenavigated", () => this.syncState());
283
281
  page.on("close", async () => {
@@ -317,36 +315,46 @@ export class RemoteBrowserService extends EventEmitter {
317
315
  }
318
316
  async getState() {
319
317
  this.log("๐Ÿ“Š Getting current state");
320
- // Get the *live* list of debuggable pages
321
- const debugData = await this.getDebugURLs();
322
- const debugMap = new Map(debugData.map((d) => [d.id, d]));
323
318
  const pagesData = [];
319
+ const pagesToDelete = []; // To clean up closed pages
324
320
  for (const [stableTabId, pageInfo] of this.pages.entries()) {
325
321
  try {
326
- // Re-verify the CDP ID in case it changed
322
+ if (pageInfo.page.isClosed()) {
323
+ this.log("๐Ÿงน Found closed page during getState, marking for deletion", { stableTabId });
324
+ pagesToDelete.push(stableTabId);
325
+ continue;
326
+ }
327
+ // Get the one, true, live CDP ID
327
328
  const currentCdpId = await this.getCdpTargetId(pageInfo.page);
328
329
  if (currentCdpId && pageInfo.cdpTargetId !== currentCdpId) {
329
330
  this.log("๐Ÿ”„ CDP ID changed", { stableTabId, old: pageInfo.cdpTargetId, new: currentCdpId });
330
- pageInfo.cdpTargetId = currentCdpId;
331
+ pageInfo.cdpTargetId = currentCdpId; // Update our internal reference
332
+ }
333
+ // Manually construct the WebSocket URL
334
+ const wsDebuggerUrl = currentCdpId ? `${this.wsUrlBase}${currentCdpId}` : "";
335
+ if (!wsDebuggerUrl) {
336
+ this.log("โš ๏ธ Could not get CDP ID, wsDebuggerUrl will be empty", { stableTabId });
331
337
  }
332
- // Get the debug info from the live map
333
- const debugInfo = currentCdpId ? debugMap.get(currentCdpId) : undefined;
334
338
  pagesData.push({
335
339
  id: stableTabId,
336
340
  title: await pageInfo.page.title(),
337
341
  url: pageInfo.page.url(),
338
- wsDebuggerUrl: debugInfo?.webSocketDebuggerUrl || "",
342
+ wsDebuggerUrl: wsDebuggerUrl, // Use the constructed URL
339
343
  });
340
344
  }
341
345
  catch (error) {
342
- // This likely means the page was closed during the loop
343
- this.log("โŒ Error getting page data (page might be closed)", { stableTabId });
344
- this.pages.delete(stableTabId); // Clean up dead page
346
+ this.log("โŒ Error getting page data", { stableTabId, error });
347
+ pagesToDelete.push(stableTabId); // Mark for deletion
345
348
  }
346
349
  }
347
- // Ensure selectedPageId is valid
350
+ pagesToDelete.forEach((id) => this.pages.delete(id));
348
351
  if (this._selectedPageId && !this.pages.has(this._selectedPageId)) {
349
352
  this._selectedPageId = pagesData.length > 0 ? pagesData[0].id : null;
353
+ this.log("๐Ÿ”„ Corrected selectedPageId", { new: this._selectedPageId });
354
+ }
355
+ if (!this._selectedPageId && pagesData.length > 0) {
356
+ this._selectedPageId = pagesData[0].id;
357
+ this.log("๐ŸŽฏ Set default selectedPageId", { new: this._selectedPageId });
350
358
  }
351
359
  const state = {
352
360
  pages: pagesData,
@@ -358,11 +366,10 @@ export class RemoteBrowserService extends EventEmitter {
358
366
  async createTab(url = "about:blank") {
359
367
  try {
360
368
  this.log("๐Ÿ†• Creating new tab", { url });
361
- const page = await this.context.newPage(); // Triggers 'page' event
369
+ const page = await this.context.newPage(); // This will trigger the 'page' event
362
370
  if (url !== "about:blank") {
363
371
  await page.goto(url, { waitUntil: "domcontentloaded" });
364
372
  }
365
- // Find the stableTabId that was just created by the 'page' event
366
373
  for (const [stableTabId, pageInfo] of this.pages.entries()) {
367
374
  if (pageInfo.page === page) {
368
375
  this._selectedPageId = stableTabId;
@@ -381,7 +388,7 @@ export class RemoteBrowserService extends EventEmitter {
381
388
  this.log("๐Ÿ—‘๏ธ Closing tab", { stableTabId });
382
389
  const pageInfo = this.pages.get(stableTabId);
383
390
  if (pageInfo) {
384
- await pageInfo.page.close(); // Triggers 'close' event
391
+ await pageInfo.page.close(); // This will trigger the 'close' event
385
392
  }
386
393
  else {
387
394
  this.log("โš ๏ธ Page not found for closing", { stableTabId });
@@ -411,16 +418,21 @@ export class RemoteBrowserService extends EventEmitter {
411
418
  }
412
419
  getSelectedPage() {
413
420
  const pageInfo = this._selectedPageId ? this.pages.get(this._selectedPageId) : null;
421
+ this.log("๐Ÿ” Getting selected page", {
422
+ selectedPageId: this._selectedPageId,
423
+ found: !!pageInfo,
424
+ url: pageInfo?.page.url(),
425
+ });
414
426
  return pageInfo?.page || null;
415
427
  }
416
428
  destroy() {
417
429
  this.log("๐Ÿ’ฅ Destroying RemoteBrowserService");
418
430
  this.context.removeAllListeners("page");
419
431
  for (const [, pageInfo] of this.pages.entries()) {
420
- pageInfo.page.removeAllListeners();
432
+ pageInfo.page.removeAllListeners(); // Remove all listeners from each page
421
433
  }
422
434
  this.pages.clear();
423
435
  this._selectedPageId = null;
424
- this.removeAllListeners();
436
+ this.removeAllListeners(); // Remove listeners on the emitter itself
425
437
  }
426
438
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dev-blinq/cucumber_client",
3
- "version": "1.0.1598-dev",
3
+ "version": "1.0.1599-dev",
4
4
  "description": " ",
5
5
  "main": "bin/index.js",
6
6
  "types": "bin/index.d.ts",