Fixes https://github.com/payloadcms/payload/issues/13563 When using the nested docs plugin with collections that do not have drafts enabled. It was not syncing breadcrumbs from parent changes. The root cause was returning early on any document that did not meet `doc._status !== 'published'` check, which was **_always_** the case for non-draft collections. ### Before ```ts if (doc._status !== 'published') { return } ``` ### After ```ts if (collection.versions.drafts && doc._status !== 'published') { return } ```
252 lines
7.1 KiB
TypeScript
252 lines
7.1 KiB
TypeScript
import type { ArrayField, Payload, RelationshipField } from 'payload'
|
|
|
|
import path from 'path'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
import type { Page } from './payload-types.js'
|
|
|
|
import { initPayloadInt } from '../helpers/initPayloadInt.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 () => {
|
|
await payload.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
|
|
const lastUpdatedChildBreadcrumbs = docs[10]?.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])
|
|
|
|
// 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')
|
|
})
|
|
})
|
|
})
|