From 4e4e2e23e3d0980072f256a966d7757d4a4e158f Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Thu, 6 Jun 2024 22:13:18 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F(e2e)=20unique=20login=20betw?= =?UTF-8?q?een=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will cache the login token in the browser storage and reuse it between tests. This will speed up the tests and reduce the load on the server. --- CHANGELOG.md | 1 + src/frontend/apps/e2e/.gitignore | 1 + .../e2e/__tests__/app-impress/404.spec.ts | 8 +- .../e2e/__tests__/app-impress/auth.setup.ts | 19 ++++ .../apps/e2e/__tests__/app-impress/common.ts | 17 ++-- .../e2e/__tests__/app-impress/footer.spec.ts | 5 +- .../e2e/__tests__/app-impress/header.spec.ts | 12 ++- .../__tests__/app-impress/language.spec.ts | 5 +- .../app-impress/pad-add-members.spec.ts | 5 +- .../__tests__/app-impress/pad-create.spec.ts | 5 +- .../__tests__/app-impress/pad-editor.spec.ts | 5 +- .../app-impress/pad-member-delete.spec.ts | 5 +- .../app-impress/pad-member-grid.spec.ts | 5 +- .../__tests__/app-impress/pad-panel.spec.ts | 87 +++++++++++++++++-- .../__tests__/app-impress/pad-tools.spec.ts | 5 +- src/frontend/apps/e2e/playwright.config.ts | 17 +++- 16 files changed, 149 insertions(+), 53 deletions(-) create mode 100644 src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 26186b84..762f80f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to - 🔧 (helm) sticky session by request_uri for signaling server (#78) - (frontend) change logo (#84) - (frontend) pdf has title doc (#84) +- ⚡️(e2e) unique login between tests (#80) ## Fixed diff --git a/src/frontend/apps/e2e/.gitignore b/src/frontend/apps/e2e/.gitignore index 848074ac..475cf2e2 100644 --- a/src/frontend/apps/e2e/.gitignore +++ b/src/frontend/apps/e2e/.gitignore @@ -2,4 +2,5 @@ test-results/ report/ blob-report/ +playwright/.auth/ playwright/.cache/ diff --git a/src/frontend/apps/e2e/__tests__/app-impress/404.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/404.spec.ts index 4e4fa70d..dc2190dd 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/404.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/404.spec.ts @@ -1,10 +1,10 @@ import { expect, test } from '@playwright/test'; -import { keyCloakSignIn } from './common'; - -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); + await expect( + page.locator('header').first().locator('h2').getByText('Docs'), + ).toBeVisible(); await page.goto('unknown-page404'); }); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts b/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts new file mode 100644 index 00000000..7a4be400 --- /dev/null +++ b/src/frontend/apps/e2e/__tests__/app-impress/auth.setup.ts @@ -0,0 +1,19 @@ +import { test as setup } from '@playwright/test'; + +import { keyCloakSignIn } from './common'; + +setup('authenticate-chromium', async ({ page }) => { + await page.goto('/'); + await keyCloakSignIn(page, 'chromium'); + await page + .context() + .storageState({ path: `playwright/.auth/user-chromium.json` }); +}); + +setup('authenticate-webkit', async ({ page }) => { + await page.goto('/'); + await keyCloakSignIn(page, 'webkit'); + await page + .context() + .storageState({ path: `playwright/.auth/user-webkit.json` }); +}); diff --git a/src/frontend/apps/e2e/__tests__/app-impress/common.ts b/src/frontend/apps/e2e/__tests__/app-impress/common.ts index f3290bff..3e09384f 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/common.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/common.ts @@ -5,14 +5,17 @@ export const keyCloakSignIn = async (page: Page, browserName: string) => { timeout: 5000, }); - if (title?.includes('Sign in to your account')) { - await page - .getByRole('textbox', { name: 'username' }) - .fill(`user-e2e-${browserName}`); + const login = `user-e2e-${browserName}`; + const password = `password-e2e-${browserName}`; - await page - .getByRole('textbox', { name: 'password' }) - .fill(`password-e2e-${browserName}`); + if (await page.getByLabel('Restart login').isVisible()) { + await page.getByRole('textbox', { name: 'password' }).fill(password); + + await page.click('input[type="submit"]', { force: true }); + } else if (title?.includes('Sign in to your account')) { + await page.getByRole('textbox', { name: 'username' }).fill(login); + + await page.getByRole('textbox', { name: 'password' }).fill(password); await page.click('input[type="submit"]', { force: true }); } diff --git a/src/frontend/apps/e2e/__tests__/app-impress/footer.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/footer.spec.ts index 8d9eb995..3496d3b0 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/footer.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/footer.spec.ts @@ -1,10 +1,7 @@ import { expect, test } from '@playwright/test'; -import { keyCloakSignIn } from './common'; - -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Footer', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts index 442e8743..4555e139 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/header.spec.ts @@ -2,9 +2,8 @@ import { expect, test } from '@playwright/test'; import { keyCloakSignIn } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Header', () => { @@ -64,8 +63,15 @@ test.describe('Header', () => { await expect(page.getByRole('link', { name: 'Grist' })).toBeVisible(); }); +}); + +test.describe('Header: Log out', () => { + test.use({ storageState: { cookies: [], origins: [] } }); + + test('checks logout button', async ({ page, browserName }) => { + await page.goto('/'); + await keyCloakSignIn(page, browserName); - test('checks logout button', async ({ page }) => { await page .getByRole('button', { name: 'My account', 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 a9efc8fb..b81d7331 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts @@ -1,10 +1,7 @@ import { expect, test } from '@playwright/test'; -import { keyCloakSignIn } from './common'; - -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Language', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-add-members.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-add-members.spec.ts index ec912321..371bbc1e 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-add-members.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-add-members.spec.ts @@ -1,10 +1,9 @@ import { expect, test } from '@playwright/test'; -import { createPad, keyCloakSignIn, randomName } from './common'; +import { createPad, randomName } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Document add users', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-create.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-create.spec.ts index 3f2fc3a8..c80735a1 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-create.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-create.spec.ts @@ -1,10 +1,7 @@ import { expect, test } from '@playwright/test'; -import { keyCloakSignIn } from './common'; - -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Pad Create', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts index d8c31319..4c56af1f 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-editor.spec.ts @@ -1,10 +1,9 @@ import { expect, test } from '@playwright/test'; -import { createPad, keyCloakSignIn } from './common'; +import { createPad } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Pad Editor', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-member-delete.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-member-delete.spec.ts index 18f66b30..8310eb40 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-member-delete.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-member-delete.spec.ts @@ -1,10 +1,9 @@ import { expect, test } from '@playwright/test'; -import { addNewMember, createPad, keyCloakSignIn } from './common'; +import { addNewMember, createPad } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Members Delete', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-member-grid.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-member-grid.spec.ts index b03192ca..38429299 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-member-grid.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-member-grid.spec.ts @@ -1,10 +1,9 @@ import { expect, test } from '@playwright/test'; -import { createPad, keyCloakSignIn } from './common'; +import { createPad } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Document grid members', () => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-panel.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-panel.spec.ts index d8513106..3d782af9 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-panel.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-panel.spec.ts @@ -2,11 +2,10 @@ import { expect, test } from '@playwright/test'; import { waitForElementCount } from '../helpers'; -import { createPad, keyCloakSignIn } from './common'; +import { createPad } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Documents Panel', () => { @@ -62,17 +61,87 @@ test.describe('Documents Panel', () => { expect(responseSortDesc.ok()).toBeTruthy(); }); - test('checks the infinite scroll', async ({ page, browserName }) => { - test.setTimeout(90000); + test('checks the infinite scroll', async ({ page }) => { + await page.route( + /.*\/documents\/\?page=.*&ordering=-created_at/, + async (route) => { + const request = route.request(); + const url = new URL(request.url()); + const pageId = url.searchParams.get('page'); + const documents = { + count: 40, + next: 'http://localhost:3000/documents/?page=2&ordering=-created_at', + previous: null, + results: Array.from({ length: 20 }, (_, i) => ({ + id: `2ff-${pageId}-${i}`, + title: `My document-${pageId}-${i}`, + accesses: [ + { + id: 'b644e9b1-0517-4cfb-90ca-f7d6f2f6bb9a', + role: `owner`, + team: '', + user: { + id: 'a4743608-c9d8-4692-bef4-f795e25a3a88', + email: 'user@chromium.e2e', + }, + }, + ], + content: '', + is_public: true, + abilities: {}, + })), + }; + + if (request.method().includes('GET')) { + await route.fulfill({ + json: documents, + }); + } else { + await route.continue(); + } + }, + ); + + await page.route(`**/documents/2ff-1-16/`, async (route) => { + const request = route.request(); + + if (request.method().includes('GET')) { + await route.fulfill({ + json: { + id: '2ff-1-16', + title: 'My document-1-16', + content: '', + abilities: { + partial_update: true, + }, + accesses: [ + { + id: 'b644e9b1-0517-4cfb-90ca-f7d6f2f6bb9a', + role: `owner`, + team: '', + user: { + id: 'a4743608-c9d8-4692-bef4-f795e25a3a88', + email: '', + }, + }, + ], + }, + }); + } else { + await route.continue(); + } + }); + + await page.goto('/'); + const panel = page.getByLabel('Documents panel').first(); - - const randomPads = await createPad(page, 'pad-infinite', browserName, 40); - await expect(panel.locator('li')).toHaveCount(20); - await panel.getByText(randomPads[24]).click(); + await panel.getByText(`My document-1-16`).click(); await waitForElementCount(panel.locator('li'), 21, 10000); expect(await panel.locator('li').count()).toBeGreaterThan(20); + await expect(panel.getByText(`My document-1-16`)).toBeVisible(); + await expect(panel.getByText(`My document-2-15`)).toBeVisible(); }); test('checks the hover and selected state', async ({ page, browserName }) => { diff --git a/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts index 72554398..3b728062 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/pad-tools.spec.ts @@ -2,11 +2,10 @@ import { expect, test } from '@playwright/test'; import cs from 'convert-stream'; import pdf from 'pdf-parse'; -import { createPad, keyCloakSignIn } from './common'; +import { createPad } from './common'; -test.beforeEach(async ({ page, browserName }) => { +test.beforeEach(async ({ page }) => { await page.goto('/'); - await keyCloakSignIn(page, browserName); }); test.describe('Pad Tools', () => { diff --git a/src/frontend/apps/e2e/playwright.config.ts b/src/frontend/apps/e2e/playwright.config.ts index 482c3c4f..18986866 100644 --- a/src/frontend/apps/e2e/playwright.config.ts +++ b/src/frontend/apps/e2e/playwright.config.ts @@ -25,7 +25,7 @@ export default defineConfig({ reporter: [['html', { outputFolder: './report' }]], /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { - baseURL: baseURL, + baseURL, /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ trace: 'on-first-retry', @@ -42,13 +42,24 @@ export default defineConfig({ /* Configure projects for major browsers */ projects: [ + { name: 'setup', testMatch: /.*\.setup\.ts/ }, { name: 'chromium', - use: { ...devices['Desktop Chrome'], locale: 'en-US' }, + use: { + ...devices['Desktop Chrome'], + locale: 'en-US', + storageState: 'playwright/.auth/user-chromium.json', + }, + dependencies: ['setup'], }, { name: 'webkit', - use: { ...devices['Desktop Safari'], locale: 'en-US' }, + use: { + ...devices['Desktop Safari'], + locale: 'en-US', + storageState: 'playwright/.auth/user-webkit.json', + }, + dependencies: ['setup'], }, ], });