chore: ensures artifacts work
This commit is contained in:
8
.github/workflows/main.yml
vendored
8
.github/workflows/main.yml
vendored
@@ -256,10 +256,10 @@ jobs:
|
||||
# - field-error-states
|
||||
# - fields-relationship
|
||||
- fields
|
||||
- fields/collections/Blocks
|
||||
- fields/collections/Array
|
||||
- fields/collections/Relationship
|
||||
- fields/collections/Lexical
|
||||
- fields__collections__Blocks
|
||||
- fields__collections__Array
|
||||
- fields__collections__Relationship
|
||||
- fields__collections__Lexical
|
||||
# - live-preview
|
||||
# - localization
|
||||
# - plugin-form-builder
|
||||
|
||||
413
test/fields/collections/RichText/e2e.spec.ts
Normal file
413
test/fields/collections/RichText/e2e.spec.ts
Normal file
@@ -0,0 +1,413 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect, test } from '@playwright/test'
|
||||
import path from 'path'
|
||||
import { wait } from 'payload/utilities'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import {
|
||||
ensureAutoLoginAndCompilationIsDone,
|
||||
initPageConsoleErrorCatch,
|
||||
saveDocAndAssert,
|
||||
} from '../../../helpers.js'
|
||||
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
|
||||
import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js'
|
||||
import { reInitializeDB } from '../../../helpers/reInit.js'
|
||||
import { RESTClient } from '../../../helpers/rest.js'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const currentFolder = path.dirname(filename)
|
||||
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' })
|
||||
|
||||
describe('Rich Text', () => {
|
||||
beforeAll(async ({ browser }) => {
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
;({ serverURL } = await initPayloadE2ENoConfig({
|
||||
dirname,
|
||||
}))
|
||||
|
||||
const context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
initPageConsoleErrorCatch(page)
|
||||
})
|
||||
beforeEach(async () => {
|
||||
await reInitializeDB({
|
||||
serverURL,
|
||||
snapshotKey: 'fieldsRichTextTest',
|
||||
uploadsDir: path.resolve(dirname, '../Upload/uploads'),
|
||||
})
|
||||
|
||||
if (client) {
|
||||
await client.logout()
|
||||
}
|
||||
client = new RESTClient(null, { defaultSlug: 'users', serverURL })
|
||||
await client.login()
|
||||
|
||||
await ensureAutoLoginAndCompilationIsDone({ page, serverURL })
|
||||
})
|
||||
|
||||
async function navigateToRichTextFields() {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields')
|
||||
await page.goto(url.list)
|
||||
await page.waitForURL(url.list)
|
||||
await page.locator('.row-1 .cell-title a').click()
|
||||
}
|
||||
|
||||
describe('cell', () => {
|
||||
test('ensure cells are smaller than 300px in height', async () => {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields')
|
||||
await page.goto(url.list) // Navigate to rich-text list view
|
||||
|
||||
const table = page.locator('.list-controls ~ .table')
|
||||
const lexicalCell = table.locator('.cell-lexicalCustomFields').first()
|
||||
const lexicalHtmlCell = table.locator('.cell-lexicalCustomFields_html').first()
|
||||
const entireRow = table.locator('.row-1').first()
|
||||
|
||||
// Make sure each of the 3 above are no larger than 300px in height:
|
||||
expect((await lexicalCell.boundingBox()).height).toBeLessThanOrEqual(300)
|
||||
expect((await lexicalHtmlCell.boundingBox()).height).toBeLessThanOrEqual(300)
|
||||
expect((await entireRow.boundingBox()).height).toBeLessThanOrEqual(300)
|
||||
})
|
||||
})
|
||||
|
||||
describe('toolbar', () => {
|
||||
test('should run url validation', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
// Fill values and click Confirm
|
||||
await editLinkModal.locator('#field-text').fill('link text')
|
||||
await editLinkModal.locator('label[for="field-linkType-custom"]').click()
|
||||
await editLinkModal.locator('#field-url').fill('')
|
||||
await wait(200)
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await wait(400)
|
||||
const errorField = page.locator(
|
||||
'[id^=drawer_1_rich-text-link-] .render-fields > :nth-child(3)',
|
||||
)
|
||||
const hasErrorClass = await errorField.evaluate((el) => el.classList.contains('error'))
|
||||
expect(hasErrorClass).toBe(true)
|
||||
})
|
||||
|
||||
test('should create new url custom link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
await wait(400)
|
||||
// Fill values and click Confirm
|
||||
await editLinkModal.locator('#field-text').fill('link text')
|
||||
await editLinkModal.locator('label[for="field-linkType-custom"]').click()
|
||||
await editLinkModal.locator('#field-url').fill('https://payloadcms.com')
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await wait(400)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
// Remove link from editor body
|
||||
await page.locator('span >> text="link text"').click()
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup.locator('.rich-text-link__link-label')).toBeVisible()
|
||||
await popup.locator('.rich-text-link__link-close').click()
|
||||
await expect(page.locator('span >> text="link text"')).toHaveCount(0)
|
||||
})
|
||||
|
||||
test('should create new internal link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
await wait(400)
|
||||
|
||||
// Fill values and click Confirm
|
||||
await editLinkModal.locator('#field-text').fill('link text')
|
||||
await editLinkModal.locator('label[for="field-linkType-internal"]').click()
|
||||
await editLinkModal.locator('#field-doc .rs__control').click()
|
||||
await page.keyboard.type('dev@')
|
||||
await editLinkModal
|
||||
.locator('#field-doc .rs__menu .rs__option:has-text("dev@payloadcms.com")')
|
||||
.click()
|
||||
// await wait(200);
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await saveDocAndAssert(page)
|
||||
})
|
||||
|
||||
test('should not create new url link when read only', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Attempt to open link popup
|
||||
const modalTrigger = page.locator('.rich-text--read-only .rich-text__toolbar button .link')
|
||||
await expect(modalTrigger).toBeDisabled()
|
||||
})
|
||||
|
||||
test('should only list RTE enabled upload collections in drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page
|
||||
.locator('.rich-text__toolbar button:not([disabled]) .upload-rich-text-button')
|
||||
.first()
|
||||
.click()
|
||||
|
||||
// open the list select menu
|
||||
await page.locator('.list-drawer__select-collection-wrap .rs__control').click()
|
||||
|
||||
const menu = page.locator('.list-drawer__select-collection-wrap .rs__menu')
|
||||
// `uploads-3` has enableRichTextRelationship set to false
|
||||
await expect(menu).not.toContainText('Uploads3')
|
||||
})
|
||||
|
||||
// TODO: this test can't find the selector for the search filter, but functionality works.
|
||||
// Need to debug
|
||||
test.skip('should search correct useAsTitle field after toggling collection in list drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// open link drawer
|
||||
const field = page.locator('#field-richText')
|
||||
const button = field.locator(
|
||||
'button.rich-text-relationship__list-drawer-toggler.list-drawer__toggler',
|
||||
)
|
||||
await button.click()
|
||||
|
||||
// check that the search is on the `name` field of the `text-fields` collection
|
||||
const drawer = page.locator('[id^=list-drawer_1_]')
|
||||
|
||||
await expect(drawer.locator('.search-filter__input')).toHaveAttribute(
|
||||
'placeholder',
|
||||
'Search by Text',
|
||||
)
|
||||
|
||||
// change the selected collection to `array-fields`
|
||||
await page.locator('.list-drawer__select-collection-wrap .rs__control').click()
|
||||
const menu = page.locator('.list-drawer__select-collection-wrap .rs__menu')
|
||||
await menu.locator('.rs__option').getByText('Array Field').click()
|
||||
|
||||
// check that `id` is now the default search field
|
||||
await expect(drawer.locator('.search-filter__input')).toHaveAttribute(
|
||||
'placeholder',
|
||||
'Search by ID',
|
||||
)
|
||||
})
|
||||
|
||||
test('should only list RTE enabled collections in link drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
await editLinkModal.locator('label[for="field-linkType-internal"]').click()
|
||||
await editLinkModal.locator('.relationship__wrap .rs__control').click()
|
||||
|
||||
const menu = page.locator('.relationship__wrap .rs__menu')
|
||||
|
||||
// array-fields has enableRichTextLink set to false
|
||||
await expect(menu).not.toContainText('Array Fields')
|
||||
})
|
||||
|
||||
test('should only list non-upload collections in relationship drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page
|
||||
.locator('.rich-text__toolbar button:not([disabled]) .relationship-rich-text-button')
|
||||
.first()
|
||||
.click()
|
||||
|
||||
await wait(300)
|
||||
|
||||
// open the list select menu
|
||||
await page.locator('.list-drawer__select-collection-wrap .rs__control').click()
|
||||
|
||||
const menu = page.locator('.list-drawer__select-collection-wrap .rs__menu')
|
||||
await expect(menu).not.toContainText('Uploads')
|
||||
})
|
||||
|
||||
test('should respect customizing the default fields', async () => {
|
||||
const linkText = 'link'
|
||||
const value = 'test value'
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('.rich-text', {
|
||||
has: page.locator('#field-richTextCustomFields'),
|
||||
})
|
||||
// open link drawer
|
||||
const button = field.locator('button.rich-text__button.link')
|
||||
await button.click()
|
||||
|
||||
// fill link fields
|
||||
const linkDrawer = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
const fields = linkDrawer.locator('.render-fields > .field-type')
|
||||
await fields.locator('#field-text').fill(linkText)
|
||||
await fields.locator('#field-url').fill('https://payloadcms.com')
|
||||
const input = fields.locator('#field-fields__customLinkField')
|
||||
await input.fill(value)
|
||||
|
||||
await wait(300)
|
||||
|
||||
// submit link closing drawer
|
||||
await linkDrawer.locator('button[type="submit"]').click()
|
||||
const linkInEditor = field.locator(`.rich-text-link >> text="${linkText}"`)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
// open modal again
|
||||
await linkInEditor.click()
|
||||
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup).toBeVisible()
|
||||
|
||||
await popup.locator('.rich-text-link__link-edit').click()
|
||||
|
||||
const linkDrawer2 = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
const fields2 = linkDrawer2.locator('.render-fields > .field-type')
|
||||
const input2 = fields2.locator('#field-fields__customLinkField')
|
||||
|
||||
await expect(input2).toHaveValue(value)
|
||||
})
|
||||
})
|
||||
|
||||
describe('editor', () => {
|
||||
test('should populate url link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link popup
|
||||
await page.locator('#field-richText span >> text="render links"').click()
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup).toBeVisible()
|
||||
await expect(popup.locator('a')).toHaveAttribute('href', 'https://payloadcms.com')
|
||||
|
||||
// Open the drawer
|
||||
await popup.locator('.rich-text-link__link-edit').click()
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
// Check the drawer values
|
||||
const textField = editLinkModal.locator('#field-text')
|
||||
await expect(textField).toHaveValue('render links')
|
||||
|
||||
// Close the drawer
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await expect(editLinkModal).toBeHidden()
|
||||
})
|
||||
|
||||
test('should populate relationship link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link popup
|
||||
await page.locator('#field-richText span >> text="link to relationships"').click()
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup).toBeVisible()
|
||||
await expect(popup.locator('a')).toHaveAttribute(
|
||||
'href',
|
||||
/\/admin\/collections\/array-fields\/.*/,
|
||||
)
|
||||
|
||||
// Open the drawer
|
||||
await popup.locator('.rich-text-link__link-edit').click()
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
// Check the drawer values
|
||||
const textField = editLinkModal.locator('#field-text')
|
||||
await expect(textField).toHaveValue('link to relationships')
|
||||
})
|
||||
|
||||
test('should open upload drawer and render custom relationship fields', async () => {
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('#field-richText')
|
||||
const button = field.locator('button.rich-text-upload__upload-drawer-toggler')
|
||||
|
||||
await button.click()
|
||||
|
||||
const documentDrawer = page.locator('[id^=drawer_1_upload-drawer-]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
const caption = documentDrawer.locator('#field-caption')
|
||||
await expect(caption).toBeVisible()
|
||||
})
|
||||
|
||||
test('should open upload document drawer from read-only field', async () => {
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('#field-richTextReadOnly')
|
||||
const button = field.locator(
|
||||
'button.rich-text-upload__doc-drawer-toggler.doc-drawer__toggler',
|
||||
)
|
||||
|
||||
await button.click()
|
||||
|
||||
const documentDrawer = page.locator('[id^=doc-drawer_uploads_1_]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
})
|
||||
|
||||
test('should open relationship document drawer from read-only field', async () => {
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('#field-richTextReadOnly')
|
||||
const button = field.locator(
|
||||
'button.rich-text-relationship__doc-drawer-toggler.doc-drawer__toggler',
|
||||
)
|
||||
|
||||
await button.click()
|
||||
|
||||
const documentDrawer = page.locator('[id^=doc-drawer_text-fields_1_]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
})
|
||||
|
||||
test('should populate new links', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Highlight existing text
|
||||
const headingElement = page.locator(
|
||||
'#field-richText h1 >> text="Hello, I\'m a rich text field."',
|
||||
)
|
||||
await headingElement.selectText()
|
||||
|
||||
// click the toolbar link button
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer and confirm the values
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
const textField = editLinkModal.locator('#field-text')
|
||||
await expect(textField).toHaveValue("Hello, I'm a rich text field.")
|
||||
})
|
||||
test('should not take value from previous block', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// check first block value
|
||||
const textField = page.locator('#field-blocks__0__text')
|
||||
await expect(textField).toHaveValue('Regular text')
|
||||
|
||||
// remove the first block
|
||||
const editBlock = page.locator('#blocks-row-0 .popup-button')
|
||||
await editBlock.click()
|
||||
const removeButton = page.locator('#blocks-row-0').getByRole('button', { name: 'Remove' })
|
||||
await expect(removeButton).toBeVisible()
|
||||
await removeButton.click()
|
||||
|
||||
// check new first block value
|
||||
const richTextField = page.locator('#field-blocks__0__text')
|
||||
const richTextValue = await richTextField.innerText()
|
||||
expect(richTextValue).toContain('Rich text')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -6,14 +6,12 @@ import { wait } from 'payload/utilities'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import type { PayloadTestSDK } from '../helpers/sdk/index.js'
|
||||
import type { Config, RelationshipField, TextField } from './payload-types.js'
|
||||
import type { Config } from './payload-types.js'
|
||||
|
||||
import {
|
||||
ensureAutoLoginAndCompilationIsDone,
|
||||
exactText,
|
||||
initPageConsoleErrorCatch,
|
||||
saveDocAndAssert,
|
||||
saveDocHotkeyAndAssert,
|
||||
} from '../helpers.js'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil.js'
|
||||
import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js'
|
||||
@@ -23,13 +21,7 @@ import { POLL_TOPASS_TIMEOUT } from '../playwright.config.js'
|
||||
import { jsonDoc } from './collections/JSON/shared.js'
|
||||
import { numberDoc } from './collections/Number/shared.js'
|
||||
import { textDoc } from './collections/Text/shared.js'
|
||||
import {
|
||||
collapsibleFieldsSlug,
|
||||
pointFieldsSlug,
|
||||
relationshipFieldsSlug,
|
||||
tabsFieldsSlug,
|
||||
textFieldsSlug,
|
||||
} from './slugs.js'
|
||||
import { collapsibleFieldsSlug, pointFieldsSlug, tabsFieldsSlug, textFieldsSlug } from './slugs.js'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
@@ -617,365 +609,6 @@ describe('fields', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
describe('richText', () => {
|
||||
async function navigateToRichTextFields() {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields')
|
||||
await page.goto(url.list)
|
||||
await page.waitForURL(url.list)
|
||||
await page.locator('.row-1 .cell-title a').click()
|
||||
}
|
||||
|
||||
describe('cell', () => {
|
||||
test('ensure cells are smaller than 300px in height', async () => {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields')
|
||||
await page.goto(url.list) // Navigate to rich-text list view
|
||||
|
||||
const table = page.locator('.list-controls ~ .table')
|
||||
const lexicalCell = table.locator('.cell-lexicalCustomFields').first()
|
||||
const lexicalHtmlCell = table.locator('.cell-lexicalCustomFields_html').first()
|
||||
const entireRow = table.locator('.row-1').first()
|
||||
|
||||
// Make sure each of the 3 above are no larger than 300px in height:
|
||||
expect((await lexicalCell.boundingBox()).height).toBeLessThanOrEqual(300)
|
||||
expect((await lexicalHtmlCell.boundingBox()).height).toBeLessThanOrEqual(300)
|
||||
expect((await entireRow.boundingBox()).height).toBeLessThanOrEqual(300)
|
||||
})
|
||||
})
|
||||
|
||||
describe('toolbar', () => {
|
||||
test('should run url validation', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
// Fill values and click Confirm
|
||||
await editLinkModal.locator('#field-text').fill('link text')
|
||||
await editLinkModal.locator('label[for="field-linkType-custom"]').click()
|
||||
await editLinkModal.locator('#field-url').fill('')
|
||||
await wait(200)
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await wait(400)
|
||||
const errorField = page.locator(
|
||||
'[id^=drawer_1_rich-text-link-] .render-fields > :nth-child(3)',
|
||||
)
|
||||
const hasErrorClass = await errorField.evaluate((el) => el.classList.contains('error'))
|
||||
expect(hasErrorClass).toBe(true)
|
||||
})
|
||||
|
||||
test('should create new url custom link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
await wait(400)
|
||||
// Fill values and click Confirm
|
||||
await editLinkModal.locator('#field-text').fill('link text')
|
||||
await editLinkModal.locator('label[for="field-linkType-custom"]').click()
|
||||
await editLinkModal.locator('#field-url').fill('https://payloadcms.com')
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await wait(400)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
// Remove link from editor body
|
||||
await page.locator('span >> text="link text"').click()
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup.locator('.rich-text-link__link-label')).toBeVisible()
|
||||
await popup.locator('.rich-text-link__link-close').click()
|
||||
await expect(page.locator('span >> text="link text"')).toHaveCount(0)
|
||||
})
|
||||
|
||||
test('should create new internal link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
await wait(400)
|
||||
|
||||
// Fill values and click Confirm
|
||||
await editLinkModal.locator('#field-text').fill('link text')
|
||||
await editLinkModal.locator('label[for="field-linkType-internal"]').click()
|
||||
await editLinkModal.locator('#field-doc .rs__control').click()
|
||||
await page.keyboard.type('dev@')
|
||||
await editLinkModal
|
||||
.locator('#field-doc .rs__menu .rs__option:has-text("dev@payloadcms.com")')
|
||||
.click()
|
||||
// await wait(200);
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await saveDocAndAssert(page)
|
||||
})
|
||||
|
||||
test('should not create new url link when read only', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Attempt to open link popup
|
||||
const modalTrigger = page.locator('.rich-text--read-only .rich-text__toolbar button .link')
|
||||
await expect(modalTrigger).toBeDisabled()
|
||||
})
|
||||
|
||||
test('should only list RTE enabled upload collections in drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page
|
||||
.locator('.rich-text__toolbar button:not([disabled]) .upload-rich-text-button')
|
||||
.first()
|
||||
.click()
|
||||
|
||||
// open the list select menu
|
||||
await page.locator('.list-drawer__select-collection-wrap .rs__control').click()
|
||||
|
||||
const menu = page.locator('.list-drawer__select-collection-wrap .rs__menu')
|
||||
// `uploads-3` has enableRichTextRelationship set to false
|
||||
await expect(menu).not.toContainText('Uploads3')
|
||||
})
|
||||
|
||||
// TODO: this test can't find the selector for the search filter, but functionality works.
|
||||
// Need to debug
|
||||
test.skip('should search correct useAsTitle field after toggling collection in list drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// open link drawer
|
||||
const field = page.locator('#field-richText')
|
||||
const button = field.locator(
|
||||
'button.rich-text-relationship__list-drawer-toggler.list-drawer__toggler',
|
||||
)
|
||||
await button.click()
|
||||
|
||||
// check that the search is on the `name` field of the `text-fields` collection
|
||||
const drawer = page.locator('[id^=list-drawer_1_]')
|
||||
|
||||
await expect(drawer.locator('.search-filter__input')).toHaveAttribute(
|
||||
'placeholder',
|
||||
'Search by Text',
|
||||
)
|
||||
|
||||
// change the selected collection to `array-fields`
|
||||
await page.locator('.list-drawer__select-collection-wrap .rs__control').click()
|
||||
const menu = page.locator('.list-drawer__select-collection-wrap .rs__menu')
|
||||
await menu.locator('.rs__option').getByText('Array Field').click()
|
||||
|
||||
// check that `id` is now the default search field
|
||||
await expect(drawer.locator('.search-filter__input')).toHaveAttribute(
|
||||
'placeholder',
|
||||
'Search by ID',
|
||||
)
|
||||
})
|
||||
|
||||
test('should only list RTE enabled collections in link drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
await editLinkModal.locator('label[for="field-linkType-internal"]').click()
|
||||
await editLinkModal.locator('.relationship__wrap .rs__control').click()
|
||||
|
||||
const menu = page.locator('.relationship__wrap .rs__menu')
|
||||
|
||||
// array-fields has enableRichTextLink set to false
|
||||
await expect(menu).not.toContainText('Array Fields')
|
||||
})
|
||||
|
||||
test('should only list non-upload collections in relationship drawer', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link drawer
|
||||
await page
|
||||
.locator('.rich-text__toolbar button:not([disabled]) .relationship-rich-text-button')
|
||||
.first()
|
||||
.click()
|
||||
|
||||
await wait(300)
|
||||
|
||||
// open the list select menu
|
||||
await page.locator('.list-drawer__select-collection-wrap .rs__control').click()
|
||||
|
||||
const menu = page.locator('.list-drawer__select-collection-wrap .rs__menu')
|
||||
await expect(menu).not.toContainText('Uploads')
|
||||
})
|
||||
|
||||
test('should respect customizing the default fields', async () => {
|
||||
const linkText = 'link'
|
||||
const value = 'test value'
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('.rich-text', {
|
||||
has: page.locator('#field-richTextCustomFields'),
|
||||
})
|
||||
// open link drawer
|
||||
const button = field.locator('button.rich-text__button.link')
|
||||
await button.click()
|
||||
|
||||
// fill link fields
|
||||
const linkDrawer = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
const fields = linkDrawer.locator('.render-fields > .field-type')
|
||||
await fields.locator('#field-text').fill(linkText)
|
||||
await fields.locator('#field-url').fill('https://payloadcms.com')
|
||||
const input = fields.locator('#field-fields__customLinkField')
|
||||
await input.fill(value)
|
||||
|
||||
await wait(300)
|
||||
|
||||
// submit link closing drawer
|
||||
await linkDrawer.locator('button[type="submit"]').click()
|
||||
const linkInEditor = field.locator(`.rich-text-link >> text="${linkText}"`)
|
||||
await saveDocAndAssert(page)
|
||||
|
||||
// open modal again
|
||||
await linkInEditor.click()
|
||||
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup).toBeVisible()
|
||||
|
||||
await popup.locator('.rich-text-link__link-edit').click()
|
||||
|
||||
const linkDrawer2 = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
const fields2 = linkDrawer2.locator('.render-fields > .field-type')
|
||||
const input2 = fields2.locator('#field-fields__customLinkField')
|
||||
|
||||
await expect(input2).toHaveValue(value)
|
||||
})
|
||||
})
|
||||
|
||||
describe('editor', () => {
|
||||
test('should populate url link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link popup
|
||||
await page.locator('#field-richText span >> text="render links"').click()
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup).toBeVisible()
|
||||
await expect(popup.locator('a')).toHaveAttribute('href', 'https://payloadcms.com')
|
||||
|
||||
// Open the drawer
|
||||
await popup.locator('.rich-text-link__link-edit').click()
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
// Check the drawer values
|
||||
const textField = editLinkModal.locator('#field-text')
|
||||
await expect(textField).toHaveValue('render links')
|
||||
|
||||
// Close the drawer
|
||||
await editLinkModal.locator('button[type="submit"]').click()
|
||||
await expect(editLinkModal).toBeHidden()
|
||||
})
|
||||
|
||||
test('should populate relationship link', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Open link popup
|
||||
await page.locator('#field-richText span >> text="link to relationships"').click()
|
||||
const popup = page.locator('.popup--active .rich-text-link__popup')
|
||||
await expect(popup).toBeVisible()
|
||||
await expect(popup.locator('a')).toHaveAttribute(
|
||||
'href',
|
||||
/\/admin\/collections\/array-fields\/.*/,
|
||||
)
|
||||
|
||||
// Open the drawer
|
||||
await popup.locator('.rich-text-link__link-edit').click()
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
|
||||
// Check the drawer values
|
||||
const textField = editLinkModal.locator('#field-text')
|
||||
await expect(textField).toHaveValue('link to relationships')
|
||||
})
|
||||
|
||||
test('should open upload drawer and render custom relationship fields', async () => {
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('#field-richText')
|
||||
const button = field.locator('button.rich-text-upload__upload-drawer-toggler')
|
||||
|
||||
await button.click()
|
||||
|
||||
const documentDrawer = page.locator('[id^=drawer_1_upload-drawer-]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
const caption = documentDrawer.locator('#field-caption')
|
||||
await expect(caption).toBeVisible()
|
||||
})
|
||||
|
||||
test('should open upload document drawer from read-only field', async () => {
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('#field-richTextReadOnly')
|
||||
const button = field.locator(
|
||||
'button.rich-text-upload__doc-drawer-toggler.doc-drawer__toggler',
|
||||
)
|
||||
|
||||
await button.click()
|
||||
|
||||
const documentDrawer = page.locator('[id^=doc-drawer_uploads_1_]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
})
|
||||
|
||||
test('should open relationship document drawer from read-only field', async () => {
|
||||
await navigateToRichTextFields()
|
||||
const field = page.locator('#field-richTextReadOnly')
|
||||
const button = field.locator(
|
||||
'button.rich-text-relationship__doc-drawer-toggler.doc-drawer__toggler',
|
||||
)
|
||||
|
||||
await button.click()
|
||||
|
||||
const documentDrawer = page.locator('[id^=doc-drawer_text-fields_1_]')
|
||||
await expect(documentDrawer).toBeVisible()
|
||||
})
|
||||
|
||||
test('should populate new links', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// Highlight existing text
|
||||
const headingElement = page.locator(
|
||||
'#field-richText h1 >> text="Hello, I\'m a rich text field."',
|
||||
)
|
||||
await headingElement.selectText()
|
||||
|
||||
// click the toolbar link button
|
||||
await page.locator('.rich-text__toolbar button:not([disabled]) .link').first().click()
|
||||
|
||||
// find the drawer and confirm the values
|
||||
const editLinkModal = page.locator('[id^=drawer_1_rich-text-link-]')
|
||||
await expect(editLinkModal).toBeVisible()
|
||||
const textField = editLinkModal.locator('#field-text')
|
||||
await expect(textField).toHaveValue("Hello, I'm a rich text field.")
|
||||
})
|
||||
test('should not take value from previous block', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
// check first block value
|
||||
const textField = page.locator('#field-blocks__0__text')
|
||||
await expect(textField).toHaveValue('Regular text')
|
||||
|
||||
// remove the first block
|
||||
const editBlock = page.locator('#blocks-row-0 .popup-button')
|
||||
await editBlock.click()
|
||||
const removeButton = page.locator('#blocks-row-0').getByRole('button', { name: 'Remove' })
|
||||
await expect(removeButton).toBeVisible()
|
||||
await removeButton.click()
|
||||
|
||||
// check new first block value
|
||||
const richTextField = page.locator('#field-blocks__0__text')
|
||||
const richTextValue = await richTextField.innerText()
|
||||
expect(richTextValue).toContain('Rich text')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('date', () => {
|
||||
let url: AdminUrlUtil
|
||||
@@ -1352,27 +985,3 @@ describe('fields', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
async function createTextFieldDoc(overrides?: Partial<TextField>): Promise<TextField> {
|
||||
return payload.create({
|
||||
collection: 'text-fields',
|
||||
data: {
|
||||
text: 'some text',
|
||||
localizedText: 'some localized text',
|
||||
...overrides,
|
||||
},
|
||||
}) as unknown as Promise<TextField>
|
||||
}
|
||||
|
||||
async function createRelationshipFieldDoc(
|
||||
relationship: RelationshipField['relationship'],
|
||||
overrides?: Partial<RelationshipField>,
|
||||
): Promise<RelationshipField> {
|
||||
return payload.create({
|
||||
collection: 'relationship-fields',
|
||||
data: {
|
||||
relationship,
|
||||
...overrides,
|
||||
},
|
||||
}) as unknown as Promise<RelationshipField>
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ if (!suiteName) {
|
||||
} else {
|
||||
// Run specific suite
|
||||
clearWebpackCache()
|
||||
const suitePath = path.resolve(dirname, suiteName, 'e2e.spec.ts')
|
||||
const suitePath = path.resolve(dirname, suiteName, 'e2e.spec.ts').replace('__', '/')
|
||||
executePlaywright(suitePath)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user