From 2c68f8fba1ff302adc8a36a18eaafb6b9e152407 Mon Sep 17 00:00:00 2001 From: Alessio Gravili Date: Fri, 22 Mar 2024 16:42:41 -0400 Subject: [PATCH] chore: unflake access-control, fix incorrect poll & toPass timeouts --- test/access-control/e2e.spec.ts | 21 ++++++++------------- test/auth/e2e.spec.ts | 7 ++++--- test/helpers.ts | 7 ++++--- test/helpers/adminUrlUtil.ts | 2 +- test/playwright.config.ts | 5 ++++- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/test/access-control/e2e.spec.ts b/test/access-control/e2e.spec.ts index e82d896f6..c7beb23ac 100644 --- a/test/access-control/e2e.spec.ts +++ b/test/access-control/e2e.spec.ts @@ -1,9 +1,8 @@ import type { Page } from '@playwright/test' -import type { Payload } from 'payload/types' +import type { Payload, TypeWithID } from 'payload/types' import { expect, test } from '@playwright/test' import path from 'path' -import { wait } from 'payload/utilities' import { fileURLToPath } from 'url' import type { ReadOnlyCollection, RestrictedVersion } from './payload-types.js' @@ -134,7 +133,6 @@ describe('access control', () => { describe('restricted fields', () => { test('should not show field without permission', async () => { await page.goto(url.account) - await wait(500) await expect(page.locator('#field-roles')).toBeHidden() }) }) @@ -163,7 +161,7 @@ describe('access control', () => { test('should have collection url', async () => { await page.goto(readOnlyUrl.list) - await expect(page).toHaveURL(readOnlyUrl.list) // no redirect + await expect(page).toHaveURL(new RegExp(`${readOnlyUrl.list}.*`)) // will redirect to ?limit=10 at the end, so we have to use a wildcard at the end }) test('should not have "Create New" button', async () => { @@ -188,7 +186,6 @@ describe('access control', () => { test('should not render dot menu popup when `create` and `delete` access control is set to false', async () => { await page.goto(readOnlyUrl.edit(existingDoc.id)) - await wait(1000) await expect(page.locator('.collection-edit .doc-controls .doc-controls__popup')).toBeHidden() }) }) @@ -213,7 +210,7 @@ describe('access control', () => { describe('doc level access', () => { let existingDoc: ReadOnlyCollection - let docLevelAccessURL + let docLevelAccessURL: AdminUrlUtil beforeAll(async () => { docLevelAccessURL = new AdminUrlUtil(serverURL, docLevelAccessSlug) @@ -265,28 +262,26 @@ describe('access control', () => { const unrestrictedURL = new AdminUrlUtil(serverURL, unrestrictedSlug) await page.goto(unrestrictedURL.edit(unrestrictedDoc.id)) - const button = page.locator( + const addDocButton = page.locator( '#userRestrictedDocs-add-new button.relationship-add-new__add-button.doc-drawer__toggler', ) - await button.click() + await addDocButton.click() const documentDrawer = page.locator('[id^=doc-drawer_user-restricted_1_]') await expect(documentDrawer).toBeVisible() await documentDrawer.locator('#field-name').fill('anonymous@email.com') await documentDrawer.locator('#action-save').click() - await wait(200) await expect(page.locator('.Toastify')).toContainText('successfully') // ensure user is not allowed to edit this document await expect(documentDrawer.locator('#field-name')).toBeDisabled() await documentDrawer.locator('button.doc-drawer__header-close').click() - await wait(200) + await expect(documentDrawer).toBeHidden() - await button.click() + await addDocButton.click() const documentDrawer2 = page.locator('[id^=doc-drawer_user-restricted_1_]') await expect(documentDrawer2).toBeVisible() await documentDrawer2.locator('#field-name').fill('dev@payloadcms.com') await documentDrawer2.locator('#action-save').click() - await wait(200) await expect(page.locator('.Toastify')).toContainText('successfully') // ensure user is allowed to edit this document @@ -294,7 +289,7 @@ describe('access control', () => { }) }) -async function createDoc(data: any): Promise<{ id: string }> { +async function createDoc(data: any): Promise> { return payload.create({ collection: slug, data, diff --git a/test/auth/e2e.spec.ts b/test/auth/e2e.spec.ts index 33d9a3a8b..f87d00e9b 100644 --- a/test/auth/e2e.spec.ts +++ b/test/auth/e2e.spec.ts @@ -8,6 +8,7 @@ import { fileURLToPath } from 'url' import { delayNetwork, initPageConsoleErrorCatch, login, saveDocAndAssert } from '../helpers.js' import { AdminUrlUtil } from '../helpers/adminUrlUtil.js' import { initPayloadE2E } from '../helpers/initPayloadE2E.js' +import { POLL_TOPASS_TIMEOUT } from '../playwright.config.js' import config from './config.js' import { apiKeysSlug, slug } from './shared.js' const filename = fileURLToPath(import.meta.url) @@ -105,7 +106,7 @@ describe('auth', () => { // assert that the value is set const apiKeyLocator = page.locator('#apiKey') await expect - .poll(async () => await apiKeyLocator.inputValue(), { timeout: 45000 }) + .poll(async () => await apiKeyLocator.inputValue(), { timeout: POLL_TOPASS_TIMEOUT }) .toBeDefined() await saveDocAndAssert(page) @@ -114,7 +115,7 @@ describe('auth', () => { const apiKey = await apiKeyLocator.inputValue() expect(await page.locator('#apiKey').inputValue()).toStrictEqual(apiKey) }).toPass({ - timeout: 45000, + timeout: POLL_TOPASS_TIMEOUT, }) }) @@ -140,7 +141,7 @@ describe('auth', () => { expect(response.user).toBeNull() }).toPass({ - timeout: 45000, + timeout: POLL_TOPASS_TIMEOUT, }) }) }) diff --git a/test/helpers.ts b/test/helpers.ts index 20528fb32..f2a17e931 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -5,6 +5,7 @@ import { wait } from 'payload/utilities' import shelljs from 'shelljs' import { devUser } from './credentials.js' +import { POLL_TOPASS_TIMEOUT } from './playwright.config.js' type FirstRegisterArgs = { page: Page @@ -91,7 +92,7 @@ export async function saveDocHotkeyAndAssert(page: Page): Promise { export async function saveDocAndAssert(page: Page, selector = '#action-save'): Promise { await page.click(selector, { delay: 100 }) await expect(page.locator('.Toastify')).toContainText('successfully') - await expect.poll(() => page.url(), { timeout: 45000 }).not.toContain('create') + await expect.poll(() => page.url(), { timeout: POLL_TOPASS_TIMEOUT }).not.toContain('create') } export async function openNav(page: Page): Promise { @@ -137,7 +138,7 @@ export function exactText(text: string) { export const checkPageTitle = async (page: Page, title: string) => { await expect .poll(async () => await page.locator('.doc-header__title.render-title')?.first()?.innerText(), { - timeout: 45000, + timeout: POLL_TOPASS_TIMEOUT, }) .toBe(title) } @@ -147,7 +148,7 @@ export const checkBreadcrumb = async (page: Page, text: string) => { .poll( async () => await page.locator('.step-nav.app-header__step-nav .step-nav__last')?.innerText(), { - timeout: 45000, + timeout: POLL_TOPASS_TIMEOUT, }, ) .toBe(text) diff --git a/test/helpers/adminUrlUtil.ts b/test/helpers/adminUrlUtil.ts index 4f5998245..09e5239d5 100644 --- a/test/helpers/adminUrlUtil.ts +++ b/test/helpers/adminUrlUtil.ts @@ -10,7 +10,7 @@ export class AdminUrlUtil { constructor(serverURL: string, slug: string) { this.account = `${serverURL}/admin/account` this.admin = `${serverURL}/admin` - this.list = `${this.admin}/collections/${slug}?limit=10` + this.list = `${this.admin}/collections/${slug}` this.create = `${this.list}/create` } diff --git a/test/playwright.config.ts b/test/playwright.config.ts index 83ead85c1..2cc020ed3 100644 --- a/test/playwright.config.ts +++ b/test/playwright.config.ts @@ -1,5 +1,8 @@ import { defineConfig } from '@playwright/test' +export const EXPECT_TIMEOUT = 45000 +export const POLL_TOPASS_TIMEOUT = EXPECT_TIMEOUT * 4 // That way expect.poll() or expect().toPass can retry 4 times + export default defineConfig({ // Look for test files in the "test" directory, relative to this configuration file testDir: '', @@ -11,7 +14,7 @@ export default defineConfig({ video: 'retain-on-failure', }, expect: { - timeout: 60000, + timeout: EXPECT_TIMEOUT, }, workers: 16, })