@dev-blinq/cucumber_client 1.0.1584-dev → 1.0.1586-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.
- package/bin/client/recorderv3/services.js +206 -35
- package/package.json +2 -2
|
@@ -219,27 +219,54 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
219
219
|
super();
|
|
220
220
|
this.CDP_CONNECT_URL = CDP_CONNECT_URL;
|
|
221
221
|
this.context = context;
|
|
222
|
+
this.log("🚀 RemoteBrowserService initialized", { CDP_CONNECT_URL });
|
|
222
223
|
this.initializeListeners();
|
|
223
224
|
}
|
|
225
|
+
log(message, data) {
|
|
226
|
+
const timestamp = new Date().toISOString();
|
|
227
|
+
console.log(`[${timestamp}] [RemoteBrowserService] ${message}`, data ? JSON.stringify(data, null, 2) : "");
|
|
228
|
+
}
|
|
224
229
|
async initializeListeners() {
|
|
230
|
+
this.log("📡 Initializing listeners");
|
|
225
231
|
// Listen for new pages
|
|
226
232
|
this.context.on("page", async (page) => {
|
|
233
|
+
this.log("🆕 New page event triggered", { url: page.url() });
|
|
227
234
|
const id = await this.getPageId(page);
|
|
235
|
+
this.log("🔍 Got page ID from CDP", { id, url: page.url() });
|
|
228
236
|
if (id) {
|
|
229
237
|
this.pages.set(id, page);
|
|
238
|
+
this.log("✅ Page added to internal map", {
|
|
239
|
+
id,
|
|
240
|
+
url: page.url(),
|
|
241
|
+
totalPages: this.pages.size,
|
|
242
|
+
allPageIds: Array.from(this.pages.keys()),
|
|
243
|
+
});
|
|
230
244
|
await this.syncState();
|
|
231
245
|
}
|
|
246
|
+
else {
|
|
247
|
+
this.log("❌ Failed to get page ID, page not added to map", { url: page.url() });
|
|
248
|
+
}
|
|
232
249
|
// Listen for page updates
|
|
233
250
|
page.on("load", async () => {
|
|
251
|
+
this.log("🔄 Page load event", { id, url: page.url() });
|
|
234
252
|
await this.syncState();
|
|
235
253
|
});
|
|
236
254
|
page.on("close", async () => {
|
|
255
|
+
this.log("🗑️ Page close event", { id, url: page.url() });
|
|
237
256
|
if (id) {
|
|
238
257
|
this.pages.delete(id);
|
|
258
|
+
this.log("✅ Page removed from internal map", {
|
|
259
|
+
id,
|
|
260
|
+
remainingPages: this.pages.size,
|
|
261
|
+
allPageIds: Array.from(this.pages.keys()),
|
|
262
|
+
});
|
|
239
263
|
if (this._selectedPageId === id) {
|
|
240
|
-
// Select first available page
|
|
241
264
|
const firstPage = Array.from(this.pages.keys())[0];
|
|
242
265
|
this._selectedPageId = firstPage || null;
|
|
266
|
+
this.log("🔄 Selected page changed after close", {
|
|
267
|
+
oldSelectedId: id,
|
|
268
|
+
newSelectedId: this._selectedPageId,
|
|
269
|
+
});
|
|
243
270
|
}
|
|
244
271
|
await this.syncState();
|
|
245
272
|
}
|
|
@@ -247,155 +274,299 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
247
274
|
});
|
|
248
275
|
// Initialize with existing pages
|
|
249
276
|
const existingPages = this.context.pages();
|
|
277
|
+
this.log("📄 Found existing pages", { count: existingPages.length });
|
|
250
278
|
for (const page of existingPages) {
|
|
251
279
|
const id = await this.getPageId(page);
|
|
280
|
+
this.log("🔍 Processing existing page", { id, url: page.url() });
|
|
252
281
|
if (id) {
|
|
253
282
|
this.pages.set(id, page);
|
|
283
|
+
this.log("✅ Existing page added to map", {
|
|
284
|
+
id,
|
|
285
|
+
url: page.url(),
|
|
286
|
+
totalPages: this.pages.size,
|
|
287
|
+
});
|
|
254
288
|
}
|
|
255
|
-
// page.on("framenavigated", async () => {
|
|
256
|
-
// await new Promise((resolve) => setTimeout(resolve, 1000)); // wait for a bit
|
|
257
|
-
// await this.syncState();
|
|
258
|
-
// });
|
|
259
289
|
}
|
|
260
290
|
// Set initial selected page
|
|
261
291
|
if (this.pages.size > 0 && !this._selectedPageId) {
|
|
262
292
|
this._selectedPageId = Array.from(this.pages.keys())[0];
|
|
293
|
+
this.log("🎯 Initial selected page set", { selectedPageId: this._selectedPageId });
|
|
263
294
|
}
|
|
295
|
+
this.log("✅ Initialization complete", {
|
|
296
|
+
totalPages: this.pages.size,
|
|
297
|
+
selectedPageId: this._selectedPageId,
|
|
298
|
+
allPageIds: Array.from(this.pages.keys()),
|
|
299
|
+
});
|
|
264
300
|
await this.syncState();
|
|
265
301
|
}
|
|
266
302
|
async getPageId(page) {
|
|
267
303
|
try {
|
|
268
|
-
const debugData = await this.getDebugURLs();
|
|
269
304
|
const pageUrl = page.url();
|
|
305
|
+
this.log("🔍 Getting page ID", { pageUrl });
|
|
306
|
+
const debugData = await this.getDebugURLs();
|
|
307
|
+
this.log("📊 CDP debug data received", {
|
|
308
|
+
totalPages: debugData.length,
|
|
309
|
+
pages: debugData.map((p) => ({ id: p.id, type: p.type, url: p.url })),
|
|
310
|
+
});
|
|
311
|
+
// Exact match
|
|
270
312
|
for (const pageData of debugData) {
|
|
271
313
|
if (pageData.type === "page" && pageData.url === pageUrl) {
|
|
314
|
+
this.log("✅ Found exact URL match", {
|
|
315
|
+
id: pageData.id,
|
|
316
|
+
url: pageUrl,
|
|
317
|
+
});
|
|
272
318
|
return pageData.id;
|
|
273
319
|
}
|
|
274
320
|
}
|
|
275
|
-
|
|
321
|
+
this.log("⚠️ No exact match found, trying normalized URLs", { pageUrl });
|
|
322
|
+
// Normalized match
|
|
276
323
|
const normalizeUrl = (url) => {
|
|
277
324
|
try {
|
|
278
325
|
const u = new URL(url);
|
|
279
|
-
|
|
326
|
+
const normalized = u.hostname.replace(/^www\./, "") + u.pathname + u.search;
|
|
327
|
+
this.log("🔧 Normalized URL", { original: url, normalized });
|
|
328
|
+
return normalized;
|
|
280
329
|
}
|
|
281
330
|
catch {
|
|
331
|
+
this.log("❌ Failed to normalize URL", { url });
|
|
282
332
|
return url;
|
|
283
333
|
}
|
|
284
334
|
};
|
|
285
335
|
const normalizedPageUrl = normalizeUrl(pageUrl);
|
|
286
336
|
for (const pageData of debugData) {
|
|
287
|
-
if (pageData.type === "page"
|
|
288
|
-
|
|
337
|
+
if (pageData.type === "page") {
|
|
338
|
+
const normalizedDebugUrl = normalizeUrl(pageData.url);
|
|
339
|
+
if (normalizedDebugUrl === normalizedPageUrl) {
|
|
340
|
+
this.log("✅ Found normalized URL match", {
|
|
341
|
+
id: pageData.id,
|
|
342
|
+
pageUrl: normalizedPageUrl,
|
|
343
|
+
debugUrl: normalizedDebugUrl,
|
|
344
|
+
});
|
|
345
|
+
return pageData.id;
|
|
346
|
+
}
|
|
289
347
|
}
|
|
290
348
|
}
|
|
349
|
+
this.log("❌ No match found for page", {
|
|
350
|
+
pageUrl,
|
|
351
|
+
normalizedPageUrl,
|
|
352
|
+
availablePages: debugData.filter((p) => p.type === "page").map((p) => p.url),
|
|
353
|
+
});
|
|
291
354
|
return null;
|
|
292
355
|
}
|
|
293
356
|
catch (error) {
|
|
294
|
-
|
|
357
|
+
this.log("❌ Error getting page ID", {
|
|
358
|
+
error: error instanceof Error ? error.message : String(error),
|
|
359
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
360
|
+
});
|
|
295
361
|
return null;
|
|
296
362
|
}
|
|
297
363
|
}
|
|
298
364
|
async getDebugURLs() {
|
|
299
365
|
const url = `${this.CDP_CONNECT_URL}/json`;
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
366
|
+
this.log("📡 Fetching debug URLs", { url });
|
|
367
|
+
try {
|
|
368
|
+
const response = await fetch(url);
|
|
369
|
+
if (!response.ok) {
|
|
370
|
+
this.log("❌ Failed to fetch debug URLs", {
|
|
371
|
+
status: response.status,
|
|
372
|
+
statusText: response.statusText,
|
|
373
|
+
});
|
|
374
|
+
throw new Error("Error while fetching debug URL");
|
|
375
|
+
}
|
|
376
|
+
const data = await response.json();
|
|
377
|
+
this.log("✅ Debug URLs fetched successfully", {
|
|
378
|
+
count: data.length,
|
|
379
|
+
pages: data.map((p) => ({ id: p.id, type: p.type, url: p.url })),
|
|
380
|
+
});
|
|
381
|
+
return data;
|
|
382
|
+
}
|
|
383
|
+
catch (error) {
|
|
384
|
+
this.log("❌ Exception while fetching debug URLs", {
|
|
385
|
+
error: error instanceof Error ? error.message : String(error),
|
|
386
|
+
});
|
|
387
|
+
throw error;
|
|
303
388
|
}
|
|
304
|
-
return response.json();
|
|
305
389
|
}
|
|
306
390
|
async syncState() {
|
|
307
391
|
try {
|
|
392
|
+
this.log("🔄 Starting state sync");
|
|
308
393
|
const state = await this.getState();
|
|
309
|
-
|
|
394
|
+
this.log("✅ State sync complete", {
|
|
395
|
+
pagesCount: state.pages.length,
|
|
396
|
+
selectedPageId: state.selectedPageId,
|
|
397
|
+
pages: state.pages.map((p) => ({ id: p.id, title: p.title, url: p.url })),
|
|
398
|
+
});
|
|
310
399
|
this.emit("BrowserService.stateSync", state);
|
|
311
400
|
}
|
|
312
401
|
catch (error) {
|
|
313
|
-
|
|
402
|
+
this.log("❌ Error syncing state", {
|
|
403
|
+
error: error instanceof Error ? error.message : String(error),
|
|
404
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
405
|
+
});
|
|
314
406
|
}
|
|
315
407
|
}
|
|
316
408
|
async getState() {
|
|
409
|
+
this.log("📊 Getting current state", {
|
|
410
|
+
internalPagesCount: this.pages.size,
|
|
411
|
+
internalPageIds: Array.from(this.pages.keys()),
|
|
412
|
+
selectedPageId: this._selectedPageId,
|
|
413
|
+
});
|
|
317
414
|
const debugData = await this.getDebugURLs();
|
|
318
|
-
|
|
415
|
+
this.log("📊 Debug data for state", {
|
|
416
|
+
debugPagesCount: debugData.length,
|
|
417
|
+
debugPages: debugData.map((p) => ({ id: p.id, type: p.type, url: p.url })),
|
|
418
|
+
});
|
|
319
419
|
const pagesData = [];
|
|
320
420
|
for (const [id, page] of this.pages.entries()) {
|
|
421
|
+
this.log("🔍 Processing page from internal map", {
|
|
422
|
+
id,
|
|
423
|
+
url: page.url(),
|
|
424
|
+
});
|
|
321
425
|
const debugInfo = debugData.find((d) => d.id === id);
|
|
322
426
|
if (debugInfo) {
|
|
427
|
+
this.log("✅ Found matching debug info", {
|
|
428
|
+
id,
|
|
429
|
+
debugUrl: debugInfo.url,
|
|
430
|
+
pageUrl: page.url(),
|
|
431
|
+
});
|
|
323
432
|
try {
|
|
324
|
-
|
|
433
|
+
const pageData = {
|
|
325
434
|
id,
|
|
326
435
|
title: await page.title(),
|
|
327
436
|
url: page.url(),
|
|
328
437
|
wsDebuggerUrl: debugInfo.webSocketDebuggerUrl || "",
|
|
329
|
-
}
|
|
438
|
+
};
|
|
439
|
+
pagesData.push(pageData);
|
|
440
|
+
this.log("✅ Page added to state", pageData);
|
|
330
441
|
}
|
|
331
442
|
catch (error) {
|
|
332
|
-
|
|
443
|
+
this.log("❌ Error getting page data", {
|
|
444
|
+
id,
|
|
445
|
+
error: error instanceof Error ? error.message : String(error),
|
|
446
|
+
});
|
|
333
447
|
}
|
|
334
448
|
}
|
|
449
|
+
else {
|
|
450
|
+
this.log("⚠️ No matching debug info found", {
|
|
451
|
+
id,
|
|
452
|
+
pageUrl: page.url(),
|
|
453
|
+
availableDebugIds: debugData.map((d) => d.id),
|
|
454
|
+
availableDebugUrls: debugData.map((d) => d.url),
|
|
455
|
+
});
|
|
456
|
+
}
|
|
335
457
|
}
|
|
336
|
-
|
|
458
|
+
const state = {
|
|
337
459
|
pages: pagesData,
|
|
338
460
|
selectedPageId: this._selectedPageId,
|
|
339
461
|
};
|
|
462
|
+
this.log("📦 Final state", state);
|
|
463
|
+
return state;
|
|
340
464
|
}
|
|
341
465
|
async createTab(url = "about:blank") {
|
|
342
466
|
try {
|
|
343
|
-
|
|
467
|
+
this.log("🆕 Creating new tab", { url });
|
|
344
468
|
const page = await this.context.newPage();
|
|
469
|
+
this.log("✅ New page created by Playwright", { url: page.url() });
|
|
345
470
|
if (typeof url === "string" && url !== "about:blank") {
|
|
471
|
+
this.log("🌐 Navigating to URL", { url });
|
|
346
472
|
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
473
|
+
this.log("✅ Navigation complete", { finalUrl: page.url() });
|
|
347
474
|
}
|
|
348
|
-
// Wait
|
|
349
|
-
|
|
475
|
+
// Wait for CDP to register the page
|
|
476
|
+
this.log("⏳ Waiting for CDP registration...");
|
|
477
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
350
478
|
const id = await this.getPageId(page);
|
|
479
|
+
this.log("🔍 Retrieved page ID after wait", { id, url: page.url() });
|
|
351
480
|
if (id) {
|
|
352
481
|
this.pages.set(id, page);
|
|
353
482
|
this._selectedPageId = id;
|
|
354
|
-
|
|
483
|
+
this.log("✅ Tab created successfully", {
|
|
484
|
+
id,
|
|
485
|
+
url: page.url(),
|
|
486
|
+
totalPages: this.pages.size,
|
|
487
|
+
allPageIds: Array.from(this.pages.keys()),
|
|
488
|
+
selectedPageId: this._selectedPageId,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
this.log("❌ Failed to get page ID for new tab", { url: page.url() });
|
|
493
|
+
// Try to get debug data to see what's available
|
|
494
|
+
const debugData = await this.getDebugURLs();
|
|
495
|
+
this.log("🔍 Current CDP state after failed ID retrieval", {
|
|
496
|
+
debugPages: debugData.map((p) => ({ id: p.id, url: p.url, type: p.type })),
|
|
497
|
+
});
|
|
355
498
|
}
|
|
356
499
|
await this.syncState();
|
|
357
500
|
}
|
|
358
501
|
catch (error) {
|
|
359
|
-
|
|
502
|
+
this.log("❌ Error creating tab", {
|
|
503
|
+
url,
|
|
504
|
+
error: error instanceof Error ? error.message : String(error),
|
|
505
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
506
|
+
});
|
|
360
507
|
throw error;
|
|
361
508
|
}
|
|
362
509
|
}
|
|
363
510
|
async closeTab(pageId) {
|
|
364
511
|
try {
|
|
365
|
-
|
|
512
|
+
this.log("🗑️ Closing tab", { pageId });
|
|
366
513
|
const page = this.pages.get(pageId);
|
|
367
514
|
if (page) {
|
|
515
|
+
this.log("✅ Found page to close", { pageId, url: page.url() });
|
|
368
516
|
await page.close();
|
|
369
|
-
|
|
517
|
+
this.log("✅ Page closed successfully", { pageId });
|
|
370
518
|
}
|
|
371
519
|
else {
|
|
372
|
-
|
|
520
|
+
this.log("⚠️ Page not found", {
|
|
521
|
+
pageId,
|
|
522
|
+
availablePageIds: Array.from(this.pages.keys()),
|
|
523
|
+
});
|
|
373
524
|
}
|
|
374
525
|
}
|
|
375
526
|
catch (error) {
|
|
376
|
-
|
|
527
|
+
this.log("❌ Error closing tab", {
|
|
528
|
+
pageId,
|
|
529
|
+
error: error instanceof Error ? error.message : String(error),
|
|
530
|
+
});
|
|
377
531
|
throw error;
|
|
378
532
|
}
|
|
379
533
|
}
|
|
380
534
|
async selectTab(pageId) {
|
|
381
535
|
try {
|
|
382
|
-
|
|
536
|
+
this.log("🎯 Selecting tab", { pageId });
|
|
383
537
|
const page = this.pages.get(pageId);
|
|
384
538
|
if (page) {
|
|
385
539
|
this._selectedPageId = pageId;
|
|
386
540
|
await page.bringToFront();
|
|
541
|
+
this.log("✅ Tab selected successfully", {
|
|
542
|
+
pageId,
|
|
543
|
+
url: page.url(),
|
|
544
|
+
selectedPageId: this._selectedPageId,
|
|
545
|
+
});
|
|
387
546
|
await this.syncState();
|
|
388
547
|
}
|
|
389
548
|
else {
|
|
390
|
-
|
|
549
|
+
this.log("⚠️ Page not found for selection", {
|
|
550
|
+
pageId,
|
|
551
|
+
availablePageIds: Array.from(this.pages.keys()),
|
|
552
|
+
});
|
|
391
553
|
}
|
|
392
554
|
}
|
|
393
555
|
catch (error) {
|
|
394
|
-
|
|
556
|
+
this.log("❌ Error selecting tab", {
|
|
557
|
+
pageId,
|
|
558
|
+
error: error instanceof Error ? error.message : String(error),
|
|
559
|
+
});
|
|
395
560
|
throw error;
|
|
396
561
|
}
|
|
397
562
|
}
|
|
398
563
|
getSelectedPage() {
|
|
399
|
-
|
|
564
|
+
const page = this._selectedPageId ? this.pages.get(this._selectedPageId) || null : null;
|
|
565
|
+
this.log("🔍 Getting selected page", {
|
|
566
|
+
selectedPageId: this._selectedPageId,
|
|
567
|
+
found: !!page,
|
|
568
|
+
url: page?.url(),
|
|
569
|
+
});
|
|
570
|
+
return page;
|
|
400
571
|
}
|
|
401
572
|
}
|
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.1586-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.200-dev",
|
|
41
41
|
"@faker-js/faker": "^8.4.1",
|
|
42
42
|
"automation_model": "1.0.889-dev",
|
|
43
43
|
"axios": "^1.7.4",
|