test: consolidates list view e2e tests (#10263)
There were a handful of list view e2e tests written into the text and email field test suite, making them hard to find as they were isolated from other related tests. A few of these tests were also duplicative across suites, making CI run them twice unnecessarily.
This commit is contained in:
@@ -182,6 +182,20 @@ export const Posts: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'disableListColumnText',
|
||||||
|
type: 'text',
|
||||||
|
admin: {
|
||||||
|
disableListColumn: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'disableListFilterText',
|
||||||
|
type: 'text',
|
||||||
|
admin: {
|
||||||
|
disableListFilter: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'sidebarField',
|
name: 'sidebarField',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
|||||||
@@ -119,7 +119,37 @@ describe('List View', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('filtering', () => {
|
describe('list view table', () => {
|
||||||
|
test('should link second cell', async () => {
|
||||||
|
const { id } = await createPost()
|
||||||
|
await page.reload()
|
||||||
|
const linkCell = page.locator(`${tableRowLocator} td`).nth(1).locator('a')
|
||||||
|
|
||||||
|
await expect(linkCell).toHaveAttribute(
|
||||||
|
'href',
|
||||||
|
`${adminRoutes.routes.admin}/collections/posts/${id}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
await page.locator('.list-controls__toggle-columns').click()
|
||||||
|
await expect(page.locator('.list-controls__columns.rah-static--height-auto')).toBeVisible()
|
||||||
|
|
||||||
|
await page
|
||||||
|
.locator('.column-selector .column-selector__column', {
|
||||||
|
hasText: exactText('ID'),
|
||||||
|
})
|
||||||
|
.click()
|
||||||
|
|
||||||
|
await page.locator('#heading-id').waitFor({ state: 'detached' })
|
||||||
|
await page.locator('.cell-id').first().waitFor({ state: 'detached' })
|
||||||
|
|
||||||
|
await expect(linkCell).toHaveAttribute(
|
||||||
|
'href',
|
||||||
|
`${adminRoutes.routes.admin}/collections/posts/${id}`,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('search', () => {
|
||||||
test('should prefill search input from query param', async () => {
|
test('should prefill search input from query param', async () => {
|
||||||
await createPost({ title: 'dennis' })
|
await createPost({ title: 'dennis' })
|
||||||
await createPost({ title: 'charlie' })
|
await createPost({ title: 'charlie' })
|
||||||
@@ -191,51 +221,13 @@ describe('List View', () => {
|
|||||||
|
|
||||||
await expect(page.locator('#search-filter-input')).toHaveValue('')
|
await expect(page.locator('#search-filter-input')).toHaveValue('')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should toggle columns', async () => {
|
|
||||||
const columnCountLocator = 'table > thead > tr > th'
|
|
||||||
await createPost()
|
|
||||||
await openListColumns(page, {})
|
|
||||||
const numberOfColumns = await page.locator(columnCountLocator).count()
|
|
||||||
await expect(page.locator('.column-selector')).toBeVisible()
|
|
||||||
await expect(page.locator('table > thead > tr > th:nth-child(2)')).toHaveText('ID')
|
|
||||||
await toggleColumn(page, { columnLabel: 'ID', targetState: 'off' })
|
|
||||||
await page.locator('#heading-id').waitFor({ state: 'detached' })
|
|
||||||
await page.locator('.cell-id').first().waitFor({ state: 'detached' })
|
|
||||||
await expect(page.locator(columnCountLocator)).toHaveCount(numberOfColumns - 1)
|
|
||||||
await expect(page.locator('table > thead > tr > th:nth-child(2)')).toHaveText('Number')
|
|
||||||
await toggleColumn(page, { columnLabel: 'ID', targetState: 'on' })
|
|
||||||
await expect(page.locator('.cell-id').first()).toBeVisible()
|
|
||||||
await expect(page.locator(columnCountLocator)).toHaveCount(numberOfColumns)
|
|
||||||
await expect(page.locator('table > thead > tr > th:nth-child(2)')).toHaveText('ID')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should link second cell', async () => {
|
describe('filters', () => {
|
||||||
const { id } = await createPost()
|
test('should respect base list filters', async () => {
|
||||||
await page.reload()
|
await page.goto(baseListFiltersUrl.list)
|
||||||
const linkCell = page.locator(`${tableRowLocator} td`).nth(1).locator('a')
|
await page.waitForURL((url) => url.toString().startsWith(baseListFiltersUrl.list))
|
||||||
|
await expect(page.locator(tableRowLocator)).toHaveCount(1)
|
||||||
await expect(linkCell).toHaveAttribute(
|
|
||||||
'href',
|
|
||||||
`${adminRoutes.routes.admin}/collections/posts/${id}`,
|
|
||||||
)
|
|
||||||
|
|
||||||
await page.locator('.list-controls__toggle-columns').click()
|
|
||||||
await expect(page.locator('.list-controls__columns.rah-static--height-auto')).toBeVisible()
|
|
||||||
|
|
||||||
await page
|
|
||||||
.locator('.column-selector .column-selector__column', {
|
|
||||||
hasText: exactText('ID'),
|
|
||||||
})
|
|
||||||
.click()
|
|
||||||
|
|
||||||
await page.locator('#heading-id').waitFor({ state: 'detached' })
|
|
||||||
await page.locator('.cell-id').first().waitFor({ state: 'detached' })
|
|
||||||
|
|
||||||
await expect(linkCell).toHaveAttribute(
|
|
||||||
'href',
|
|
||||||
`${adminRoutes.routes.admin}/collections/posts/${id}`,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should filter rows', async () => {
|
test('should filter rows', async () => {
|
||||||
@@ -452,9 +444,228 @@ describe('List View', () => {
|
|||||||
await page.waitForURL(new RegExp(`${postsUrl.list}\\?limit=5&page=1`))
|
await page.waitForURL(new RegExp(`${postsUrl.list}\\?limit=5&page=1`))
|
||||||
await expect(page.locator('.collection-list__page-info')).toHaveText('1-3 of 3')
|
await expect(page.locator('.collection-list__page-info')).toHaveText('1-3 of 3')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should reset filter values for every additional filters', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await openListFilters(page, {})
|
||||||
|
await page.locator('.where-builder__add-first-filter').click()
|
||||||
|
const firstConditionField = page.locator('.condition__field')
|
||||||
|
const firstOperatorField = page.locator('.condition__operator')
|
||||||
|
const firstValueField = page.locator('.condition__value >> input')
|
||||||
|
|
||||||
|
await firstConditionField.click()
|
||||||
|
await firstConditionField
|
||||||
|
.locator('.rs__option', {
|
||||||
|
hasText: exactText('Tab 1 > Title'),
|
||||||
|
})
|
||||||
|
.click()
|
||||||
|
|
||||||
|
await expect(firstConditionField.locator('.rs__single-value')).toContainText('Tab 1 > Title')
|
||||||
|
await firstOperatorField.click()
|
||||||
|
await firstOperatorField.locator('.rs__option').locator('text=equals').click()
|
||||||
|
await firstValueField.fill('Test')
|
||||||
|
await expect(firstValueField).toHaveValue('Test')
|
||||||
|
await page.locator('.condition__actions-add').click()
|
||||||
|
const secondLi = page.locator('.where-builder__and-filters li:nth-child(2)')
|
||||||
|
await expect(secondLi).toBeVisible()
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
secondLi.locator('.condition__field').locator('.rs__single-value'),
|
||||||
|
).toContainText('Tab 1 > Title')
|
||||||
|
|
||||||
|
await expect(secondLi.locator('.condition__operator >> input')).toHaveValue('')
|
||||||
|
await expect(secondLi.locator('.condition__value >> input')).toHaveValue('')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should not re-render page upon typing in a value in the filter value field', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await openListFilters(page, {})
|
||||||
|
await page.locator('.where-builder__add-first-filter').click()
|
||||||
|
const firstConditionField = page.locator('.condition__field')
|
||||||
|
const firstOperatorField = page.locator('.condition__operator')
|
||||||
|
const firstValueField = page.locator('.condition__value >> input')
|
||||||
|
|
||||||
|
await firstConditionField.click()
|
||||||
|
await firstConditionField
|
||||||
|
.locator('.rs__option', { hasText: exactText('Tab 1 > Title') })
|
||||||
|
.click()
|
||||||
|
await expect(firstConditionField.locator('.rs__single-value')).toContainText('Tab 1 > Title')
|
||||||
|
|
||||||
|
await firstOperatorField.click()
|
||||||
|
await firstOperatorField.locator('.rs__option').locator('text=equals').click()
|
||||||
|
|
||||||
|
// Type into the input field instead of filling it
|
||||||
|
await firstValueField.click()
|
||||||
|
await firstValueField.type('Test', { delay: 100 }) // Add a delay to simulate typing speed
|
||||||
|
|
||||||
|
// Wait for a short period to see if the input loses focus
|
||||||
|
await page.waitForTimeout(500)
|
||||||
|
|
||||||
|
// Check if the input still has the correct value
|
||||||
|
await expect(firstValueField).toHaveValue('Test')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should still show second filter if two filters exist and first filter is removed', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await openListFilters(page, {})
|
||||||
|
await page.locator('.where-builder__add-first-filter').click()
|
||||||
|
const firstConditionField = page.locator('.condition__field')
|
||||||
|
const firstOperatorField = page.locator('.condition__operator')
|
||||||
|
const firstValueField = page.locator('.condition__value >> input')
|
||||||
|
await firstConditionField.click()
|
||||||
|
await firstConditionField
|
||||||
|
.locator('.rs__option', { hasText: exactText('Tab 1 > Title') })
|
||||||
|
.click()
|
||||||
|
await expect(firstConditionField.locator('.rs__single-value')).toContainText('Tab 1 > Title')
|
||||||
|
await firstOperatorField.click()
|
||||||
|
await firstOperatorField.locator('.rs__option').locator('text=equals').click()
|
||||||
|
await firstValueField.fill('Test 1')
|
||||||
|
await expect(firstValueField).toHaveValue('Test 1')
|
||||||
|
|
||||||
|
await wait(500)
|
||||||
|
|
||||||
|
await page.locator('.condition__actions-add').click()
|
||||||
|
|
||||||
|
const secondLi = page.locator('.where-builder__and-filters li:nth-child(2)')
|
||||||
|
await expect(secondLi).toBeVisible()
|
||||||
|
const secondConditionField = secondLi.locator('.condition__field')
|
||||||
|
const secondOperatorField = secondLi.locator('.condition__operator')
|
||||||
|
const secondValueField = secondLi.locator('.condition__value >> input')
|
||||||
|
await secondConditionField.click()
|
||||||
|
|
||||||
|
await secondConditionField
|
||||||
|
.locator('.rs__option', { hasText: exactText('Tab 1 > Title') })
|
||||||
|
.click()
|
||||||
|
|
||||||
|
await expect(secondConditionField.locator('.rs__single-value')).toContainText('Tab 1 > Title')
|
||||||
|
await secondOperatorField.click()
|
||||||
|
await secondOperatorField.locator('.rs__option').locator('text=equals').click()
|
||||||
|
await secondValueField.fill('Test 2')
|
||||||
|
await expect(secondValueField).toHaveValue('Test 2')
|
||||||
|
|
||||||
|
const firstLi = page.locator('.where-builder__and-filters li:nth-child(1)')
|
||||||
|
const removeButton = firstLi.locator('.condition__actions-remove')
|
||||||
|
|
||||||
|
await wait(500)
|
||||||
|
|
||||||
|
// remove first filter
|
||||||
|
await removeButton.click()
|
||||||
|
const filterListItems = page.locator('.where-builder__and-filters li')
|
||||||
|
await expect(filterListItems).toHaveCount(1)
|
||||||
|
await expect(firstValueField).toHaveValue('Test 2')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should hide field filter when admin.disableListFilter is true', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await openListFilters(page, {})
|
||||||
|
await page.locator('.where-builder__add-first-filter').click()
|
||||||
|
|
||||||
|
const initialField = page.locator('.condition__field')
|
||||||
|
await initialField.click()
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
initialField.locator(`.rs__option :has-text("Disable List Filter Text")`),
|
||||||
|
).toBeHidden()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should simply disable field filter when admin.disableListFilter is true but still exists in the query', async () => {
|
||||||
|
await page.goto(
|
||||||
|
`${postsUrl.list}${qs.stringify(
|
||||||
|
{
|
||||||
|
where: {
|
||||||
|
or: [
|
||||||
|
{
|
||||||
|
and: [
|
||||||
|
{
|
||||||
|
disableListFilterText: {
|
||||||
|
equals: 'Disable List Filter Text',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ addQueryPrefix: true },
|
||||||
|
)}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
await openListFilters(page, {})
|
||||||
|
|
||||||
|
const condition = page.locator('.condition__field')
|
||||||
|
await expect(condition.locator('input.rs__input')).toBeDisabled()
|
||||||
|
await expect(page.locator('.condition__operator input.rs__input')).toBeDisabled()
|
||||||
|
await expect(page.locator('.condition__value input.condition-value-text')).toBeDisabled()
|
||||||
|
await expect(condition.locator('.rs__single-value')).toHaveText('Disable List Filter Text')
|
||||||
|
await page.locator('button.condition__actions-add').click()
|
||||||
|
const condition2 = page.locator('.condition__field').nth(1)
|
||||||
|
await condition2.click()
|
||||||
|
await expect(
|
||||||
|
condition2?.locator('.rs__menu-list:has-text("Disable List Filter Text")'),
|
||||||
|
).toBeHidden()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('table columns', () => {
|
describe('table columns', () => {
|
||||||
|
test('should hide field in column selector when admin.disableListColumn is true', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await page.locator('.list-controls__toggle-columns').click()
|
||||||
|
|
||||||
|
await expect(page.locator('.column-selector')).toBeVisible()
|
||||||
|
|
||||||
|
// Check if "Disable List Column Text" is not present in the column options
|
||||||
|
await expect(
|
||||||
|
page.locator(`.column-selector .column-selector__column`, {
|
||||||
|
hasText: exactText('Disable List Column Text'),
|
||||||
|
}),
|
||||||
|
).toBeHidden()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should display field in column selector despite admin.disableListFilter', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await page.locator('.list-controls__toggle-columns').click()
|
||||||
|
|
||||||
|
await expect(page.locator('.column-selector')).toBeVisible()
|
||||||
|
|
||||||
|
// Check if "Disable List Filter Text" is present in the column options
|
||||||
|
await expect(
|
||||||
|
page.locator(`.column-selector .column-selector__column`, {
|
||||||
|
hasText: exactText('Disable List Filter Text'),
|
||||||
|
}),
|
||||||
|
).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should still show field in filter when admin.disableListColumn is true', async () => {
|
||||||
|
await page.goto(postsUrl.list)
|
||||||
|
await openListFilters(page, {})
|
||||||
|
await page.locator('.where-builder__add-first-filter').click()
|
||||||
|
|
||||||
|
const initialField = page.locator('.condition__field')
|
||||||
|
await initialField.click()
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
initialField.locator(`.rs__menu-list:has-text("Disable List Column Text")`),
|
||||||
|
).toBeVisible()
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should toggle columns', async () => {
|
||||||
|
const columnCountLocator = 'table > thead > tr > th'
|
||||||
|
await createPost()
|
||||||
|
await openListColumns(page, {})
|
||||||
|
const numberOfColumns = await page.locator(columnCountLocator).count()
|
||||||
|
await expect(page.locator('.column-selector')).toBeVisible()
|
||||||
|
await expect(page.locator('table > thead > tr > th:nth-child(2)')).toHaveText('ID')
|
||||||
|
await toggleColumn(page, { columnLabel: 'ID', targetState: 'off' })
|
||||||
|
await page.locator('#heading-id').waitFor({ state: 'detached' })
|
||||||
|
await page.locator('.cell-id').first().waitFor({ state: 'detached' })
|
||||||
|
await expect(page.locator(columnCountLocator)).toHaveCount(numberOfColumns - 1)
|
||||||
|
await expect(page.locator('table > thead > tr > th:nth-child(2)')).toHaveText('Number')
|
||||||
|
await toggleColumn(page, { columnLabel: 'ID', targetState: 'on' })
|
||||||
|
await expect(page.locator('.cell-id').first()).toBeVisible()
|
||||||
|
await expect(page.locator(columnCountLocator)).toHaveCount(numberOfColumns)
|
||||||
|
await expect(page.locator('table > thead > tr > th:nth-child(2)')).toHaveText('ID')
|
||||||
|
})
|
||||||
|
|
||||||
test('should drag to reorder columns and save to preferences', async () => {
|
test('should drag to reorder columns and save to preferences', async () => {
|
||||||
await createPost()
|
await createPost()
|
||||||
|
|
||||||
@@ -813,14 +1024,6 @@ describe('List View', () => {
|
|||||||
).toHaveText('Title')
|
).toHaveText('Title')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('base list filters', () => {
|
|
||||||
test('should respect base list filters', async () => {
|
|
||||||
await page.goto(baseListFiltersUrl.list)
|
|
||||||
await page.waitForURL((url) => url.toString().startsWith(baseListFiltersUrl.list))
|
|
||||||
await expect(page.locator(tableRowLocator)).toHaveCount(1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
async function createPost(overrides?: Partial<Post>): Promise<Post> {
|
async function createPost(overrides?: Partial<Post>): Promise<Post> {
|
||||||
|
|||||||
@@ -165,6 +165,8 @@ export interface Post {
|
|||||||
defaultValueField?: string | null;
|
defaultValueField?: string | null;
|
||||||
relationship?: (string | null) | Post;
|
relationship?: (string | null) | Post;
|
||||||
customCell?: string | null;
|
customCell?: string | null;
|
||||||
|
disableListColumnText?: string | null;
|
||||||
|
disableListFilterText?: string | null;
|
||||||
sidebarField?: string | null;
|
sidebarField?: string | null;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -520,6 +522,8 @@ export interface PostsSelect<T extends boolean = true> {
|
|||||||
defaultValueField?: T;
|
defaultValueField?: T;
|
||||||
relationship?: T;
|
relationship?: T;
|
||||||
customCell?: T;
|
customCell?: T;
|
||||||
|
disableListColumnText?: T;
|
||||||
|
disableListFilterText?: T;
|
||||||
sidebarField?: T;
|
sidebarField?: T;
|
||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
|
|||||||
@@ -9,19 +9,14 @@ import { fileURLToPath } from 'url'
|
|||||||
import type { PayloadTestSDK } from '../../../helpers/sdk/index.js'
|
import type { PayloadTestSDK } from '../../../helpers/sdk/index.js'
|
||||||
import type { Config } from '../../payload-types.js'
|
import type { Config } from '../../payload-types.js'
|
||||||
|
|
||||||
import {
|
import { ensureCompilationIsDone, initPageConsoleErrorCatch } from '../../../helpers.js'
|
||||||
ensureCompilationIsDone,
|
|
||||||
exactText,
|
|
||||||
initPageConsoleErrorCatch,
|
|
||||||
saveDocAndAssert,
|
|
||||||
} from '../../../helpers.js'
|
|
||||||
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
|
import { AdminUrlUtil } from '../../../helpers/adminUrlUtil.js'
|
||||||
import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js'
|
import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js'
|
||||||
import { reInitializeDB } from '../../../helpers/reInitializeDB.js'
|
import { reInitializeDB } from '../../../helpers/reInitializeDB.js'
|
||||||
import { RESTClient } from '../../../helpers/rest.js'
|
import { RESTClient } from '../../../helpers/rest.js'
|
||||||
import { TEST_TIMEOUT_LONG } from '../../../playwright.config.js'
|
import { TEST_TIMEOUT_LONG } from '../../../playwright.config.js'
|
||||||
import { emailFieldsSlug } from '../../slugs.js'
|
import { emailFieldsSlug } from '../../slugs.js'
|
||||||
import { anotherEmailDoc, emailDoc } from './shared.js'
|
import { emailDoc } from './shared.js'
|
||||||
|
|
||||||
const filename = fileURLToPath(import.meta.url)
|
const filename = fileURLToPath(import.meta.url)
|
||||||
const currentFolder = path.dirname(filename)
|
const currentFolder = path.dirname(filename)
|
||||||
@@ -74,60 +69,6 @@ describe('Email', () => {
|
|||||||
await expect(emailCell).toHaveText(emailDoc.email)
|
await expect(emailCell).toHaveText(emailDoc.email)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should hide field in column selector when admin.disableListColumn', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await page.locator('.list-controls__toggle-columns').click()
|
|
||||||
|
|
||||||
await expect(page.locator('.column-selector')).toBeVisible()
|
|
||||||
|
|
||||||
// Check if "Disable List Column Text" is not present in the column options
|
|
||||||
await expect(
|
|
||||||
page.locator(`.column-selector .column-selector__column`, {
|
|
||||||
hasText: exactText('Disable List Column Text'),
|
|
||||||
}),
|
|
||||||
).toBeHidden()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should show field in filter when admin.disableListColumn is true', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const initialField = page.locator('.condition__field')
|
|
||||||
await initialField.click()
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
initialField.locator(`.rs__menu-list:has-text("Disable List Column Text")`),
|
|
||||||
).toBeVisible()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should display field in list view column selector despite admin.disableListFilter', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await page.locator('.list-controls__toggle-columns').click()
|
|
||||||
|
|
||||||
await expect(page.locator('.column-selector')).toBeVisible()
|
|
||||||
|
|
||||||
// Check if "Disable List Filter Text" is present in the column options
|
|
||||||
await expect(
|
|
||||||
page.locator(`.column-selector .column-selector__column`, {
|
|
||||||
hasText: exactText('Disable List Filter Text'),
|
|
||||||
}),
|
|
||||||
).toBeVisible()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should hide field in filter when admin.disableListFilter is true', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const initialField = page.locator('.condition__field')
|
|
||||||
await initialField.click()
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
initialField.locator(`.rs__option :has-text("Disable List Filter Text")`),
|
|
||||||
).toBeHidden()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should have autocomplete', async () => {
|
test('should have autocomplete', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
const autoCompleteEmail = page.locator('#field-emailWithAutocomplete')
|
const autoCompleteEmail = page.locator('#field-emailWithAutocomplete')
|
||||||
|
|||||||
@@ -3,12 +3,9 @@ import type { GeneratedTypes } from 'helpers/sdk/types.js'
|
|||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { openListColumns } from 'helpers/e2e/openListColumns.js'
|
import { openListColumns } from 'helpers/e2e/openListColumns.js'
|
||||||
import { openListFilters } from 'helpers/e2e/openListFilters.js'
|
|
||||||
import { toggleColumn } from 'helpers/e2e/toggleColumn.js'
|
import { toggleColumn } from 'helpers/e2e/toggleColumn.js'
|
||||||
import { upsertPrefs } from 'helpers/e2e/upsertPrefs.js'
|
import { upsertPrefs } from 'helpers/e2e/upsertPrefs.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
|
||||||
import * as qs from 'qs-esm'
|
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
import type { PayloadTestSDK } from '../../../helpers/sdk/index.js'
|
import type { PayloadTestSDK } from '../../../helpers/sdk/index.js'
|
||||||
@@ -167,84 +164,6 @@ describe('Text', () => {
|
|||||||
await expect(textCell).toHaveText(textDoc.text)
|
await expect(textCell).toHaveText(textDoc.text)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should hide field in column selector when admin.disableListColumn', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await page.locator('.list-controls__toggle-columns').click()
|
|
||||||
|
|
||||||
await expect(page.locator('.column-selector')).toBeVisible()
|
|
||||||
|
|
||||||
// Check if "Disable List Column Text" is not present in the column options
|
|
||||||
await expect(
|
|
||||||
page.locator(`.column-selector .column-selector__column`, {
|
|
||||||
hasText: exactText('Disable List Column Text'),
|
|
||||||
}),
|
|
||||||
).toBeHidden()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should show field in filter when admin.disableListColumn is true', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const initialField = page.locator('.condition__field')
|
|
||||||
await initialField.click()
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
initialField.locator(`.rs__menu-list:has-text("Disable List Column Text")`),
|
|
||||||
).toBeVisible()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should display field in list view column selector despite admin.disableListFilter', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await page.locator('.list-controls__toggle-columns').click()
|
|
||||||
|
|
||||||
await expect(page.locator('.column-selector')).toBeVisible()
|
|
||||||
|
|
||||||
// Check if "Disable List Filter Text" is present in the column options
|
|
||||||
await expect(
|
|
||||||
page.locator(`.column-selector .column-selector__column`, {
|
|
||||||
hasText: exactText('Disable List Filter Text'),
|
|
||||||
}),
|
|
||||||
).toBeVisible()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should disable field when admin.disableListFilter is true but still exists in the query', async () => {
|
|
||||||
await page.goto(
|
|
||||||
`${url.list}${qs.stringify(
|
|
||||||
{
|
|
||||||
where: {
|
|
||||||
or: [
|
|
||||||
{
|
|
||||||
and: [
|
|
||||||
{
|
|
||||||
disableListFilterText: {
|
|
||||||
equals: 'Disable List Filter Text',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ addQueryPrefix: true },
|
|
||||||
)}`,
|
|
||||||
)
|
|
||||||
|
|
||||||
await openListFilters(page, {})
|
|
||||||
|
|
||||||
const condition = page.locator('.condition__field')
|
|
||||||
await expect(condition.locator('input.rs__input')).toBeDisabled()
|
|
||||||
await expect(page.locator('.condition__operator input.rs__input')).toBeDisabled()
|
|
||||||
await expect(page.locator('.condition__value input.condition-value-text')).toBeDisabled()
|
|
||||||
await expect(condition.locator('.rs__single-value')).toHaveText('Disable List Filter Text')
|
|
||||||
await page.locator('button.condition__actions-add').click()
|
|
||||||
const condition2 = page.locator('.condition__field').nth(1)
|
|
||||||
await condition2.click()
|
|
||||||
await expect(
|
|
||||||
condition2?.locator('.rs__menu-list:has-text("Disable List Filter Text")'),
|
|
||||||
).toBeHidden()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should respect admin.disableListColumn despite preferences', async () => {
|
test('should respect admin.disableListColumn despite preferences', async () => {
|
||||||
await upsertPrefs<Config, GeneratedTypes<any>>({
|
await upsertPrefs<Config, GeneratedTypes<any>>({
|
||||||
payload,
|
payload,
|
||||||
@@ -271,19 +190,6 @@ describe('Text', () => {
|
|||||||
await expect(page.locator('table .row-1 .cell-disableListColumnText')).toBeHidden()
|
await expect(page.locator('table .row-1 .cell-disableListColumnText')).toBeHidden()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should hide field in filter when admin.disableListFilter is true', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const initialField = page.locator('.condition__field')
|
|
||||||
await initialField.click()
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
initialField.locator(`.rs__option :has-text("Disable List Filter Text")`),
|
|
||||||
).toBeHidden()
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should display i18n label in cells when missing field data', async () => {
|
test('should display i18n label in cells when missing field data', async () => {
|
||||||
await page.goto(url.list)
|
await page.goto(url.list)
|
||||||
await page.waitForURL(new RegExp(`${url.list}.*\\?.*`))
|
await page.waitForURL(new RegExp(`${url.list}.*\\?.*`))
|
||||||
@@ -333,136 +239,4 @@ describe('Text', () => {
|
|||||||
await expect(field.locator('.rs__value-container')).toContainText(input)
|
await expect(field.locator('.rs__value-container')).toContainText(input)
|
||||||
await expect(field.locator('.rs__value-container')).toContainText(furtherInput)
|
await expect(field.locator('.rs__value-container')).toContainText(furtherInput)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should reset filter conditions when adding additional filters', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
|
|
||||||
// open the first filter options
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const firstInitialField = page.locator('.condition__field')
|
|
||||||
const firstOperatorField = page.locator('.condition__operator')
|
|
||||||
const firstValueField = page.locator('.condition__value >> input')
|
|
||||||
|
|
||||||
await firstInitialField.click()
|
|
||||||
const firstInitialFieldOptions = firstInitialField.locator('.rs__option')
|
|
||||||
await firstInitialFieldOptions.locator('text=text').first().click()
|
|
||||||
await expect(firstInitialField.locator('.rs__single-value')).toContainText('Text')
|
|
||||||
|
|
||||||
await firstOperatorField.click()
|
|
||||||
await firstOperatorField.locator('.rs__option').locator('text=equals').click()
|
|
||||||
|
|
||||||
await firstValueField.fill('hello')
|
|
||||||
|
|
||||||
await wait(500)
|
|
||||||
|
|
||||||
await expect(firstValueField).toHaveValue('hello')
|
|
||||||
|
|
||||||
// open the second filter options
|
|
||||||
await page.locator('.condition__actions-add').click()
|
|
||||||
|
|
||||||
const secondLi = page.locator('.where-builder__and-filters li:nth-child(2)')
|
|
||||||
|
|
||||||
await expect(secondLi).toBeVisible()
|
|
||||||
|
|
||||||
const secondInitialField = secondLi.locator('.condition__field')
|
|
||||||
const secondOperatorField = secondLi.locator('.condition__operator >> input')
|
|
||||||
const secondValueField = secondLi.locator('.condition__value >> input')
|
|
||||||
|
|
||||||
await expect(secondInitialField.locator('.rs__single-value')).toContainText('Text')
|
|
||||||
await expect(secondOperatorField).toHaveValue('')
|
|
||||||
await expect(secondValueField).toHaveValue('')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should not re-render page upon typing in a value in the filter value field', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
|
|
||||||
// open the first filter options
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const firstInitialField = page.locator('.condition__field')
|
|
||||||
const firstOperatorField = page.locator('.condition__operator')
|
|
||||||
const firstValueField = page.locator('.condition__value >> input')
|
|
||||||
|
|
||||||
await firstInitialField.click()
|
|
||||||
const firstInitialFieldOptions = firstInitialField.locator('.rs__option')
|
|
||||||
await firstInitialFieldOptions.locator('text=text').first().click()
|
|
||||||
await expect(firstInitialField.locator('.rs__single-value')).toContainText('Text')
|
|
||||||
|
|
||||||
await firstOperatorField.click()
|
|
||||||
await firstOperatorField.locator('.rs__option').locator('text=equals').click()
|
|
||||||
|
|
||||||
// Type into the input field instead of filling it
|
|
||||||
await firstValueField.click()
|
|
||||||
await firstValueField.type('hello', { delay: 100 }) // Add a delay to simulate typing speed
|
|
||||||
|
|
||||||
// Wait for a short period to see if the input loses focus
|
|
||||||
await page.waitForTimeout(500)
|
|
||||||
|
|
||||||
// Check if the input still has the correct value
|
|
||||||
await expect(firstValueField).toHaveValue('hello')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('should still show second filter if two filters exist and first filter is removed', async () => {
|
|
||||||
await page.goto(url.list)
|
|
||||||
|
|
||||||
// open the first filter options
|
|
||||||
await openListFilters(page, {})
|
|
||||||
await page.locator('.where-builder__add-first-filter').click()
|
|
||||||
|
|
||||||
const firstInitialField = page.locator('.condition__field')
|
|
||||||
const firstOperatorField = page.locator('.condition__operator')
|
|
||||||
const firstValueField = page.locator('.condition__value >> input')
|
|
||||||
|
|
||||||
await firstInitialField.click()
|
|
||||||
const firstInitialFieldOptions = firstInitialField.locator('.rs__option')
|
|
||||||
await firstInitialFieldOptions.locator('text=text').first().click()
|
|
||||||
await expect(firstInitialField.locator('.rs__single-value')).toContainText('Text')
|
|
||||||
|
|
||||||
await firstOperatorField.click()
|
|
||||||
await firstOperatorField.locator('.rs__option').locator('text=equals').click()
|
|
||||||
|
|
||||||
await firstValueField.fill('hello')
|
|
||||||
|
|
||||||
await wait(500)
|
|
||||||
|
|
||||||
await expect(firstValueField).toHaveValue('hello')
|
|
||||||
|
|
||||||
// open the second filter options
|
|
||||||
await page.locator('.condition__actions-add').click()
|
|
||||||
|
|
||||||
const secondLi = page.locator('.where-builder__and-filters li:nth-child(2)')
|
|
||||||
|
|
||||||
await expect(secondLi).toBeVisible()
|
|
||||||
|
|
||||||
const secondInitialField = secondLi.locator('.condition__field')
|
|
||||||
const secondOperatorField = secondLi.locator('.condition__operator')
|
|
||||||
const secondValueField = secondLi.locator('.condition__value >> input')
|
|
||||||
|
|
||||||
await secondInitialField.click()
|
|
||||||
const secondInitialFieldOptions = secondInitialField.locator('.rs__option')
|
|
||||||
await secondInitialFieldOptions.locator('text=text').first().click()
|
|
||||||
await expect(secondInitialField.locator('.rs__single-value')).toContainText('Text')
|
|
||||||
|
|
||||||
await secondOperatorField.click()
|
|
||||||
await secondOperatorField.locator('.rs__option').locator('text=equals').click()
|
|
||||||
|
|
||||||
await secondValueField.fill('world')
|
|
||||||
await expect(secondValueField).toHaveValue('world')
|
|
||||||
|
|
||||||
await wait(500)
|
|
||||||
|
|
||||||
const firstLi = page.locator('.where-builder__and-filters li:nth-child(1)')
|
|
||||||
const removeButton = firstLi.locator('.condition__actions-remove')
|
|
||||||
|
|
||||||
// remove first filter
|
|
||||||
await removeButton.click()
|
|
||||||
|
|
||||||
const filterListItems = page.locator('.where-builder__and-filters li')
|
|
||||||
await expect(filterListItems).toHaveCount(1)
|
|
||||||
|
|
||||||
await expect(firstValueField).toHaveValue('world')
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -158,20 +158,6 @@ const TextFields: CollectionConfig = {
|
|||||||
return Promise.resolve(req.context.defaultValue)
|
return Promise.resolve(req.context.defaultValue)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'disableListColumnText',
|
|
||||||
type: 'text',
|
|
||||||
admin: {
|
|
||||||
disableListColumn: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'disableListFilterText',
|
|
||||||
type: 'text',
|
|
||||||
admin: {
|
|
||||||
disableListFilter: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'array',
|
name: 'array',
|
||||||
type: 'array',
|
type: 'array',
|
||||||
|
|||||||
@@ -310,6 +310,9 @@ export interface LexicalMigrateField {
|
|||||||
export interface LexicalLocalizedField {
|
export interface LexicalLocalizedField {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
/**
|
||||||
|
* Non-localized field with localized block subfields
|
||||||
|
*/
|
||||||
lexicalBlocksSubLocalized?: {
|
lexicalBlocksSubLocalized?: {
|
||||||
root: {
|
root: {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -325,6 +328,9 @@ export interface LexicalLocalizedField {
|
|||||||
};
|
};
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
} | null;
|
} | null;
|
||||||
|
/**
|
||||||
|
* Localized field with localized block subfields
|
||||||
|
*/
|
||||||
lexicalBlocksLocalized?: {
|
lexicalBlocksLocalized?: {
|
||||||
root: {
|
root: {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -475,6 +481,9 @@ export interface ArrayField {
|
|||||||
id?: string | null;
|
id?: string | null;
|
||||||
}[]
|
}[]
|
||||||
| null;
|
| null;
|
||||||
|
/**
|
||||||
|
* Row labels rendered as react components.
|
||||||
|
*/
|
||||||
rowLabelAsComponent?:
|
rowLabelAsComponent?:
|
||||||
| {
|
| {
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
@@ -589,6 +598,9 @@ export interface BlockField {
|
|||||||
}
|
}
|
||||||
)[]
|
)[]
|
||||||
| null;
|
| null;
|
||||||
|
/**
|
||||||
|
* The purpose of this field is to test validateExistingBlockIsIdentical works with similar blocks with group fields
|
||||||
|
*/
|
||||||
blocksWithSimilarGroup?:
|
blocksWithSimilarGroup?:
|
||||||
| (
|
| (
|
||||||
| {
|
| {
|
||||||
@@ -777,9 +789,18 @@ export interface TextField {
|
|||||||
id: string;
|
id: string;
|
||||||
text: string;
|
text: string;
|
||||||
hiddenTextField?: string | null;
|
hiddenTextField?: string | null;
|
||||||
|
/**
|
||||||
|
* This field should be hidden
|
||||||
|
*/
|
||||||
adminHiddenTextField?: string | null;
|
adminHiddenTextField?: string | null;
|
||||||
|
/**
|
||||||
|
* This field should be disabled
|
||||||
|
*/
|
||||||
disabledTextField?: string | null;
|
disabledTextField?: string | null;
|
||||||
localizedText?: string | null;
|
localizedText?: string | null;
|
||||||
|
/**
|
||||||
|
* en description
|
||||||
|
*/
|
||||||
i18nText?: string | null;
|
i18nText?: string | null;
|
||||||
defaultString?: string | null;
|
defaultString?: string | null;
|
||||||
defaultEmptyString?: string | null;
|
defaultEmptyString?: string | null;
|
||||||
@@ -794,8 +815,6 @@ export interface TextField {
|
|||||||
withMinRows?: string[] | null;
|
withMinRows?: string[] | null;
|
||||||
withMaxRows?: string[] | null;
|
withMaxRows?: string[] | null;
|
||||||
defaultValueFromReq?: string | null;
|
defaultValueFromReq?: string | null;
|
||||||
disableListColumnText?: string | null;
|
|
||||||
disableListFilterText?: string | null;
|
|
||||||
array?:
|
array?:
|
||||||
| {
|
| {
|
||||||
texts?: string[] | null;
|
texts?: string[] | null;
|
||||||
@@ -900,8 +919,14 @@ export interface ConditionalLogic {
|
|||||||
userConditional?: string | null;
|
userConditional?: string | null;
|
||||||
parentGroup?: {
|
parentGroup?: {
|
||||||
enableParentGroupFields?: boolean | null;
|
enableParentGroupFields?: boolean | null;
|
||||||
|
/**
|
||||||
|
* Ensures we can rely on nested fields within `data`.
|
||||||
|
*/
|
||||||
siblingField?: string | null;
|
siblingField?: string | null;
|
||||||
};
|
};
|
||||||
|
/**
|
||||||
|
* Ensures we can rely on nested fields within `siblingsData`.
|
||||||
|
*/
|
||||||
reliesOnParentGroup?: string | null;
|
reliesOnParentGroup?: string | null;
|
||||||
groupSelection?: ('group1' | 'group2') | null;
|
groupSelection?: ('group1' | 'group2') | null;
|
||||||
group1?: {
|
group1?: {
|
||||||
@@ -981,6 +1006,9 @@ export interface EmailField {
|
|||||||
email: string;
|
email: string;
|
||||||
localizedEmail?: string | null;
|
localizedEmail?: string | null;
|
||||||
emailWithAutocomplete?: string | null;
|
emailWithAutocomplete?: string | null;
|
||||||
|
/**
|
||||||
|
* en description
|
||||||
|
*/
|
||||||
i18nEmail?: string | null;
|
i18nEmail?: string | null;
|
||||||
defaultEmail?: string | null;
|
defaultEmail?: string | null;
|
||||||
defaultEmptyString?: string | null;
|
defaultEmptyString?: string | null;
|
||||||
@@ -1010,6 +1038,9 @@ export interface RadioField {
|
|||||||
*/
|
*/
|
||||||
export interface GroupField {
|
export interface GroupField {
|
||||||
id: string;
|
id: string;
|
||||||
|
/**
|
||||||
|
* This is a group.
|
||||||
|
*/
|
||||||
group: {
|
group: {
|
||||||
text: string;
|
text: string;
|
||||||
defaultParent?: string | null;
|
defaultParent?: string | null;
|
||||||
@@ -1402,6 +1433,9 @@ export interface RichTextField {
|
|||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
};
|
};
|
||||||
lexicalCustomFields_html?: string | null;
|
lexicalCustomFields_html?: string | null;
|
||||||
|
/**
|
||||||
|
* This rich text field uses the lexical editor.
|
||||||
|
*/
|
||||||
lexical?: {
|
lexical?: {
|
||||||
root: {
|
root: {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -1417,6 +1451,9 @@ export interface RichTextField {
|
|||||||
};
|
};
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
} | null;
|
} | null;
|
||||||
|
/**
|
||||||
|
* This select field is rendered here to ensure its options dropdown renders above the rich text toolbar.
|
||||||
|
*/
|
||||||
selectHasMany?: ('one' | 'two' | 'three' | 'four' | 'five' | 'six')[] | null;
|
selectHasMany?: ('one' | 'two' | 'three' | 'four' | 'five' | 'six')[] | null;
|
||||||
richText: {
|
richText: {
|
||||||
[k: string]: unknown;
|
[k: string]: unknown;
|
||||||
@@ -1505,6 +1542,9 @@ export interface TabsFields2 {
|
|||||||
*/
|
*/
|
||||||
export interface TabsField {
|
export interface TabsField {
|
||||||
id: string;
|
id: string;
|
||||||
|
/**
|
||||||
|
* This should not collapse despite there being many tabs pushing the main fields open.
|
||||||
|
*/
|
||||||
sidebarField?: string | null;
|
sidebarField?: string | null;
|
||||||
array: {
|
array: {
|
||||||
text: string;
|
text: string;
|
||||||
@@ -2115,257 +2155,42 @@ export interface BlockFieldsSelect<T extends boolean = true> {
|
|||||||
blocks?:
|
blocks?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
content?:
|
content?: T | ContentBlockSelect<T>;
|
||||||
| T
|
number?: T | NumberBlockSelect<T>;
|
||||||
| {
|
subBlocks?: T | SubBlocksBlockSelect<T>;
|
||||||
text?: T;
|
tabs?: T | TabsBlockSelect<T>;
|
||||||
richText?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
tabs?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInCollapsible?: T;
|
|
||||||
textInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
duplicate?:
|
duplicate?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
content?:
|
content?: T | ContentBlockSelect<T>;
|
||||||
| T
|
number?: T | NumberBlockSelect<T>;
|
||||||
| {
|
subBlocks?: T | SubBlocksBlockSelect<T>;
|
||||||
text?: T;
|
tabs?: T | TabsBlockSelect<T>;
|
||||||
richText?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
tabs?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInCollapsible?: T;
|
|
||||||
textInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
collapsedByDefaultBlocks?:
|
collapsedByDefaultBlocks?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
localizedContent?:
|
localizedContent?: T | LocalizedContentBlockSelect<T>;
|
||||||
| T
|
localizedNumber?: T | LocalizedNumberBlockSelect<T>;
|
||||||
| {
|
localizedSubBlocks?: T | LocalizedSubBlocksBlockSelect<T>;
|
||||||
text?: T;
|
localizedTabs?: T | LocalizedTabsBlockSelect<T>;
|
||||||
richText?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedNumber?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedSubBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedTabs?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInCollapsible?: T;
|
|
||||||
textInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
disableSort?:
|
disableSort?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
localizedContent?:
|
localizedContent?: T | LocalizedContentBlockSelect<T>;
|
||||||
| T
|
localizedNumber?: T | LocalizedNumberBlockSelect<T>;
|
||||||
| {
|
localizedSubBlocks?: T | LocalizedSubBlocksBlockSelect<T>;
|
||||||
text?: T;
|
localizedTabs?: T | LocalizedTabsBlockSelect<T>;
|
||||||
richText?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedNumber?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedSubBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedTabs?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInCollapsible?: T;
|
|
||||||
textInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
localizedBlocks?:
|
localizedBlocks?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
localizedContent?:
|
localizedContent?: T | LocalizedContentBlockSelect<T>;
|
||||||
| T
|
localizedNumber?: T | LocalizedNumberBlockSelect<T>;
|
||||||
| {
|
localizedSubBlocks?: T | LocalizedSubBlocksBlockSelect<T>;
|
||||||
text?: T;
|
localizedTabs?: T | LocalizedTabsBlockSelect<T>;
|
||||||
richText?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedNumber?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedSubBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
localizedTabs?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInCollapsible?: T;
|
|
||||||
textInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
i18nBlocks?:
|
i18nBlocks?:
|
||||||
| T
|
| T
|
||||||
@@ -2503,6 +2328,116 @@ export interface BlockFieldsSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "ContentBlock_select".
|
||||||
|
*/
|
||||||
|
export interface ContentBlockSelect<T extends boolean = true> {
|
||||||
|
text?: T;
|
||||||
|
richText?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "NumberBlock_select".
|
||||||
|
*/
|
||||||
|
export interface NumberBlockSelect<T extends boolean = true> {
|
||||||
|
number?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "SubBlocksBlock_select".
|
||||||
|
*/
|
||||||
|
export interface SubBlocksBlockSelect<T extends boolean = true> {
|
||||||
|
subBlocks?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
text?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
text?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
};
|
||||||
|
number?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
number?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "TabsBlock_select".
|
||||||
|
*/
|
||||||
|
export interface TabsBlockSelect<T extends boolean = true> {
|
||||||
|
textInCollapsible?: T;
|
||||||
|
textInRow?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "localizedContentBlock_select".
|
||||||
|
*/
|
||||||
|
export interface LocalizedContentBlockSelect<T extends boolean = true> {
|
||||||
|
text?: T;
|
||||||
|
richText?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "localizedNumberBlock_select".
|
||||||
|
*/
|
||||||
|
export interface LocalizedNumberBlockSelect<T extends boolean = true> {
|
||||||
|
number?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "localizedSubBlocksBlock_select".
|
||||||
|
*/
|
||||||
|
export interface LocalizedSubBlocksBlockSelect<T extends boolean = true> {
|
||||||
|
subBlocks?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
text?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
text?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
};
|
||||||
|
number?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
number?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "localizedTabsBlock_select".
|
||||||
|
*/
|
||||||
|
export interface LocalizedTabsBlockSelect<T extends boolean = true> {
|
||||||
|
textInCollapsible?: T;
|
||||||
|
textInRow?: T;
|
||||||
|
id?: T;
|
||||||
|
blockName?: T;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "checkbox-fields_select".
|
* via the `definition` "checkbox-fields_select".
|
||||||
@@ -3085,53 +3020,10 @@ export interface TabsFieldsSelect<T extends boolean = true> {
|
|||||||
blocks?:
|
blocks?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
content?:
|
content?: T | ContentBlockSelect<T>;
|
||||||
| T
|
number?: T | NumberBlockSelect<T>;
|
||||||
| {
|
subBlocks?: T | SubBlocksBlockSelect<T>;
|
||||||
text?: T;
|
tabs?: T | TabsBlockSelect<T>;
|
||||||
richText?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
subBlocks?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
number?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
number?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
tabs?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInCollapsible?: T;
|
|
||||||
textInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
blockName?: T;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
group?:
|
group?:
|
||||||
| T
|
| T
|
||||||
@@ -3141,24 +3033,7 @@ export interface TabsFieldsSelect<T extends boolean = true> {
|
|||||||
textInRow?: T;
|
textInRow?: T;
|
||||||
numberInRow?: T;
|
numberInRow?: T;
|
||||||
json?: T;
|
json?: T;
|
||||||
tab?:
|
tab?: T | TabWithNameSelect<T>;
|
||||||
| T
|
|
||||||
| {
|
|
||||||
array?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
text?: T;
|
|
||||||
id?: T;
|
|
||||||
};
|
|
||||||
text?: T;
|
|
||||||
defaultValue?: T;
|
|
||||||
arrayInRow?:
|
|
||||||
| T
|
|
||||||
| {
|
|
||||||
textInArrayInRow?: T;
|
|
||||||
id?: T;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
namedTabWithDefaultValue?:
|
namedTabWithDefaultValue?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
@@ -3208,6 +3083,26 @@ export interface TabsFieldsSelect<T extends boolean = true> {
|
|||||||
updatedAt?: T;
|
updatedAt?: T;
|
||||||
createdAt?: T;
|
createdAt?: T;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
* via the `definition` "TabWithName_select".
|
||||||
|
*/
|
||||||
|
export interface TabWithNameSelect<T extends boolean = true> {
|
||||||
|
array?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
text?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
text?: T;
|
||||||
|
defaultValue?: T;
|
||||||
|
arrayInRow?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
textInArrayInRow?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
* via the `definition` "text-fields_select".
|
* via the `definition` "text-fields_select".
|
||||||
@@ -3232,8 +3127,6 @@ export interface TextFieldsSelect<T extends boolean = true> {
|
|||||||
withMinRows?: T;
|
withMinRows?: T;
|
||||||
withMaxRows?: T;
|
withMaxRows?: T;
|
||||||
defaultValueFromReq?: T;
|
defaultValueFromReq?: T;
|
||||||
disableListColumnText?: T;
|
|
||||||
disableListFilterText?: T;
|
|
||||||
array?:
|
array?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
|
|||||||
@@ -126,9 +126,6 @@ export interface UserAuthOperations {
|
|||||||
export interface Post {
|
export interface Post {
|
||||||
id: string;
|
id: string;
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
/**
|
|
||||||
* Hides posts for the `filtered` join field in categories
|
|
||||||
*/
|
|
||||||
isFiltered?: boolean | null;
|
isFiltered?: boolean | null;
|
||||||
restrictedField?: string | null;
|
restrictedField?: string | null;
|
||||||
upload?: (string | null) | Upload;
|
upload?: (string | null) | Upload;
|
||||||
@@ -231,9 +228,6 @@ export interface Category {
|
|||||||
docs?: (string | Post)[] | null;
|
docs?: (string | Post)[] | null;
|
||||||
hasNextPage?: boolean | null;
|
hasNextPage?: boolean | null;
|
||||||
} | null;
|
} | null;
|
||||||
/**
|
|
||||||
* Static Description
|
|
||||||
*/
|
|
||||||
hasManyPosts?: {
|
hasManyPosts?: {
|
||||||
docs?: (string | Post)[] | null;
|
docs?: (string | Post)[] | null;
|
||||||
hasNextPage?: boolean | null;
|
hasNextPage?: boolean | null;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@payload-config": ["./test/_community/config.ts"],
|
"@payload-config": ["./test/admin/config.ts"],
|
||||||
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
"@payloadcms/live-preview": ["./packages/live-preview/src"],
|
||||||
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
"@payloadcms/live-preview-react": ["./packages/live-preview-react/src/index.ts"],
|
||||||
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
"@payloadcms/live-preview-vue": ["./packages/live-preview-vue/src/index.ts"],
|
||||||
|
|||||||
Reference in New Issue
Block a user