From 251787b835cd22f1785cf6a9fe71fb26a78f282e Mon Sep 17 00:00:00 2001 From: rvveber Date: Tue, 25 Feb 2025 15:44:33 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A8(tests)=20add=20language=20related?= =?UTF-8?q?=20tests;=20fix=20getByRole=20not=20working=20in=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - adds tests and test-utility for solid language switching in tests - fixes where ...getByRole(menuitem... would not return a valid object --- .../apps/e2e/__tests__/app-impress/common.ts | 2 +- .../__tests__/app-impress/doc-editor.spec.ts | 41 +----- .../__tests__/app-impress/doc-header.spec.ts | 38 ++---- .../app-impress/doc-member-create.spec.ts | 63 ++------- .../app-impress/doc-member-list.spec.ts | 8 +- .../__tests__/app-impress/doc-version.spec.ts | 22 +--- .../app-impress/doc-visibility.spec.ts | 14 +- .../__tests__/app-impress/language.spec.ts | 123 +++++++++++++++--- 8 files changed, 136 insertions(+), 175 deletions(-) diff --git a/src/frontend/apps/e2e/__tests__/app-impress/common.ts b/src/frontend/apps/e2e/__tests__/app-impress/common.ts index 04597058..7e445093 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/common.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/common.ts @@ -97,7 +97,7 @@ export const addNewMember = async ( // Choose a role await page.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: role }).click(); + await page.getByLabel(role).click(); await page.getByRole('button', { name: 'Invite' }).click(); return users[index].email; 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 c74ff92c..4efdd71e 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 @@ -15,41 +15,6 @@ test.beforeEach(async ({ page }) => { }); test.describe('Doc Editor', () => { - test('it check translations of the slash menu when changing language', async ({ - page, - browserName, - }) => { - 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 header.click(); - await header.getByRole('button', { name: /Language/ }).click(); - await page.getByRole('menuitem', { name: 'Français' }).click(); - await expect( - header.getByRole('button').getByText('Français'), - ).toBeVisible(); - - // Trigger slash menu to show french menu - await editor.click(); - await editor.fill('/'); - await expect(page.getByText('Titres', { exact: true })).toBeVisible(); - await header.click(); - await expect(page.getByText('Titres', { exact: true })).toBeHidden(); - }); - test('it checks default toolbar buttons are displayed', async ({ page, browserName, @@ -128,11 +93,7 @@ test.describe('Doc Editor', () => { const wsClosePromise = webSocket.waitForEvent('close'); await selectVisibility.click(); - await page - .getByRole('menuitem', { - name: 'Connected', - }) - .click(); + await page.getByLabel('Connected').click(); // Assert that the doc reconnects to the ws const wsClose = await wsClosePromise; diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts index 9a789654..09b6bad0 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-header.spec.ts @@ -88,11 +88,7 @@ test.describe('Doc Header', () => { const [randomDoc] = await createDoc(page, 'doc-delete', browserName, 1); await page.getByLabel('Open the document options').click(); - await page - .getByRole('menuitem', { - name: 'Delete document', - }) - .click(); + await page.getByLabel('Delete document').click(); await expect( page.getByRole('heading', { name: 'Delete a doc' }), @@ -150,9 +146,7 @@ test.describe('Doc Header', () => { await page.getByLabel('Open the document options').click(); - await expect( - page.getByRole('menuitem', { name: 'Delete document' }), - ).toBeDisabled(); + await expect(page.getByLabel('Delete document')).toBeDisabled(); // Click somewhere else to close the options await page.click('body', { position: { x: 0, y: 0 } }); @@ -174,11 +168,7 @@ test.describe('Doc Header', () => { await invitationCard.getByRole('button', { name: 'more_horiz' }).click(); - await expect( - page.getByRole('menuitem', { - name: 'delete', - }), - ).toBeEnabled(); + await expect(page.getByLabel('Delete')).toBeEnabled(); await invitationCard.click(); const memberCard = shareModal.getByLabel('List members card'); @@ -192,11 +182,7 @@ test.describe('Doc Header', () => { ).toBeVisible(); await memberCard.getByRole('button', { name: 'more_horiz' }).click(); - await expect( - page.getByRole('menuitem', { - name: 'delete', - }), - ).toBeEnabled(); + await expect(page.getByLabel('Delete')).toBeEnabled(); }); test('it checks the options available if editor', async ({ page }) => { @@ -230,9 +216,7 @@ test.describe('Doc Header', () => { await expect(page.getByRole('button', { name: 'download' })).toBeVisible(); await page.getByLabel('Open the document options').click(); - await expect( - page.getByRole('menuitem', { name: 'Delete document' }), - ).toBeDisabled(); + await expect(page.getByLabel('Delete document')).toBeDisabled(); // Click somewhere else to close the options await page.click('body', { position: { x: 0, y: 0 } }); @@ -292,9 +276,7 @@ test.describe('Doc Header', () => { await expect(page.getByRole('button', { name: 'download' })).toBeVisible(); await page.getByLabel('Open the document options').click(); - await expect( - page.getByRole('menuitem', { name: 'Delete document' }), - ).toBeDisabled(); + await expect(page.getByLabel('Delete document')).toBeDisabled(); // Click somewhere else to close the options await page.click('body', { position: { x: 0, y: 0 } }); @@ -350,7 +332,7 @@ test.describe('Doc Header', () => { // Copy content to clipboard await page.getByLabel('Open the document options').click(); - await page.getByRole('menuitem', { name: 'Copy as Markdown' }).click(); + await page.getByLabel('Copy as Markdown').click(); await expect(page.getByText('Copied to clipboard')).toBeVisible(); // Test that clipboard is in Markdown format @@ -385,7 +367,7 @@ test.describe('Doc Header', () => { // Copy content to clipboard await page.getByLabel('Open the document options').click(); - await page.getByRole('menuitem', { name: 'Copy as HTML' }).click(); + await page.getByLabel('Copy as HTML').click(); await expect(page.getByText('Copied to clipboard')).toBeVisible(); // Test that clipboard is in HTML format @@ -458,7 +440,7 @@ test.describe('Documents Header mobile', () => { await expect(page.getByRole('button', { name: 'Copy link' })).toBeHidden(); await page.getByLabel('Open the document options').click(); - await page.getByRole('menuitem', { name: 'Share' }).click(); + await page.getByLabel('Share').click(); await page.getByRole('button', { name: 'Copy link' }).click(); await expect(page.getByText('Link Copied !')).toBeVisible(); // Test that clipboard is in HTML format @@ -492,7 +474,7 @@ test.describe('Documents Header mobile', () => { await goToGridDoc(page); await page.getByLabel('Open the document options').click(); - await page.getByRole('menuitem', { name: 'Share' }).click(); + await page.getByLabel('Share').click(); await expect(page.getByLabel('Share modal')).toBeVisible(); await page.getByRole('button', { name: 'close' }).click(); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts index 8d9dbfc0..7411c2ac 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-create.spec.ts @@ -65,15 +65,13 @@ test.describe('Document create member', () => { // Check roles are displayed await list.getByLabel('doc-role-dropdown').click(); - await expect(page.getByRole('menuitem', { name: 'Reader' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Editor' })).toBeVisible(); - await expect(page.getByRole('menuitem', { name: 'Owner' })).toBeVisible(); - await expect( - page.getByRole('menuitem', { name: 'Administrator' }), - ).toBeVisible(); + await expect(page.getByLabel('Reader')).toBeVisible(); + await expect(page.getByLabel('Editor')).toBeVisible(); + await expect(page.getByLabel('Owner')).toBeVisible(); + await expect(page.getByLabel('Administrator')).toBeVisible(); // Validate - await page.getByRole('menuitem', { name: 'Administrator' }).click(); + await page.getByLabel('Administrator').click(); await page.getByRole('button', { name: 'Invite' }).click(); // Check invitation added @@ -121,7 +119,7 @@ test.describe('Document create member', () => { // Choose a role const container = page.getByTestId('doc-share-add-member-list'); await container.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: 'Owner' }).click(); + await page.getByLabel('Owner').click(); const responsePromiseCreateInvitation = page.waitForResponse( (response) => @@ -139,7 +137,7 @@ test.describe('Document create member', () => { // Choose a role await container.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: 'Owner' }).click(); + await page.getByLabel('Owner').click(); const responsePromiseCreateInvitationFail = page.waitForResponse( (response) => @@ -155,47 +153,6 @@ test.describe('Document create member', () => { expect(responseCreateInvitationFail.ok()).toBeFalsy(); }); - test('The invitation endpoint get the language of the website', async ({ - page, - browserName, - }) => { - await createDoc(page, 'user-invitation', browserName, 1); - - const header = page.locator('header').first(); - await header.getByRole('button', { name: /Language/ }).click(); - await page.getByRole('menuitem', { name: 'Français' }).click(); - - await page.getByRole('button', { name: 'Partager' }).click(); - - const inputSearch = page.getByRole('combobox', { - name: 'Saisie de recherche rapide', - }); - - const email = randomName('test@test.fr', browserName, 1)[0]; - await inputSearch.fill(email); - await page.getByTestId(`search-user-row-${email}`).click(); - - // Choose a role - const container = page.getByTestId('doc-share-add-member-list'); - await container.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: 'Administrateur' }).click(); - - const responsePromiseCreateInvitation = page.waitForResponse( - (response) => - response.url().includes('/invitations/') && response.status() === 201, - ); - - await page.getByRole('button', { name: 'Invite' }).click(); - - // Check invitation sent - - const responseCreateInvitation = await responsePromiseCreateInvitation; - expect(responseCreateInvitation.ok()).toBeTruthy(); - expect( - responseCreateInvitation.request().headers()['content-language'], - ).toBe('fr-fr'); - }); - test('it manages invitation', async ({ page, browserName }) => { await createDoc(page, 'user-invitation', browserName, 1); @@ -212,7 +169,7 @@ test.describe('Document create member', () => { // Choose a role const container = page.getByTestId('doc-share-add-member-list'); await container.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: 'Administrator' }).click(); + await page.getByLabel('Administrator').click(); const responsePromiseCreateInvitation = page.waitForResponse( (response) => @@ -232,14 +189,14 @@ test.describe('Document create member', () => { await expect(userInvitation).toBeVisible(); await userInvitation.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: 'Reader' }).click(); + await page.getByLabel('Reader').click(); const moreActions = userInvitation.getByRole('button', { name: 'more_horiz', }); await moreActions.click(); - await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByLabel('Delete').click(); await expect(userInvitation).toBeHidden(); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts index f27c9baf..7feced8a 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-member-list.spec.ts @@ -161,12 +161,12 @@ test.describe('Document list members', () => { await list.click(); await currentUserRole.click(); - await page.getByRole('menuitem', { name: 'Administrator' }).click(); + await page.getByLabel('Administrator').click(); await list.click(); await expect(currentUserRole).toBeVisible(); await currentUserRole.click(); - await page.getByRole('menuitem', { name: 'Reader' }).click(); + await page.getByLabel('Reader').click(); await list.click(); await expect(currentUserRole).toBeHidden(); }); @@ -215,11 +215,11 @@ test.describe('Document list members', () => { await expect(mySelfMoreActions).toBeVisible(); await userReaderMoreActions.click(); - await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByLabel('Delete').click(); await expect(userReader).toBeHidden(); await mySelfMoreActions.click(); - await page.getByRole('menuitem', { name: 'Delete' }).click(); + await page.getByLabel('Delete').click(); await expect( page.getByText('You do not have permission to view this document.'), ).toBeVisible(); 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 31d6fd59..913c88ec 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 @@ -18,11 +18,7 @@ test.describe('Doc Version', () => { await verifyDocName(page, randomDoc); await page.getByLabel('Open the document options').click(); - await page - .getByRole('menuitem', { - name: 'Version history', - }) - .click(); + await page.getByLabel('Version history').click(); await expect(page.getByText('History', { exact: true })).toBeVisible(); const modal = page.getByLabel('version history modal'); @@ -58,11 +54,7 @@ test.describe('Doc Version', () => { ).toBeVisible(); await page.getByLabel('Open the document options').click(); - await page - .getByRole('menuitem', { - name: 'Version history', - }) - .click(); + await page.getByLabel('Version history').click(); await expect(panel).toBeVisible(); await expect(page.getByText('History', { exact: true })).toBeVisible(); @@ -90,9 +82,7 @@ test.describe('Doc Version', () => { await verifyDocName(page, 'Mocked document'); await page.getByLabel('Open the document options').click(); - await expect( - page.getByRole('menuitem', { name: 'Version history' }), - ).toBeDisabled(); + await expect(page.getByLabel('Version history')).toBeDisabled(); }); test('it restores the doc version', async ({ page, browserName }) => { @@ -119,11 +109,7 @@ test.describe('Doc Version', () => { await expect(page.getByText('World')).toBeVisible(); await page.getByLabel('Open the document options').click(); - await page - .getByRole('menuitem', { - name: 'Version history', - }) - .click(); + await page.getByLabel('Version history').click(); const modal = page.getByLabel('version history modal'); const panel = modal.getByLabel('version list'); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts index 4d3fabad..89b47922 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-visibility.spec.ts @@ -49,21 +49,13 @@ test.describe('Doc Visibility', () => { await expect(page.getByLabel('Can read and edit')).toBeHidden(); await selectVisibility.click(); - await page - .getByRole('menuitem', { - name: 'Connected', - }) - .click(); + await page.getByLabel('Connected').click(); await expect(page.getByLabel('Visibility mode')).toBeVisible(); await selectVisibility.click(); - await page - .getByRole('menuitem', { - name: 'Public', - }) - .click(); + await page.getByLabel('Public', { exact: true }).click(); await expect(page.getByLabel('Visibility mode')).toBeVisible(); }); @@ -162,7 +154,7 @@ test.describe('Doc Visibility: Restricted', () => { // Choose a role const container = page.getByTestId('doc-share-add-member-list'); await container.getByLabel('doc-role-dropdown').click(); - await page.getByRole('menuitem', { name: 'Administrator' }).click(); + await page.getByLabel('Administrator').click(); await page.getByRole('button', { name: 'Invite' }).click(); 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 4a03870c..58f3646c 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts @@ -1,19 +1,41 @@ -import { expect, test } from '@playwright/test'; +import { Page, expect, test } from '@playwright/test'; -test.beforeEach(async ({ page }) => { - await page.goto('/'); -}); +import { createDoc } from './common'; -test.describe('Language', () => { - test('checks the language picker', async ({ page }) => { - await expect(page.getByLabel('Logout')).toBeVisible(); +test.describe.serial('Language', () => { + let page: Page; + test.beforeAll(async ({ browser }) => { + page = await browser.newPage(); + }); + + test.afterAll(async () => { + await page.close(); + }); + + test.beforeEach(async ({ page }) => { + await page.goto('/'); + await waitForLanguageSwitch(page, TestLanguage.English); + }); + + test.afterEach(async ({ page }) => { + // Switch back to English - important for other tests to run as expected + await waitForLanguageSwitch(page, TestLanguage.English); + }); + + test('checks language switching', async ({ page }) => { const header = page.locator('header').first(); - await header - .getByRole('button', { name: /Language/ }) - .getByText('English') - .click(); - await page.getByRole('menuitem', { name: 'Français' }).click(); + + // initial language should be english + await expect( + page.getByRole('button', { + name: 'New doc', + }), + ).toBeVisible(); + + // switch to french + await waitForLanguageSwitch(page, TestLanguage.French); + await expect( header.getByRole('button').getByText('Français'), ).toBeVisible(); @@ -21,7 +43,7 @@ test.describe('Language', () => { await expect(page.getByLabel('Se déconnecter')).toBeVisible(); await header.getByRole('button').getByText('Français').click(); - await page.getByRole('menuitem', { name: 'Deutsch' }).click(); + await page.getByLabel('Deutsch').click(); await expect(header.getByRole('button').getByText('Deutsch')).toBeVisible(); await expect(page.getByLabel('Abmelden')).toBeVisible(); @@ -52,15 +74,76 @@ test.describe('Language', () => { // Check for English 404 response await check404Response('Not found.'); - // Switch language to French - const header = page.locator('header').first(); - await header - .getByRole('button', { name: /Language/ }) - .getByText('English') - .click(); - await page.getByRole('menuitem', { name: 'Français' }).click(); + await waitForLanguageSwitch(page, TestLanguage.French); // Check for French 404 response await check404Response('Pas trouvé.'); }); + + test('it check translations of the slash menu when changing language', async ({ + page, + browserName, + }) => { + 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 expect(page.getByText('Titres', { exact: true })).toBeVisible(); + await header.click(); + await expect(page.getByText('Titres', { exact: true })).toBeHidden(); + }); }); + +// language helper +export const TestLanguage = { + English: { + label: 'English', + expectedLocale: ['en-us'], + }, + French: { + label: 'Français', + expectedLocale: ['fr-fr'], + }, + German: { + label: 'Deutsch', + expectedLocale: ['de-de'], + }, +} as const; + +type TestLanguageKey = keyof typeof TestLanguage; +type TestLanguageValue = (typeof TestLanguage)[TestLanguageKey]; + +export async function waitForLanguageSwitch( + page: Page, + lang: TestLanguageValue, +) { + const header = page.locator('header').first(); + await header.getByRole('button', { name: 'arrow_drop_down' }).click(); + + const responsePromise = page.waitForResponse( + (resp) => + resp.url().includes('/user') && resp.request().method() === 'PATCH', + ); + await page.getByLabel(lang.label).click(); + const resolvedResponsePromise = await responsePromise; + const responseData = await resolvedResponsePromise.json(); + + expect(lang.expectedLocale).toContain(responseData.language); +}