test: add array field helpers (#13493)
Adds various helpers to make it easier and more standard to manage array fields within e2e tests. Retrofits existing tests to ensure consistent interactions across the board, and also organizes existing blocks and relationship field helpers in the same way. --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1211094073049046
This commit is contained in:
@@ -2,6 +2,7 @@ import type { BrowserContext, Locator, Page } from '@playwright/test'
|
|||||||
import type { PayloadTestSDK } from 'helpers/sdk/index.js'
|
import type { PayloadTestSDK } from 'helpers/sdk/index.js'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
|
import { addArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import { toggleBlockOrArrayRow } from 'helpers/e2e/toggleCollapsible.js'
|
import { toggleBlockOrArrayRow } from 'helpers/e2e/toggleCollapsible.js'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
@@ -498,7 +499,7 @@ test.describe('Bulk Edit', () => {
|
|||||||
|
|
||||||
await wait(500)
|
await wait(500)
|
||||||
|
|
||||||
await field.locator('button.array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'array' })
|
||||||
|
|
||||||
const row = page.locator(`#array-row-0`)
|
const row = page.locator(`#array-row-0`)
|
||||||
const toggler = row.locator('button.collapsible__toggle')
|
const toggler = row.locator('button.collapsible__toggle')
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { Page } from '@playwright/test'
|
|||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { AdminUrlUtil } from 'helpers/adminUrlUtil.js'
|
import { AdminUrlUtil } from 'helpers/adminUrlUtil.js'
|
||||||
|
import { addArrayRow, openArrayRowActions, removeArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
@@ -45,7 +46,7 @@ describe('Field Error States', () => {
|
|||||||
await page.goto(`${serverURL}/admin/collections/error-fields/create`)
|
await page.goto(`${serverURL}/admin/collections/error-fields/create`)
|
||||||
|
|
||||||
// add parent array
|
// add parent array
|
||||||
await page.locator('#field-parentArray > .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'parentArray' })
|
||||||
|
|
||||||
// add first child array
|
// add first child array
|
||||||
await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-row').click()
|
await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-row').click()
|
||||||
@@ -60,12 +61,10 @@ describe('Field Error States', () => {
|
|||||||
// add third child array
|
// add third child array
|
||||||
await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-row').click()
|
await page.locator('#parentArray-row-0 .collapsible__content .array-field__add-row').click()
|
||||||
|
|
||||||
// remove the row
|
await removeArrayRow(page, {
|
||||||
await page.locator('#parentArray-0-childArray-row-2 .array-actions__button').click()
|
fieldName: 'parentArray__0__childArray',
|
||||||
|
rowIndex: 2,
|
||||||
await page
|
})
|
||||||
.locator('#parentArray-0-childArray-row-2 .array-actions__action.array-actions__remove')
|
|
||||||
.click()
|
|
||||||
|
|
||||||
await page.locator('#action-save').click()
|
await page.locator('#action-save').click()
|
||||||
|
|
||||||
|
|||||||
@@ -330,6 +330,13 @@ export interface User {
|
|||||||
hash?: string | null;
|
hash?: string | null;
|
||||||
loginAttempts?: number | null;
|
loginAttempts?: number | null;
|
||||||
lockUntil?: string | null;
|
lockUntil?: string | null;
|
||||||
|
sessions?:
|
||||||
|
| {
|
||||||
|
id: string;
|
||||||
|
createdAt?: string | null;
|
||||||
|
expiresAt: string;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
password?: string | null;
|
password?: string | null;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -707,6 +714,13 @@ export interface UsersSelect<T extends boolean = true> {
|
|||||||
hash?: T;
|
hash?: T;
|
||||||
loginAttempts?: T;
|
loginAttempts?: T;
|
||||||
lockUntil?: T;
|
lockUntil?: T;
|
||||||
|
sessions?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
id?: T;
|
||||||
|
createdAt?: T;
|
||||||
|
expiresAt?: T;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `Config`'s JSON-Schema
|
* This interface was referenced by `Config`'s JSON-Schema
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import type { CollectionSlug } from 'payload'
|
|||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { assertToastErrors } from 'helpers/assertToastErrors.js'
|
import { assertToastErrors } from 'helpers/assertToastErrors.js'
|
||||||
import { addListFilter } from 'helpers/e2e/addListFilter.js'
|
import { addListFilter } from 'helpers/e2e/addListFilter.js'
|
||||||
|
import { openCreateDocDrawer } from 'helpers/e2e/fields/relationship/openCreateDocDrawer.js'
|
||||||
import { goToNextPage } from 'helpers/e2e/goToNextPage.js'
|
import { goToNextPage } from 'helpers/e2e/goToNextPage.js'
|
||||||
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
||||||
import { openCreateDocDrawer, openDocDrawer } from 'helpers/e2e/toggleDocDrawer.js'
|
import { openDocDrawer } from 'helpers/e2e/toggleDocDrawer.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type { Page } from '@playwright/test'
|
|||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { assertToastErrors } from 'helpers/assertToastErrors.js'
|
import { assertToastErrors } from 'helpers/assertToastErrors.js'
|
||||||
import { copyPasteField } from 'helpers/e2e/copyPasteField.js'
|
import { copyPasteField } from 'helpers/e2e/copyPasteField.js'
|
||||||
|
import { addArrayRow, duplicateArrayRow, removeArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import { toggleBlockOrArrayRow } from 'helpers/e2e/toggleCollapsible.js'
|
import { toggleBlockOrArrayRow } from 'helpers/e2e/toggleCollapsible.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
@@ -89,7 +90,7 @@ describe('Array', () => {
|
|||||||
test('should render RowLabel using a component', async () => {
|
test('should render RowLabel using a component', async () => {
|
||||||
const label = 'custom row label as component'
|
const label = 'custom row label as component'
|
||||||
await loadCreatePage()
|
await loadCreatePage()
|
||||||
await page.locator('#field-rowLabelAsComponent >> .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'rowLabelAsComponent' })
|
||||||
await expect(page.locator('#field-rowLabelAsComponent__0__title')).toBeVisible()
|
await expect(page.locator('#field-rowLabelAsComponent__0__title')).toBeVisible()
|
||||||
await expect(page.locator('.shimmer-effect')).toHaveCount(0)
|
await expect(page.locator('.shimmer-effect')).toHaveCount(0)
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ describe('Array', () => {
|
|||||||
const label = 'test custom row label'
|
const label = 'test custom row label'
|
||||||
const updatedLabel = 'updated custom row label'
|
const updatedLabel = 'updated custom row label'
|
||||||
await loadCreatePage()
|
await loadCreatePage()
|
||||||
await page.locator('#field-rowLabelAsComponent >> .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'rowLabelAsComponent' })
|
||||||
|
|
||||||
await page.locator('#field-rowLabelAsComponent__0__title').fill(label)
|
await page.locator('#field-rowLabelAsComponent__0__title').fill(label)
|
||||||
|
|
||||||
@@ -130,14 +131,7 @@ describe('Array', () => {
|
|||||||
await expect(customRowLabel).toBeVisible()
|
await expect(customRowLabel).toBeVisible()
|
||||||
await expect(customRowLabel).toHaveCSS('text-transform', 'uppercase')
|
await expect(customRowLabel).toHaveCSS('text-transform', 'uppercase')
|
||||||
|
|
||||||
const rowActionsButton = page.locator('#rowLabelAsComponent-row-0 .array-actions__button')
|
await duplicateArrayRow(page, { fieldName: 'rowLabelAsComponent' })
|
||||||
await rowActionsButton.click()
|
|
||||||
|
|
||||||
const duplicateButton = page.locator(
|
|
||||||
'#rowLabelAsComponent-row-0 .popup__scroll-container .array-actions__duplicate',
|
|
||||||
)
|
|
||||||
await expect(duplicateButton).toBeVisible()
|
|
||||||
await duplicateButton.click()
|
|
||||||
|
|
||||||
await expect(page.locator('#rowLabelAsComponent-row-1')).toBeVisible()
|
await expect(page.locator('#rowLabelAsComponent-row-1')).toBeVisible()
|
||||||
await expect(
|
await expect(
|
||||||
@@ -157,8 +151,7 @@ describe('Array', () => {
|
|||||||
|
|
||||||
test('should render default array field within custom component', async () => {
|
test('should render default array field within custom component', async () => {
|
||||||
await loadCreatePage()
|
await loadCreatePage()
|
||||||
|
await addArrayRow(page, { fieldName: 'customArrayField' })
|
||||||
await page.locator('#field-customArrayField >> .array-field__add-row').click()
|
|
||||||
await expect(page.locator('#field-customArrayField__0__text')).toBeVisible()
|
await expect(page.locator('#field-customArrayField__0__text')).toBeVisible()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -169,7 +162,7 @@ describe('Array', () => {
|
|||||||
|
|
||||||
test('should fail min rows validation when rows are present', async () => {
|
test('should fail min rows validation when rows are present', async () => {
|
||||||
await loadCreatePage()
|
await loadCreatePage()
|
||||||
await page.locator('#field-arrayWithMinRows >> .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'arrayWithMinRows' })
|
||||||
|
|
||||||
// Ensure new array row is visible and fields are rendered
|
// Ensure new array row is visible and fields are rendered
|
||||||
await expect(page.locator('#arrayWithMinRows-row-0')).toBeVisible()
|
await expect(page.locator('#arrayWithMinRows-row-0')).toBeVisible()
|
||||||
@@ -210,36 +203,29 @@ describe('Array', () => {
|
|||||||
await wait(300)
|
await wait(300)
|
||||||
|
|
||||||
// Add 3 rows
|
// Add 3 rows
|
||||||
await page.locator('#field-potentiallyEmptyArray > .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'potentiallyEmptyArray' })
|
||||||
await wait(300)
|
await addArrayRow(page, { fieldName: 'potentiallyEmptyArray' })
|
||||||
await page.locator('#field-potentiallyEmptyArray > .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'potentiallyEmptyArray' })
|
||||||
await wait(300)
|
|
||||||
await page.locator('#field-potentiallyEmptyArray > .array-field__add-row').click()
|
|
||||||
await wait(300)
|
|
||||||
|
|
||||||
// Fill out row 1
|
// Fill out row 1
|
||||||
await page.locator('#field-potentiallyEmptyArray__0__text').fill(assertText0)
|
await page.locator('#field-potentiallyEmptyArray__0__text').fill(assertText0)
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.locator('#field-potentiallyEmptyArray__0__groupInRow__textInGroupInRow')
|
.locator('#field-potentiallyEmptyArray__0__groupInRow__textInGroupInRow')
|
||||||
.fill(assertGroupText0)
|
.fill(assertGroupText0)
|
||||||
|
|
||||||
// Fill out row 2
|
// Fill out row 2
|
||||||
await page.locator('#field-potentiallyEmptyArray__1__text').fill(assertText1)
|
await page.locator('#field-potentiallyEmptyArray__1__text').fill(assertText1)
|
||||||
|
|
||||||
// Fill out row 3
|
// Fill out row 3
|
||||||
await page.locator('#field-potentiallyEmptyArray__2__text').fill(assertText3)
|
await page.locator('#field-potentiallyEmptyArray__2__text').fill(assertText3)
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.locator('#field-potentiallyEmptyArray__2__groupInRow__textInGroupInRow')
|
.locator('#field-potentiallyEmptyArray__2__groupInRow__textInGroupInRow')
|
||||||
.fill(assertGroupText3)
|
.fill(assertGroupText3)
|
||||||
|
|
||||||
// Remove row 1
|
await removeArrayRow(page, { fieldName: 'potentiallyEmptyArray', rowIndex: 1 })
|
||||||
await page.locator('#potentiallyEmptyArray-row-0 .array-actions__button').click()
|
await removeArrayRow(page, { fieldName: 'potentiallyEmptyArray', rowIndex: 0 })
|
||||||
await page
|
|
||||||
.locator('#potentiallyEmptyArray-row-0 .popup__scroll-container .array-actions__remove')
|
|
||||||
.click()
|
|
||||||
// Remove row 2
|
|
||||||
await page.locator('#potentiallyEmptyArray-row-0 .array-actions__button').click()
|
|
||||||
await page
|
|
||||||
.locator('#potentiallyEmptyArray-row-0 .popup__scroll-container .array-actions__remove')
|
|
||||||
.click()
|
|
||||||
|
|
||||||
// Save document
|
// Save document
|
||||||
await saveDocAndAssert(page)
|
await saveDocAndAssert(page)
|
||||||
@@ -251,11 +237,7 @@ describe('Array', () => {
|
|||||||
const input = page.locator('#field-potentiallyEmptyArray__0__groupInRow__textInGroupInRow')
|
const input = page.locator('#field-potentiallyEmptyArray__0__groupInRow__textInGroupInRow')
|
||||||
await expect(input).toHaveValue(assertGroupText3)
|
await expect(input).toHaveValue(assertGroupText3)
|
||||||
|
|
||||||
// Duplicate row
|
await duplicateArrayRow(page, { fieldName: 'potentiallyEmptyArray' })
|
||||||
await page.locator('#potentiallyEmptyArray-row-0 .array-actions__button').click()
|
|
||||||
await page
|
|
||||||
.locator('#potentiallyEmptyArray-row-0 .popup__scroll-container .array-actions__duplicate')
|
|
||||||
.click()
|
|
||||||
|
|
||||||
// Update duplicated row group field text
|
// Update duplicated row group field text
|
||||||
await page
|
await page
|
||||||
@@ -270,11 +252,7 @@ describe('Array', () => {
|
|||||||
page.locator('#field-potentiallyEmptyArray__1__groupInRow__textInGroupInRow'),
|
page.locator('#field-potentiallyEmptyArray__1__groupInRow__textInGroupInRow'),
|
||||||
).toHaveValue(`${assertGroupText3} duplicate`)
|
).toHaveValue(`${assertGroupText3} duplicate`)
|
||||||
|
|
||||||
// Remove row 1
|
await removeArrayRow(page, { fieldName: 'potentiallyEmptyArray', rowIndex: 0 })
|
||||||
await page.locator('#potentiallyEmptyArray-row-0 .array-actions__button').click()
|
|
||||||
await page
|
|
||||||
.locator('#potentiallyEmptyArray-row-0 .popup__scroll-container .array-actions__remove')
|
|
||||||
.click()
|
|
||||||
|
|
||||||
// Save document
|
// Save document
|
||||||
await saveDocAndAssert(page)
|
await saveDocAndAssert(page)
|
||||||
@@ -361,11 +339,8 @@ describe('Array', () => {
|
|||||||
await arrayOption.click()
|
await arrayOption.click()
|
||||||
await wait(200)
|
await wait(200)
|
||||||
|
|
||||||
const addRowButton = page.locator('#field-items > .array-field__add-row')
|
await addArrayRow(page, { fieldName: 'items' })
|
||||||
|
|
||||||
await expect(addRowButton).toBeVisible()
|
|
||||||
|
|
||||||
await addRowButton.click()
|
|
||||||
await wait(200)
|
await wait(200)
|
||||||
|
|
||||||
const targetInput = page.locator('#field-items__0__text')
|
const targetInput = page.locator('#field-items__0__text')
|
||||||
@@ -389,7 +364,7 @@ describe('Array', () => {
|
|||||||
test('should initialize array rows with collapsed state', async () => {
|
test('should initialize array rows with collapsed state', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
|
|
||||||
await page.locator('#field-collapsedArray >> .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'collapsedArray' })
|
||||||
|
|
||||||
const row = page.locator(`#collapsedArray-row-0`)
|
const row = page.locator(`#collapsedArray-row-0`)
|
||||||
const toggler = row.locator('button.collapsible__toggle')
|
const toggler = row.locator('button.collapsible__toggle')
|
||||||
@@ -401,7 +376,7 @@ describe('Array', () => {
|
|||||||
test('should not collapse array rows on input change', async () => {
|
test('should not collapse array rows on input change', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
|
|
||||||
await page.locator('#field-collapsedArray >> .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'collapsedArray' })
|
||||||
|
|
||||||
const row = page.locator(`#collapsedArray-row-0`)
|
const row = page.locator(`#collapsedArray-row-0`)
|
||||||
const toggler = row.locator('button.collapsible__toggle')
|
const toggler = row.locator('button.collapsible__toggle')
|
||||||
@@ -599,10 +574,8 @@ describe('Array', () => {
|
|||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
|
|
||||||
const field = page.locator('#field-items')
|
const field = page.locator('#field-items')
|
||||||
const addSubArrayBtn = field.locator(
|
|
||||||
'#field-items__0__subArray > button.array-field__add-row',
|
await addArrayRow(page, { fieldName: 'items__0__subArray' })
|
||||||
)
|
|
||||||
await addSubArrayBtn.click()
|
|
||||||
|
|
||||||
const textInputRowOne = field.locator('#field-items__0__subArray__0__text')
|
const textInputRowOne = field.locator('#field-items__0__subArray__0__text')
|
||||||
await expect(textInputRowOne).toBeVisible()
|
await expect(textInputRowOne).toBeVisible()
|
||||||
@@ -633,18 +606,10 @@ describe('Array', () => {
|
|||||||
|
|
||||||
const field = page.locator('#field-items')
|
const field = page.locator('#field-items')
|
||||||
|
|
||||||
const addSubArrayBtn = field.locator(
|
await addArrayRow(page, { fieldName: 'items__0__subArray' })
|
||||||
'#field-items__0__subArray > button.array-field__add-row',
|
await addArrayRow(page, { fieldName: 'items__0__subArray' })
|
||||||
)
|
|
||||||
await expect(addSubArrayBtn).toBeVisible()
|
|
||||||
await addSubArrayBtn.click()
|
|
||||||
await addSubArrayBtn.click()
|
|
||||||
|
|
||||||
const addSubArrayBtn2 = field.locator(
|
await addArrayRow(page, { fieldName: 'items__1__subArray' })
|
||||||
'#field-items__1__subArray > button.array-field__add-row',
|
|
||||||
)
|
|
||||||
await expect(addSubArrayBtn2).toBeVisible()
|
|
||||||
await addSubArrayBtn2.click()
|
|
||||||
|
|
||||||
const subArrayContainer = field.locator(
|
const subArrayContainer = field.locator(
|
||||||
'#field-items__0__subArray > div.array-field__draggable-rows > div',
|
'#field-items__0__subArray > div.array-field__draggable-rows > div',
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import type { BrowserContext, Page } from '@playwright/test'
|
import type { BrowserContext, Page } from '@playwright/test'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { addBlock } from 'helpers/e2e/addBlock.js'
|
|
||||||
import { copyPasteField } from 'helpers/e2e/copyPasteField.js'
|
import { copyPasteField } from 'helpers/e2e/copyPasteField.js'
|
||||||
import { openBlocksDrawer } from 'helpers/e2e/openBlocksDrawer.js'
|
import { addArrayRowBelow, duplicateArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import { reorderBlocks } from 'helpers/e2e/reorderBlocks.js'
|
import { addBlock, openBlocksDrawer, reorderBlocks } from 'helpers/e2e/fields/blocks/index.js'
|
||||||
import { scrollEntirePage } from 'helpers/e2e/scrollEntirePage.js'
|
import { scrollEntirePage } from 'helpers/e2e/scrollEntirePage.js'
|
||||||
import { toggleBlockOrArrayRow } from 'helpers/e2e/toggleCollapsible.js'
|
import { toggleBlockOrArrayRow } from 'helpers/e2e/toggleCollapsible.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
@@ -127,14 +126,8 @@ describe('Block fields', () => {
|
|||||||
|
|
||||||
test('should open blocks drawer from block row and add below', async () => {
|
test('should open blocks drawer from block row and add below', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
const firstRow = page.locator('#field-blocks #blocks-row-0')
|
|
||||||
const rowActions = firstRow.locator('.collapsible__actions')
|
|
||||||
await expect(rowActions).toBeVisible()
|
|
||||||
|
|
||||||
await rowActions.locator('.array-actions__button').click()
|
await addArrayRowBelow(page, { fieldName: 'blocks' })
|
||||||
const addBelowButton = rowActions.locator('.array-actions__action.array-actions__add')
|
|
||||||
await expect(addBelowButton).toBeVisible()
|
|
||||||
await addBelowButton.click()
|
|
||||||
|
|
||||||
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
const blocksDrawer = page.locator('[id^=drawer_1_blocks-drawer-]')
|
||||||
await expect(blocksDrawer).toBeVisible()
|
await expect(blocksDrawer).toBeVisible()
|
||||||
@@ -157,14 +150,8 @@ describe('Block fields', () => {
|
|||||||
|
|
||||||
test('should duplicate block', async () => {
|
test('should duplicate block', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
const firstRow = page.locator('#field-blocks #blocks-row-0')
|
|
||||||
const rowActions = firstRow.locator('.collapsible__actions')
|
|
||||||
await expect(rowActions).toBeVisible()
|
|
||||||
|
|
||||||
await rowActions.locator('.array-actions__button').click()
|
await duplicateArrayRow(page, { fieldName: 'blocks' })
|
||||||
const duplicateButton = rowActions.locator('.array-actions__action.array-actions__duplicate')
|
|
||||||
await expect(duplicateButton).toBeVisible()
|
|
||||||
await duplicateButton.click()
|
|
||||||
|
|
||||||
const blocks = page.locator('#field-blocks > .blocks-field__rows > div')
|
const blocks = page.locator('#field-blocks > .blocks-field__rows > div')
|
||||||
expect(await blocks.count()).toEqual(5)
|
expect(await blocks.count()).toEqual(5)
|
||||||
@@ -172,14 +159,8 @@ describe('Block fields', () => {
|
|||||||
|
|
||||||
test('should save when duplicating subblocks', async () => {
|
test('should save when duplicating subblocks', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
const subblocksRow = page.locator('#field-blocks #blocks-row-2')
|
|
||||||
const rowActions = subblocksRow.locator('.collapsible__actions').first()
|
|
||||||
await expect(rowActions).toBeVisible()
|
|
||||||
|
|
||||||
await rowActions.locator('.array-actions__button').click()
|
await duplicateArrayRow(page, { fieldName: 'blocks', rowIndex: 2 })
|
||||||
const duplicateButton = rowActions.locator('.array-actions__action.array-actions__duplicate')
|
|
||||||
await expect(duplicateButton).toBeVisible()
|
|
||||||
await duplicateButton.click()
|
|
||||||
|
|
||||||
const blocks = page.locator('#field-blocks > .blocks-field__rows > div')
|
const blocks = page.locator('#field-blocks > .blocks-field__rows > div')
|
||||||
expect(await blocks.count()).toEqual(5)
|
expect(await blocks.count()).toEqual(5)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
|
import { addArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
@@ -87,7 +88,7 @@ describe('Collapsibles', () => {
|
|||||||
const arrayWithCollapsibles = page.locator('#field-arrayWithCollapsibles')
|
const arrayWithCollapsibles = page.locator('#field-arrayWithCollapsibles')
|
||||||
await expect(arrayWithCollapsibles).toBeVisible()
|
await expect(arrayWithCollapsibles).toBeVisible()
|
||||||
|
|
||||||
await page.locator('#field-arrayWithCollapsibles >> .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'arrayWithCollapsibles' })
|
||||||
|
|
||||||
await page
|
await page
|
||||||
.locator(
|
.locator(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { BrowserContext, Page } from '@playwright/test'
|
import type { BrowserContext, Page } from '@playwright/test'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
|
import { addArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
@@ -175,7 +176,7 @@ describe('Conditional Logic', () => {
|
|||||||
|
|
||||||
test('should not render fields when adding array or blocks rows until form state returns', async () => {
|
test('should not render fields when adding array or blocks rows until form state returns', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
await page.locator('#field-arrayWithConditionalField .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'arrayWithConditionalField' })
|
||||||
const shimmer = '#field-arrayWithConditionalField .collapsible__content > .shimmer-effect'
|
const shimmer = '#field-arrayWithConditionalField .collapsible__content > .shimmer-effect'
|
||||||
|
|
||||||
await expect(page.locator(shimmer)).toBeVisible()
|
await expect(page.locator(shimmer)).toBeVisible()
|
||||||
@@ -204,14 +205,11 @@ describe('Conditional Logic', () => {
|
|||||||
test('should render field based on path argument', async () => {
|
test('should render field based on path argument', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
|
|
||||||
const arrayOneButton = page.locator('#field-arrayOne .array-field__add-row')
|
await addArrayRow(page, { fieldName: 'arrayOne' })
|
||||||
await arrayOneButton.click()
|
|
||||||
|
|
||||||
const arrayTwoButton = page.locator('#arrayOne-row-0 .array-field__add-row')
|
await addArrayRow(page, { fieldName: 'arrayOne__0__arrayTwo' })
|
||||||
await arrayTwoButton.click()
|
|
||||||
|
|
||||||
const arrayThreeButton = page.locator('#arrayOne-0-arrayTwo-row-0 .array-field__add-row')
|
await addArrayRow(page, { fieldName: 'arrayOne__0__arrayTwo__0__arrayThree' })
|
||||||
await arrayThreeButton.click()
|
|
||||||
|
|
||||||
const numberField = page.locator('#field-arrayOne__0__arrayTwo__0__arrayThree__0__numberField')
|
const numberField = page.locator('#field-arrayOne__0__arrayTwo__0__arrayThree__0__numberField')
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ import type { Page } from '@playwright/test'
|
|||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { addListFilter } from 'helpers/e2e/addListFilter.js'
|
import { addListFilter } from 'helpers/e2e/addListFilter.js'
|
||||||
|
import { openCreateDocDrawer } from 'helpers/e2e/fields/relationship/openCreateDocDrawer.js'
|
||||||
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
|
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
|
||||||
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
||||||
import { openCreateDocDrawer, openDocDrawer } from 'helpers/e2e/toggleDocDrawer.js'
|
import { openDocDrawer } from 'helpers/e2e/toggleDocDrawer.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
|
import { addArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ describe('Tabs', () => {
|
|||||||
test('should correctly save nested unnamed and named tabs', async () => {
|
test('should correctly save nested unnamed and named tabs', async () => {
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
|
|
||||||
await page.locator('#field-tabsInArray .array-field__add-row').click()
|
await addArrayRow(page, { fieldName: 'tabsInArray' })
|
||||||
await page.locator('#field-tabsInArray__0__text').fill('tab 1 text')
|
await page.locator('#field-tabsInArray__0__text').fill('tab 1 text')
|
||||||
await page.locator('.tabs-field__tabs button:nth-child(2)').click()
|
await page.locator('.tabs-field__tabs button:nth-child(2)').click()
|
||||||
await page.locator('#field-tabsInArray__0__tab2__text2').fill('tab 2 text')
|
await page.locator('#field-tabsInArray__0__tab2__text2').fill('tab 2 text')
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import type { PayloadTestSDK } from 'helpers/sdk/index.js'
|
|||||||
import type { FormState } from 'payload'
|
import type { FormState } from 'payload'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
import { addBlock } from 'helpers/e2e/addBlock.js'
|
|
||||||
import { assertElementStaysVisible } from 'helpers/e2e/assertElementStaysVisible.js'
|
import { assertElementStaysVisible } from 'helpers/e2e/assertElementStaysVisible.js'
|
||||||
import { assertNetworkRequests } from 'helpers/e2e/assertNetworkRequests.js'
|
import { assertNetworkRequests } from 'helpers/e2e/assertNetworkRequests.js'
|
||||||
import { assertRequestBody } from 'helpers/e2e/assertRequestBody.js'
|
import { assertRequestBody } from 'helpers/e2e/assertRequestBody.js'
|
||||||
|
import { addArrayRowAsync, removeArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
|
import { addBlock } from 'helpers/e2e/fields/blocks/index.js'
|
||||||
import { waitForAutoSaveToRunAndComplete } from 'helpers/e2e/waitForAutoSaveToRunAndComplete.js'
|
import { waitForAutoSaveToRunAndComplete } from 'helpers/e2e/waitForAutoSaveToRunAndComplete.js'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { fileURLToPath } from 'url'
|
import { fileURLToPath } from 'url'
|
||||||
@@ -162,7 +163,7 @@ test.describe('Form State', () => {
|
|||||||
|
|
||||||
// The `array` itself SHOULD have a `lastRenderedPath` because it was rendered on initial load
|
// The `array` itself SHOULD have a `lastRenderedPath` because it was rendered on initial load
|
||||||
await assertRequestBody<{ args: { formState: FormState } }[]>(page, {
|
await assertRequestBody<{ args: { formState: FormState } }[]>(page, {
|
||||||
action: async () => await page.locator('#field-array .array-field__add-row').click(),
|
action: async () => await addArrayRowAsync(page, 'array'),
|
||||||
url: postsUrl.create,
|
url: postsUrl.create,
|
||||||
expect: (body) =>
|
expect: (body) =>
|
||||||
Boolean(
|
Boolean(
|
||||||
@@ -181,7 +182,7 @@ test.describe('Form State', () => {
|
|||||||
// The `array` itself SHOULD still have a `lastRenderedPath`
|
// The `array` itself SHOULD still have a `lastRenderedPath`
|
||||||
// The custom text field in the first row SHOULD ALSO have a `lastRenderedPath` bc it was rendered in the first request
|
// The custom text field in the first row SHOULD ALSO have a `lastRenderedPath` bc it was rendered in the first request
|
||||||
await assertRequestBody<{ args: { formState: FormState } }[]>(page, {
|
await assertRequestBody<{ args: { formState: FormState } }[]>(page, {
|
||||||
action: async () => await page.locator('#field-array .array-field__add-row').click(),
|
action: async () => await addArrayRowAsync(page, 'array'),
|
||||||
url: postsUrl.create,
|
url: postsUrl.create,
|
||||||
expect: (body) =>
|
expect: (body) =>
|
||||||
Boolean(
|
Boolean(
|
||||||
@@ -203,7 +204,7 @@ test.describe('Form State', () => {
|
|||||||
// The custom text field in the first row SHOULD ALSO have a `lastRenderedPath` bc it was rendered in the first request
|
// The custom text field in the first row SHOULD ALSO have a `lastRenderedPath` bc it was rendered in the first request
|
||||||
// The custom text field in the second row SHOULD ALSO have a `lastRenderedPath` bc it was rendered in the second request
|
// The custom text field in the second row SHOULD ALSO have a `lastRenderedPath` bc it was rendered in the second request
|
||||||
await assertRequestBody<{ args: { formState: FormState } }[]>(page, {
|
await assertRequestBody<{ args: { formState: FormState } }[]>(page, {
|
||||||
action: async () => await page.locator('#field-array .array-field__add-row').click(),
|
action: async () => await addArrayRowAsync(page, 'array'),
|
||||||
url: postsUrl.create,
|
url: postsUrl.create,
|
||||||
expect: (body) =>
|
expect: (body) =>
|
||||||
Boolean(
|
Boolean(
|
||||||
@@ -220,10 +221,10 @@ test.describe('Form State', () => {
|
|||||||
test('should not render stale values for server components while form state is in flight', async () => {
|
test('should not render stale values for server components while form state is in flight', async () => {
|
||||||
await page.goto(postsUrl.create)
|
await page.goto(postsUrl.create)
|
||||||
|
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
await page.locator('#field-array #array-row-0 #field-array__0__customTextField').fill('1')
|
await page.locator('#field-array #array-row-0 #field-array__0__customTextField').fill('1')
|
||||||
|
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
await page.locator('#field-array #array-row-1 #field-array__1__customTextField').fill('2')
|
await page.locator('#field-array #array-row-1 #field-array__1__customTextField').fill('2')
|
||||||
|
|
||||||
// block the next form state request from firing to ensure the field remains in stale state
|
// block the next form state request from firing to ensure the field remains in stale state
|
||||||
@@ -235,12 +236,7 @@ test.describe('Form State', () => {
|
|||||||
await route.continue()
|
await route.continue()
|
||||||
})
|
})
|
||||||
|
|
||||||
// remove the first row
|
await removeArrayRow(page, { fieldName: 'array' })
|
||||||
await page.locator('#field-array #array-row-0 .array-actions__button').click()
|
|
||||||
|
|
||||||
await page
|
|
||||||
.locator('#field-array #array-row-0 .array-actions__action.array-actions__remove')
|
|
||||||
.click()
|
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
page.locator('#field-array #array-row-0 #field-array__0__customTextField'),
|
page.locator('#field-array #array-row-0 #field-array__0__customTextField'),
|
||||||
@@ -390,7 +386,7 @@ test.describe('Form State', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Add the first row and expect an optimistic loading state
|
// Add the first row and expect an optimistic loading state
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
await expect(page.locator('#field-array #array-row-0')).toBeVisible()
|
await expect(page.locator('#field-array #array-row-0')).toBeVisible()
|
||||||
|
|
||||||
// use waitForSelector because the shimmer effect is not always visible
|
// use waitForSelector because the shimmer effect is not always visible
|
||||||
@@ -401,7 +397,7 @@ test.describe('Form State', () => {
|
|||||||
await page.waitForRequest((request) => request.url() === postsUrl.create)
|
await page.waitForRequest((request) => request.url() === postsUrl.create)
|
||||||
|
|
||||||
// Before the first request comes back, add the second row and expect an optimistic loading state
|
// Before the first request comes back, add the second row and expect an optimistic loading state
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
await expect(page.locator('#field-array #array-row-1')).toBeVisible()
|
await expect(page.locator('#field-array #array-row-1')).toBeVisible()
|
||||||
|
|
||||||
// use waitForSelector because the shimmer effect is not always visible
|
// use waitForSelector because the shimmer effect is not always visible
|
||||||
@@ -456,7 +452,7 @@ test.describe('Form State', () => {
|
|||||||
page,
|
page,
|
||||||
postsUrl.create,
|
postsUrl.create,
|
||||||
async () => {
|
async () => {
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
await page.locator('#field-title').fill('Test 2')
|
await page.locator('#field-title').fill('Test 2')
|
||||||
|
|
||||||
// use `waitForSelector` to ensure the element doesn't appear and then disappear
|
// use `waitForSelector` to ensure the element doesn't appear and then disappear
|
||||||
@@ -485,8 +481,8 @@ test.describe('Form State', () => {
|
|||||||
page,
|
page,
|
||||||
postsUrl.create,
|
postsUrl.create,
|
||||||
async () => {
|
async () => {
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
await page.locator('#field-array .array-field__add-row').click()
|
await addArrayRowAsync(page, 'array')
|
||||||
|
|
||||||
// use `waitForSelector` to ensure the element doesn't appear and then disappear
|
// use `waitForSelector` to ensure the element doesn't appear and then disappear
|
||||||
// eslint-disable-next-line playwright/no-wait-for-selector
|
// eslint-disable-next-line playwright/no-wait-for-selector
|
||||||
|
|||||||
47
test/helpers/e2e/fields/array/addArrayRow.ts
Normal file
47
test/helpers/e2e/fields/array/addArrayRow.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import type { Locator, Page } from 'playwright'
|
||||||
|
|
||||||
|
import { wait } from 'payload/shared'
|
||||||
|
|
||||||
|
import { openArrayRowActions } from './openArrayRowActions.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does not wait after adding the row for the row to appear and fully load in. Simply clicks the primary "Add Row" button and moves on.
|
||||||
|
*/
|
||||||
|
export const addArrayRowAsync = async (page: Page, fieldName: string) => {
|
||||||
|
await page.locator(`#field-${fieldName} > .array-field__add-row`).first().click()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an array row to the end of the array using the primary "Add Row" button.
|
||||||
|
*/
|
||||||
|
export const addArrayRow = async (
|
||||||
|
page: Page,
|
||||||
|
{ fieldName }: Omit<Parameters<typeof openArrayRowActions>[1], 'rowIndex'>,
|
||||||
|
) => {
|
||||||
|
await addArrayRowAsync(page, fieldName)
|
||||||
|
|
||||||
|
// TODO: test the array row has appeared
|
||||||
|
await wait(300)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like `addArrayRow`, but inserts the row at the specified index using the row actions menu.
|
||||||
|
*/
|
||||||
|
export const addArrayRowBelow = async (
|
||||||
|
page: Page,
|
||||||
|
{ fieldName, rowIndex = 0 }: Parameters<typeof openArrayRowActions>[1],
|
||||||
|
): Promise<{ popupContentLocator: Locator; rowActionsButtonLocator: Locator }> => {
|
||||||
|
const { popupContentLocator, rowActionsButtonLocator } = await openArrayRowActions(page, {
|
||||||
|
fieldName,
|
||||||
|
rowIndex,
|
||||||
|
})
|
||||||
|
|
||||||
|
const addBelowButton = popupContentLocator.locator('.array-actions__action.array-actions__add')
|
||||||
|
|
||||||
|
await addBelowButton.click()
|
||||||
|
|
||||||
|
// TODO: test the array row has appeared
|
||||||
|
await wait(300)
|
||||||
|
|
||||||
|
return { popupContentLocator, rowActionsButtonLocator }
|
||||||
|
}
|
||||||
25
test/helpers/e2e/fields/array/duplicateArrayRow.ts
Normal file
25
test/helpers/e2e/fields/array/duplicateArrayRow.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import type { Locator, Page } from 'playwright'
|
||||||
|
|
||||||
|
import { openArrayRowActions } from './openArrayRowActions.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duplicates the array row at the specified index.
|
||||||
|
*/
|
||||||
|
export const duplicateArrayRow = async (
|
||||||
|
page: Page,
|
||||||
|
{ fieldName, rowIndex = 0 }: Parameters<typeof openArrayRowActions>[1],
|
||||||
|
): Promise<{
|
||||||
|
popupContentLocator: Locator
|
||||||
|
rowActionsButtonLocator: Locator
|
||||||
|
}> => {
|
||||||
|
const { popupContentLocator, rowActionsButtonLocator } = await openArrayRowActions(page, {
|
||||||
|
fieldName,
|
||||||
|
rowIndex,
|
||||||
|
})
|
||||||
|
|
||||||
|
await popupContentLocator.locator('.array-actions__action.array-actions__duplicate').click()
|
||||||
|
|
||||||
|
// TODO: test the array row has been duplicated
|
||||||
|
|
||||||
|
return { popupContentLocator, rowActionsButtonLocator }
|
||||||
|
}
|
||||||
4
test/helpers/e2e/fields/array/index.ts
Normal file
4
test/helpers/e2e/fields/array/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export { addArrayRow, addArrayRowAsync, addArrayRowBelow } from './addArrayRow.js'
|
||||||
|
export { duplicateArrayRow } from './duplicateArrayRow.js'
|
||||||
|
export { openArrayRowActions } from './openArrayRowActions.js'
|
||||||
|
export { removeArrayRow } from './removeArrayRow.js'
|
||||||
45
test/helpers/e2e/fields/array/openArrayRowActions.ts
Normal file
45
test/helpers/e2e/fields/array/openArrayRowActions.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import type { Locator, Page } from 'playwright'
|
||||||
|
|
||||||
|
import { expect } from 'playwright/test'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the row actions menu for the specified array row.
|
||||||
|
* If already open, does nothing.
|
||||||
|
*/
|
||||||
|
export const openArrayRowActions = async (
|
||||||
|
page: Page,
|
||||||
|
{
|
||||||
|
fieldName,
|
||||||
|
rowIndex = 0,
|
||||||
|
}: {
|
||||||
|
fieldName: string
|
||||||
|
rowIndex?: number
|
||||||
|
},
|
||||||
|
): Promise<{
|
||||||
|
popupContentLocator: Locator
|
||||||
|
rowActionsButtonLocator: Locator
|
||||||
|
}> => {
|
||||||
|
// replace double underscores with single hyphens for the row ID
|
||||||
|
const formattedRowID = fieldName.toString().replace(/__/g, '-')
|
||||||
|
|
||||||
|
const rowActions = page
|
||||||
|
.locator(`#field-${fieldName} #${formattedRowID}-row-${rowIndex} .array-actions`)
|
||||||
|
.first()
|
||||||
|
|
||||||
|
const popupContentLocator = rowActions.locator('.popup__content')
|
||||||
|
|
||||||
|
if (await popupContentLocator.isVisible()) {
|
||||||
|
throw new Error(`Row actions for field "${fieldName}" at index ${rowIndex} are already open.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const rowActionsButtonLocator = rowActions.locator(`.array-actions__button`)
|
||||||
|
|
||||||
|
await rowActionsButtonLocator.click()
|
||||||
|
|
||||||
|
await expect(popupContentLocator).toBeVisible()
|
||||||
|
|
||||||
|
return {
|
||||||
|
rowActionsButtonLocator,
|
||||||
|
popupContentLocator,
|
||||||
|
}
|
||||||
|
}
|
||||||
26
test/helpers/e2e/fields/array/removeArrayRow.ts
Normal file
26
test/helpers/e2e/fields/array/removeArrayRow.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import type { Locator, Page } from 'playwright'
|
||||||
|
|
||||||
|
import { openArrayRowActions } from './openArrayRowActions.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes an array row at the specified index.
|
||||||
|
*/
|
||||||
|
export const removeArrayRow = async (
|
||||||
|
page: Page,
|
||||||
|
{ fieldName, rowIndex = 0 }: Parameters<typeof openArrayRowActions>[1],
|
||||||
|
): Promise<{
|
||||||
|
popupContentLocator: Locator
|
||||||
|
rowActionsButtonLocator: Locator
|
||||||
|
}> => {
|
||||||
|
const { popupContentLocator, rowActionsButtonLocator } = await openArrayRowActions(page, {
|
||||||
|
fieldName,
|
||||||
|
rowIndex,
|
||||||
|
})
|
||||||
|
|
||||||
|
await popupContentLocator.locator('.array-actions__action.array-actions__remove').click()
|
||||||
|
|
||||||
|
// TODO: test the array row has been removed
|
||||||
|
// another row may have been moved into its place, though
|
||||||
|
|
||||||
|
return { popupContentLocator, rowActionsButtonLocator }
|
||||||
|
}
|
||||||
4
test/helpers/e2e/fields/blocks/index.ts
Normal file
4
test/helpers/e2e/fields/blocks/index.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
export { addBlock } from './addBlock.js'
|
||||||
|
export { openBlocksDrawer } from './openBlocksDrawer.js'
|
||||||
|
export { removeAllBlocks } from './removeAllBlocks.js'
|
||||||
|
export { reorderBlocks } from './reorderBlocks.js'
|
||||||
20
test/helpers/e2e/fields/relationship/openCreateDocDrawer.ts
Normal file
20
test/helpers/e2e/fields/relationship/openCreateDocDrawer.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { Page } from 'playwright'
|
||||||
|
|
||||||
|
import { wait } from 'payload/shared'
|
||||||
|
import { expect } from 'playwright/test'
|
||||||
|
|
||||||
|
export async function openCreateDocDrawer({
|
||||||
|
page,
|
||||||
|
fieldSelector,
|
||||||
|
}: {
|
||||||
|
fieldSelector: string
|
||||||
|
page: Page
|
||||||
|
}): Promise<void> {
|
||||||
|
await wait(500) // wait for parent form state to initialize
|
||||||
|
const relationshipField = page.locator(fieldSelector)
|
||||||
|
await expect(relationshipField.locator('input')).toBeEnabled()
|
||||||
|
const addNewButton = relationshipField.locator('.relationship-add-new__add-button')
|
||||||
|
await expect(addNewButton).toBeVisible()
|
||||||
|
await addNewButton.click()
|
||||||
|
await wait(500) // wait for drawer form state to initialize
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { Page } from '@playwright/test'
|
import type { Page } from '@playwright/test'
|
||||||
|
|
||||||
import { expect } from '@playwright/test'
|
|
||||||
import { wait } from 'payload/shared'
|
import { wait } from 'payload/shared'
|
||||||
|
|
||||||
export async function openDocDrawer({
|
export async function openDocDrawer({
|
||||||
@@ -20,19 +19,3 @@ export async function openDocDrawer({
|
|||||||
await page.locator(selector).click(clickProperties)
|
await page.locator(selector).click(clickProperties)
|
||||||
await wait(500) // wait for drawer form state to initialize
|
await wait(500) // wait for drawer form state to initialize
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openCreateDocDrawer({
|
|
||||||
page,
|
|
||||||
fieldSelector,
|
|
||||||
}: {
|
|
||||||
fieldSelector: string
|
|
||||||
page: Page
|
|
||||||
}): Promise<void> {
|
|
||||||
await wait(500) // wait for parent form state to initialize
|
|
||||||
const relationshipField = page.locator(fieldSelector)
|
|
||||||
await expect(relationshipField.locator('input')).toBeEnabled()
|
|
||||||
const addNewButton = relationshipField.locator('.relationship-add-new__add-button')
|
|
||||||
await expect(addNewButton).toBeVisible()
|
|
||||||
await addNewButton.click()
|
|
||||||
await wait(500) // wait for drawer form state to initialize
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { BrowserContext, Page } from '@playwright/test'
|
|||||||
import type { GeneratedTypes } from 'helpers/sdk/types.js'
|
import type { GeneratedTypes } from 'helpers/sdk/types.js'
|
||||||
|
|
||||||
import { expect, test } from '@playwright/test'
|
import { expect, test } from '@playwright/test'
|
||||||
|
import { addArrayRow } from 'helpers/e2e/fields/array/index.js'
|
||||||
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
|
import { navigateToDoc } from 'helpers/e2e/navigateToDoc.js'
|
||||||
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
import { openDocControls } from 'helpers/e2e/openDocControls.js'
|
||||||
import { upsertPreferences } from 'helpers/e2e/preferences.js'
|
import { upsertPreferences } from 'helpers/e2e/preferences.js'
|
||||||
@@ -420,8 +421,7 @@ describe('Localization', () => {
|
|||||||
const nestedArrayURL = new AdminUrlUtil(serverURL, nestedToArrayAndBlockCollectionSlug)
|
const nestedArrayURL = new AdminUrlUtil(serverURL, nestedToArrayAndBlockCollectionSlug)
|
||||||
await page.goto(nestedArrayURL.create)
|
await page.goto(nestedArrayURL.create)
|
||||||
await changeLocale(page, 'ar')
|
await changeLocale(page, 'ar')
|
||||||
const addArrayRow = page.locator('#field-topLevelArray .array-field__add-row')
|
await addArrayRow(page, { fieldName: 'topLevelArray' })
|
||||||
await addArrayRow.click()
|
|
||||||
|
|
||||||
const arrayField = page.locator('#field-topLevelArray__0__localizedText')
|
const arrayField = page.locator('#field-topLevelArray__0__localizedText')
|
||||||
await expect(arrayField).toBeVisible()
|
await expect(arrayField).toBeVisible()
|
||||||
@@ -676,8 +676,7 @@ describe('Localization', () => {
|
|||||||
async function createLocalizedArrayItem(page: Page, url: AdminUrlUtil) {
|
async function createLocalizedArrayItem(page: Page, url: AdminUrlUtil) {
|
||||||
await changeLocale(page, defaultLocale)
|
await changeLocale(page, defaultLocale)
|
||||||
await page.goto(url.create)
|
await page.goto(url.create)
|
||||||
const addArrayRow = page.locator('#field-items .array-field__add-row')
|
await addArrayRow(page, { fieldName: 'items' })
|
||||||
await addArrayRow.click()
|
|
||||||
const textField = page.locator('#field-items__0__text')
|
const textField = page.locator('#field-items__0__text')
|
||||||
await textField.fill('test')
|
await textField.fill('test')
|
||||||
await saveDocAndAssert(page)
|
await saveDocAndAssert(page)
|
||||||
|
|||||||
Reference in New Issue
Block a user