diff --git a/packages/testing/playwright/pages/components/NotificationsPage.ts b/packages/testing/playwright/pages/components/NotificationsPage.ts index 09481eba4c7..0217fb216e1 100644 --- a/packages/testing/playwright/pages/components/NotificationsPage.ts +++ b/packages/testing/playwright/pages/components/NotificationsPage.ts @@ -54,63 +54,50 @@ export class NotificationsPage { /** * Clicks the close button on the FIRST notification matching the text. - * Fast execution with short timeouts for snappy notifications. + * Throws if the notification is still on screen afterwards - a toast left + * open covers the top-right of the app and intercepts later clicks. * @param text The text of the notification to close. * @param options Optional configuration */ async closeNotificationByText( text: string | RegExp, options: { timeout?: number } = {}, - ): Promise { + ): Promise { const { timeout = 2000 } = options; + const notification = this.getNotificationByTitle(text).first(); try { - const notification = this.getNotificationByTitle(text).first(); - await notification.waitFor({ state: 'visible', timeout }); - - const closeBtn = notification.locator('.el-notification__closeBtn'); - await closeBtn.click({ timeout: 500 }); - - // Quick check that it's gone - don't wait long - await notification.waitFor({ state: 'hidden', timeout: 1000 }); - return true; - } catch (error) { - return false; + await notification.locator('.el-notification__closeBtn').click({ timeout }); + } catch { + // It may have auto-dismissed; the hidden check below is the real contract. } + + await notification.waitFor({ state: 'hidden', timeout }); } /** - * Wait for a notification to appear with specific text. - * Reasonable timeout for waiting, but still faster than before. + * Wait for a notification to appear with specific text. Throws if it never shows - + * callers use this as a synchronisation point, so a silent miss lets the test run + * on against unfinished state and fail later with a misleading error. * @param text The text to search for in notification title. * @param options Optional configuration */ async waitForNotification( text: string | RegExp, options: { timeout?: number } = {}, - ): Promise { + ): Promise { const { timeout = 5000 } = options; - - try { - const notification = this.getNotificationByTitle(text).first(); - await notification.waitFor({ state: 'visible', timeout }); - return true; - } catch { - return false; - } + await this.getNotificationByTitle(text).first().waitFor({ state: 'visible', timeout }); } // Wait for notification and then close it async waitForNotificationAndClose( text: string | RegExp, options: { timeout?: number } = {}, - ): Promise { + ): Promise { const { timeout = 3000 } = options; - const isVisible = await this.waitForNotification(text, { timeout }); - if (!isVisible) { - return false; - } - return await this.closeNotificationByText(text, { timeout }); + await this.waitForNotification(text, { timeout }); + await this.closeNotificationByText(text, { timeout }); } /** diff --git a/packages/testing/playwright/tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts b/packages/testing/playwright/tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts index aa083d3ae4e..50b746f2564 100644 --- a/packages/testing/playwright/tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts +++ b/packages/testing/playwright/tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts @@ -19,7 +19,7 @@ test.describe( }) => { await setupRequirements(requirements); await n8n.workflowComposer.executeWorkflowAndWaitForNotification( - 'Workflow successfully executed', + 'Workflow executed successfully', ); await n8n.canvas.openNode('Discourse1'); diff --git a/packages/testing/playwright/tests/e2e/workflows/editor/expressions/modal.spec.ts b/packages/testing/playwright/tests/e2e/workflows/editor/expressions/modal.spec.ts index 2fcd8e0aca5..ec93db73aca 100644 --- a/packages/testing/playwright/tests/e2e/workflows/editor/expressions/modal.spec.ts +++ b/packages/testing/playwright/tests/e2e/workflows/editor/expressions/modal.spec.ts @@ -23,8 +23,10 @@ test.describe( await n8n.ndv.fillExpressionEditorModalInput('{{ "hello"'); await expect(n8n.ndv.getExpressionEditorModalOutput()).toContainText('hello'); + // There is no save toast any more, so assert on the save request itself + const saved = n8n.canvas.waitForSaveWorkflowCompleted(); await input.press('ControlOrMeta+s'); - await n8n.notifications.waitForNotificationAndClose('Saved successfully'); + await saved; }); });