@dev-blinq/cucumber_client 1.0.1597-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.
|
@@ -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
|
|
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",
|
|
@@ -216,10 +218,12 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
216
218
|
context;
|
|
217
219
|
pages = new Map();
|
|
218
220
|
_selectedPageId = null;
|
|
221
|
+
wsUrlBase; // Store the base URL
|
|
219
222
|
constructor({ CDP_CONNECT_URL, context }) {
|
|
220
223
|
super();
|
|
221
224
|
this.CDP_CONNECT_URL = CDP_CONNECT_URL;
|
|
222
225
|
this.context = context;
|
|
226
|
+
this.wsUrlBase = this.CDP_CONNECT_URL.replace(/^http/, "ws") + "/devtools/page/";
|
|
223
227
|
this.log("๐ RemoteBrowserService initialized", { CDP_CONNECT_URL });
|
|
224
228
|
this.initializeListeners();
|
|
225
229
|
}
|
|
@@ -227,9 +231,16 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
227
231
|
const timestamp = new Date().toISOString();
|
|
228
232
|
console.log(`[${timestamp}] [RemoteBrowserService] ${message}`, data ? JSON.stringify(data, null, 2) : "");
|
|
229
233
|
}
|
|
230
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Gets the CDP Target ID for a page *directly* from the page.
|
|
236
|
+
* This is the only reliable method during restarts.
|
|
237
|
+
*/
|
|
231
238
|
async getCdpTargetId(page) {
|
|
232
239
|
try {
|
|
240
|
+
if (page.isClosed()) {
|
|
241
|
+
this.log("โ ๏ธ Attempted to get CDP ID from a closed page");
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
233
244
|
const cdpSession = await page.context().newCDPSession(page);
|
|
234
245
|
const { targetInfo } = await cdpSession.send("Target.getTargetInfo");
|
|
235
246
|
await cdpSession.detach();
|
|
@@ -244,38 +255,27 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
244
255
|
return null;
|
|
245
256
|
}
|
|
246
257
|
}
|
|
247
|
-
async getDebugURLs() {
|
|
248
|
-
const url = `${this.CDP_CONNECT_URL}/json?t=${Date.now()}`; // Cache-busting
|
|
249
|
-
try {
|
|
250
|
-
const response = await fetch(url, { cache: "no-store" });
|
|
251
|
-
if (!response.ok) {
|
|
252
|
-
this.log("โ Failed to fetch debug URLs", { status: response.status });
|
|
253
|
-
throw new Error("Error while fetching debug URL");
|
|
254
|
-
}
|
|
255
|
-
return await response.json();
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
this.log("โ Exception while fetching debug URLs", { error });
|
|
259
|
-
return [];
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
258
|
async initializeListeners() {
|
|
263
259
|
this.log("๐ก Initializing listeners");
|
|
264
260
|
this.context.on("page", async (page) => {
|
|
265
261
|
const stableTabId = uuidv4();
|
|
266
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
|
|
267
264
|
const cdpTargetId = await this.getCdpTargetId(page);
|
|
268
265
|
this.pages.set(stableTabId, { page, cdpTargetId });
|
|
269
266
|
if (cdpTargetId) {
|
|
270
267
|
this.log("โ
Page mapped to CDP ID", { stableTabId, cdpTargetId });
|
|
271
268
|
}
|
|
272
269
|
else {
|
|
273
|
-
this.log("โ ๏ธ Could not find CDP ID for new page", { stableTabId });
|
|
270
|
+
this.log("โ ๏ธ Could not find CDP ID for new page yet", { stableTabId });
|
|
274
271
|
}
|
|
275
|
-
if (this.
|
|
272
|
+
if (!this._selectedPageId) {
|
|
273
|
+
// Select the first page that opens
|
|
276
274
|
this._selectedPageId = stableTabId;
|
|
275
|
+
this.log("๐ฏ Initial selected page set", { selectedPageId: this._selectedPageId });
|
|
277
276
|
}
|
|
278
277
|
await this.syncState();
|
|
278
|
+
// Add listeners
|
|
279
279
|
page.on("load", () => this.syncState());
|
|
280
280
|
page.on("framenavigated", () => this.syncState());
|
|
281
281
|
page.on("close", async () => {
|
|
@@ -315,36 +315,46 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
315
315
|
}
|
|
316
316
|
async getState() {
|
|
317
317
|
this.log("๐ Getting current state");
|
|
318
|
-
// Get the *live* list of debuggable pages
|
|
319
|
-
const debugData = await this.getDebugURLs();
|
|
320
|
-
const debugMap = new Map(debugData.map((d) => [d.id, d]));
|
|
321
318
|
const pagesData = [];
|
|
319
|
+
const pagesToDelete = []; // To clean up closed pages
|
|
322
320
|
for (const [stableTabId, pageInfo] of this.pages.entries()) {
|
|
323
321
|
try {
|
|
324
|
-
|
|
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
|
|
325
328
|
const currentCdpId = await this.getCdpTargetId(pageInfo.page);
|
|
326
329
|
if (currentCdpId && pageInfo.cdpTargetId !== currentCdpId) {
|
|
327
330
|
this.log("๐ CDP ID changed", { stableTabId, old: pageInfo.cdpTargetId, new: currentCdpId });
|
|
328
|
-
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 });
|
|
329
337
|
}
|
|
330
|
-
// Get the debug info from the live map
|
|
331
|
-
const debugInfo = currentCdpId ? debugMap.get(currentCdpId) : undefined;
|
|
332
338
|
pagesData.push({
|
|
333
339
|
id: stableTabId,
|
|
334
340
|
title: await pageInfo.page.title(),
|
|
335
341
|
url: pageInfo.page.url(),
|
|
336
|
-
wsDebuggerUrl:
|
|
342
|
+
wsDebuggerUrl: wsDebuggerUrl, // Use the constructed URL
|
|
337
343
|
});
|
|
338
344
|
}
|
|
339
345
|
catch (error) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
this.pages.delete(stableTabId); // Clean up dead page
|
|
346
|
+
this.log("โ Error getting page data", { stableTabId, error });
|
|
347
|
+
pagesToDelete.push(stableTabId); // Mark for deletion
|
|
343
348
|
}
|
|
344
349
|
}
|
|
345
|
-
|
|
350
|
+
pagesToDelete.forEach((id) => this.pages.delete(id));
|
|
346
351
|
if (this._selectedPageId && !this.pages.has(this._selectedPageId)) {
|
|
347
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 });
|
|
348
358
|
}
|
|
349
359
|
const state = {
|
|
350
360
|
pages: pagesData,
|
|
@@ -356,11 +366,10 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
356
366
|
async createTab(url = "about:blank") {
|
|
357
367
|
try {
|
|
358
368
|
this.log("๐ Creating new tab", { url });
|
|
359
|
-
const page = await this.context.newPage(); //
|
|
369
|
+
const page = await this.context.newPage(); // This will trigger the 'page' event
|
|
360
370
|
if (url !== "about:blank") {
|
|
361
371
|
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
362
372
|
}
|
|
363
|
-
// Find the stableTabId that was just created by the 'page' event
|
|
364
373
|
for (const [stableTabId, pageInfo] of this.pages.entries()) {
|
|
365
374
|
if (pageInfo.page === page) {
|
|
366
375
|
this._selectedPageId = stableTabId;
|
|
@@ -379,7 +388,7 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
379
388
|
this.log("๐๏ธ Closing tab", { stableTabId });
|
|
380
389
|
const pageInfo = this.pages.get(stableTabId);
|
|
381
390
|
if (pageInfo) {
|
|
382
|
-
await pageInfo.page.close(); //
|
|
391
|
+
await pageInfo.page.close(); // This will trigger the 'close' event
|
|
383
392
|
}
|
|
384
393
|
else {
|
|
385
394
|
this.log("โ ๏ธ Page not found for closing", { stableTabId });
|
|
@@ -409,16 +418,21 @@ export class RemoteBrowserService extends EventEmitter {
|
|
|
409
418
|
}
|
|
410
419
|
getSelectedPage() {
|
|
411
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
|
+
});
|
|
412
426
|
return pageInfo?.page || null;
|
|
413
427
|
}
|
|
414
428
|
destroy() {
|
|
415
429
|
this.log("๐ฅ Destroying RemoteBrowserService");
|
|
416
430
|
this.context.removeAllListeners("page");
|
|
417
431
|
for (const [, pageInfo] of this.pages.entries()) {
|
|
418
|
-
pageInfo.page.removeAllListeners();
|
|
432
|
+
pageInfo.page.removeAllListeners(); // Remove all listeners from each page
|
|
419
433
|
}
|
|
420
434
|
this.pages.clear();
|
|
421
435
|
this._selectedPageId = null;
|
|
422
|
-
this.removeAllListeners();
|
|
436
|
+
this.removeAllListeners(); // Remove listeners on the emitter itself
|
|
423
437
|
}
|
|
424
438
|
}
|