@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
|
-
|
|
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.
|
|
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
|
-
|
|
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:
|
|
342
|
+
wsDebuggerUrl: wsDebuggerUrl, // Use the constructed URL
|
|
339
343
|
});
|
|
340
344
|
}
|
|
341
345
|
catch (error) {
|
|
342
|
-
|
|
343
|
-
|
|
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
|
-
|
|
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(); //
|
|
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(); //
|
|
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
|
}
|