From ef0f896922d868f657497447c516ac056adb54f4 Mon Sep 17 00:00:00 2001 From: Steven Thompson <44806974+thompsonsj@users.noreply.github.com> Date: Sun, 20 Oct 2024 23:23:35 +0100 Subject: [PATCH] fix(document): detect lexical field collection inside a lexical block --- ...al-editor-with-blocks-inside-array.test.ts | 582 ++++++++++-------- .../payload-crowdin-sync/files/document.ts | 14 +- plugin/src/lib/utilities/index.ts | 8 +- 3 files changed, 336 insertions(+), 268 deletions(-) diff --git a/dev/src/lib/tests/collections/lexical-editor-with-blocks-inside-array.test.ts b/dev/src/lib/tests/collections/lexical-editor-with-blocks-inside-array.test.ts index a422f17..d23b068 100644 --- a/dev/src/lib/tests/collections/lexical-editor-with-blocks-inside-array.test.ts +++ b/dev/src/lib/tests/collections/lexical-editor-with-blocks-inside-array.test.ts @@ -1,8 +1,6 @@ import payload from 'payload'; import { initPayloadTest } from '../helpers/config'; -import { - utilities, -} from 'plugin'; +import { getArticleDirectory, utilities } from 'plugin'; import NestedFieldCollection from '../../collections/NestedFieldCollection'; import { fixture } from './lexical-editor-with-blocks-inside-array.fixture'; import nock from 'nock'; @@ -10,8 +8,11 @@ import { extractLexicalBlockContent } from 'plugin/src/lib/utilities/lexical'; import { mockCrowdinClient } from 'plugin/src/lib/api/mock/crowdin-api-responses'; import { pluginConfig } from '../helpers/plugin-config'; import { + CrowdinArticleDirectory, NestedFieldCollection as NestedFieldCollectionType, } from '../../payload-types'; +import { getFilesByParent } from 'plugin/src/lib/api/helpers'; +import { getRelationshipId } from 'plugin/src/lib/utilities/payload'; const pluginOptions = pluginConfig(); const mockClient = mockCrowdinClient(pluginOptions); @@ -360,10 +361,10 @@ describe('Lexical editor with multiple blocks', () => { .times(5) .reply(200, mockClient.createFile({})); - const doc: NestedFieldCollectionType = await payload.create({ + const doc: NestedFieldCollectionType = (await payload.create({ collection: 'nested-field-collection', data: fixture, - }) as any; + })) as any; const arrayIds = (doc.items || []).map((item) => item.id) || ([] as string[]); @@ -371,9 +372,13 @@ describe('Lexical editor with multiple blocks', () => { (doc.items || []).map( (item) => (item.block || []).find((x) => x !== undefined)?.id ) || ([] as string[]); - const firstLexicalBlock = doc.items?.[1]?.block?.[0]?.content + const firstLexicalBlock = doc.items?.[1]?.block?.[0]?.content; - const lexicalBlockIds = firstLexicalBlock ? extractLexicalBlockContent(firstLexicalBlock.root).map(block => block.id) : ['lexical-block-id-not-found'] + const lexicalBlockIds = firstLexicalBlock + ? extractLexicalBlockContent(firstLexicalBlock.root).map( + (block) => block.id + ) + : ['lexical-block-id-not-found']; const crowdinHtmlObject = utilities.buildCrowdinHtmlObject({ doc, @@ -390,271 +395,324 @@ describe('Lexical editor with multiple blocks', () => { fields: NestedFieldCollection.fields, document: doc, }) - ).toEqual( - { - "items": [ - { - "block": [ - { - "blockType": "basicBlockLexical", - "content": { - "root": { - "children": [ - { - "children": [ - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": "Lexical fields nested within complex layouts - such as this one (a ", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 16, - "mode": "normal", - "style": "", - "text": "blocks", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": " field in an ", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 16, - "mode": "normal", - "style": "", - "text": "array", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": " item within a ", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 16, - "mode": "normal", - "style": "", - "text": "tab", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": "), are supported.", - "type": "text", - "version": 1, - }, - ], - "direction": "ltr", - "format": "", - "indent": 0, - "type": "paragraph", - "version": 1, - }, - ], - "direction": "ltr", - "format": "", - "indent": 0, - "type": "root", - "version": 1, - }, + ).toEqual({ + items: [ + { + block: [ + { + blockType: 'basicBlockLexical', + content: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: 'Lexical fields nested within complex layouts - such as this one (a ', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 16, + mode: 'normal', + style: '', + text: 'blocks', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: ' field in an ', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 16, + mode: 'normal', + style: '', + text: 'array', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: ' item within a ', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 16, + mode: 'normal', + style: '', + text: 'tab', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: '), are supported.', + type: 'text', + version: 1, + }, + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'paragraph', + version: 1, + }, + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'root', + version: 1, }, - "id": `${blockIds[0]}`, }, - ], - "heading": "Nested Lexical fields are supported", - "id": `${arrayIds[0]}`, - }, - { - "block": [ - { - "blockType": "basicBlockLexical", - "content": { - "root": { - "children": [ - { - "children": [ - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": "If you add custom blocks, these will also be translated!", - "type": "text", - "version": 1, - }, - ], - "direction": "ltr", - "format": "", - "indent": 0, - "type": "paragraph", - "version": 1, - }, - { - "fields": { - "blockName": "", - "blockType": "highlight", - "content": { - "root": { - "children": [ - { - "children": [ - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": "Note a key difference with regular blocks - all ", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 16, - "mode": "normal", - "style": "", - "text": "text", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": ", ", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 16, - "mode": "normal", - "style": "", - "text": "textarea", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": " and ", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 16, - "mode": "normal", - "style": "", - "text": "richText", - "type": "text", - "version": 1, - }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": " fields will be sent to Crowdin regardless of whether or not they are ", - "type": "text", - "version": 1, - }, - { - "children": [ - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": "localized fields", - "type": "text", - "version": 1, - }, - ], - "direction": "ltr", - "fields": { - "linkType": "custom", - "newTab": false, - "url": "https://payloadcms.com/docs/configuration/localization#field-by-field-localization", + id: `${blockIds[0]}`, + }, + ], + heading: 'Nested Lexical fields are supported', + id: `${arrayIds[0]}`, + }, + { + block: [ + { + blockType: 'basicBlockLexical', + content: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: 'If you add custom blocks, these will also be translated!', + type: 'text', + version: 1, + }, + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'paragraph', + version: 1, + }, + { + fields: { + blockName: '', + blockType: 'highlight', + content: { + root: { + children: [ + { + children: [ + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: 'Note a key difference with regular blocks - all ', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 16, + mode: 'normal', + style: '', + text: 'text', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: ', ', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 16, + mode: 'normal', + style: '', + text: 'textarea', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: ' and ', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 16, + mode: 'normal', + style: '', + text: 'richText', + type: 'text', + version: 1, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: ' fields will be sent to Crowdin regardless of whether or not they are ', + type: 'text', + version: 1, + }, + { + children: [ + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: 'localized fields', + type: 'text', + version: 1, }, - "format": "", - "indent": 0, - "type": "link", - "version": 2, + ], + direction: 'ltr', + fields: { + linkType: 'custom', + newTab: false, + url: 'https://payloadcms.com/docs/configuration/localization#field-by-field-localization', }, - { - "detail": 0, - "format": 0, - "mode": "normal", - "style": "", - "text": ".", - "type": "text", - "version": 1, - }, - ], - "direction": "ltr", - "format": "", - "indent": 0, - "type": "paragraph", - "version": 1, - }, - ], - "direction": "ltr", - "format": "", - "indent": 0, - "type": "root", - "version": 1, - }, - }, - "heading": { - "title": "Block configuration in Lexical fields", + format: '', + indent: 0, + type: 'link', + version: 2, + }, + { + detail: 0, + format: 0, + mode: 'normal', + style: '', + text: '.', + type: 'text', + version: 1, + }, + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'paragraph', + version: 1, + }, + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'root', + version: 1, }, - "id": `${lexicalBlockIds[0]}`, }, - "format": "", - "type": "block", - "version": 2, + heading: { + title: 'Block configuration in Lexical fields', + }, + id: `${lexicalBlockIds[0]}`, }, - ], - "direction": "ltr", - "format": "", - "indent": 0, - "type": "root", - "version": 1, - }, + format: '', + type: 'block', + version: 2, + }, + ], + direction: 'ltr', + format: '', + indent: 0, + type: 'root', + version: 1, }, - "id": `${blockIds[1]}`, }, - ], - "heading": "Nested Lexical fields are supported - and blocks in that Lexical field are also translated", - "id": `${arrayIds[1]}`, + id: `${blockIds[1]}`, + }, + ], + heading: + 'Nested Lexical fields are supported - and blocks in that Lexical field are also translated', + id: `${arrayIds[1]}`, + }, + ], + }); + }); + + it('associates a parent Crowdin article directory with a lexical blocks Crowdin article directory', async () => { + nock('https://api.crowdin.com') + .post(`/api/v2/projects/${pluginOptions.projectId}/directories`) + .times(2) + .reply(200, mockClient.createDirectory({})) + .post(`/api/v2/storages`) + .times(5) + .reply(200, mockClient.addStorage()) + .post(`/api/v2/projects/${pluginOptions.projectId}/files`) + .times(5) + .reply(200, mockClient.createFile({})); + + const create = await payload.create({ + collection: 'nested-field-collection', + data: fixture, + }); + // update now that a Crowdin article directory is available + const doc: NestedFieldCollectionType = (await payload.update({ + id: create.id, + collection: 'nested-field-collection', + data: { + title: 'Test nested field collection', + }, + })) as any; + + const files = await getFilesByParent( + `${getRelationshipId(doc.crowdinArticleDirectory)}`, + payload + ); + + expect(files.length).toEqual(2); + + expect(files[0].fileData).toMatchInlineSnapshot(` + { + "html": "
Note a key difference with regular blocks - all text
, textarea
and richText
fields will be sent to Crowdin regardless of whether or not they are localized fields.