fix(next): sparse block and arrays diffs were not rendered correctly (#13829)

Assuming you have 3 block/array rows and you only modify the middle one
- the version view would still display row 1 and row 3:

<img width="2354" height="1224" alt="Screenshot 2025-09-16 at 16 15
22@2x"
src="https://github.com/user-attachments/assets/5f823276-fda2-4192-a7d3-482f2a2228f9"
/>

After this PR, it's now displayed correctly:

<img width="2368" height="980" alt="Screenshot 2025-09-16 at 16 15
09@2x"
src="https://github.com/user-attachments/assets/7fc5ee25-f925-4c41-b62a-9b33652e19f9"
/>

## The Fix

The generated version fields will contain holes in the `rows` array for
rows that have no changes. The fix is to simply skip rendering those
rows. We still need to keep those holes in order to maintain the correct
row indexes.

Additionally, this PR improves the naming of some legacy variables and
function arguments that I missed out on during the version view
overhaul:

> comparison => valueFrom
> version => valueTo

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1211267837905382
This commit is contained in:
Alessio Gravili
2025-09-17 01:36:34 -07:00
committed by GitHub
parent 91e7f0c2e1
commit 433c5136fc
8 changed files with 287 additions and 155 deletions

View File

@@ -26,6 +26,7 @@ import type { BrowserContext, Dialog, Page } from '@playwright/test'
import { expect, test } from '@playwright/test'
import { postsCollectionSlug } from 'admin/slugs.js'
import mongoose from 'mongoose'
import path from 'path'
import { wait } from 'payload/shared'
import { fileURLToPath } from 'url'
@@ -1535,6 +1536,7 @@ describe('Versions', () => {
let versionID: string
let oldVersionID: string
let diffID: string
let diffDoc: Diff
let versionDiffID: string
beforeAll(() => {
@@ -1583,7 +1585,7 @@ describe('Versions', () => {
versionID = versions.docs[0].id
oldVersionID = versions.docs[1].id
const diffDoc = (
diffDoc = (
await payload.find({
collection: diffCollectionSlug,
depth: 0,
@@ -1613,8 +1615,8 @@ describe('Versions', () => {
await expect(page.locator('.render-field-diffs').first()).toBeVisible()
}
async function navigateToDiffVersionView() {
const versionURL = `${serverURL}/admin/collections/${diffCollectionSlug}/${diffID}/versions/${versionDiffID}`
async function navigateToDiffVersionView(versionID?: string) {
const versionURL = `${serverURL}/admin/collections/${diffCollectionSlug}/${diffID}/versions/${versionID ?? versionDiffID}`
await page.goto(versionURL)
await expect(page.locator('.render-field-diffs').first()).toBeVisible()
}
@@ -2084,6 +2086,118 @@ describe('Versions', () => {
})
await Promise.all(checkPromises)
})
test('diff is displayed correctly when editing 2nd block in a blocks field with 3 blocks', async () => {
await payload.update({
collection: 'diff',
data: {
blocks: [
...diffDoc!.blocks!.map((block, i) => {
if (i === 1) {
return {
...block,
textInRowInCollapsibleBlock: 'textInRowInCollapsibleBlock3',
}
}
return block
}),
],
},
id: diffID,
})
const latestVersionDiff = (
await payload.findVersions({
collection: diffCollectionSlug,
depth: 0,
limit: 1,
where: {
parent: { equals: diffID },
},
})
).docs[0] as Diff
await navigateToDiffVersionView(latestVersionDiff.id)
const blocks = page.locator('[data-field-path="blocks"]')
await expect(blocks.locator('.iterable-diff__label')).toHaveCount(1)
await expect(blocks.locator('.iterable-diff__label')).toHaveText('Block 02')
const blockDiff = page.locator('[data-field-path="blocks.1.textInRowInCollapsibleBlock"]')
await expect(blockDiff.locator('.html-diff__diff-old')).toHaveText(
'textInRowInCollapsibleBlock2',
)
await expect(blockDiff.locator('.html-diff__diff-new')).toHaveText(
'textInRowInCollapsibleBlock3',
)
})
test('diff is displayed correctly when editing 2nd array in a arrays field with 3 arrays', async () => {
const newArray = [
{
id: new mongoose.Types.ObjectId().toHexString(),
textInArray: 'textInArray1',
},
{
id: new mongoose.Types.ObjectId().toHexString(),
textInArray: 'textInArray2',
},
{
id: new mongoose.Types.ObjectId().toHexString(),
textInArray: 'textInArray3',
},
]
await payload.update({
collection: 'diff',
data: {
array: newArray,
},
id: diffID,
})
await payload.update({
collection: 'diff',
data: {
array: newArray.map((arrayItem, i) => {
if (i === 1) {
return {
...arrayItem,
textInArray: 'textInArray2Modified',
}
}
return arrayItem
}),
},
id: diffID,
})
const latestVersionDiff = (
await payload.findVersions({
collection: diffCollectionSlug,
depth: 0,
limit: 1,
where: {
parent: { equals: diffID },
},
})
).docs[0] as Diff
await navigateToDiffVersionView(latestVersionDiff.id)
const blocks = page.locator('[data-field-path="array"]')
await expect(blocks.locator('.iterable-diff__label')).toHaveCount(1)
await expect(blocks.locator('.iterable-diff__label')).toHaveText('Item 02')
const blockDiff = page.locator('[data-field-path="array.1.textInArray"]')
await expect(blockDiff.locator('.html-diff__diff-old')).toHaveText('textInArray2')
await expect(blockDiff.locator('.html-diff__diff-new')).toHaveText('textInArray2Modified')
})
})
describe('Scheduled publish', () => {