chore: unflake access-control, fix incorrect poll & toPass timeouts
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
import type { Page } from '@playwright/test'
|
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 { expect, test } from '@playwright/test'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/utilities'
|
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
import type { ReadOnlyCollection, RestrictedVersion } from './payload-types.js'
|
import type { ReadOnlyCollection, RestrictedVersion } from './payload-types.js'
|
||||||
@@ -134,7 +133,6 @@ describe('access control', () => {
|
|||||||
describe('restricted fields', () => {
|
describe('restricted fields', () => {
|
||||||
test('should not show field without permission', async () => {
|
test('should not show field without permission', async () => {
|
||||||
await page.goto(url.account)
|
await page.goto(url.account)
|
||||||
await wait(500)
|
|
||||||
await expect(page.locator('#field-roles')).toBeHidden()
|
await expect(page.locator('#field-roles')).toBeHidden()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -163,7 +161,7 @@ describe('access control', () => {
|
|||||||
|
|
||||||
test('should have collection url', async () => {
|
test('should have collection url', async () => {
|
||||||
await page.goto(readOnlyUrl.list)
|
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 () => {
|
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 () => {
|
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 page.goto(readOnlyUrl.edit(existingDoc.id))
|
||||||
await wait(1000)
|
|
||||||
await expect(page.locator('.collection-edit .doc-controls .doc-controls__popup')).toBeHidden()
|
await expect(page.locator('.collection-edit .doc-controls .doc-controls__popup')).toBeHidden()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -213,7 +210,7 @@ describe('access control', () => {
|
|||||||
|
|
||||||
describe('doc level access', () => {
|
describe('doc level access', () => {
|
||||||
let existingDoc: ReadOnlyCollection
|
let existingDoc: ReadOnlyCollection
|
||||||
let docLevelAccessURL
|
let docLevelAccessURL: AdminUrlUtil
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
docLevelAccessURL = new AdminUrlUtil(serverURL, docLevelAccessSlug)
|
docLevelAccessURL = new AdminUrlUtil(serverURL, docLevelAccessSlug)
|
||||||
@@ -265,28 +262,26 @@ describe('access control', () => {
|
|||||||
const unrestrictedURL = new AdminUrlUtil(serverURL, unrestrictedSlug)
|
const unrestrictedURL = new AdminUrlUtil(serverURL, unrestrictedSlug)
|
||||||
await page.goto(unrestrictedURL.edit(unrestrictedDoc.id))
|
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',
|
'#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_]')
|
const documentDrawer = page.locator('[id^=doc-drawer_user-restricted_1_]')
|
||||||
await expect(documentDrawer).toBeVisible()
|
await expect(documentDrawer).toBeVisible()
|
||||||
await documentDrawer.locator('#field-name').fill('anonymous@email.com')
|
await documentDrawer.locator('#field-name').fill('anonymous@email.com')
|
||||||
await documentDrawer.locator('#action-save').click()
|
await documentDrawer.locator('#action-save').click()
|
||||||
await wait(200)
|
|
||||||
await expect(page.locator('.Toastify')).toContainText('successfully')
|
await expect(page.locator('.Toastify')).toContainText('successfully')
|
||||||
|
|
||||||
// ensure user is not allowed to edit this document
|
// ensure user is not allowed to edit this document
|
||||||
await expect(documentDrawer.locator('#field-name')).toBeDisabled()
|
await expect(documentDrawer.locator('#field-name')).toBeDisabled()
|
||||||
await documentDrawer.locator('button.doc-drawer__header-close').click()
|
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_]')
|
const documentDrawer2 = page.locator('[id^=doc-drawer_user-restricted_1_]')
|
||||||
await expect(documentDrawer2).toBeVisible()
|
await expect(documentDrawer2).toBeVisible()
|
||||||
await documentDrawer2.locator('#field-name').fill('dev@payloadcms.com')
|
await documentDrawer2.locator('#field-name').fill('dev@payloadcms.com')
|
||||||
await documentDrawer2.locator('#action-save').click()
|
await documentDrawer2.locator('#action-save').click()
|
||||||
await wait(200)
|
|
||||||
await expect(page.locator('.Toastify')).toContainText('successfully')
|
await expect(page.locator('.Toastify')).toContainText('successfully')
|
||||||
|
|
||||||
// ensure user is allowed to edit this document
|
// 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<TypeWithID & Record<string, unknown>> {
|
||||||
return payload.create({
|
return payload.create({
|
||||||
collection: slug,
|
collection: slug,
|
||||||
data,
|
data,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'url'
|
|||||||
import { delayNetwork, initPageConsoleErrorCatch, login, saveDocAndAssert } from '../helpers.js'
|
import { delayNetwork, initPageConsoleErrorCatch, login, saveDocAndAssert } from '../helpers.js'
|
||||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||||
import { initPayloadE2E } from '../helpers/initPayloadE2E.js'
|
import { initPayloadE2E } from '../helpers/initPayloadE2E.js'
|
||||||
|
import { POLL_TOPASS_TIMEOUT } from '../playwright.config.js'
|
||||||
import config from './config.js'
|
import config from './config.js'
|
||||||
import { apiKeysSlug, slug } from './shared.js'
|
import { apiKeysSlug, slug } from './shared.js'
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
@@ -105,7 +106,7 @@ describe('auth', () => {
|
|||||||
// assert that the value is set
|
// assert that the value is set
|
||||||
const apiKeyLocator = page.locator('#apiKey')
|
const apiKeyLocator = page.locator('#apiKey')
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => await apiKeyLocator.inputValue(), { timeout: 45000 })
|
.poll(async () => await apiKeyLocator.inputValue(), { timeout: POLL_TOPASS_TIMEOUT })
|
||||||
.toBeDefined()
|
.toBeDefined()
|
||||||
|
|
||||||
await saveDocAndAssert(page)
|
await saveDocAndAssert(page)
|
||||||
@@ -114,7 +115,7 @@ describe('auth', () => {
|
|||||||
const apiKey = await apiKeyLocator.inputValue()
|
const apiKey = await apiKeyLocator.inputValue()
|
||||||
expect(await page.locator('#apiKey').inputValue()).toStrictEqual(apiKey)
|
expect(await page.locator('#apiKey').inputValue()).toStrictEqual(apiKey)
|
||||||
}).toPass({
|
}).toPass({
|
||||||
timeout: 45000,
|
timeout: POLL_TOPASS_TIMEOUT,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ describe('auth', () => {
|
|||||||
|
|
||||||
expect(response.user).toBeNull()
|
expect(response.user).toBeNull()
|
||||||
}).toPass({
|
}).toPass({
|
||||||
timeout: 45000,
|
timeout: POLL_TOPASS_TIMEOUT,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { wait } from 'payload/utilities'
|
|||||||
import shelljs from 'shelljs'
|
import shelljs from 'shelljs'
|
||||||
|
|
||||||
import { devUser } from './credentials.js'
|
import { devUser } from './credentials.js'
|
||||||
|
import { POLL_TOPASS_TIMEOUT } from './playwright.config.js'
|
||||||
|
|
||||||
type FirstRegisterArgs = {
|
type FirstRegisterArgs = {
|
||||||
page: Page
|
page: Page
|
||||||
@@ -91,7 +92,7 @@ export async function saveDocHotkeyAndAssert(page: Page): Promise<void> {
|
|||||||
export async function saveDocAndAssert(page: Page, selector = '#action-save'): Promise<void> {
|
export async function saveDocAndAssert(page: Page, selector = '#action-save'): Promise<void> {
|
||||||
await page.click(selector, { delay: 100 })
|
await page.click(selector, { delay: 100 })
|
||||||
await expect(page.locator('.Toastify')).toContainText('successfully')
|
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<void> {
|
export async function openNav(page: Page): Promise<void> {
|
||||||
@@ -137,7 +138,7 @@ export function exactText(text: string) {
|
|||||||
export const checkPageTitle = async (page: Page, title: string) => {
|
export const checkPageTitle = async (page: Page, title: string) => {
|
||||||
await expect
|
await expect
|
||||||
.poll(async () => await page.locator('.doc-header__title.render-title')?.first()?.innerText(), {
|
.poll(async () => await page.locator('.doc-header__title.render-title')?.first()?.innerText(), {
|
||||||
timeout: 45000,
|
timeout: POLL_TOPASS_TIMEOUT,
|
||||||
})
|
})
|
||||||
.toBe(title)
|
.toBe(title)
|
||||||
}
|
}
|
||||||
@@ -147,7 +148,7 @@ export const checkBreadcrumb = async (page: Page, text: string) => {
|
|||||||
.poll(
|
.poll(
|
||||||
async () => await page.locator('.step-nav.app-header__step-nav .step-nav__last')?.innerText(),
|
async () => await page.locator('.step-nav.app-header__step-nav .step-nav__last')?.innerText(),
|
||||||
{
|
{
|
||||||
timeout: 45000,
|
timeout: POLL_TOPASS_TIMEOUT,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.toBe(text)
|
.toBe(text)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export class AdminUrlUtil {
|
|||||||
constructor(serverURL: string, slug: string) {
|
constructor(serverURL: string, slug: string) {
|
||||||
this.account = `${serverURL}/admin/account`
|
this.account = `${serverURL}/admin/account`
|
||||||
this.admin = `${serverURL}/admin`
|
this.admin = `${serverURL}/admin`
|
||||||
this.list = `${this.admin}/collections/${slug}?limit=10`
|
this.list = `${this.admin}/collections/${slug}`
|
||||||
this.create = `${this.list}/create`
|
this.create = `${this.list}/create`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { defineConfig } from '@playwright/test'
|
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({
|
export default defineConfig({
|
||||||
// Look for test files in the "test" directory, relative to this configuration file
|
// Look for test files in the "test" directory, relative to this configuration file
|
||||||
testDir: '',
|
testDir: '',
|
||||||
@@ -11,7 +14,7 @@ export default defineConfig({
|
|||||||
video: 'retain-on-failure',
|
video: 'retain-on-failure',
|
||||||
},
|
},
|
||||||
expect: {
|
expect: {
|
||||||
timeout: 60000,
|
timeout: EXPECT_TIMEOUT,
|
||||||
},
|
},
|
||||||
workers: 16,
|
workers: 16,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user