From a22f27de1c2435cf857079207b4e7dc2661cebb7 Mon Sep 17 00:00:00 2001 From: Jarrod Flesch <30633324+JarrodMFlesch@users.noreply.github.com> Date: Wed, 30 Jul 2025 08:52:01 -0400 Subject: [PATCH] test: stabilize frequent fails (#13318) Adjusts tests that "flake" frequently. --- .../ui/src/views/List/GroupByHeader/index.tsx | 4 ++- test/access-control/e2e.spec.ts | 22 ++++++---------- test/eslint.config.js | 1 + test/fields/collections/JSON/e2e.spec.ts | 26 +++++++++++++------ .../collections/Relationship/e2e.spec.ts | 10 +------ test/fields/collections/Upload/e2e.spec.ts | 8 ------ test/group-by/e2e.spec.ts | 18 +++++-------- test/helpers/e2e/openListFilters.ts | 1 + test/i18n/e2e.spec.ts | 2 +- test/lexical/collections/RichText/e2e.spec.ts | 8 ------ test/live-preview/e2e.spec.ts | 7 +++-- test/localization/e2e.spec.ts | 3 +-- test/query-presets/e2e.spec.ts | 8 +++--- 13 files changed, 47 insertions(+), 71 deletions(-) diff --git a/packages/ui/src/views/List/GroupByHeader/index.tsx b/packages/ui/src/views/List/GroupByHeader/index.tsx index 37c826a16..42e5fea0f 100644 --- a/packages/ui/src/views/List/GroupByHeader/index.tsx +++ b/packages/ui/src/views/List/GroupByHeader/index.tsx @@ -15,7 +15,9 @@ export const GroupByHeader: React.FC<{ }> = ({ collectionConfig, groupByFieldPath, groupByValue, heading }) => { return (
-

{heading}

+

+ {heading} +

{ let disabledFields: AdminUrlUtil let serverURL: string let context: BrowserContext - let logoutURL: string let authFields: AdminUrlUtil beforeAll(async ({ browser }, testInfo) => { @@ -98,17 +96,6 @@ describe('Access Control', () => { await ensureCompilationIsDone({ page, serverURL, noAutoLogin: true }) await login({ page, serverURL }) - - await ensureCompilationIsDone({ page, serverURL }) - - const { - admin: { - routes: { logout: logoutRoute }, - }, - routes: { admin: adminRoute }, - } = getRoutes({}) - - logoutURL = `${serverURL}${adminRoute}${logoutRoute}` }) describe('fields', () => { @@ -515,6 +502,13 @@ describe('Access Control', () => { describe('global', () => { test('should restrict update access based on document field', async () => { + await payload.updateGlobal({ + slug: userRestrictedGlobalSlug, + data: { + name: 'dev@payloadcms.com', + }, + }) + await page.goto(userRestrictedGlobalURL.global(userRestrictedGlobalSlug)) await expect(page.locator('#field-name')).toBeVisible() await expect(page.locator('#field-name')).toHaveValue(devUser.email) diff --git a/test/eslint.config.js b/test/eslint.config.js index 8cdafaa8f..1f0163535 100644 --- a/test/eslint.config.js +++ b/test/eslint.config.js @@ -75,6 +75,7 @@ export const testEslintConfig = [ 'createFolder', 'createFolderFromDoc', 'assertURLParams', + 'uploadImage', ], }, ], diff --git a/test/fields/collections/JSON/e2e.spec.ts b/test/fields/collections/JSON/e2e.spec.ts index 1683e0916..c4ed0f972 100644 --- a/test/fields/collections/JSON/e2e.spec.ts +++ b/test/fields/collections/JSON/e2e.spec.ts @@ -131,13 +131,23 @@ describe('JSON', () => { const jsonField = page.locator('.json-field:not(.read-only) #field-customJSON') await expect(jsonField).toContainText('"default": "value"') - const originalHeight = - (await page.locator('.json-field:not(.read-only) #field-customJSON').boundingBox())?.height || - 0 - await page.locator('#set-custom-json').click() - const newHeight = - (await page.locator('.json-field:not(.read-only) #field-customJSON').boundingBox())?.height || - 0 - expect(newHeight).toBeGreaterThan(originalHeight) + const boundingBox = await page + .locator('.json-field:not(.read-only) #field-customJSON') + .boundingBox() + await expect(() => expect(boundingBox).not.toBeNull()).toPass() + const originalHeight = boundingBox!.height + + // click the button to set custom JSON + await page.locator('#set-custom-json').click({ delay: 1000 }) + + const newBoundingBox = await page + .locator('.json-field:not(.read-only) #field-customJSON') + .boundingBox() + await expect(() => expect(newBoundingBox).not.toBeNull()).toPass() + const newHeight = newBoundingBox!.height + + await expect(() => { + expect(newHeight).toBeGreaterThan(originalHeight) + }).toPass() }) }) diff --git a/test/fields/collections/Relationship/e2e.spec.ts b/test/fields/collections/Relationship/e2e.spec.ts index 09624cddb..0f2010305 100644 --- a/test/fields/collections/Relationship/e2e.spec.ts +++ b/test/fields/collections/Relationship/e2e.spec.ts @@ -23,7 +23,6 @@ import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js' import { assertToastErrors } from '../../../helpers/assertToastErrors.js' import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js' import { reInitializeDB } from '../../../helpers/reInitializeDB.js' -import { RESTClient } from '../../../helpers/rest.js' import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../../../playwright.config.js' import { relationshipFieldsSlug, textFieldsSlug } from '../../slugs.js' const filename = fileURLToPath(import.meta.url) @@ -33,7 +32,6 @@ const dirname = path.resolve(currentFolder, '../../') const { beforeAll, beforeEach, describe } = test let payload: PayloadTestSDK -let client: RESTClient let page: Page let serverURL: string // If we want to make this run in parallel: test.describe.configure({ mode: 'parallel' }) @@ -59,12 +57,6 @@ describe('relationship', () => { uploadsDir: path.resolve(dirname, './collections/Upload/uploads'), }) - if (client) { - await client.logout() - } - client = new RESTClient({ defaultSlug: 'users', serverURL }) - await client.login() - await ensureCompilationIsDone({ page, serverURL }) }) @@ -693,7 +685,7 @@ describe('relationship', () => { await createRelationshipFieldDoc({ value: textDoc.id, relationTo: 'text-fields' }) await page.goto(url.list) - await wait(300) + await wait(1000) // wait for page to load await addListFilter({ page, diff --git a/test/fields/collections/Upload/e2e.spec.ts b/test/fields/collections/Upload/e2e.spec.ts index 683fd66f6..5f8b33035 100644 --- a/test/fields/collections/Upload/e2e.spec.ts +++ b/test/fields/collections/Upload/e2e.spec.ts @@ -17,7 +17,6 @@ import { import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js' import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js' import { reInitializeDB } from '../../../helpers/reInitializeDB.js' -import { RESTClient } from '../../../helpers/rest.js' import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../../../playwright.config.js' import { uploadsSlug } from '../../slugs.js' @@ -28,7 +27,6 @@ const dirname = path.resolve(currentFolder, '../../') const { beforeAll, beforeEach, describe } = test let payload: PayloadTestSDK -let client: RESTClient let page: Page let serverURL: string // If we want to make this run in parallel: test.describe.configure({ mode: 'parallel' }) @@ -57,12 +55,6 @@ describe('Upload', () => { uploadsDir: path.resolve(dirname, './collections/Upload/uploads'), }) - if (client) { - await client.logout() - } - client = new RESTClient({ defaultSlug: 'users', serverURL }) - await client.login() - await ensureCompilationIsDone({ page, serverURL }) }) diff --git a/test/group-by/e2e.spec.ts b/test/group-by/e2e.spec.ts index 716f88316..e11d529df 100644 --- a/test/group-by/e2e.spec.ts +++ b/test/group-by/e2e.spec.ts @@ -57,17 +57,6 @@ test.describe('Group By', () => { password: devUser.password, }, }) - - // Fetch category IDs from already-seeded data - const categories = await payload.find({ - collection: 'categories', - limit: 1, - sort: 'title', - where: { title: { equals: 'Category 1' } }, - }) - - const [category1] = categories.docs - category1Id = category1?.id as number | string }) beforeEach(async () => { @@ -649,7 +638,12 @@ test.describe('Group By', () => { await firstTable.locator('.row-1 .cell-_select input').check() await firstTable.locator('.list-selection__button[aria-label="Delete"]').click() - const modalId = `[id^="${category1Id}-confirm-delete-many-docs"]` + const firstGroupID = await firstTable + .locator('.group-by-header__heading') + .getAttribute('data-group-id') + + const modalId = `[id^="${firstGroupID}-confirm-delete-many-docs"]` + await expect(page.locator(modalId)).toBeVisible() // Confirm trash (skip permanent delete) await page.locator(`${modalId} #confirm-action`).click() diff --git a/test/helpers/e2e/openListFilters.ts b/test/helpers/e2e/openListFilters.ts index 8d1cda257..ebd698ef4 100644 --- a/test/helpers/e2e/openListFilters.ts +++ b/test/helpers/e2e/openListFilters.ts @@ -18,6 +18,7 @@ export const openListFilters = async ( ): Promise<{ filterContainer: Locator }> => { + await expect(page.locator(togglerSelector)).toBeVisible() const filterContainer = page.locator(filterContainerSelector).first() const isAlreadyOpen = await filterContainer.isVisible() diff --git a/test/i18n/e2e.spec.ts b/test/i18n/e2e.spec.ts index f93bfb245..a57bd9f12 100644 --- a/test/i18n/e2e.spec.ts +++ b/test/i18n/e2e.spec.ts @@ -44,8 +44,8 @@ describe('i18n', () => { const context = await browser.newContext() page = await context.newPage() - initPageConsoleErrorCatch(page) + initPageConsoleErrorCatch(page) await ensureCompilationIsDone({ page, serverURL }) }) beforeEach(async () => { diff --git a/test/lexical/collections/RichText/e2e.spec.ts b/test/lexical/collections/RichText/e2e.spec.ts index 370efa4f7..2fcace2d7 100644 --- a/test/lexical/collections/RichText/e2e.spec.ts +++ b/test/lexical/collections/RichText/e2e.spec.ts @@ -13,7 +13,6 @@ import { import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js' import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js' import { reInitializeDB } from '../../../helpers/reInitializeDB.js' -import { RESTClient } from '../../../helpers/rest.js' import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../../../playwright.config.js' const filename = fileURLToPath(import.meta.url) @@ -22,7 +21,6 @@ const dirname = path.resolve(currentFolder, '../../') const { beforeAll, beforeEach, describe } = test -let client: RESTClient let page: Page let serverURL: string // If we want to make this run in parallel: test.describe.configure({ mode: 'parallel' }) @@ -48,12 +46,6 @@ describe('Rich Text', () => { uploadsDir: [path.resolve(dirname, './collections/Upload/uploads')], }) - if (client) { - await client.logout() - } - client = new RESTClient({ defaultSlug: 'users', serverURL }) - await client.login() - await ensureCompilationIsDone({ page, serverURL }) }) diff --git a/test/live-preview/e2e.spec.ts b/test/live-preview/e2e.spec.ts index ff761ad48..7415f55ed 100644 --- a/test/live-preview/e2e.spec.ts +++ b/test/live-preview/e2e.spec.ts @@ -66,6 +66,9 @@ describe('Live Preview', () => { const context = await browser.newContext() page = await context.newPage() + initPageConsoleErrorCatch(page) + await ensureCompilationIsDone({ page, serverURL }) + user = await payload .login({ collection: 'users', @@ -75,10 +78,6 @@ describe('Live Preview', () => { }, }) ?.then((res) => res.user) // TODO: this type is wrong - - initPageConsoleErrorCatch(page) - - await ensureCompilationIsDone({ page, serverURL }) }) beforeEach(async () => { diff --git a/test/localization/e2e.spec.ts b/test/localization/e2e.spec.ts index c2afa64e5..8a1d66361 100644 --- a/test/localization/e2e.spec.ts +++ b/test/localization/e2e.spec.ts @@ -86,11 +86,10 @@ describe('Localization', () => { page = await context.newPage() initPageConsoleErrorCatch(page) + await ensureCompilationIsDone({ page, serverURL }) client = new RESTClient({ defaultSlug: 'users', serverURL }) await client.login() - - await ensureCompilationIsDone({ page, serverURL }) }) beforeEach(async () => { diff --git a/test/query-presets/e2e.spec.ts b/test/query-presets/e2e.spec.ts index cb87dbaf6..ff1921734 100644 --- a/test/query-presets/e2e.spec.ts +++ b/test/query-presets/e2e.spec.ts @@ -58,6 +58,10 @@ describe('Query Presets', () => { context = await browser.newContext() page = await context.newPage() + initPageConsoleErrorCatch(page) + + await ensureCompilationIsDone({ page, serverURL }) + user = await payload .login({ collection: 'users', @@ -80,10 +84,6 @@ describe('Query Presets', () => { depth: 0, }) ?.then((res) => res.docs[0]) - - initPageConsoleErrorCatch(page) - - await ensureCompilationIsDone({ page, serverURL }) }) beforeEach(async () => {