From 7ecb6aaefd3fd5d8915af7a7f18c7377c7d9b1d3 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Mon, 26 Oct 2026 12:53:36 +0100 Subject: [PATCH] fix(ui): match the "Save and launch scan" footer in the provider E2E flows (#13133) --- .github/workflows/ui-e2e-tests-v2.yml | 9 ++++ .github/workflows/ui-tests.yml | 3 ++ ui/tests/providers/providers-page.ts | 62 +++++++++++---------------- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ui-e2e-tests-v2.yml b/.github/workflows/ui-e2e-tests-v2.yml index c2df788f5b..bb48215b74 100644 --- a/.github/workflows/ui-e2e-tests-v2.yml +++ b/.github/workflows/ui-e2e-tests-v2.yml @@ -39,6 +39,9 @@ jobs: github.repository == 'prowler-cloud/prowler' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork == false) && (needs.impact-analysis.outputs.has-ui-e2e == 'true' || needs.impact-analysis.outputs.run-all == 'true') + # ubuntu-latest is moving to 26.04 (rollout began October 19, 2026; completion + # targeted for November 19, 2026), where `playwright install` refuses to install + # Chromium for the pinned Playwright. Stay on 24.04 until the suite upgrades. runs-on: ubuntu-24.04 env: AUTH_SECRET: "fallback-ci-secret-for-testing" @@ -391,6 +394,12 @@ jobs: working-directory: ./ui run: pnpm run test:e2e:registry + # A worker that crashes on import or a connection test that never resolves + # only shows up here; Playwright just reports a missing footer button. + - name: Dump API service logs + if: failure() + run: docker compose logs --no-color --tail=300 api worker worker-beat || true + - name: Upload test reports uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: failure() diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 0e63ff6922..c4d9c91368 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -21,6 +21,9 @@ permissions: {} jobs: ui-tests: + # ubuntu-latest is moving to 26.04 (rollout began October 19, 2026; completion + # targeted for November 19, 2026), where `playwright install` refuses to install + # Chromium for the pinned Playwright. Stay on 24.04 until the suite upgrades. runs-on: ubuntu-24.04 timeout-minutes: 20 permissions: diff --git a/ui/tests/providers/providers-page.ts b/ui/tests/providers/providers-page.ts index cb245862dc..042726fe5c 100644 --- a/ui/tests/providers/providers-page.ts +++ b/ui/tests/providers/providers-page.ts @@ -267,6 +267,11 @@ export interface VercelProviderCredential { apiToken: string; } +// The wizard's final action. Setup pre-ticks "launch an initial scan", so the +// schedule step reads "Save and launch scan" ("Save" once unticked); manual-only +// accounts get "Launch scan" instead. Anchored so "Save" never matches a longer label. +const LAUNCH_STEP_ACTION_NAME = /^(Save|Save and launch scan|Launch scan)$/; + // Providers page export class ProvidersPage extends BasePage { readonly wizardModal: Locator; @@ -934,6 +939,10 @@ export class ProvidersPage extends BasePage { } } + private get launchStepAction(): Locator { + return this.page.getByRole("button", { name: LAUNCH_STEP_ACTION_NAME }); + } + async clickNext(): Promise { await this.verifyWizardModalOpen(); @@ -943,6 +952,7 @@ export class ProvidersPage extends BasePage { "Connect account", "Next", "Save", + "Save and launch scan", "Check connection", "Launch scan", ] as const; @@ -957,9 +967,8 @@ export class ProvidersPage extends BasePage { if (actionName === "Check connection") { await this.handleCheckConnectionCompletion(); } - // "Save" is the wizard's final action (saves the scan schedule) and - // "Launch scan" its legacy/manual counterpart; both close the modal. - if (actionName === "Launch scan" || actionName === "Save") { + // The launch step's action (see LAUNCH_STEP_ACTION_NAME) closes the modal. + if (LAUNCH_STEP_ACTION_NAME.test(actionName)) { await this.handleLaunchScanCompletion(); } return; @@ -972,24 +981,16 @@ export class ProvidersPage extends BasePage { } private async handleCheckConnectionCompletion(): Promise { - // A successful connection advances to the schedule step ("Save"); older - // flows surfaced a "Launch scan" action instead. - const saveScheduleButton = this.page.getByRole("button", { - name: "Save", - exact: true, - }); - const launchScanButton = this.page.getByRole("button", { - name: "Launch scan", - exact: true, - }); + // A successful connection advances to the launch step; update flows may + // close the modal instead. + const launchAction = this.launchStepAction; const connectionError = this.page.locator( "div.border-border-error p.text-text-error-primary", ); try { await Promise.race([ - saveScheduleButton.waitFor({ state: "visible", timeout: 30000 }), - launchScanButton.waitFor({ state: "visible", timeout: 30000 }), + launchAction.waitFor({ state: "visible", timeout: 30000 }), this.wizardModal.waitFor({ state: "hidden", timeout: 30000 }), connectionError.waitFor({ state: "visible", timeout: 30000 }), ]); @@ -1004,19 +1005,14 @@ export class ProvidersPage extends BasePage { ); } - if (await saveScheduleButton.isVisible().catch(() => false)) { - await saveScheduleButton.click(); - await this.handleLaunchScanCompletion(); - } else if (await launchScanButton.isVisible().catch(() => false)) { - await launchScanButton.click(); + if (await launchAction.isVisible().catch(() => false)) { + await launchAction.click(); await this.handleLaunchScanCompletion(); } } private async waitForProviderLaunchChoice(): Promise { - const launchAction = this.page - .getByRole("button", { name: "Save", exact: true }) - .or(this.page.getByRole("button", { name: "Launch scan", exact: true })); + const launchAction = this.launchStepAction; const connectionError = this.page.locator( "div.border-border-error p.text-text-error-primary", ); @@ -1049,9 +1045,7 @@ export class ProvidersPage extends BasePage { name: "Check connection", exact: true, }); - const launchAction = this.page - .getByRole("button", { name: "Save", exact: true }) - .or(this.page.getByRole("button", { name: "Launch scan", exact: true })); + const launchAction = this.launchStepAction; const connectionError = this.page.locator( "div.border-border-error p.text-text-error-primary", ); @@ -1664,17 +1658,11 @@ export class ProvidersPage extends BasePage { await this.verifyPageHasProwlerTitle(); await this.verifyWizardModalOpen(); - // The final step saves the scan schedule ("Save"); manual-only accounts - // show "Launch scan" and some providers show "Check connection" first. - const launchAction = this.page - .getByRole("button", { name: "Save", exact: true }) - .or(this.page.getByRole("button", { name: "Launch scan", exact: true })) - .or( - this.page.getByRole("button", { - name: "Check connection", - exact: true, - }), - ); + // The launch step's action, or "Check connection" for providers that + // still have to test the connection first. + const launchAction = this.launchStepAction.or( + this.page.getByRole("button", { name: "Check connection", exact: true }), + ); await expect(launchAction).toBeVisible(); }