fix(ui): group/array error paths persisting when valid (#13347)
Fields such as groups and arrays would not always reset errorPaths when there were no more errors. The server and client state was not being merged safely and the client state was always persisting when the server sent back no errorPaths, i.e. itterable fields with fully valid children. This change ensures errorPaths is defaulted to an empty array if it is not present on the incoming field. Likely a regression from https://github.com/payloadcms/payload/pull/9388. Adds e2e test.
This commit is contained in:
@@ -40,6 +40,14 @@ export const mergeServerFormState = ({
|
||||
...incomingField,
|
||||
}
|
||||
|
||||
if (
|
||||
currentState[path] &&
|
||||
'errorPaths' in currentState[path] &&
|
||||
!('errorPaths' in incomingField)
|
||||
) {
|
||||
newState[path].errorPaths = []
|
||||
}
|
||||
|
||||
/**
|
||||
* Intelligently merge the rows array to ensure changes to local state are not lost while the request was pending
|
||||
* For example, the server response could come back with a row which has been deleted on the client
|
||||
|
||||
@@ -23,6 +23,7 @@ describe('Field Error States', () => {
|
||||
let validateDraftsOnAutosave: AdminUrlUtil
|
||||
let prevValue: AdminUrlUtil
|
||||
let prevValueRelation: AdminUrlUtil
|
||||
let errorFieldsURL: AdminUrlUtil
|
||||
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
@@ -32,6 +33,7 @@ describe('Field Error States', () => {
|
||||
validateDraftsOnAutosave = new AdminUrlUtil(serverURL, collectionSlugs.validateDraftsOnAutosave)
|
||||
prevValue = new AdminUrlUtil(serverURL, collectionSlugs.prevValue)
|
||||
prevValueRelation = new AdminUrlUtil(serverURL, collectionSlugs.prevValueRelation)
|
||||
errorFieldsURL = new AdminUrlUtil(serverURL, collectionSlugs.errorFields)
|
||||
const context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
initPageConsoleErrorCatch(page)
|
||||
@@ -124,4 +126,46 @@ describe('Field Error States', () => {
|
||||
await expect(page.locator('#field-title')).toHaveValue('original value 2')
|
||||
})
|
||||
})
|
||||
|
||||
describe('error field types', () => {
|
||||
async function prefillBaseRequiredFields() {
|
||||
const homeTabLocator = page.locator('.tabs-field__tab-button', {
|
||||
hasText: 'Home',
|
||||
})
|
||||
const heroTabLocator = page.locator('.tabs-field__tab-button', {
|
||||
hasText: 'Hero',
|
||||
})
|
||||
|
||||
await homeTabLocator.click()
|
||||
// fill out all required fields in the home tab
|
||||
await page.locator('#field-home__text').fill('Home Collapsible Text')
|
||||
await page.locator('#field-home__tabText').fill('Home Tab Text')
|
||||
|
||||
await page.locator('#field-group__text').fill('Home Group Text')
|
||||
await heroTabLocator.click()
|
||||
// fill out all required fields in the hero tab
|
||||
await page.locator('#field-tabText').fill('Hero Tab Text')
|
||||
await page.locator('#field-text').fill('Hero Tab Collapsible Text')
|
||||
}
|
||||
test('group errors', async () => {
|
||||
await page.goto(errorFieldsURL.create)
|
||||
await prefillBaseRequiredFields()
|
||||
|
||||
// clear group and save
|
||||
await page.locator('#field-group__text').fill('')
|
||||
await saveDocAndAssert(page, '#action-save', 'error')
|
||||
|
||||
// should show the error pill and count
|
||||
const groupFieldErrorPill = page.locator('#field-group .group-field__header .error-pill', {
|
||||
hasText: '1 error',
|
||||
})
|
||||
await expect(groupFieldErrorPill).toBeVisible()
|
||||
|
||||
// finish filling out the group
|
||||
await page.locator('#field-group__text').fill('filled out')
|
||||
|
||||
await expect(page.locator('#field-group .group-field__header .error-pill')).toBeHidden()
|
||||
await saveDocAndAssert(page, '#action-save')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -8,6 +8,7 @@ export const collectionSlugs: {
|
||||
validateDraftsOnAutosave: 'validate-drafts-on-autosave',
|
||||
prevValue: 'prev-value',
|
||||
prevValueRelation: 'prev-value-relation',
|
||||
errorFields: 'error-fields',
|
||||
}
|
||||
|
||||
export const globalSlugs: {
|
||||
|
||||
@@ -309,6 +309,7 @@ describe('Form State', () => {
|
||||
it('should merge array rows without losing rows added to local state', () => {
|
||||
const currentState: FormState = {
|
||||
array: {
|
||||
errorPaths: [],
|
||||
rows: [
|
||||
{
|
||||
id: '1',
|
||||
@@ -358,6 +359,7 @@ describe('Form State', () => {
|
||||
// Row 2 should still exist
|
||||
expect(newState).toStrictEqual({
|
||||
array: {
|
||||
errorPaths: [],
|
||||
passesCondition: true,
|
||||
valid: true,
|
||||
rows: [
|
||||
|
||||
Reference in New Issue
Block a user