From 66207bddcae8a52b904c4d0a4e275d34a7ad775f Mon Sep 17 00:00:00 2001 From: lironsh Date: Thu, 26 Jun 2025 09:26:31 +0300 Subject: [PATCH 1/6] recreate the problem --- packages/drivers/puppeteer/examples/example.test.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/drivers/puppeteer/examples/example.test.ts b/packages/drivers/puppeteer/examples/example.test.ts index bcd310d2..0e42f900 100644 --- a/packages/drivers/puppeteer/examples/example.test.ts +++ b/packages/drivers/puppeteer/examples/example.test.ts @@ -113,7 +113,7 @@ describe("Example Test Suite", () => { }), ); - it.only("filter by color", async () => { + it.skip("filter by color", async () => { await pilot.perform( "Open https://www.yohaiknaani.com", "Go to `Shop All` page.", @@ -138,4 +138,12 @@ describe("Example Test Suite", () => { "Tap on the `Submit` button", ); }); + + it.only("open new tab", async () => { + await pilot.perform( + "Open https://www.bgu.ac.il/", + "Click `לפורטל האישי`", + "Type `lironmir` in the username input" + ); + }); }); From b37d333e803e2b576b35ca1647fb617f35656b18 Mon Sep 17 00:00:00 2001 From: lironsh Date: Sun, 29 Jun 2025 17:47:50 +0300 Subject: [PATCH 2/6] chore: first working version of both playwright and puppeteer using their frameworkCatalog --- .../step-performer/StepPerformer.ts | 2 ++ packages/drivers/basewebdriver/index.ts | 10 +++++---- .../playwright/examples/example.test.ts | 14 ++++++++++++- .../drivers/playwright/frameworkCatalog.ts | 9 +++++++- .../playwright/test-results/.last-run.json | 6 ++++++ .../puppeteer/examples/example.test.ts | 18 +++++++++------- .../drivers/puppeteer/frameworkCatalog.ts | 21 ++++++++++++++++++- 7 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 packages/drivers/playwright/test-results/.last-run.json diff --git a/packages/core/src/performers/step-performer/StepPerformer.ts b/packages/core/src/performers/step-performer/StepPerformer.ts index 0b2cbe66..aae26fa1 100644 --- a/packages/core/src/performers/step-performer/StepPerformer.ts +++ b/packages/core/src/performers/step-performer/StepPerformer.ts @@ -73,6 +73,8 @@ export class StepPerformer { const screenCapture = await screenshotHandler(); + screenCapture.viewHierarchy ? logger.warn("VIEW HIERARCHY", screenCapture.viewHierarchy) : logger.warn("VIEW HIERARCHY NULL") + // No cache match found, generate new code const prompt = this.promptCreator.createPrompt( currentStep, diff --git a/packages/drivers/basewebdriver/index.ts b/packages/drivers/basewebdriver/index.ts index 7925bd5f..548942d8 100644 --- a/packages/drivers/basewebdriver/index.ts +++ b/packages/drivers/basewebdriver/index.ts @@ -1,9 +1,10 @@ import WebTestingFrameworkDriverHelper from "@wix-pilot/web-utils"; import type { ElementMatchingCriteria, Page } from "@wix-pilot/web-utils"; -import type { - TestingFrameworkAPICatalog, - TestingFrameworkDriver, - TestingFrameworkDriverConfig, +import { + logger, + TestingFrameworkAPICatalog, + TestingFrameworkDriver, + TestingFrameworkDriverConfig, } from "@wix-pilot/core"; import { baseDriverCategories } from "./baseDriverCategories"; import extendAPICategories from "./extendAPICategories"; @@ -29,6 +30,7 @@ export class BaseWebDriver implements TestingFrameworkDriver { * Sets the current page identifier, must be set if the driver needs to interact with a specific page */ setCurrentPage(page: T): void { + logger.error("SET CURRENT PAGE") this.driverUtils.setCurrentPage(page); } diff --git a/packages/drivers/playwright/examples/example.test.ts b/packages/drivers/playwright/examples/example.test.ts index 30bfaeaf..db2e3b54 100644 --- a/packages/drivers/playwright/examples/example.test.ts +++ b/packages/drivers/playwright/examples/example.test.ts @@ -34,9 +34,21 @@ describe("Example Test Suite", () => { pilot.end(); }); - it("perform test with pilot", async () => { + it.skip("perform test with pilot", async () => { await pilot.autopilot( "Open https://github.com/wix-incubator/pilot and tell me what was the last commit about and who have created it", ); }); + + it.skip("open new tab", async () => { + await pilot.perform( + "Open https://wix.github.io/Detox/", + "Tap `#StandWithUkraine` link", + "Tap `Donate to the military`" + ); + }); + + it.only("open new tab", async () => { + await pilot.autopilot("Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`") + }) }); diff --git a/packages/drivers/playwright/frameworkCatalog.ts b/packages/drivers/playwright/frameworkCatalog.ts index bc7d1c96..8265b6ab 100644 --- a/packages/drivers/playwright/frameworkCatalog.ts +++ b/packages/drivers/playwright/frameworkCatalog.ts @@ -26,10 +26,17 @@ export const createAPICatalog: TestingFrameworkAPICatalog = { timeout: 30000 // Default timeout for all operations }); const context = await browser.newContext(); + //IMPORTANT! + context.on('page', async page => { + await page.waitForLoadState(); + await page.bringToFront(); + setCurrentPage(page); +}); const page = await context.newPage(); setCurrentPage(page); await page.goto('https://www.test.com/'); - await page.waitForLoadState('load');`, + await page.waitForLoadState('load'); + `, guidelines: [ "Set longer timeouts (30s or more) to handle slow operations.", "Can use chromium, firefox, or webkit browsers.", diff --git a/packages/drivers/playwright/test-results/.last-run.json b/packages/drivers/playwright/test-results/.last-run.json new file mode 100644 index 00000000..d45b5ee7 --- /dev/null +++ b/packages/drivers/playwright/test-results/.last-run.json @@ -0,0 +1,6 @@ +{ + "status": "failed", + "failedTests": [ + "85533e7544b493bab02b-947de5f59fb64680a145" + ] +} \ No newline at end of file diff --git a/packages/drivers/puppeteer/examples/example.test.ts b/packages/drivers/puppeteer/examples/example.test.ts index 0e42f900..3f9d4def 100644 --- a/packages/drivers/puppeteer/examples/example.test.ts +++ b/packages/drivers/puppeteer/examples/example.test.ts @@ -139,11 +139,15 @@ describe("Example Test Suite", () => { ); }); - it.only("open new tab", async () => { - await pilot.perform( - "Open https://www.bgu.ac.il/", - "Click `לפורטל האישי`", - "Type `lironmir` in the username input" - ); - }); + it.skip("open new tab", async () => { + await pilot.perform( + "Open https://wix.github.io/Detox/", + "Tap `#StandWithUkraine` link", + "Tap `Donate to the military`" + ); + }); + + it.only("open new tab", async () => { + await pilot.autopilot("Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`") + }) }); diff --git a/packages/drivers/puppeteer/frameworkCatalog.ts b/packages/drivers/puppeteer/frameworkCatalog.ts index 206c75f7..e4133fbc 100644 --- a/packages/drivers/puppeteer/frameworkCatalog.ts +++ b/packages/drivers/puppeteer/frameworkCatalog.ts @@ -17,7 +17,26 @@ export const createAPICatalog = ( { signature: "const browser = await puppeteer.launch([options])", description: "Launches a new browser instance.", - example: `const browser = await puppeteer.launch({ headless: false, executablePath: "${executablePath}" });`, + example: `const browser = await puppeteer.launch({ headless: false, executablePath: "${executablePath}", + defaultViewport: null, + args: ['--start-maximized'] +}); + +// IMPORTANT! +browser.on('targetcreated', async target => { + if (target.type() === 'page') { + const page = await target.page(); + await page.bringToFront(); // Only works for non-headless + await page.waitForNavigation({ waitUntil: 'load' }).catch(() => {}); + setCurrentPage(page); + } +}); + +const [page] = await browser.pages(); +await page.bringToFront(); +setCurrentPage(page); +await page.goto('https://www.test.com/'); +await page.waitForNavigation({ waitUntil: 'load' });`, guidelines: [ `Executable path is required always, use the path: ${executablePath}`, "Options can specify `headless`, `slowMo`, `args`, etc.", From a83c2fea2cc4800654cc85aea2465f5e02971974 Mon Sep 17 00:00:00 2001 From: lironsh Date: Mon, 30 Jun 2025 15:48:13 +0300 Subject: [PATCH 3/6] wip: playwright working, problem with puppeteer. --- packages/drivers/basewebdriver/index.ts | 1 - packages/drivers/playwright/examples/example.test.ts | 4 ++-- packages/drivers/puppeteer/examples/example.test.ts | 5 ++--- packages/drivers/puppeteer/frameworkCatalog.ts | 7 ++----- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/drivers/basewebdriver/index.ts b/packages/drivers/basewebdriver/index.ts index 548942d8..7dd9b970 100644 --- a/packages/drivers/basewebdriver/index.ts +++ b/packages/drivers/basewebdriver/index.ts @@ -30,7 +30,6 @@ export class BaseWebDriver implements TestingFrameworkDriver { * Sets the current page identifier, must be set if the driver needs to interact with a specific page */ setCurrentPage(page: T): void { - logger.error("SET CURRENT PAGE") this.driverUtils.setCurrentPage(page); } diff --git a/packages/drivers/playwright/examples/example.test.ts b/packages/drivers/playwright/examples/example.test.ts index db2e3b54..a0f42928 100644 --- a/packages/drivers/playwright/examples/example.test.ts +++ b/packages/drivers/playwright/examples/example.test.ts @@ -40,7 +40,7 @@ describe("Example Test Suite", () => { ); }); - it.skip("open new tab", async () => { + it("open new tab", async () => { await pilot.perform( "Open https://wix.github.io/Detox/", "Tap `#StandWithUkraine` link", @@ -48,7 +48,7 @@ describe("Example Test Suite", () => { ); }); - it.only("open new tab", async () => { + it("open new tab", async () => { await pilot.autopilot("Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`") }) }); diff --git a/packages/drivers/puppeteer/examples/example.test.ts b/packages/drivers/puppeteer/examples/example.test.ts index 3f9d4def..7c1d23e4 100644 --- a/packages/drivers/puppeteer/examples/example.test.ts +++ b/packages/drivers/puppeteer/examples/example.test.ts @@ -139,15 +139,14 @@ describe("Example Test Suite", () => { ); }); - it.skip("open new tab", async () => { + it.only("open new tab", async () => { await pilot.perform( "Open https://wix.github.io/Detox/", "Tap `#StandWithUkraine` link", - "Tap `Donate to the military`" ); }); - it.only("open new tab", async () => { + it.skip("open new tab", async () => { await pilot.autopilot("Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`") }) }); diff --git a/packages/drivers/puppeteer/frameworkCatalog.ts b/packages/drivers/puppeteer/frameworkCatalog.ts index e4133fbc..369f1977 100644 --- a/packages/drivers/puppeteer/frameworkCatalog.ts +++ b/packages/drivers/puppeteer/frameworkCatalog.ts @@ -17,16 +17,13 @@ export const createAPICatalog = ( { signature: "const browser = await puppeteer.launch([options])", description: "Launches a new browser instance.", - example: `const browser = await puppeteer.launch({ headless: false, executablePath: "${executablePath}", - defaultViewport: null, - args: ['--start-maximized'] -}); + example: `const browser = await puppeteer.launch({ headless: false, executablePath: "${executablePath}"}); // IMPORTANT! browser.on('targetcreated', async target => { if (target.type() === 'page') { const page = await target.page(); - await page.bringToFront(); // Only works for non-headless + await page.bringToFront(); await page.waitForNavigation({ waitUntil: 'load' }).catch(() => {}); setCurrentPage(page); } From 32d81afe6fb2f28e8d11ce0e027ded57c541b76a Mon Sep 17 00:00:00 2001 From: lironsh Date: Wed, 2 Jul 2025 11:54:00 +0300 Subject: [PATCH 4/6] puppeteer prevent timeout --- packages/drivers/puppeteer/frameworkCatalog.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/drivers/puppeteer/frameworkCatalog.ts b/packages/drivers/puppeteer/frameworkCatalog.ts index 369f1977..9f20e747 100644 --- a/packages/drivers/puppeteer/frameworkCatalog.ts +++ b/packages/drivers/puppeteer/frameworkCatalog.ts @@ -32,8 +32,7 @@ browser.on('targetcreated', async target => { const [page] = await browser.pages(); await page.bringToFront(); setCurrentPage(page); -await page.goto('https://www.test.com/'); -await page.waitForNavigation({ waitUntil: 'load' });`, +await page.goto('https://www.test.com/', {waitUntil: 'load' });`, guidelines: [ `Executable path is required always, use the path: ${executablePath}`, "Options can specify `headless`, `slowMo`, `args`, etc.", From e235e4b8f0a0c61c3a5265feec200ad55c4a2556 Mon Sep 17 00:00:00 2001 From: lironsh Date: Thu, 3 Jul 2025 15:03:01 +0300 Subject: [PATCH 5/6] fix: add a timeout for playwright working in the first attempt --- packages/drivers/web-utils/src/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/drivers/web-utils/src/index.ts b/packages/drivers/web-utils/src/index.ts index 3afa8d7a..6ba06365 100644 --- a/packages/drivers/web-utils/src/index.ts +++ b/packages/drivers/web-utils/src/index.ts @@ -156,6 +156,9 @@ export default class WebTestingFrameworkDriverHelper { "START A NEW ONE BASED ON THE ACTION NEED OR RAISE AN ERROR" ); } + + await new Promise((resolve) => setTimeout(resolve, 700)); + await this.waitForStableDOM(this.currentPage); await this.markImportantElements(this.currentPage); return await this.createMarkedViewHierarchy(this.currentPage); From 819b82e7cb9a28b4b71d10bed0b3900be3c16cec Mon Sep 17 00:00:00 2001 From: lironsh Date: Thu, 3 Jul 2025 15:25:13 +0300 Subject: [PATCH 6/6] working version puppeteer and playwright --- .../step-performer/StepPerformer.ts | 2 -- packages/drivers/basewebdriver/index.ts | 7 +++--- .../playwright/examples/example.test.ts | 22 ++++++++++--------- .../drivers/playwright/frameworkCatalog.ts | 2 +- .../puppeteer/examples/example.test.ts | 21 ++++++++++-------- .../drivers/puppeteer/frameworkCatalog.ts | 15 +++++++++---- 6 files changed, 39 insertions(+), 30 deletions(-) diff --git a/packages/core/src/performers/step-performer/StepPerformer.ts b/packages/core/src/performers/step-performer/StepPerformer.ts index aae26fa1..0b2cbe66 100644 --- a/packages/core/src/performers/step-performer/StepPerformer.ts +++ b/packages/core/src/performers/step-performer/StepPerformer.ts @@ -73,8 +73,6 @@ export class StepPerformer { const screenCapture = await screenshotHandler(); - screenCapture.viewHierarchy ? logger.warn("VIEW HIERARCHY", screenCapture.viewHierarchy) : logger.warn("VIEW HIERARCHY NULL") - // No cache match found, generate new code const prompt = this.promptCreator.createPrompt( currentStep, diff --git a/packages/drivers/basewebdriver/index.ts b/packages/drivers/basewebdriver/index.ts index 7dd9b970..2c45b3ad 100644 --- a/packages/drivers/basewebdriver/index.ts +++ b/packages/drivers/basewebdriver/index.ts @@ -1,10 +1,9 @@ import WebTestingFrameworkDriverHelper from "@wix-pilot/web-utils"; import type { ElementMatchingCriteria, Page } from "@wix-pilot/web-utils"; import { - logger, - TestingFrameworkAPICatalog, - TestingFrameworkDriver, - TestingFrameworkDriverConfig, + TestingFrameworkAPICatalog, + TestingFrameworkDriver, + TestingFrameworkDriverConfig, } from "@wix-pilot/core"; import { baseDriverCategories } from "./baseDriverCategories"; import extendAPICategories from "./extendAPICategories"; diff --git a/packages/drivers/playwright/examples/example.test.ts b/packages/drivers/playwright/examples/example.test.ts index a0f42928..216f6ac2 100644 --- a/packages/drivers/playwright/examples/example.test.ts +++ b/packages/drivers/playwright/examples/example.test.ts @@ -40,15 +40,17 @@ describe("Example Test Suite", () => { ); }); - it("open new tab", async () => { - await pilot.perform( - "Open https://wix.github.io/Detox/", - "Tap `#StandWithUkraine` link", - "Tap `Donate to the military`" - ); - }); + it.skip("open new tab", async () => { + await pilot.perform( + "Open https://wix.github.io/Detox/", + "Tap `#StandWithUkraine` link", + "Tap `Donate to the military`", + ); + }); - it("open new tab", async () => { - await pilot.autopilot("Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`") - }) + it.only("open new tab", async () => { + await pilot.autopilot( + "Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`", + ); + }); }); diff --git a/packages/drivers/playwright/frameworkCatalog.ts b/packages/drivers/playwright/frameworkCatalog.ts index 8265b6ab..bf96e9ed 100644 --- a/packages/drivers/playwright/frameworkCatalog.ts +++ b/packages/drivers/playwright/frameworkCatalog.ts @@ -27,7 +27,7 @@ export const createAPICatalog: TestingFrameworkAPICatalog = { }); const context = await browser.newContext(); //IMPORTANT! - context.on('page', async page => { + context.on('page', async page => { await page.waitForLoadState(); await page.bringToFront(); setCurrentPage(page); diff --git a/packages/drivers/puppeteer/examples/example.test.ts b/packages/drivers/puppeteer/examples/example.test.ts index 7c1d23e4..a253c776 100644 --- a/packages/drivers/puppeteer/examples/example.test.ts +++ b/packages/drivers/puppeteer/examples/example.test.ts @@ -139,14 +139,17 @@ describe("Example Test Suite", () => { ); }); - it.only("open new tab", async () => { - await pilot.perform( - "Open https://wix.github.io/Detox/", - "Tap `#StandWithUkraine` link", - ); - }); + it.only("open new tab", async () => { + await pilot.perform( + "Open https://wix.github.io/Detox/", + "Tap `#StandWithUkraine` link", + "Tap `Donate to the military`", + ); + }); - it.skip("open new tab", async () => { - await pilot.autopilot("Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`") - }) + it.skip("open new tab", async () => { + await pilot.autopilot( + "Open https://wix.github.io/Detox/ tap `#StandWithUkraine` link. Tap `Donate to the military`", + ); + }); }); diff --git a/packages/drivers/puppeteer/frameworkCatalog.ts b/packages/drivers/puppeteer/frameworkCatalog.ts index 9f20e747..daedff5c 100644 --- a/packages/drivers/puppeteer/frameworkCatalog.ts +++ b/packages/drivers/puppeteer/frameworkCatalog.ts @@ -1,6 +1,8 @@ import { TestingFrameworkAPICatalog } from "@wix-pilot/core"; import * as puppeteer from "puppeteer-core"; +const waitForNewTab = () => new Promise((resolve) => setTimeout(resolve, 2000)); + export const createAPICatalog = ( executablePath: string, ): TestingFrameworkAPICatalog => ({ @@ -9,6 +11,7 @@ export const createAPICatalog = ( "Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol.\nYou can assume that puppeteer is already imported (as `puppeteer`).", context: { puppeteer, + waitForNewTab, }, categories: [ { @@ -23,21 +26,25 @@ export const createAPICatalog = ( browser.on('targetcreated', async target => { if (target.type() === 'page') { const page = await target.page(); - await page.bringToFront(); - await page.waitForNavigation({ waitUntil: 'load' }).catch(() => {}); - setCurrentPage(page); + if (page) { + await page.waitForFunction(() => document.readyState === 'complete', {timeout: 5000}).catch(() => {}); + await page.bringToFront(); + setCurrentPage(page); + } } }); const [page] = await browser.pages(); await page.bringToFront(); setCurrentPage(page); -await page.goto('https://www.test.com/', {waitUntil: 'load' });`, +await page.goto('https://www.test.com/', {waitUntil: 'load' }); +await this.waitForStableDOM(page);`, guidelines: [ `Executable path is required always, use the path: ${executablePath}`, "Options can specify `headless`, `slowMo`, `args`, etc.", "Prefer passing `headless: false` to `puppeteer.launch()` unless headless mode is explicitly required.", "Use a large viewport size (e.g. `viewport: { width: 1920, height: 1080 }`) to avoid responsive design issues (for example, use `defaultViewport: null` and `args: ['--start-maximized']`).", + "After clicking any link that opens in a new tab (target='_blank'), always call `await waitForNewTab()` and NOT `await page.waitForNavigation()` to ensure the new tab becomes active before proceeding.", ], }, {