@dev-blinq/cucumber_client 1.0.1591-dev → 1.0.1593-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.
|
@@ -831,7 +831,10 @@ export class BVTRecorder {
|
|
|
831
831
|
this.previousHistoryLength = null;
|
|
832
832
|
this.previousUrl = null;
|
|
833
833
|
this.previousEntries = null;
|
|
834
|
-
|
|
834
|
+
if (this.browserEmitter) {
|
|
835
|
+
this.browserEmitter.destroy();
|
|
836
|
+
this.browserEmitter = null; // Clear the reference
|
|
837
|
+
}
|
|
835
838
|
await closeContext();
|
|
836
839
|
this.pageSet.clear();
|
|
837
840
|
}
|
|
@@ -231,11 +231,9 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
231
231
|
async initializeListeners() {
|
|
232
232
|
this.log("📡 Initializing listeners");
|
|
233
233
|
this.context.on("page", async (page) => {
|
|
234
|
-
const stableTabId = uuidv4();
|
|
234
|
+
const stableTabId = uuidv4();
|
|
235
235
|
this.log("🆕 New page event triggered", { stableTabId, url: page.url() });
|
|
236
|
-
// Add to map immediately with the stable ID
|
|
237
236
|
this.pages.set(stableTabId, { page, cdpTargetId: null });
|
|
238
|
-
// Asynchronously find its CDP ID
|
|
239
237
|
const cdpTargetId = await this.findCdpTargetId(page);
|
|
240
238
|
if (cdpTargetId) {
|
|
241
239
|
this.pages.get(stableTabId).cdpTargetId = cdpTargetId;
|
|
@@ -244,15 +242,12 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
244
242
|
else {
|
|
245
243
|
this.log("⚠️ Could not find CDP ID for new page", { stableTabId });
|
|
246
244
|
}
|
|
247
|
-
// If this is the first page, select it
|
|
248
245
|
if (this.pages.size === 1) {
|
|
249
246
|
this._selectedPageId = stableTabId;
|
|
250
247
|
}
|
|
251
248
|
await this.syncState();
|
|
252
|
-
// Listen for page updates
|
|
253
249
|
page.on("load", async () => {
|
|
254
250
|
this.log("🔄 Page load event", { stableTabId, url: page.url() });
|
|
255
|
-
// Navigation can *sometimes* change the CDP ID. We must re-verify.
|
|
256
251
|
const newCdpId = await this.findCdpTargetId(page);
|
|
257
252
|
const pageInfo = this.pages.get(stableTabId);
|
|
258
253
|
if (pageInfo && newCdpId && pageInfo.cdpTargetId !== newCdpId) {
|
|
@@ -283,13 +278,10 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
283
278
|
await this.syncState();
|
|
284
279
|
});
|
|
285
280
|
page.on("framenavigated", async (frame) => {
|
|
286
|
-
// This event fires for *all* frames (iframes and the main page)
|
|
287
|
-
// We'll sync state to capture any potential title changes
|
|
288
281
|
this.log("🔄 Frame navigated event", { stableTabId, url: frame.url() });
|
|
289
282
|
await this.syncState();
|
|
290
283
|
});
|
|
291
284
|
});
|
|
292
|
-
// Initialize with existing pages
|
|
293
285
|
const existingPages = this.context.pages();
|
|
294
286
|
this.log("📄 Found existing pages", { count: existingPages.length });
|
|
295
287
|
for (const page of existingPages) {
|
|
@@ -308,68 +300,40 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
308
300
|
}
|
|
309
301
|
await this.syncState();
|
|
310
302
|
}
|
|
311
|
-
// Renamed from getPageId to be more descriptive
|
|
312
303
|
async findCdpTargetId(page) {
|
|
313
304
|
try {
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
// Check if any page in our map *already* has this CDP ID
|
|
322
|
-
for (const info of this.pages.values()) {
|
|
323
|
-
if (info.cdpTargetId === debugPage.id)
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
return true;
|
|
327
|
-
});
|
|
328
|
-
// 1. Exact URL match
|
|
329
|
-
let match = unmappedCdpPages.find((p) => p.url === pageUrl);
|
|
330
|
-
if (match) {
|
|
331
|
-
this.log("✅ Found CDP ID by exact URL", { id: match.id, url: pageUrl });
|
|
332
|
-
return match.id;
|
|
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("✅ Found CDP ID by session", { id: targetInfo.targetId, url: page.url() });
|
|
311
|
+
return targetInfo.targetId;
|
|
333
312
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
try {
|
|
337
|
-
const u = new URL(url);
|
|
338
|
-
return u.hostname.replace(/^www\./, "") + u.pathname + u.search;
|
|
339
|
-
}
|
|
340
|
-
catch {
|
|
341
|
-
return url;
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
const normalizedPageUrl = normalizeUrl(pageUrl);
|
|
345
|
-
match = unmappedCdpPages.find((p) => normalizeUrl(p.url) === normalizedPageUrl);
|
|
346
|
-
if (match) {
|
|
347
|
-
this.log("✅ Found CDP ID by normalized URL", { id: match.id, url: pageUrl });
|
|
348
|
-
return match.id;
|
|
313
|
+
else {
|
|
314
|
+
throw new Error("Target.getTargetInfo did not return a targetId");
|
|
349
315
|
}
|
|
350
|
-
|
|
316
|
+
}
|
|
317
|
+
catch (cdpError) {
|
|
318
|
+
// If the session fails, fall back to a simple URL match
|
|
319
|
+
this.log("⚠️ CDP session failed, trying URL match as fallback...", { url: page.url(), cdpError });
|
|
351
320
|
try {
|
|
352
|
-
const
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
return targetInfo.targetId;
|
|
321
|
+
const debugData = await this.getDebugURLs(); // This now has the cache-busting fix
|
|
322
|
+
const match = debugData.find((p) => p.type === "page" && p.url === page.url());
|
|
323
|
+
if (match) {
|
|
324
|
+
this.log("✅ Found CDP ID by exact URL as fallback", { id: match.id, url: page.url() });
|
|
325
|
+
return match.id;
|
|
358
326
|
}
|
|
359
327
|
}
|
|
360
|
-
catch (
|
|
361
|
-
this.log("
|
|
328
|
+
catch (fetchError) {
|
|
329
|
+
this.log("❌ Error in fallback getDebugURLs", { fetchError });
|
|
362
330
|
}
|
|
363
|
-
this.log("❌ No match found for page", { pageUrl });
|
|
364
|
-
return null;
|
|
365
|
-
}
|
|
366
|
-
catch (error) {
|
|
367
|
-
this.log("❌ Error finding CDP target ID", { error });
|
|
368
|
-
return null;
|
|
369
331
|
}
|
|
332
|
+
this.log("❌ No match found for page", { url: page.url() });
|
|
333
|
+
return null;
|
|
370
334
|
}
|
|
371
335
|
async getDebugURLs() {
|
|
372
|
-
const url = `${this.CDP_CONNECT_URL}/json`;
|
|
336
|
+
const url = `${this.CDP_CONNECT_URL}/json?_=${Date.now()}`; // Cache-busting query param
|
|
373
337
|
try {
|
|
374
338
|
const response = await fetch(url, { cache: "no-store" });
|
|
375
339
|
if (!response.ok) {
|
|
@@ -379,7 +343,7 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
379
343
|
}
|
|
380
344
|
catch (error) {
|
|
381
345
|
this.log("❌ Exception while fetching debug URLs", { error });
|
|
382
|
-
return [];
|
|
346
|
+
return [];
|
|
383
347
|
}
|
|
384
348
|
}
|
|
385
349
|
async syncState() {
|
|
@@ -400,12 +364,9 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
400
364
|
this.log("📊 Getting current state");
|
|
401
365
|
const debugData = await this.getDebugURLs();
|
|
402
366
|
const pagesData = [];
|
|
403
|
-
// Re-verify CDP Target IDs for all pages, as they might have changed
|
|
404
367
|
for (const [stableTabId, pageInfo] of this.pages.entries()) {
|
|
405
368
|
let currentCdpId = pageInfo.cdpTargetId;
|
|
406
|
-
// Find the CDP info for our KNOWN cdpTargetId
|
|
407
369
|
let debugInfo = debugData.find((d) => d.id === currentCdpId);
|
|
408
|
-
// If not found (e.g., ID changed), try to find it again
|
|
409
370
|
if (!debugInfo) {
|
|
410
371
|
this.log("⚠️ Re-finding CDP ID for", { stableTabId });
|
|
411
372
|
const newCdpId = await this.findCdpTargetId(pageInfo.page);
|
|
@@ -427,7 +388,6 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
427
388
|
this.log("❌ Error getting page data (page might be closed)", { stableTabId });
|
|
428
389
|
}
|
|
429
390
|
}
|
|
430
|
-
// Ensure selectedPageId is valid
|
|
431
391
|
if (this._selectedPageId && !this.pages.has(this._selectedPageId)) {
|
|
432
392
|
this._selectedPageId = this.pages.size > 0 ? Array.from(this.pages.keys())[0] : null;
|
|
433
393
|
this.log("🔄 Corrected selectedPageId", { new: this._selectedPageId });
|
|
@@ -446,8 +406,6 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
446
406
|
if (url !== "about:blank") {
|
|
447
407
|
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
448
408
|
}
|
|
449
|
-
// The 'page' event handler now manages setting the selected ID
|
|
450
|
-
// We just need to find the new page and select it
|
|
451
409
|
for (const [stableTabId, pageInfo] of this.pages.entries()) {
|
|
452
410
|
if (pageInfo.page === page) {
|
|
453
411
|
this._selectedPageId = stableTabId;
|
|
@@ -471,7 +429,6 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
471
429
|
else {
|
|
472
430
|
this.log("⚠️ Page not found for closing", { stableTabId });
|
|
473
431
|
}
|
|
474
|
-
// 'close' event handler will manage state update
|
|
475
432
|
}
|
|
476
433
|
catch (error) {
|
|
477
434
|
this.log("❌ Error closing tab", { error });
|
|
@@ -495,7 +452,6 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
495
452
|
this.log("❌ Error selecting tab", { error });
|
|
496
453
|
}
|
|
497
454
|
}
|
|
498
|
-
// ... (getSelectedPage remains the same, but operates on new state)
|
|
499
455
|
getSelectedPage() {
|
|
500
456
|
const pageInfo = this._selectedPageId ? this.pages.get(this._selectedPageId) : null;
|
|
501
457
|
this.log("🔍 Getting selected page", {
|
|
@@ -505,6 +461,22 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
505
461
|
});
|
|
506
462
|
return pageInfo?.page || null;
|
|
507
463
|
}
|
|
464
|
+
destroy() {
|
|
465
|
+
this.log("💥 Destroying RemoteBrowserService");
|
|
466
|
+
// Remove all listeners *this* instance has registered
|
|
467
|
+
// This stops it from listening to context/page events
|
|
468
|
+
this.context.removeAllListeners("page");
|
|
469
|
+
for (const [stableId, pageInfo] of this.pages.entries()) {
|
|
470
|
+
pageInfo.page.removeAllListeners("load");
|
|
471
|
+
pageInfo.page.removeAllListeners("close");
|
|
472
|
+
pageInfo.page.removeAllListeners("framenavigated");
|
|
473
|
+
}
|
|
474
|
+
// Clear internal maps
|
|
475
|
+
this.pages.clear();
|
|
476
|
+
this._selectedPageId = null;
|
|
477
|
+
// Remove all listeners *on this* emitter
|
|
478
|
+
this.removeAllListeners();
|
|
479
|
+
}
|
|
508
480
|
}
|
|
509
481
|
// export class RemoteBrowserService extends EventEmitter {
|
|
510
482
|
// private CDP_CONNECT_URL: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dev-blinq/cucumber_client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1593-dev",
|
|
4
4
|
"description": " ",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"types": "bin/index.d.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@babel/traverse": "^7.27.1",
|
|
38
38
|
"@babel/types": "^7.27.1",
|
|
39
39
|
"@cucumber/tag-expressions": "^6.1.1",
|
|
40
|
-
"@dev-blinq/cucumber-js": "1.0.
|
|
40
|
+
"@dev-blinq/cucumber-js": "1.0.201-dev",
|
|
41
41
|
"@faker-js/faker": "^8.4.1",
|
|
42
42
|
"automation_model": "1.0.890-dev",
|
|
43
43
|
"axios": "^1.7.4",
|