Compare commits
1 Commits
chore/bump
...
fix/blocks
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d1c4d5dc4 |
@@ -1,6 +1,10 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
import type { BrowserContext, Page } from '@playwright/test'
|
||||
|
||||
import { expect, test } from '@playwright/test'
|
||||
import { addBlock } from 'helpers/e2e/addBlock.js'
|
||||
import { openBlockDrawer } from 'helpers/e2e/openBlockDrawer.js'
|
||||
import { removeAllBlocks } from 'helpers/e2e/removeAllBlocks.js'
|
||||
import { reorderBlocks } from 'helpers/e2e/reorderBlocks.js'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
@@ -8,6 +12,7 @@ import {
|
||||
ensureCompilationIsDone,
|
||||
initPageConsoleErrorCatch,
|
||||
saveDocAndAssert,
|
||||
throttleTest,
|
||||
} from '../../../helpers.js'
|
||||
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
|
||||
import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js'
|
||||
@@ -24,6 +29,8 @@ const { beforeAll, beforeEach, describe } = test
|
||||
let client: RESTClient
|
||||
let page: Page
|
||||
let serverURL: string
|
||||
let context: BrowserContext
|
||||
|
||||
// If we want to make this run in parallel: test.describe.configure({ mode: 'parallel' })
|
||||
|
||||
describe('Block fields', () => {
|
||||
@@ -35,7 +42,7 @@ describe('Block fields', () => {
|
||||
dirname,
|
||||
}))
|
||||
|
||||
const context = await browser.newContext()
|
||||
context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
initPageConsoleErrorCatch(page)
|
||||
|
||||
@@ -64,19 +71,8 @@ describe('Block fields', () => {
|
||||
|
||||
test('should open blocks drawer and select first block', async () => {
|
||||
await page.goto(url.create)
|
||||
const addButton = page.locator('#field-blocks > .blocks-field__drawer-toggler')
|
||||
await expect(addButton).toContainText('Add Block')
|
||||
await addButton.click()
|
||||
|
||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||
await expect(blocksDrawer).toBeVisible()
|
||||
|
||||
// select the first block in the drawer
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
await expect(firstBlockSelector).toContainText('Content')
|
||||
await firstBlockSelector.click()
|
||||
await addBlock({ page, fieldName: 'blocks', fieldLabel: 'Blocks', blockLabel: 'Content' })
|
||||
|
||||
// ensure the block was appended to the rows
|
||||
const addedRow = page.locator('#field-blocks .blocks-field__row').last()
|
||||
@@ -88,17 +84,14 @@ describe('Block fields', () => {
|
||||
|
||||
test('should reset search state in blocks drawer on re-open', async () => {
|
||||
await page.goto(url.create)
|
||||
const addButton = page.locator('#field-blocks > .blocks-field__drawer-toggler')
|
||||
await expect(addButton).toContainText('Add Block')
|
||||
await addButton.click()
|
||||
|
||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||
await expect(blocksDrawer).toBeVisible()
|
||||
const blocksDrawer = await openBlockDrawer({ page, fieldName: 'blocks', fieldLabel: 'Blocks' })
|
||||
|
||||
const searchInput = page.locator('.block-search__input')
|
||||
await searchInput.fill('Number')
|
||||
|
||||
// select the first block in the drawer
|
||||
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
@@ -106,6 +99,7 @@ describe('Block fields', () => {
|
||||
await expect(firstBlockSelector).toContainText('Number')
|
||||
|
||||
await page.locator('.drawer__header__close').click()
|
||||
const addButton = page.locator('#field-blocks > .blocks-field__drawer-toggler')
|
||||
await addButton.click()
|
||||
|
||||
await expect(blocksDrawer).toBeVisible()
|
||||
@@ -131,6 +125,7 @@ describe('Block fields', () => {
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
|
||||
await expect(firstBlockSelector).toContainText('Content')
|
||||
await firstBlockSelector.click()
|
||||
|
||||
@@ -179,19 +174,12 @@ describe('Block fields', () => {
|
||||
await page.goto(url.create)
|
||||
await expect(page.locator('#field-i18nBlocks .blocks-field__header')).toContainText('Block en')
|
||||
|
||||
const addButton = page.locator('#field-i18nBlocks > .blocks-field__drawer-toggler')
|
||||
await expect(addButton).toContainText('Add Block en')
|
||||
await addButton.click()
|
||||
|
||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||
await expect(blocksDrawer).toBeVisible()
|
||||
|
||||
// select the first block in the drawer
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
await expect(firstBlockSelector).toContainText('Text en')
|
||||
await firstBlockSelector.click()
|
||||
await addBlock({
|
||||
page,
|
||||
fieldName: 'i18nBlocks',
|
||||
fieldLabel: 'I18n Blocks',
|
||||
blockLabel: 'Text en',
|
||||
})
|
||||
|
||||
// ensure the block was appended to the rows
|
||||
const firstRow = page.locator('#field-i18nBlocks .blocks-field__row').first()
|
||||
@@ -201,15 +189,8 @@ describe('Block fields', () => {
|
||||
|
||||
test('should render custom block row label', async () => {
|
||||
await page.goto(url.create)
|
||||
const addButton = page.locator('#field-blocks > .blocks-field__drawer-toggler')
|
||||
await addButton.click()
|
||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||
|
||||
await blocksDrawer
|
||||
.locator('.blocks-drawer__block .thumbnail-card__label', {
|
||||
hasText: 'Content',
|
||||
})
|
||||
.click()
|
||||
await addBlock({ page, fieldName: 'blocks', fieldLabel: 'Blocks', blockLabel: 'Content' })
|
||||
|
||||
await expect(
|
||||
page.locator('#field-blocks .blocks-field__row .blocks-field__block-header', {
|
||||
@@ -221,20 +202,18 @@ describe('Block fields', () => {
|
||||
test('should add different blocks with similar field configs', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
async function addBlock(name: 'Block A' | 'Block B') {
|
||||
await page
|
||||
.locator('#field-blocksWithSimilarConfigs')
|
||||
.getByRole('button', { name: 'Add Blocks With Similar Config' })
|
||||
.click()
|
||||
await page.getByRole('button', { name }).click()
|
||||
}
|
||||
|
||||
await addBlock('Block A')
|
||||
await addBlock({
|
||||
page,
|
||||
fieldName: 'blocksWithSimilarConfigs',
|
||||
fieldLabel: 'Blocks With Similar Config',
|
||||
blockLabel: 'Block A',
|
||||
})
|
||||
|
||||
await page
|
||||
.locator('#blocksWithSimilarConfigs-row-0')
|
||||
.getByRole('button', { name: 'Add Item' })
|
||||
.click()
|
||||
|
||||
await page
|
||||
.locator('input[name="blocksWithSimilarConfigs.0.items.0.title"]')
|
||||
.fill('items>0>title')
|
||||
@@ -243,12 +222,18 @@ describe('Block fields', () => {
|
||||
page.locator('input[name="blocksWithSimilarConfigs.0.items.0.title"]'),
|
||||
).toHaveValue('items>0>title')
|
||||
|
||||
await addBlock('Block B')
|
||||
await addBlock({
|
||||
page,
|
||||
fieldName: 'blocksWithSimilarConfigs',
|
||||
fieldLabel: 'Blocks With Similar Config',
|
||||
blockLabel: 'Block B',
|
||||
})
|
||||
|
||||
await page
|
||||
.locator('#blocksWithSimilarConfigs-row-1')
|
||||
.getByRole('button', { name: 'Add Item' })
|
||||
.click()
|
||||
|
||||
await page
|
||||
.locator('input[name="blocksWithSimilarConfigs.1.items.0.title2"]')
|
||||
.fill('items>1>title')
|
||||
@@ -267,19 +252,12 @@ describe('Block fields', () => {
|
||||
test('should fail min rows validation when rows are present', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
await page
|
||||
.locator('#field-blocksWithMinRows')
|
||||
.getByRole('button', { name: 'Add Blocks With Min Row' })
|
||||
.click()
|
||||
|
||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||
await expect(blocksDrawer).toBeVisible()
|
||||
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
|
||||
await firstBlockSelector.click()
|
||||
await addBlock({
|
||||
page,
|
||||
fieldName: 'blocksWithMinRows',
|
||||
fieldLabel: 'Blocks With Min Rows',
|
||||
blockLabel: 'Block',
|
||||
})
|
||||
|
||||
const firstRow = page.locator('input[name="blocksWithMinRows.0.blockTitle"]')
|
||||
await expect(firstRow).toBeVisible()
|
||||
@@ -326,6 +304,7 @@ describe('Block fields', () => {
|
||||
.locator('.custom-blocks-field-management')
|
||||
.getByRole('button', { name: 'Add Block 2' })
|
||||
.click()
|
||||
|
||||
await expect(
|
||||
page.locator('#field-customBlocks input[name="customBlocks.1.block2Title"]'),
|
||||
).toHaveValue('Block 2: Prefilled Title')
|
||||
@@ -334,6 +313,7 @@ describe('Block fields', () => {
|
||||
.locator('.custom-blocks-field-management')
|
||||
.getByRole('button', { name: 'Replace Block 2' })
|
||||
.click()
|
||||
|
||||
await expect(
|
||||
page.locator('#field-customBlocks input[name="customBlocks.1.block1Title"]'),
|
||||
).toHaveValue('REPLACED BLOCK')
|
||||
@@ -342,18 +322,68 @@ describe('Block fields', () => {
|
||||
})
|
||||
|
||||
describe('sortable blocks', () => {
|
||||
test('should have disabled admin sorting', async () => {
|
||||
test('should not render sort controls when sorting is disabled', async () => {
|
||||
await page.goto(url.create)
|
||||
const field = page.locator('#field-disableSort > div > div > .array-actions__action-chevron')
|
||||
expect(await field.count()).toEqual(0)
|
||||
})
|
||||
|
||||
test('the drag handle should be hidden', async () => {
|
||||
test('should not render drag handle when sorting is disabled', async () => {
|
||||
await page.goto(url.create)
|
||||
const field = page.locator(
|
||||
'#field-disableSort > .blocks-field__rows > div > div > .collapsible__drag',
|
||||
)
|
||||
expect(await field.count()).toEqual(0)
|
||||
})
|
||||
|
||||
test('should quickly sort blocks on slow networks without losing data', async () => {
|
||||
await page.goto(url.create)
|
||||
|
||||
await removeAllBlocks({ page, fieldName: 'blocks' })
|
||||
|
||||
await addBlock({
|
||||
page,
|
||||
fieldName: 'blocks',
|
||||
blockLabelSingular: 'Number',
|
||||
fieldLabelSingular: 'Block',
|
||||
})
|
||||
|
||||
await addBlock({
|
||||
page,
|
||||
fieldName: 'blocks',
|
||||
blockLabelSingular: 'Content',
|
||||
fieldLabelSingular: 'Block',
|
||||
})
|
||||
|
||||
// fill in the first block with a value
|
||||
await page.locator('input[name="blocks.0.number"]').fill('1')
|
||||
await page.locator('input[name="blocks.1.text"]').fill('Content')
|
||||
|
||||
// only throttle test after initial load to avoid timeouts
|
||||
const cdpSession = await throttleTest({
|
||||
page,
|
||||
context,
|
||||
delay: 'Slow 3G',
|
||||
})
|
||||
|
||||
await reorderBlocks({
|
||||
page,
|
||||
fieldName: 'blocks',
|
||||
fromBlockIndex: 1,
|
||||
toBlockIndex: 0,
|
||||
})
|
||||
|
||||
await expect(page.locator('input[name="blocks.0.text"]')).toHaveValue('Content')
|
||||
await expect(page.locator('input[name="blocks.1.number"]')).toHaveValue('1')
|
||||
|
||||
await cdpSession.send('Network.emulateNetworkConditions', {
|
||||
offline: false,
|
||||
latency: 0,
|
||||
downloadThroughput: -1,
|
||||
uploadThroughput: -1,
|
||||
})
|
||||
|
||||
await cdpSession.detach()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -6,60 +6,6 @@
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported timezones in IANA format.
|
||||
*
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "supportedTimezones".
|
||||
*/
|
||||
export type SupportedTimezones =
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji'
|
||||
| 'America/Monterrey';
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "BlockColumns".
|
||||
@@ -1136,16 +1082,163 @@ export interface DateField {
|
||||
dayAndTime?: string | null;
|
||||
monthOnly?: string | null;
|
||||
defaultWithTimezone?: string | null;
|
||||
defaultWithTimezone_tz?: SupportedTimezones;
|
||||
defaultWithTimezone_tz?:
|
||||
| (
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji'
|
||||
| 'America/Monterrey'
|
||||
)
|
||||
| null;
|
||||
/**
|
||||
* This date here should be required.
|
||||
*/
|
||||
dayAndTimeWithTimezone: string;
|
||||
dayAndTimeWithTimezone_tz: SupportedTimezones;
|
||||
dayAndTimeWithTimezone_tz:
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji'
|
||||
| 'America/Monterrey';
|
||||
timezoneBlocks?:
|
||||
| {
|
||||
dayAndTime?: string | null;
|
||||
dayAndTime_tz?: SupportedTimezones;
|
||||
dayAndTime_tz?:
|
||||
| (
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji'
|
||||
| 'America/Monterrey'
|
||||
)
|
||||
| null;
|
||||
id?: string | null;
|
||||
blockName?: string | null;
|
||||
blockType: 'dateBlock';
|
||||
@@ -1154,7 +1247,57 @@ export interface DateField {
|
||||
timezoneArray?:
|
||||
| {
|
||||
dayAndTime?: string | null;
|
||||
dayAndTime_tz?: SupportedTimezones;
|
||||
dayAndTime_tz?:
|
||||
| (
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji'
|
||||
| 'America/Monterrey'
|
||||
)
|
||||
| null;
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
|
||||
29
test/helpers/e2e/addBlock.ts
Normal file
29
test/helpers/e2e/addBlock.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
import { openBlockDrawer } from './openBlockDrawer.js'
|
||||
|
||||
export const addBlock = async ({
|
||||
page,
|
||||
fieldName = 'blocks',
|
||||
blockLabelSingular = 'Block',
|
||||
fieldLabelSingular = 'Blocks',
|
||||
}: {
|
||||
blockLabelSingular: string
|
||||
fieldLabelSingular: string
|
||||
fieldName: string
|
||||
page: Page
|
||||
}) => {
|
||||
const blocksDrawer = await openBlockDrawer({ page, fieldName, fieldLabelSingular })
|
||||
|
||||
const blockCard = blocksDrawer.locator('.blocks-drawer__block .thumbnail-card__label', {
|
||||
hasText: blockLabelSingular,
|
||||
})
|
||||
|
||||
await expect(blockCard).toBeVisible()
|
||||
|
||||
await page.getByRole('button', { name: blockLabelSingular }).click()
|
||||
|
||||
// expect to see the block on the page
|
||||
}
|
||||
25
test/helpers/e2e/openBlockDrawer.ts
Normal file
25
test/helpers/e2e/openBlockDrawer.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { Locator, Page } from '@playwright/test'
|
||||
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
export const openBlockDrawer = async ({
|
||||
page,
|
||||
fieldName = 'blocks',
|
||||
fieldLabelSingular = 'Block',
|
||||
}: {
|
||||
fieldLabelSingular: string
|
||||
fieldName: string
|
||||
page: Page
|
||||
}): Promise<Locator> => {
|
||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||
|
||||
if (!(await blocksDrawer.isVisible())) {
|
||||
const addButton = page.locator(`#field-${fieldName} > .blocks-field__drawer-toggler`)
|
||||
await expect(addButton).toContainText(`Add ${fieldLabelSingular}`)
|
||||
await addButton.click()
|
||||
}
|
||||
|
||||
await expect(blocksDrawer).toBeVisible()
|
||||
|
||||
return blocksDrawer
|
||||
}
|
||||
25
test/helpers/e2e/removeAllBlocks.ts
Normal file
25
test/helpers/e2e/removeAllBlocks.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect } from '@playwright/test'
|
||||
|
||||
export const removeAllBlocks = async ({
|
||||
page,
|
||||
fieldName = 'blocks',
|
||||
}: {
|
||||
fieldName: string
|
||||
page: Page
|
||||
}) => {
|
||||
const blocksField = page.locator(`#field-${fieldName}`)
|
||||
|
||||
const blocks = blocksField.locator(`[id^="${fieldName}-row-"]`)
|
||||
const count = await blocks.count()
|
||||
|
||||
expect(count).toBeGreaterThan(0)
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
// delete in reverse order to avoid index issues
|
||||
const block = blocksField.locator(`[id^="${fieldName}-row-${count - i - 1}"]`)
|
||||
await block.locator('.array-actions__button').first().click()
|
||||
await block.locator('.array-actions__action.array-actions__remove').first().click()
|
||||
}
|
||||
}
|
||||
41
test/helpers/e2e/reorderBlocks.ts
Normal file
41
test/helpers/e2e/reorderBlocks.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { wait } from 'payload/shared'
|
||||
|
||||
import { exactText } from '../../helpers.js'
|
||||
|
||||
export const reorderBlocks = async ({
|
||||
page,
|
||||
fromBlockIndex = 1,
|
||||
toBlockIndex = 2,
|
||||
fieldName = 'blocks',
|
||||
}: {
|
||||
fieldName?: string
|
||||
fromBlockIndex: number
|
||||
page: Page
|
||||
toBlockIndex: number
|
||||
}) => {
|
||||
const blocksField = page.locator(`#field-${fieldName}`).first()
|
||||
|
||||
const fromField = blocksField.locator(`[id^="${fieldName}-row-${fromBlockIndex}"]`)
|
||||
|
||||
const fromBoundingBox = await fromField.locator(`.collapsible__drag`).boundingBox()
|
||||
|
||||
const toField = blocksField.locator(`[id^="${fieldName}-row-${toBlockIndex}"]`)
|
||||
|
||||
const toBoundingBox = await toField.locator(`.collapsible__drag`).boundingBox()
|
||||
|
||||
if (!fromBoundingBox || !toBoundingBox) {
|
||||
return
|
||||
}
|
||||
|
||||
// drag the "from" column to the left of the "to" column
|
||||
await page.mouse.move(fromBoundingBox.x + 2, fromBoundingBox.y + 2, { steps: 10 })
|
||||
await page.mouse.down()
|
||||
await wait(300)
|
||||
await page.mouse.move(toBoundingBox.x - 2, toBoundingBox.y - 2, { steps: 10 })
|
||||
await page.mouse.up()
|
||||
|
||||
// TODO: This wait makes sure the preferences are actually saved. Just waiting for the UI to update is not enough. We should replace this wait
|
||||
await wait(1000)
|
||||
}
|
||||
@@ -31,7 +31,7 @@
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@payload-config": ["./test/_community/config.ts"],
|
||||
"@payload-config": ["./test/fields/config.ts"],
|
||||
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
||||
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
||||
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
||||
|
||||
Reference in New Issue
Block a user