From 879d52041f9a2656d1e9dc3e80abe3e296c683fe Mon Sep 17 00:00:00 2001 From: Matthias Mair Date: Sun, 18 Oct 2026 22:21:52 +0200 Subject: [PATCH] Fix flaky test (#13038) * fix machine driver * fix flaky output tests --- src/frontend/tests/helpers.ts | 19 ++++++++++++++ src/frontend/tests/pages/pui_build.spec.ts | 8 +++--- .../tests/pages/pui_purchasing.spec.ts | 8 +++--- src/frontend/tests/pui_exporting.spec.ts | 22 +++++++++------- src/frontend/tests/pui_machines.spec.ts | 25 +++++++++++++------ src/frontend/tests/pui_printing.spec.ts | 12 ++++++--- 6 files changed, 69 insertions(+), 25 deletions(-) diff --git a/src/frontend/tests/helpers.ts b/src/frontend/tests/helpers.ts index 8b82527491..f6e5183eaa 100644 --- a/src/frontend/tests/helpers.ts +++ b/src/frontend/tests/helpers.ts @@ -230,3 +230,22 @@ export const openDetailAction = async ( }) .click(); }; + +export const waitForDataOutput = async ( + page: Page, + trigger: () => Promise +) => { + const closePopup = async (popup: Page) => { + await popup.close(); + await page.bringToFront(); + }; + page.on('popup', closePopup); + + try { + await page.bringToFront(); + await trigger(); + await page.getByText('Process completed successfully').first().waitFor(); + } finally { + page.off('popup', closePopup); + } +}; diff --git a/src/frontend/tests/pages/pui_build.spec.ts b/src/frontend/tests/pages/pui_build.spec.ts index fcc9e3cc33..46d568ff77 100644 --- a/src/frontend/tests/pages/pui_build.spec.ts +++ b/src/frontend/tests/pages/pui_build.spec.ts @@ -11,7 +11,8 @@ import { setTableChoiceFilter, showCalendarView, showParametricView, - showTableView + showTableView, + waitForDataOutput } from '../helpers.ts'; import { doCachedLogin } from '../login.ts'; @@ -218,8 +219,9 @@ test('Build Order - Calendar', async ({ browser }) => { // Export calendar data await page.getByLabel('calendar-export-data').click(); - await page.getByRole('button', { name: 'Export', exact: true }).click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Export', exact: true }).click() + ); // Check "part category" filter await page.getByLabel('calendar-select-filters').click(); diff --git a/src/frontend/tests/pages/pui_purchasing.spec.ts b/src/frontend/tests/pages/pui_purchasing.spec.ts index a83434f135..be277b5e8e 100644 --- a/src/frontend/tests/pages/pui_purchasing.spec.ts +++ b/src/frontend/tests/pages/pui_purchasing.spec.ts @@ -15,7 +15,8 @@ import { setTableChoiceFilter, showCalendarView, showParametricView, - showTableView + showTableView, + waitForDataOutput } from '../helpers.ts'; import { doCachedLogin } from '../login.ts'; @@ -166,8 +167,9 @@ test('Purchasing - Manufacturer Parts', async ({ browser }) => { await page .getByRole('combobox', { name: 'choice-field-export_plugin' }) .fill('CSV'); - await page.getByRole('button', { name: 'Export', exact: true }).click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Export', exact: true }).click() + ); await loadTab(page, 'Manufacturers'); await page.getByText('Murata Electronics').waitFor(); diff --git a/src/frontend/tests/pui_exporting.spec.ts b/src/frontend/tests/pui_exporting.spec.ts index f39d0b2e41..d8f58c6ee7 100644 --- a/src/frontend/tests/pui_exporting.spec.ts +++ b/src/frontend/tests/pui_exporting.spec.ts @@ -1,6 +1,6 @@ import { test } from './baseFixtures'; import { stevenuser } from './defaults'; -import { globalSearch, loadTab, navigate } from './helpers'; +import { globalSearch, loadTab, navigate, waitForDataOutput } from './helpers'; import { doCachedLogin } from './login'; // Helper function to open the export data dialog @@ -30,8 +30,9 @@ test('Exporting - Orders', async ({ browser }) => { await page.getByRole('option', { name: 'InvenTree Exporter' }).click(); // // Export the data - await page.getByRole('button', { name: 'Export', exact: true }).click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Export', exact: true }).click() + ); // Download list of purchase order items await page.getByRole('cell', { name: 'PO0014' }).click(); @@ -48,14 +49,16 @@ test('Exporting - Orders', async ({ browser }) => { await loadTab(page, 'Line Items'); await openExportDialog(page); - await page.getByRole('button', { name: 'Export', exact: true }).click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Export', exact: true }).click() + ); // Download a list of build orders await navigate(page, 'manufacturing/index/buildorders/'); await openExportDialog(page); - await page.getByRole('button', { name: 'Export', exact: true }).click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Export', exact: true }).click() + ); // Finally, navigate to the admin center and ensure the export data is available await navigate(page, 'settings/admin/export/'); @@ -118,8 +121,9 @@ test('Exporting - BOM', async ({ browser }) => { .nth(1) .click(); - await page.getByRole('button', { name: 'Export', exact: true }).click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Export', exact: true }).click() + ); // Finally, navigate to the admin center and ensure the export data is available await navigate(page, 'settings/admin/export/'); diff --git a/src/frontend/tests/pui_machines.spec.ts b/src/frontend/tests/pui_machines.spec.ts index f24da371a5..0ea47a9841 100644 --- a/src/frontend/tests/pui_machines.spec.ts +++ b/src/frontend/tests/pui_machines.spec.ts @@ -1,6 +1,7 @@ -import { test } from './baseFixtures'; +import { createApi } from './api'; +import { expect, test } from './baseFixtures'; import { adminuser } from './defaults'; -import { clickOnRowMenu, navigate } from './helpers'; +import { clickOnRowMenu, navigate, waitForDataOutput } from './helpers'; import { doCachedLogin } from './login'; import { setPluginState } from './settings'; @@ -25,10 +26,22 @@ test('Machines - Activation', async ({ browser }) => { }); // Ensure that the sample machine plugin is enabled + const api = await createApi({}); await setPluginState({ plugin: 'sample-printer-machine-plugin', state: true }); + // ensure machine driver for printer is online and active + await expect + .poll( + async () => { + const response = await api.get('machine/drivers/'); + const drivers = await response.json(); + return drivers.map((d: any) => d.slug); + }, + { timeout: 30000 } + ) + .toContain('sample-printer-driver'); await page.reload(); await page.waitForLoadState('networkidle'); @@ -121,11 +134,9 @@ test('Machines - Activation', async ({ browser }) => { .fill('dummy'); await page.getByRole('option', { name: 'my-dummy-machine' }).click(); - await page - .getByRole('button', { name: 'Print', exact: true }) - .first() - .click(); - await page.getByText('Process completed successfully').waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Print', exact: true }).first().click() + ); await navigate(page, 'settings/admin/machine/'); diff --git a/src/frontend/tests/pui_printing.spec.ts b/src/frontend/tests/pui_printing.spec.ts index cea0f9ae2b..47eb686abe 100644 --- a/src/frontend/tests/pui_printing.spec.ts +++ b/src/frontend/tests/pui_printing.spec.ts @@ -1,7 +1,12 @@ import type { Locator } from '@playwright/test'; import { expect, test } from './baseFixtures.js'; import { adminuser } from './defaults.js'; -import { activateTableView, loadTab, navigate } from './helpers.js'; +import { + activateTableView, + loadTab, + navigate, + waitForDataOutput +} from './helpers.js'; import { doCachedLogin } from './login.js'; import { setPluginState } from './settings.js'; @@ -128,8 +133,9 @@ test('Printing - Report Printing', async ({ browser }) => { // Template should auto-fill (there is only one template available) await page.getByText('Sample purchase order report').waitFor(); await page.getByRole('button', { name: 'Print', exact: true }).isEnabled(); - await page.getByRole('button', { name: 'Print', exact: true }).click(); - await page.getByText('Process completed successfully').first().waitFor(); + await waitForDataOutput(page, () => + page.getByRole('button', { name: 'Print', exact: true }).click() + ); await page.context().close(); });