chore(tests): flakey drawer, tab, navigation tests (#5792)
This commit is contained in:
@@ -429,7 +429,10 @@ describe('admin', () => {
|
||||
|
||||
test('collection — should render `id` as `useAsTitle` fallback', async () => {
|
||||
const { id } = await createPost()
|
||||
await page.goto(postsUrl.edit(id))
|
||||
const postURL = postsUrl.edit(id)
|
||||
await page.goto(postURL)
|
||||
await page.waitForURL(postURL)
|
||||
await wait(500)
|
||||
await page.locator('#field-title')?.fill('')
|
||||
await expect(page.locator('.doc-header__title.render-title:has-text("ID:")')).toBeVisible()
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
ensureAutoLoginAndCompilationIsDone,
|
||||
initPageConsoleErrorCatch,
|
||||
openDocControls,
|
||||
openDocDrawer,
|
||||
saveDocAndAssert,
|
||||
} from '../helpers.js'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
@@ -387,20 +388,15 @@ describe('fields - relationship', () => {
|
||||
})
|
||||
|
||||
test('should open document drawer from read-only relationships', async () => {
|
||||
await page.goto(url.edit(docWithExistingRelations.id))
|
||||
const editURL = url.edit(docWithExistingRelations.id)
|
||||
await page.goto(editURL)
|
||||
await page.waitForURL(editURL)
|
||||
|
||||
const field = page.locator('#field-relationshipReadOnly')
|
||||
|
||||
const button = field.locator(
|
||||
'button.relationship--single-value__drawer-toggler.doc-drawer__toggler',
|
||||
await openDocDrawer(
|
||||
page,
|
||||
'#field-relationshipReadOnly button.relationship--single-value__drawer-toggler.doc-drawer__toggler',
|
||||
)
|
||||
|
||||
await wait(1000)
|
||||
|
||||
await button.click()
|
||||
|
||||
await wait(1000)
|
||||
|
||||
const documentDrawer = page.locator('[id^=doc-drawer_relation-one_1_]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
})
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
ensureAutoLoginAndCompilationIsDone,
|
||||
exactText,
|
||||
initPageConsoleErrorCatch,
|
||||
openDocDrawer,
|
||||
saveDocAndAssert,
|
||||
saveDocHotkeyAndAssert,
|
||||
} from '../../../helpers.js'
|
||||
@@ -70,8 +71,8 @@ describe('relationship', () => {
|
||||
test('should create inline relationship within field with many relations', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
const button = page.locator('#relationship-add-new .relationship-add-new__add-button')
|
||||
await button.click()
|
||||
await openDocDrawer(page, '#relationship-add-new .relationship-add-new__add-button')
|
||||
|
||||
await page
|
||||
.locator('#field-relationship .relationship-add-new__relation-button--text-fields')
|
||||
.click()
|
||||
@@ -97,7 +98,7 @@ describe('relationship', () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(`**/${url.create}`)
|
||||
// Open first modal
|
||||
await page.locator('#relationToSelf-add-new .relationship-add-new__add-button').click()
|
||||
await openDocDrawer(page, '#relationToSelf-add-new .relationship-add-new__add-button')
|
||||
|
||||
// Fill first modal's required relationship field
|
||||
await page.locator('[id^=doc-drawer_relationship-fields_1_] #field-relationship').click()
|
||||
@@ -108,9 +109,10 @@ describe('relationship', () => {
|
||||
.click()
|
||||
|
||||
// Open second modal
|
||||
await page
|
||||
.locator('[id^=doc-drawer_relationship-fields_1_] #relationToSelf-add-new button')
|
||||
.click()
|
||||
await openDocDrawer(
|
||||
page,
|
||||
'[id^=doc-drawer_relationship-fields_1_] #relationToSelf-add-new button',
|
||||
)
|
||||
|
||||
// Fill second modal's required relationship field
|
||||
await page.locator('[id^=doc-drawer_relationship-fields_2_] #field-relationship').click()
|
||||
@@ -174,6 +176,7 @@ describe('relationship', () => {
|
||||
// TODO: React-Select not loading things sometimes. Fix later
|
||||
test.skip('should display `hasMany` polymorphic relationships', async () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(url.create)
|
||||
const field = page.locator('#field-relationHasManyPolymorphic')
|
||||
await field.click()
|
||||
|
||||
@@ -209,6 +212,7 @@ describe('relationship', () => {
|
||||
|
||||
test('should populate relationship dynamic default value', async () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(url.create)
|
||||
await expect(
|
||||
page.locator('#field-relationWithDynamicDefault .relationship--single-value__text'),
|
||||
).toContainText('dev@payloadcms.com')
|
||||
@@ -230,7 +234,7 @@ describe('relationship', () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(`**/${url.create}`)
|
||||
// First fill out the relationship field, as it's required
|
||||
await page.locator('#relationship-add-new .relationship-add-new__add-button').click()
|
||||
await openDocDrawer(page, '#relationship-add-new .relationship-add-new__add-button')
|
||||
await page
|
||||
.locator('#field-relationship .relationship-add-new__relation-button--text-fields')
|
||||
.click()
|
||||
@@ -245,7 +249,7 @@ describe('relationship', () => {
|
||||
|
||||
// Create a new doc for the `relationshipHasMany` field
|
||||
await expect.poll(() => page.url(), { timeout: POLL_TOPASS_TIMEOUT }).not.toContain('create')
|
||||
await page.locator('#field-relationshipHasMany .relationship-add-new__add-button').click()
|
||||
await openDocDrawer(page, '#field-relationshipHasMany .relationship-add-new__add-button')
|
||||
const value = 'Hello, world!'
|
||||
await page.locator('.drawer__content #field-text').fill(value)
|
||||
|
||||
@@ -293,7 +297,8 @@ describe('relationship', () => {
|
||||
// opened through the edit button can be saved using the hotkey.
|
||||
test('should save using hotkey in edit document drawer', async () => {
|
||||
await page.goto(url.create)
|
||||
await wait(500)
|
||||
// First fill out the relationship field, as it's required
|
||||
await openDocDrawer(page, '#relationship-add-new .relationship-add-new__add-button')
|
||||
await page.locator('#field-relationship .value-container').click()
|
||||
await wait(500)
|
||||
// Select "Seeded text document" relationship
|
||||
@@ -334,7 +339,7 @@ describe('relationship', () => {
|
||||
test.skip('should bypass min rows validation when no rows present and field is not required', async () => {
|
||||
await page.goto(url.create)
|
||||
// First fill out the relationship field, as it's required
|
||||
await page.locator('#relationship-add-new .relationship-add-new__add-button').click()
|
||||
await openDocDrawer(page, '#relationship-add-new .relationship-add-new__add-button')
|
||||
await page.locator('#field-relationship .value-container').click()
|
||||
await page.getByText('Seeded text document', { exact: true }).click()
|
||||
|
||||
@@ -344,8 +349,9 @@ describe('relationship', () => {
|
||||
|
||||
test('should fail min rows validation when rows are present', async () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(url.create)
|
||||
// First fill out the relationship field, as it's required
|
||||
await page.locator('#relationship-add-new .relationship-add-new__add-button').click()
|
||||
await openDocDrawer(page, '#relationship-add-new .relationship-add-new__add-button')
|
||||
await page.locator('#field-relationship .value-container').click()
|
||||
await page.getByText('Seeded text document', { exact: true }).click()
|
||||
|
||||
@@ -366,26 +372,28 @@ describe('relationship', () => {
|
||||
|
||||
test('should sort relationship options by sortOptions property (ID in ascending order)', async () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(url.create)
|
||||
|
||||
const field = page.locator('#field-relationship')
|
||||
await field.click()
|
||||
|
||||
const firstOption = page.locator('.rs__option').first()
|
||||
await expect(firstOption).toBeVisible()
|
||||
const firstOptionText = await firstOption.textContent()
|
||||
expect(firstOptionText.trim()).toBe('Another text document')
|
||||
const textDocsGroup = page.locator('.rs__group-heading:has-text("Text Fields")')
|
||||
const firstTextDocOption = textDocsGroup.locator('+div .rs__option').first()
|
||||
const firstOptionLabel = await firstTextDocOption.textContent()
|
||||
expect(firstOptionLabel.trim()).toBe('Another text document')
|
||||
})
|
||||
|
||||
test('should sort relationHasManyPolymorphic options by sortOptions property: text-fields collection (items in descending order)', async () => {
|
||||
await page.goto(url.create)
|
||||
await page.waitForURL(url.create)
|
||||
|
||||
const field = page.locator('#field-relationHasManyPolymorphic')
|
||||
await field.click()
|
||||
|
||||
const firstOption = page.locator('.rs__option').first()
|
||||
await expect(firstOption).toBeVisible()
|
||||
const firstOptionText = await firstOption.textContent()
|
||||
expect(firstOptionText.trim()).toBe('Seeded text document')
|
||||
const textDocsGroup = page.locator('.rs__group-heading:has-text("Text Fields")')
|
||||
const firstTextDocOption = textDocsGroup.locator('+div .rs__option').first()
|
||||
const firstOptionLabel = await firstTextDocOption.textContent()
|
||||
expect(firstOptionLabel).toBe('Seeded text document')
|
||||
})
|
||||
|
||||
test('should allow filtering by relationship field / equals', async () => {
|
||||
@@ -393,6 +401,7 @@ describe('relationship', () => {
|
||||
await createRelationshipFieldDoc({ value: textDoc.id, relationTo: 'text-fields' })
|
||||
|
||||
await page.goto(url.list)
|
||||
await page.waitForURL(url.list)
|
||||
|
||||
await page.locator('.list-controls__toggle-columns').click()
|
||||
await page.locator('.list-controls__toggle-where').click()
|
||||
|
||||
@@ -685,10 +685,7 @@ describe('fields', () => {
|
||||
|
||||
// enter date in default date field
|
||||
await dateField.fill('02/07/2023')
|
||||
await page.locator('#action-save').click()
|
||||
|
||||
// wait for navigation to update route
|
||||
await expect.poll(() => page.url(), { timeout: 1000 }).not.toContain('create')
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
// get the ID of the doc
|
||||
const routeSegments = page.url().split('/')
|
||||
|
||||
@@ -131,8 +131,9 @@ export async function openNav(page: Page): Promise<void> {
|
||||
}
|
||||
|
||||
export async function openDocDrawer(page: Page, selector: string): Promise<void> {
|
||||
await page.locator(selector).click()
|
||||
await wait(1000) // wait for drawer form state to initialize
|
||||
await wait(300) // wait for parent form state to initialize
|
||||
await page.locator(selector).click({ delay: 100 })
|
||||
await wait(500) // wait for drawer form state to initializ
|
||||
}
|
||||
|
||||
export async function closeNav(page: Page): Promise<void> {
|
||||
|
||||
@@ -3,11 +3,11 @@ import type { Endpoint, PayloadHandler } from 'payload/config'
|
||||
import httpStatus from 'http-status'
|
||||
|
||||
export const handler: PayloadHandler = async ({ payload, data, user }) => {
|
||||
const method = String(data.method)
|
||||
const operation = String(data.operation)
|
||||
|
||||
if (typeof payload[method] === 'function') {
|
||||
if (typeof payload[operation] === 'function') {
|
||||
try {
|
||||
const result = await payload[method]({
|
||||
const result = await payload[operation]({
|
||||
...(typeof data.args === 'object' ? data.args : {}),
|
||||
user,
|
||||
})
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
FindArgs,
|
||||
GeneratedTypes,
|
||||
UpdateArgs,
|
||||
UpdateGlobalArgs,
|
||||
} from './types.js'
|
||||
|
||||
type Args = {
|
||||
@@ -15,7 +16,7 @@ type Args = {
|
||||
}
|
||||
|
||||
export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTypes>> {
|
||||
private fetch = async <T>({ jwt, reduceJSON, args, method }: FetchOptions): Promise<T> => {
|
||||
private fetch = async <T>({ jwt, reduceJSON, args, operation }: FetchOptions): Promise<T> => {
|
||||
const headers: HeadersInit = {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
@@ -27,7 +28,7 @@ export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTyp
|
||||
headers,
|
||||
body: JSON.stringify({
|
||||
args,
|
||||
method,
|
||||
operation,
|
||||
}),
|
||||
}).then((res) => res.json())
|
||||
|
||||
@@ -41,7 +42,7 @@ export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTyp
|
||||
...args
|
||||
}: CreateArgs<TGeneratedTypes, T>) => {
|
||||
return this.fetch<TGeneratedTypes['collections'][T]>({
|
||||
method: 'create',
|
||||
operation: 'create',
|
||||
args,
|
||||
jwt,
|
||||
})
|
||||
@@ -52,7 +53,7 @@ export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTyp
|
||||
...args
|
||||
}: DeleteArgs<TGeneratedTypes, T>) => {
|
||||
return this.fetch<PaginatedDocs<TGeneratedTypes['collections'][T]>>({
|
||||
method: 'delete',
|
||||
operation: 'delete',
|
||||
args,
|
||||
jwt,
|
||||
})
|
||||
@@ -63,7 +64,7 @@ export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTyp
|
||||
...args
|
||||
}: FindArgs<TGeneratedTypes, T>) => {
|
||||
return this.fetch<PaginatedDocs<TGeneratedTypes['collections'][T]>>({
|
||||
method: 'find',
|
||||
operation: 'find',
|
||||
args,
|
||||
jwt,
|
||||
})
|
||||
@@ -71,7 +72,7 @@ export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTyp
|
||||
|
||||
sendEmail = async ({ jwt, ...args }: { jwt?: string } & SendMailOptions): Promise<unknown> => {
|
||||
return this.fetch({
|
||||
method: 'sendEmail',
|
||||
operation: 'sendEmail',
|
||||
args,
|
||||
jwt,
|
||||
})
|
||||
@@ -84,7 +85,18 @@ export class PayloadTestSDK<TGeneratedTypes extends GeneratedTypes<TGeneratedTyp
|
||||
...args
|
||||
}: UpdateArgs<TGeneratedTypes, T>) => {
|
||||
return this.fetch<TGeneratedTypes['collections'][T]>({
|
||||
method: 'update',
|
||||
operation: 'update',
|
||||
args,
|
||||
jwt,
|
||||
})
|
||||
}
|
||||
|
||||
updateGlobal = async <T extends keyof TGeneratedTypes['globals']>({
|
||||
jwt,
|
||||
...args
|
||||
}: UpdateGlobalArgs<TGeneratedTypes, T>) => {
|
||||
return this.fetch<TGeneratedTypes['collections'][T]>({
|
||||
operation: 'updateGlobal',
|
||||
args,
|
||||
jwt,
|
||||
})
|
||||
|
||||
@@ -25,7 +25,7 @@ export type GeneratedTypes<T extends BaseTypes> = {
|
||||
export type FetchOptions = {
|
||||
args?: Record<string, unknown>
|
||||
jwt?: string
|
||||
method: 'create' | 'delete' | 'find' | 'sendEmail' | 'update'
|
||||
operation: 'create' | 'delete' | 'find' | 'sendEmail' | 'update' | 'updateGlobal'
|
||||
reduceJSON?: <R>(json: any) => R
|
||||
}
|
||||
|
||||
@@ -94,6 +94,14 @@ export type UpdateArgs<
|
||||
TSlug extends keyof TGeneratedTypes['collections'],
|
||||
> = UpdateByIDArgs<TGeneratedTypes, TSlug> | UpdateManyArgs<TGeneratedTypes, TSlug>
|
||||
|
||||
export type UpdateGlobalArgs<
|
||||
TGeneratedTypes extends GeneratedTypes<TGeneratedTypes>,
|
||||
TSlug extends keyof TGeneratedTypes['globals'],
|
||||
> = {
|
||||
data: DeepPartial<TGeneratedTypes['globals'][TSlug]>
|
||||
slug: TSlug
|
||||
} & BaseArgs
|
||||
|
||||
export type FindArgs<
|
||||
TGeneratedTypes extends GeneratedTypes<TGeneratedTypes>,
|
||||
TSlug extends keyof TGeneratedTypes['collections'],
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useLivePreview } from '@payloadcms/live-preview-react'
|
||||
import React from 'react'
|
||||
|
||||
import type { Page as PageType } from '../../../../test/live-preview/payload-types.js'
|
||||
import type { Page as PageType } from '../../../../payload-types.js'
|
||||
|
||||
import { PAYLOAD_SERVER_URL } from '../../_api/serverURL.js'
|
||||
import { Blocks } from '../../_components/Blocks/index.js'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { notFound } from 'next/navigation.js'
|
||||
import React from 'react'
|
||||
|
||||
import type { Page } from '../../../../test/live-preview/payload-types.js'
|
||||
import type { Page } from '../../../../payload-types.js'
|
||||
|
||||
import { fetchDoc } from '../../_api/fetchDoc.js'
|
||||
import { fetchDocs } from '../../_api/fetchDocs.js'
|
||||
@@ -28,6 +28,7 @@ export default async function Page({ params: { slug = 'home' } }) {
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
process.env.PAYLOAD_DROP_DATABASE = 'false'
|
||||
try {
|
||||
const pages = await fetchDocs<Page>('pages')
|
||||
return pages?.map(({ slug }) => slug)
|
||||
|
||||
@@ -27,6 +27,7 @@ export default async function Post({ params: { slug = '' } }) {
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
process.env.PAYLOAD_DROP_DATABASE = 'false'
|
||||
try {
|
||||
const posts = await fetchDocs<Post>('posts')
|
||||
return posts?.map(({ slug }) => slug)
|
||||
|
||||
@@ -214,6 +214,7 @@ describe('uploads', () => {
|
||||
await page.waitForURL(audioURL.edit(audioDoc.id))
|
||||
|
||||
// remove the selection and open the list drawer
|
||||
await wait(500) // flake workaround
|
||||
await page.locator('.file-details__remove').click()
|
||||
|
||||
await openDocDrawer(page, '.upload__toggler.list-drawer__toggler')
|
||||
|
||||
Reference in New Issue
Block a user