From 95a55e780501746cc1503eb2e6b31e6807113019 Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 27 Jun 2025 16:50:10 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=85(e2e)=20reduce=20flakiness=20in=20e2e?= =?UTF-8?q?=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flakiness in e2e tests has been reduced by: - Adding waits for media-check processing in image tests. - Ensuring that slash menu resets are handled correctly to avoid flakiness. - Wait for the Download button to be stable before clicking --- .../e2e/__tests__/app-impress/config.spec.ts | 4 + .../__tests__/app-impress/doc-editor.spec.ts | 16 +++- .../__tests__/app-impress/doc-export.spec.ts | 87 ++++++++++++------- .../__tests__/app-impress/doc-version.spec.ts | 6 +- .../__tests__/app-impress/language.spec.ts | 13 +-- 5 files changed, 79 insertions(+), 47 deletions(-) diff --git a/src/frontend/apps/e2e/__tests__/app-impress/config.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/config.spec.ts index 8e2ff06b..52889171 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/config.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/config.spec.ts @@ -47,6 +47,10 @@ test.describe('Config', () => { await expect(image).toBeVisible(); + // Wait for the media-check to be processed + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(1000); + // Check src of image expect(await image.getAttribute('src')).toMatch( /http:\/\/localhost:8083\/media\/.*\/attachments\/.*.png/, diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts index 06b2d54b..f64139b7 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-editor.spec.ts @@ -275,6 +275,10 @@ test.describe('Doc Editor', () => { await expect(image).toBeVisible(); + // Wait for the media-check to be processed + // eslint-disable-next-line playwright/no-wait-for-timeout + await page.waitForTimeout(1000); + // Check src of image expect(await image.getAttribute('src')).toMatch( /http:\/\/localhost:8083\/media\/.*\/attachments\/.*.png/, @@ -452,7 +456,17 @@ test.describe('Doc Editor', () => { page.getByText('This file is flagged as unsafe.'), ).toBeVisible(); - await page.getByRole('button', { name: 'Download' }).click(); + await expect( + page.getByRole('button', { + name: 'Download', + }), + ).toBeVisible(); + + void page + .getByRole('button', { + name: 'Download', + }) + .click(); const download = await downloadPromise; expect(download.suggestedFilename()).toContain(`-unsafe.html`); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts index f523d3ea..cefa76ee 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-export.spec.ts @@ -52,10 +52,6 @@ test.describe('Doc Export', () => { 1, ); - const downloadPromise = page.waitForEvent('download', (download) => { - return download.suggestedFilename().includes(`${randomDoc}.pdf`); - }); - await verifyDocName(page, randomDoc); const editor = page.locator('.ProseMirror.bn-editor'); @@ -79,6 +75,10 @@ test.describe('Doc Export', () => { }) .click(); + const downloadPromise = page.waitForEvent('download', (download) => { + return download.suggestedFilename().includes(`${randomDoc}.pdf`); + }); + void page .getByRole('button', { name: 'Download', @@ -98,11 +98,6 @@ test.describe('Doc Export', () => { test('it exports the doc to docx', async ({ page, browserName }) => { const [randomDoc] = await createDoc(page, 'doc-editor', browserName, 1); - const fileChooserPromise = page.waitForEvent('filechooser'); - const downloadPromise = page.waitForEvent('download', (download) => { - return download.suggestedFilename().includes(`${randomDoc}.docx`); - }); - await verifyDocName(page, randomDoc); await page.locator('.ProseMirror.bn-editor').click(); @@ -111,6 +106,8 @@ test.describe('Doc Export', () => { await page.keyboard.press('Enter'); await page.locator('.bn-block-outer').last().fill('/'); await page.getByText('Resizable image with caption').click(); + + const fileChooserPromise = page.waitForEvent('filechooser'); await page.getByText('Upload image').click(); const fileChooser = await fileChooserPromise; @@ -129,6 +126,16 @@ test.describe('Doc Export', () => { await page.getByRole('combobox', { name: 'Format' }).click(); await page.getByRole('option', { name: 'Docx' }).click(); + await expect( + page.getByRole('button', { + name: 'Download', + }), + ).toBeVisible(); + + const downloadPromise = page.waitForEvent('download', (download) => { + return download.suggestedFilename().includes(`${randomDoc}.docx`); + }); + void page .getByRole('button', { name: 'Download', @@ -149,16 +156,6 @@ test.describe('Doc Export', () => { test('it exports the docs with images', async ({ page, browserName }) => { const [randomDoc] = await createDoc(page, 'doc-editor', browserName, 1); - const responseCorsPromise = page.waitForResponse( - (response) => - response.url().includes('/cors-proxy/') && response.status() === 200, - ); - - const fileChooserPromise = page.waitForEvent('filechooser'); - const downloadPromise = page.waitForEvent('download', (download) => { - return download.suggestedFilename().includes(`${randomDoc}.pdf`); - }); - await verifyDocName(page, randomDoc); await page.locator('.ProseMirror.bn-editor').click(); @@ -167,8 +164,9 @@ test.describe('Doc Export', () => { await page.keyboard.press('Enter'); await page.locator('.bn-block-outer').last().fill('/'); await page.getByText('Resizable image with caption').click(); - await page.getByText('Upload image').click(); + const fileChooserPromise = page.waitForEvent('filechooser'); + await page.getByText('Upload image').click(); const fileChooser = await fileChooserPromise; await fileChooser.setFiles(path.join(__dirname, 'assets/test.svg')); @@ -206,6 +204,21 @@ test.describe('Doc Export', () => { await new Promise((resolve) => setTimeout(resolve, 1000)); + await expect( + page.getByRole('button', { + name: 'Download', + }), + ).toBeVisible(); + + const responseCorsPromise = page.waitForResponse( + (response) => + response.url().includes('/cors-proxy/') && response.status() === 200, + ); + + const downloadPromise = page.waitForEvent('download', (download) => { + return download.suggestedFilename().includes(`${randomDoc}.pdf`); + }); + void page .getByRole('button', { name: 'Download', @@ -227,11 +240,7 @@ test.describe('Doc Export', () => { test('it exports the doc with quotes', async ({ page, browserName }) => { const [randomDoc] = await createDoc(page, 'export-quotes', browserName, 1); - const downloadPromise = page.waitForEvent('download', (download) => { - return download.suggestedFilename().includes(`${randomDoc}.pdf`); - }); - - const editor = page.locator('.ProseMirror'); + const editor = page.locator('.ProseMirror.bn-editor'); // Trigger slash menu to show menu await editor.click(); await editor.fill('/'); @@ -241,7 +250,9 @@ test.describe('Doc Export', () => { editor.locator('.bn-block-content[data-content-type="quote"]'), ).toBeVisible(); - await editor.fill('Hello World'); + await editor + .locator('.bn-block-content[data-content-type="quote"]') + .fill('Hello World'); await expect(editor.getByText('Hello World')).toHaveCSS( 'font-style', @@ -254,6 +265,16 @@ test.describe('Doc Export', () => { }) .click(); + await expect( + page.getByRole('button', { + name: 'Download', + }), + ).toBeVisible(); + + const downloadPromise = page.waitForEvent('download', (download) => { + return download.suggestedFilename().includes(`${randomDoc}.pdf`); + }); + void page .getByRole('button', { name: 'Download', @@ -276,10 +297,6 @@ test.describe('Doc Export', () => { test('it exports the doc with divider', async ({ page, browserName }) => { const [randomDoc] = await createDoc(page, 'export-divider', browserName, 1); - const downloadPromise = page.waitForEvent('download', (download) => { - return download.suggestedFilename().includes(`${randomDoc}.pdf`); - }); - const editor = page.locator('.ProseMirror'); await editor.click(); await editor.fill('Hello World'); @@ -298,6 +315,16 @@ test.describe('Doc Export', () => { }) .click(); + await expect( + page.getByRole('button', { + name: 'Download', + }), + ).toBeVisible(); + + const downloadPromise = page.waitForEvent('download', (download) => { + return download.suggestedFilename().includes(`${randomDoc}.pdf`); + }); + void page .getByRole('button', { name: 'Download', diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts index 913c88ec..7223ec44 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-version.spec.ts @@ -116,11 +116,7 @@ test.describe('Doc Version', () => { await expect(panel).toBeVisible(); await expect(page.getByText('History', { exact: true })).toBeVisible(); - await expect(page.getByRole('status')).toBeVisible(); - await expect(page.getByRole('status')).toBeHidden(); - const items = await panel.locator('.version-item').all(); - expect(items.length).toBe(1); - await items[0].click(); + await panel.getByRole('button', { name: 'version item' }).click(); await expect(modal.getByText('World')).toBeHidden(); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts index 04802083..28a07f8f 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts @@ -79,28 +79,19 @@ test.describe.serial('Language', () => { }) => { await createDoc(page, 'doc-toolbar', browserName, 1); - const header = page.locator('header').first(); const editor = page.locator('.ProseMirror'); + // Trigger slash menu to show english menu await editor.click(); await editor.fill('/'); await expect(page.getByText('Headings', { exact: true })).toBeVisible(); - await header.click(); - await expect(page.getByText('Headings', { exact: true })).toBeHidden(); - - // Reset menu - await editor.click(); - await editor.fill(''); // Change language to French await waitForLanguageSwitch(page, TestLanguage.French); // Trigger slash menu to show french menu - await editor.click(); - await editor.fill('/'); + await editor.locator('.bn-block-outer').last().fill('/'); await expect(page.getByText('Titres', { exact: true })).toBeVisible(); - await header.click(); - await expect(page.getByText('Titres', { exact: true })).toBeHidden(); }); });