fix: skip validation when trashing documents with empty required fields (#13807)
### What? Skip field validation when trashing documents with empty required fields. ### Why? When trashing a document that was saved as a draft with empty required fields, Payload would run full validation and fail with "The following fields are invalid" errors. This happened because trash operations were treated as regular updates that require full field validation, even though trashing is just a metadata change (setting `deletedAt`) and shouldn't be blocked by content validation issues. ### How? - Modified `skipValidation` logic in `updateDocument()` to skip validation when `deletedAt` is being set in the update data Fixes #13706
This commit is contained in:
@@ -237,9 +237,11 @@ export const updateDocument = async <
|
|||||||
overrideAccess,
|
overrideAccess,
|
||||||
req,
|
req,
|
||||||
skipValidation:
|
skipValidation:
|
||||||
shouldSaveDraft &&
|
(shouldSaveDraft &&
|
||||||
collectionConfig.versions.drafts &&
|
collectionConfig.versions.drafts &&
|
||||||
!collectionConfig.versions.drafts.validate,
|
!collectionConfig.versions.drafts.validate) ||
|
||||||
|
// Skip validation for trash operations since they're just metadata updates
|
||||||
|
Boolean(data?.deletedAt),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (publishSpecificLocale) {
|
if (publishSpecificLocale) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const Posts: CollectionConfig = {
|
|||||||
{
|
{
|
||||||
name: 'title',
|
name: 'title',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
versions: {
|
versions: {
|
||||||
|
|||||||
@@ -648,6 +648,43 @@ describe('trash', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('trashing documents with validation issues', () => {
|
||||||
|
it('should allow trashing documents with empty required fields (draft scenario)', async () => {
|
||||||
|
// Create a draft document with empty required field
|
||||||
|
const draftDoc = await payload.create({
|
||||||
|
collection: postsSlug,
|
||||||
|
data: {
|
||||||
|
title: '', // Empty required field
|
||||||
|
_status: 'draft',
|
||||||
|
},
|
||||||
|
draft: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(draftDoc.title).toBe('')
|
||||||
|
expect(draftDoc._status).toBe('draft')
|
||||||
|
|
||||||
|
// Should be able to trash the document even with empty required field
|
||||||
|
const trashedDoc = await payload.update({
|
||||||
|
collection: postsSlug,
|
||||||
|
id: draftDoc.id,
|
||||||
|
data: {
|
||||||
|
deletedAt: new Date().toISOString(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(trashedDoc.deletedAt).toBeDefined()
|
||||||
|
expect(trashedDoc.title).toBe('') // Title should still be empty
|
||||||
|
expect(trashedDoc._status).toBe('draft')
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
await payload.delete({
|
||||||
|
collection: postsSlug,
|
||||||
|
id: draftDoc.id,
|
||||||
|
trash: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('deleteByID operation', () => {
|
describe('deleteByID operation', () => {
|
||||||
it('should throw NotFound error when trying to delete a soft-deleted document w/o trash: true', async () => {
|
it('should throw NotFound error when trying to delete a soft-deleted document w/o trash: true', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ export interface Page {
|
|||||||
*/
|
*/
|
||||||
export interface Post {
|
export interface Post {
|
||||||
id: string;
|
id: string;
|
||||||
title?: string | null;
|
title: string;
|
||||||
updatedAt: string;
|
updatedAt: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
deletedAt?: string | null;
|
deletedAt?: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user