Files
payloadcms/test/plugin-nested-docs/int.spec.ts
Jessica Chowdhury d92c0009ed fix(plugin-nested-docs): corrects data shape of breadcrumbs returned in hooks (#10866)
### What?
The `plugin-nested-docs` returns an array of breadcrumbs - the
`resaveChildren` file accidentally processed the breadcrumbs twice, once
where the data is updated and once within the `populateBreadcrumbs`
function which was causing the objects to be double nested.

### How?
Removes the extra nesting from `resaveChildren` file and allows the
`populateBreadcrumbs` to return the final data.

Fixes #10855
2025-02-24 11:10:21 -05:00

257 lines
7.2 KiB
TypeScript

import type { ArrayField, Payload, RelationshipField } from 'payload'
import path from 'path'
import { fileURLToPath } from 'url'
import { initPayloadInt } from '../helpers/initPayloadInt.js'
import { Page } from './payload-types.js'
let payload: Payload
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
describe('@payloadcms/plugin-nested-docs', () => {
beforeAll(async () => {
;({ payload } = await initPayloadInt(dirname))
})
afterAll(async () => {
if (typeof payload.db.destroy === 'function') {
await payload.db.destroy()
}
})
describe('seed', () => {
it('should populate two levels of breadcrumbs', async () => {
const query = await payload.find({
collection: 'pages',
where: {
slug: {
equals: 'child-page',
},
},
})
expect(query.docs[0].breadcrumbs).toHaveLength(2)
})
it('should populate three levels of breadcrumbs', async () => {
const query = await payload.find({
collection: 'pages',
where: {
slug: {
equals: 'grandchild-page',
},
},
})
expect(query.docs[0].breadcrumbs).toHaveLength(3)
expect(query.docs[0].breadcrumbs[0].url).toStrictEqual('/parent-page')
expect(query.docs[0].breadcrumbs[1].url).toStrictEqual('/parent-page/child-page')
expect(query.docs[0].breadcrumbs[2].url).toStrictEqual(
'/parent-page/child-page/grandchild-page',
)
})
it('should update more than 10 (default limit) breadcrumbs', async () => {
// create a parent doc
const parentDoc = await payload.create({
collection: 'pages',
data: {
title: '11 children',
slug: '11-children',
},
})
// create 11 children docs
for (let i = 0; i < 11; i++) {
await payload.create({
collection: 'pages',
data: {
title: `Child ${i + 1}`,
slug: `child-${i + 1}`,
parent: parentDoc.id,
_status: 'published',
},
})
}
// update parent doc
await payload.update({
collection: 'pages',
id: parentDoc.id,
data: {
title: '11 children updated',
slug: '11-children-updated',
_status: 'published',
},
})
// read children docs
const { docs } = await payload.find({
collection: 'pages',
limit: 0,
where: {
parent: {
equals: parentDoc.id,
},
},
})
const firstUpdatedChildBreadcrumbs = docs[0]?.breadcrumbs as Page['breadcrumbs']
const lastUpdatedChildBreadcrumbs = docs[10]?.breadcrumbs as Page['breadcrumbs']
expect(firstUpdatedChildBreadcrumbs).toHaveLength(2)
// @ts-ignore
expect(firstUpdatedChildBreadcrumbs[0].url).toStrictEqual('/11-children-updated')
expect(firstUpdatedChildBreadcrumbs).toBeDefined()
// @ts-ignore
expect(lastUpdatedChildBreadcrumbs[0].url).toStrictEqual('/11-children-updated')
})
it('should return breadcrumbs as an array of objects', async () => {
const parentDoc = await payload.create({
collection: 'pages',
data: {
title: 'parent doc',
slug: 'parent-doc',
_status: 'published',
},
})
const childDoc = await payload.create({
collection: 'pages',
data: {
title: 'child doc',
slug: 'child-doc',
parent: parentDoc.id,
_status: 'published',
},
})
// expect breadcrumbs to be an array
expect(childDoc.breadcrumbs).toBeInstanceOf(Array)
expect(childDoc.breadcrumbs).toBeDefined()
// expect each to be objects
childDoc.breadcrumbs?.map((breadcrumb) => {
expect(breadcrumb).toBeInstanceOf(Object)
})
})
it('should update child doc breadcrumb without affecting any other data', async () => {
const parentDoc = await payload.create({
collection: 'pages',
data: {
title: 'parent doc',
slug: 'parent',
},
})
const childDoc = await payload.create({
collection: 'pages',
data: {
title: 'child doc',
slug: 'child',
parent: parentDoc.id,
_status: 'published',
},
})
await payload.update({
collection: 'pages',
id: parentDoc.id,
data: {
title: 'parent updated',
slug: 'parent-updated',
_status: 'published',
},
})
const updatedChild = await payload
.find({
collection: 'pages',
where: {
id: {
equals: childDoc.id,
},
},
})
.then(({ docs }) => docs[0])
if (!updatedChild) {
return
}
// breadcrumbs should be updated
expect(updatedChild.breadcrumbs).toHaveLength(2)
expect(updatedChild.breadcrumbs?.[0]?.url).toStrictEqual('/parent-updated')
expect(updatedChild.breadcrumbs?.[1]?.url).toStrictEqual('/parent-updated/child')
// no other data should be affected
expect(updatedChild.title).toEqual('child doc')
expect(updatedChild.slug).toEqual('child')
})
})
describe('overrides', () => {
let collection
beforeAll(() => {
collection = payload.config.collections.find(({ slug }) => slug === 'categories')
})
it('should allow overriding breadcrumbs field', () => {
const breadcrumbField = collection.fields.find(
(field) => field.type === 'array' && field.name === 'categorization',
) as ArrayField
const customField = breadcrumbField.fields.find(
(field) => field.type === 'text' && field.name === 'test',
) as ArrayField
expect(breadcrumbField.admin.description).toStrictEqual('custom')
expect(customField).toBeDefined()
expect(breadcrumbField.admin.readOnly).toStrictEqual(true)
expect(breadcrumbField.admin.readOnly).toStrictEqual(true)
})
it('should allow overriding parent field', () => {
const parentField = collection.fields.find(
(field) => field.type === 'relationship' && field.name === 'owner',
) as RelationshipField
expect(parentField.admin.description).toStrictEqual('custom')
})
it('should allow custom breadcrumb and parent slugs', async () => {
const parent = await payload.create({
collection: 'categories',
data: {
name: 'parent',
},
})
const child = await payload.create({
collection: 'categories',
data: {
name: 'child',
owner: parent.id,
},
})
const grandchild = await payload.create({
collection: 'categories',
data: {
name: 'grandchild',
owner: child.id,
},
})
expect(grandchild.categorization[0].doc).toStrictEqual(parent.id)
expect(grandchild.categorization[0].label).toStrictEqual('parent')
expect(grandchild.categorization[1].doc).toStrictEqual(child.id)
expect(grandchild.categorization[1].label).toStrictEqual('child')
expect(grandchild.categorization[2].label).toStrictEqual('grandchild')
})
})
})