From 5d575726949308fda31ca28fbf783983bc50502b Mon Sep 17 00:00:00 2001 From: James Date: Thu, 4 Apr 2024 14:41:58 -0400 Subject: [PATCH] chore: work to add consistency to fields e2e --- .vscode/launch.json | 2 +- .../next/src/routes/rest/buildFormState.ts | 281 +++++----- .../queryValidation/validateSearchParams.ts | 11 +- packages/payload/src/fields/validations.ts | 110 ++-- test/dev.js | 11 + test/fields/config.ts | 4 +- test/fields/e2e.spec.ts | 30 +- test/fields/seed.ts | 506 +++++++++--------- tsconfig.json | 2 +- 9 files changed, 488 insertions(+), 469 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 2420515fba..0f07cf2be6 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,7 +34,7 @@ } }, { - "command": "pnpm run dev fields", + "command": "node --no-deprecation test/dev.js fields", "cwd": "${workspaceFolder}", "name": "Run Dev Fields", "request": "launch", diff --git a/packages/next/src/routes/rest/buildFormState.ts b/packages/next/src/routes/rest/buildFormState.ts index 90466f5bda..31222dc327 100644 --- a/packages/next/src/routes/rest/buildFormState.ts +++ b/packages/next/src/routes/rest/buildFormState.ts @@ -33,164 +33,177 @@ export const getFieldSchemaMap = (config: SanitizedConfig): FieldSchemaMap => { } export const buildFormState = async ({ req }: { req: PayloadRequest }) => { - const reqData: BuildFormStateArgs = req.data as BuildFormStateArgs - const { collectionSlug, formState, globalSlug, locale, operation, schemaPath } = reqData + try { + const reqData: BuildFormStateArgs = req.data as BuildFormStateArgs + const { collectionSlug, formState, globalSlug, locale, operation, schemaPath } = reqData - const incomingUserSlug = req.user?.collection - const adminUserSlug = req.payload.config.admin.user + const incomingUserSlug = req.user?.collection + const adminUserSlug = req.payload.config.admin.user - // If we have a user slug, test it against the functions - if (incomingUserSlug) { - const adminAccessFunction = req.payload.collections[incomingUserSlug].config.access?.admin + // If we have a user slug, test it against the functions + if (incomingUserSlug) { + const adminAccessFunction = req.payload.collections[incomingUserSlug].config.access?.admin - // Run the admin access function from the config if it exists - if (adminAccessFunction) { - const canAccessAdmin = await adminAccessFunction(req) + // Run the admin access function from the config if it exists + if (adminAccessFunction) { + const canAccessAdmin = await adminAccessFunction(req) - if (!canAccessAdmin) { + if (!canAccessAdmin) { + return Response.json(null, { + status: httpStatus.UNAUTHORIZED, + }) + } + // Match the user collection to the global admin config + } else if (adminUserSlug !== incomingUserSlug) { return Response.json(null, { status: httpStatus.UNAUTHORIZED, }) } - // Match the user collection to the global admin config - } else if (adminUserSlug !== incomingUserSlug) { + } else { return Response.json(null, { status: httpStatus.UNAUTHORIZED, }) } - } else { - return Response.json(null, { - status: httpStatus.UNAUTHORIZED, - }) - } - const fieldSchemaMap = getFieldSchemaMap(req.payload.config) + const fieldSchemaMap = getFieldSchemaMap(req.payload.config) - const id = collectionSlug ? reqData.id : undefined - const schemaPathSegments = schemaPath.split('.') + const id = collectionSlug ? reqData.id : undefined + const schemaPathSegments = schemaPath.split('.') - let fieldSchema: Field[] + let fieldSchema: Field[] - if (schemaPathSegments.length === 1) { - if (req.payload.collections[schemaPath]) { - fieldSchema = req.payload.collections[schemaPath].config.fields - } else { - fieldSchema = req.payload.config.globals.find((global) => global.slug === schemaPath)?.fields + if (schemaPathSegments.length === 1) { + if (req.payload.collections[schemaPath]) { + fieldSchema = req.payload.collections[schemaPath].config.fields + } else { + fieldSchema = req.payload.config.globals.find( + (global) => global.slug === schemaPath, + )?.fields + } + } else if (fieldSchemaMap.has(schemaPath)) { + fieldSchema = fieldSchemaMap.get(schemaPath) } - } else if (fieldSchemaMap.has(schemaPath)) { - fieldSchema = fieldSchemaMap.get(schemaPath) - } - if (!fieldSchema) { + if (!fieldSchema) { + return Response.json( + { + message: 'Could not find field schema for given path', + }, + { + status: httpStatus.BAD_REQUEST, + }, + ) + } + + let docPreferences = reqData.docPreferences + let data = reqData.data + + const promises: { + data?: Promise + preferences?: Promise + } = {} + + // If the request does not include doc preferences, + // we should fetch them. This is useful for DocumentInfoProvider + // as it reduces the amount of client-side fetches necessary + // when we fetch data for the Edit view + if (!docPreferences) { + let preferencesKey + + if (collectionSlug && id) { + preferencesKey = `collection-${collectionSlug}-${id}` + } + + if (globalSlug) { + preferencesKey = `global-${globalSlug}` + } + + if (preferencesKey) { + const fetchPreferences = async () => { + const preferencesResult = (await req.payload.find({ + collection: 'payload-preferences', + depth: 0, + limit: 1, + where: { + key: { + equals: preferencesKey, + }, + }, + })) as unknown as { docs: { value: DocumentPreferences }[] } + + if (preferencesResult?.docs?.[0]?.value) docPreferences = preferencesResult.docs[0].value + } + + promises.preferences = fetchPreferences() + } + } + + // If there is a form state, + // then we can deduce data from that form state + if (formState) data = reduceFieldsToValues(formState, true) + + // If we do not have data at this point, + // we can fetch it. This is useful for DocumentInfoProvider + // to reduce the amount of fetches required + if (!data) { + const fetchData = async () => { + let resolvedData: TypeWithID + + if (collectionSlug && id) { + resolvedData = await req.payload.findByID({ + id, + collection: collectionSlug, + depth: 0, + draft: true, + fallbackLocale: null, + locale, + overrideAccess: false, + user: req.user, + }) + } + + if (globalSlug) { + resolvedData = await req.payload.findGlobal({ + slug: globalSlug, + depth: 0, + draft: true, + fallbackLocale: null, + locale, + overrideAccess: false, + user: req.user, + }) + } + + data = resolvedData + } + + promises.data = fetchData() + } + + if (Object.keys(promises).length > 0) { + await Promise.all(Object.values(promises)) + } + + const result = await buildStateFromSchema({ + id, + data, + fieldSchema, + operation, + preferences: docPreferences || { fields: {} }, + req, + }) + + return Response.json(result, { + status: httpStatus.OK, + }) + } catch (err) { return Response.json( { - message: 'Could not find field schema for given path', + message: 'There was an error building form state', }, { status: httpStatus.BAD_REQUEST, }, ) } - - let docPreferences = reqData.docPreferences - let data = reqData.data - - const promises: { - data?: Promise - preferences?: Promise - } = {} - - // If the request does not include doc preferences, - // we should fetch them. This is useful for DocumentInfoProvider - // as it reduces the amount of client-side fetches necessary - // when we fetch data for the Edit view - if (!docPreferences) { - let preferencesKey - - if (collectionSlug && id) { - preferencesKey = `collection-${collectionSlug}-${id}` - } - - if (globalSlug) { - preferencesKey = `global-${globalSlug}` - } - - if (preferencesKey) { - const fetchPreferences = async () => { - const preferencesResult = (await req.payload.find({ - collection: 'payload-preferences', - depth: 0, - limit: 1, - where: { - key: { - equals: preferencesKey, - }, - }, - })) as unknown as { docs: { value: DocumentPreferences }[] } - - if (preferencesResult?.docs?.[0]?.value) docPreferences = preferencesResult.docs[0].value - } - - promises.preferences = fetchPreferences() - } - } - - // If there is a form state, - // then we can deduce data from that form state - if (formState) data = reduceFieldsToValues(formState, true) - - // If we do not have data at this point, - // we can fetch it. This is useful for DocumentInfoProvider - // to reduce the amount of fetches required - if (!data) { - const fetchData = async () => { - let resolvedData: TypeWithID - - if (collectionSlug && id) { - resolvedData = await req.payload.findByID({ - id, - collection: collectionSlug, - depth: 0, - draft: true, - fallbackLocale: null, - locale, - overrideAccess: false, - user: req.user, - }) - } - - if (globalSlug) { - resolvedData = await req.payload.findGlobal({ - slug: globalSlug, - depth: 0, - draft: true, - fallbackLocale: null, - locale, - overrideAccess: false, - user: req.user, - }) - } - - data = resolvedData - } - - promises.data = fetchData() - } - - if (Object.keys(promises).length > 0) { - await Promise.all(Object.values(promises)) - } - - const result = await buildStateFromSchema({ - id, - data, - fieldSchema, - operation, - preferences: docPreferences || { fields: {} }, - req, - }) - - return Response.json(result, { - status: httpStatus.OK, - }) } diff --git a/packages/payload/src/database/queryValidation/validateSearchParams.ts b/packages/payload/src/database/queryValidation/validateSearchParams.ts index 87e101e149..8f637b2b64 100644 --- a/packages/payload/src/database/queryValidation/validateSearchParams.ts +++ b/packages/payload/src/database/queryValidation/validateSearchParams.ts @@ -5,6 +5,7 @@ import type { PayloadRequest } from '../../types/index.js' import type { EntityPolicies, PathToQuery } from './types.js' import { fieldAffectsData } from '../../fields/config/types.js' +import { createLocalReq } from '../../utilities/createLocalReq.js' import { getEntityPolicies } from '../../utilities/getEntityPolicies.js' import { getLocalizedPaths } from '../getLocalizedPaths.js' import { validateQueryPaths } from './validateQueryPaths.js' @@ -89,7 +90,15 @@ export async function validateSearchParam({ type: 'collection', entity: req.payload.collections[collectionSlug].config, operations: ['read'], - req, + req: createLocalReq( + { + context: req.context, + fallbackLocale: req.fallbackLocale, + locale: req.locale, + user: req.user, + }, + req.payload, + ), }) } diff --git a/packages/payload/src/fields/validations.ts b/packages/payload/src/fields/validations.ts index 5744be5e40..7d24f2e63c 100644 --- a/packages/payload/src/fields/validations.ts +++ b/packages/payload/src/fields/validations.ts @@ -314,69 +314,67 @@ const validateFilterOptions: Validate< const collections = typeof relationTo === 'string' ? [relationTo] : relationTo const values = Array.isArray(value) ? value : [value] - await Promise.all( - collections.map(async (collection) => { - try { - let optionFilter = - typeof filterOptions === 'function' - ? await filterOptions({ - id, - data, - relationTo: collection, - siblingData, - user, - }) - : filterOptions + for (const collection of collections) { + try { + let optionFilter = + typeof filterOptions === 'function' + ? await filterOptions({ + id, + data, + relationTo: collection, + siblingData, + user, + }) + : filterOptions - if (optionFilter === true) { - optionFilter = null + if (optionFilter === true) { + optionFilter = null + } + + const valueIDs: (number | string)[] = [] + + values.forEach((val) => { + if (typeof val === 'object' && val?.value) { + valueIDs.push(val.value) } - const valueIDs: (number | string)[] = [] - - values.forEach((val) => { - if (typeof val === 'object' && val?.value) { - valueIDs.push(val.value) - } - - if (typeof val === 'string' || typeof val === 'number') { - valueIDs.push(val) - } - }) - - if (valueIDs.length > 0) { - const findWhere: Where = { - and: [{ id: { in: valueIDs } }], - } - - if (optionFilter && optionFilter !== true) findWhere.and.push(optionFilter) - - if (optionFilter === false) { - falseCollections.push(collection) - } - - const result = await payload.find({ - collection, - depth: 0, - limit: 0, - pagination: false, - req, - where: findWhere, - }) - - options[collection] = result.docs.map((doc) => doc.id) - } else { - options[collection] = [] + if (typeof val === 'string' || typeof val === 'number') { + valueIDs.push(val) } - } catch (err) { - req.payload.logger.error({ - err, - msg: `Error validating filter options for collection ${collection}`, + }) + + if (valueIDs.length > 0) { + const findWhere: Where = { + and: [{ id: { in: valueIDs } }], + } + + if (optionFilter && optionFilter !== true) findWhere.and.push(optionFilter) + + if (optionFilter === false) { + falseCollections.push(collection) + } + + const result = await payload.find({ + collection, + depth: 0, + limit: 0, + pagination: false, + req, + where: findWhere, }) + + options[collection] = result.docs.map((doc) => doc.id) + } else { options[collection] = [] } - }), - ) + } catch (err) { + req.payload.logger.error({ + err, + msg: `Error validating filter options for collection ${collection}`, + }) + options[collection] = [] + } + } const invalidRelationships = values.filter((val) => { let collection: string diff --git a/test/dev.js b/test/dev.js index 319bfc42e2..124bedb1d8 100644 --- a/test/dev.js +++ b/test/dev.js @@ -1,4 +1,5 @@ import minimist from 'minimist' +import { MongoMemoryReplSet } from 'mongodb-memory-server' import { nextDev } from 'next/dist/cli/next-dev.js' import { dirname, resolve } from 'path' import { fileURLToPath } from 'url' @@ -31,6 +32,16 @@ const rootDir = resolve(_dirname, '../') if (args.o) { await open('http://localhost:3000/admin') } + +global._mongoMemoryServer = await MongoMemoryReplSet.create({ + replSet: { + count: 3, + dbName: 'payloadmemory', + }, +}) + +process.env.MONGODB_MEMORY_SERVER_URI = global._mongoMemoryServer.getUri() + // @ts-expect-error await nextDev({ port: process.env.PORT || 3000, dirname: rootDir }, 'default', rootDir) diff --git a/test/fields/config.ts b/test/fields/config.ts index db0fa8f645..96e765092a 100644 --- a/test/fields/config.ts +++ b/test/fields/config.ts @@ -26,7 +26,7 @@ import Uploads from './collections/Upload/index.js' import Uploads2 from './collections/Upload2/index.js' import Uploads3 from './collections/Uploads3/index.js' import TabsWithRichText from './globals/TabsWithRichText.js' -import { clearAndSeedEverything } from './seed.js' +import { seed } from './seed.js' export const collectionSlugs: CollectionConfig[] = [ LexicalFields, @@ -79,7 +79,7 @@ export default buildConfigWithDefaults({ }, onInit: async (payload) => { if (process.env.SEED_IN_CONFIG_ONINIT !== 'false') { - await clearAndSeedEverything(payload) + await seed(payload) } }, }) diff --git a/test/fields/e2e.spec.ts b/test/fields/e2e.spec.ts index 436f559f7a..556bca4bc0 100644 --- a/test/fields/e2e.spec.ts +++ b/test/fields/e2e.spec.ts @@ -1,12 +1,12 @@ import type { Page } from '@playwright/test' -import type { Payload } from 'payload' import { expect, test } from '@playwright/test' import path from 'path' import { wait } from 'payload/utilities' import { fileURLToPath } from 'url' -import type { RelationshipField, TextField } from './payload-types.js' +import type { PayloadTestSDK } from '../helpers/sdk/index.js' +import type { Config, RelationshipField, TextField } from './payload-types.js' import { exactText, @@ -15,13 +15,13 @@ import { saveDocHotkeyAndAssert, } from '../helpers.js' import { AdminUrlUtil } from '../helpers/adminUrlUtil.js' -import { initPayloadE2E } from '../helpers/initPayloadE2E.js' +import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js' +import { reInitializeDB } from '../helpers/reInit.js' import { RESTClient } from '../helpers/rest.js' import { POLL_TOPASS_TIMEOUT } from '../playwright.config.js' import { jsonDoc } from './collections/JSON/shared.js' import { numberDoc } from './collections/Number/shared.js' import { textDoc } from './collections/Text/shared.js' -import { clearAndSeedEverything } from './seed.js' import { collapsibleFieldsSlug, pointFieldsSlug, @@ -34,7 +34,7 @@ const dirname = path.dirname(filename) const { beforeAll, beforeEach, describe } = test -let payload: Payload +let payload: PayloadTestSDK let client: RESTClient let page: Page let serverURL: string @@ -43,14 +43,19 @@ let serverURL: string describe('fields', () => { beforeAll(async ({ browser }) => { process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit - ;({ payload, serverURL } = await initPayloadE2E({ dirname })) + ;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname })) const context = await browser.newContext() page = await context.newPage() initPageConsoleErrorCatch(page) }) beforeEach(async () => { - await clearAndSeedEverything(payload) + await reInitializeDB({ + serverURL, + snapshotKey: 'fieldsTest', + uploadsDir: path.resolve(dirname, './collections/Upload/uploads'), + }) + if (client) { await client.logout() } @@ -262,7 +267,7 @@ describe('fields', () => { }) await page.goto(url.create) - await page.waitForURL(`**/${url.create}`) + await page.waitForURL(url.create) await page.locator('#field-text').fill('test') await page.locator('#field-uniqueText').fill(uniqueText) @@ -952,6 +957,8 @@ describe('fields', () => { await page.goto(url.create) + await wait(300) + await page.locator('.tabs-field__tab-button:has-text("Tab with Row")').click() await page.locator('#field-textInRow').fill(textInRowValue) await page.locator('#field-numberInRow').fill(numberInRowValue) @@ -1020,6 +1027,7 @@ describe('fields', () => { async function navigateToRichTextFields() { const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields') await page.goto(url.list) + await page.waitForURL(url.list) await page.locator('.row-1 .cell-title a').click() } @@ -1057,6 +1065,7 @@ describe('fields', () => { await editLinkModal.locator('#field-url').fill('') await wait(200) await editLinkModal.locator('button[type="submit"]').click() + await wait(400) const errorField = page.locator( '[id^=drawer_1_rich-text-link-] .render-fields > :nth-child(3)', ) @@ -1075,11 +1084,12 @@ describe('fields', () => { await expect(editLinkModal).toBeVisible() // Fill values and click Confirm - await editLinkModal.locator('#field-text').fill('link text') + await editLinkModal.locator('.drawer__content #field-text').fill('link text') await editLinkModal.locator('label[for="field-linkType-custom"]').click() await editLinkModal.locator('#field-url').fill('https://payloadcms.com') - await wait(200) + await wait(2000) await editLinkModal.locator('button[type="submit"]').click() + await wait(400) await saveDocAndAssert(page) // Remove link from editor body diff --git a/test/fields/seed.ts b/test/fields/seed.ts index 1438364500..47696603e2 100644 --- a/test/fields/seed.ts +++ b/test/fields/seed.ts @@ -1,11 +1,8 @@ import path from 'path' -import { type Payload } from 'payload' import { getFileByPath } from 'payload/uploads' import { fileURLToPath } from 'url' import { devUser } from '../credentials.js' -import { executePromises } from '../helpers/executePromises.js' -import { seedDB } from '../helpers/seed.js' import { anotherArrayDoc, arrayDoc } from './collections/Array/shared.js' import { blocksDoc } from './collections/Blocks/shared.js' import { codeDoc } from './collections/Code/shared.js' @@ -29,7 +26,6 @@ import { blockFieldsSlug, codeFieldsSlug, collapsibleFieldsSlug, - collectionSlugs, conditionalLogicSlug, dateFieldsSlug, groupFieldsSlug, @@ -49,274 +45,256 @@ import { const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) -export async function clearAndSeedEverything(_payload: Payload, parallel: boolean = false) { - return await seedDB({ - _payload, - collectionSlugs, - seedFunction: async (_payload) => { - const jpgPath = path.resolve(dirname, './collections/Upload/payload.jpg') - const pngPath = path.resolve(dirname, './uploads/payload.png') +export const seed = async (_payload) => { + if (_payload.db.name === 'mongoose') { + await Promise.all( + _payload.config.collections.map(async (coll) => { + await new Promise((resolve, reject) => { + _payload.db?.collections[coll.slug]?.ensureIndexes(function (err) { + if (err) reject(err) + resolve(true) + }) + }) + }), + ) + } - // Get both files in parallel - const [jpgFile, pngFile] = await Promise.all([getFileByPath(jpgPath), getFileByPath(pngPath)]) + const jpgPath = path.resolve(dirname, './collections/Upload/payload.jpg') + const pngPath = path.resolve(dirname, './uploads/payload.png') - const [ - createdArrayDoc, - createdAnotherArrayDoc, - createdTextDoc, - createdAnotherTextDoc, - createdPNGDoc, - ] = await executePromises( - [ - () => - _payload.create({ - collection: arrayFieldsSlug, - data: arrayDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: arrayFieldsSlug, - data: anotherArrayDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: textFieldsSlug, - data: textDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: textFieldsSlug, - data: anotherTextDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: uploadsSlug, - data: {}, - file: pngFile, - depth: 0, - overrideAccess: true, - }), - ], - parallel, - ) + // Get both files in parallel + const [jpgFile, pngFile] = await Promise.all([getFileByPath(jpgPath), getFileByPath(pngPath)]) - const createdJPGDoc = await _payload.create({ - collection: uploadsSlug, - data: { - ...uploadsDoc, - media: createdPNGDoc.id, - }, - file: jpgFile, - depth: 0, - overrideAccess: true, - }) + const createdArrayDoc = await _payload.create({ + collection: arrayFieldsSlug, + data: arrayDoc, + depth: 0, + overrideAccess: true, + }) - const formattedID = - _payload.db.defaultIDType === 'number' ? createdArrayDoc.id : `"${createdArrayDoc.id}"` + const createdAnotherArrayDoc = await _payload.create({ + collection: arrayFieldsSlug, + data: anotherArrayDoc, + depth: 0, + overrideAccess: true, + }) - const formattedJPGID = - _payload.db.defaultIDType === 'number' ? createdJPGDoc.id : `"${createdJPGDoc.id}"` + const createdTextDoc = await _payload.create({ + collection: textFieldsSlug, + data: textDoc, + depth: 0, + overrideAccess: true, + }) - const formattedTextID = - _payload.db.defaultIDType === 'number' ? createdTextDoc.id : `"${createdTextDoc.id}"` + const createdAnotherTextDoc = await _payload.create({ + collection: textFieldsSlug, + data: anotherTextDoc, + depth: 0, + overrideAccess: true, + }) - const richTextDocWithRelId = JSON.parse( - JSON.stringify(richTextDocData) - .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) - .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) - .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`), - ) - const richTextBulletsDocWithRelId = JSON.parse( - JSON.stringify(richTextBulletsDocData) - .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) - .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) - .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`), - ) + const createdPNGDoc = await _payload.create({ + collection: uploadsSlug, + data: {}, + file: pngFile, + depth: 0, + overrideAccess: true, + }) - const richTextDocWithRelationship = { ...richTextDocWithRelId } - - const blocksDocWithRichText = { - ...(blocksDoc as any), - } - - blocksDocWithRichText.blocks[0].richText = richTextDocWithRelationship.richText - blocksDocWithRichText.localizedBlocks[0].richText = richTextDocWithRelationship.richText - - await _payload.create({ - collection: richTextFieldsSlug, - data: richTextBulletsDocWithRelId, - depth: 0, - overrideAccess: true, - }) - - const createdRichTextDoc = await _payload.create({ - collection: richTextFieldsSlug, - data: richTextDocWithRelationship, - depth: 0, - overrideAccess: true, - }) - - const formattedRichTextDocID = - _payload.db.defaultIDType === 'number' - ? createdRichTextDoc.id - : `"${createdRichTextDoc.id}"` - - const lexicalDocWithRelId = JSON.parse( - JSON.stringify(lexicalDocData) - .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) - .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) - .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`) - .replace(/"\{\{RICH_TEXT_DOC_ID\}\}"/g, `${formattedRichTextDocID}`), - ) - - const lexicalMigrateDocWithRelId = JSON.parse( - JSON.stringify(lexicalMigrateDocData) - .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) - .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) - .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`) - .replace(/"\{\{RICH_TEXT_DOC_ID\}\}"/g, `${formattedRichTextDocID}`), - ) - - await executePromises( - [ - () => - _payload.create({ - collection: usersSlug, - depth: 0, - data: { - email: devUser.email, - password: devUser.password, - }, - overrideAccess: true, - }), - () => - _payload.create({ - collection: collapsibleFieldsSlug, - data: collapsibleDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: conditionalLogicSlug, - data: conditionalLogicDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: groupFieldsSlug, - data: groupDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: selectFieldsSlug, - data: selectsDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: radioFieldsSlug, - data: radiosDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: tabsFieldsSlug, - data: tabsDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: pointFieldsSlug, - data: pointDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: dateFieldsSlug, - data: dateDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: codeFieldsSlug, - data: codeDoc, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: jsonFieldsSlug, - data: jsonDoc, - depth: 0, - overrideAccess: true, - }), - - () => - _payload.create({ - collection: blockFieldsSlug, - data: blocksDocWithRichText, - depth: 0, - overrideAccess: true, - }), - - () => - _payload.create({ - collection: lexicalFieldsSlug, - data: lexicalDocWithRelId, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: lexicalMigrateFieldsSlug, - data: lexicalMigrateDocWithRelId, - depth: 0, - overrideAccess: true, - }), - - () => - _payload.create({ - collection: numberFieldsSlug, - data: { number: 2 }, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: numberFieldsSlug, - data: { number: 3 }, - depth: 0, - overrideAccess: true, - }), - () => - _payload.create({ - collection: numberFieldsSlug, - data: numberDoc, - depth: 0, - overrideAccess: true, - }), - ], - parallel, - ) + const createdJPGDoc = await _payload.create({ + collection: uploadsSlug, + data: { + ...uploadsDoc, + media: createdPNGDoc.id, }, - snapshotKey: 'fieldsTest', - uploadsDir: path.resolve(dirname, './collections/Upload/uploads'), + file: jpgFile, + depth: 0, + overrideAccess: true, + }) + + const formattedID = + _payload.db.defaultIDType === 'number' ? createdArrayDoc.id : `"${createdArrayDoc.id}"` + + const formattedJPGID = + _payload.db.defaultIDType === 'number' ? createdJPGDoc.id : `"${createdJPGDoc.id}"` + + const formattedTextID = + _payload.db.defaultIDType === 'number' ? createdTextDoc.id : `"${createdTextDoc.id}"` + + const richTextDocWithRelId = JSON.parse( + JSON.stringify(richTextDocData) + .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) + .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) + .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`), + ) + const richTextBulletsDocWithRelId = JSON.parse( + JSON.stringify(richTextBulletsDocData) + .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) + .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) + .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`), + ) + + const richTextDocWithRelationship = { ...richTextDocWithRelId } + + const blocksDocWithRichText = { + ...(blocksDoc as any), + } + + blocksDocWithRichText.blocks[0].richText = richTextDocWithRelationship.richText + blocksDocWithRichText.localizedBlocks[0].richText = richTextDocWithRelationship.richText + + await _payload.create({ + collection: richTextFieldsSlug, + data: richTextBulletsDocWithRelId, + depth: 0, + overrideAccess: true, + }) + + const createdRichTextDoc = await _payload.create({ + collection: richTextFieldsSlug, + data: richTextDocWithRelationship, + depth: 0, + overrideAccess: true, + }) + + const formattedRichTextDocID = + _payload.db.defaultIDType === 'number' ? createdRichTextDoc.id : `"${createdRichTextDoc.id}"` + + const lexicalDocWithRelId = JSON.parse( + JSON.stringify(lexicalDocData) + .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) + .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) + .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`) + .replace(/"\{\{RICH_TEXT_DOC_ID\}\}"/g, `${formattedRichTextDocID}`), + ) + + const lexicalMigrateDocWithRelId = JSON.parse( + JSON.stringify(lexicalMigrateDocData) + .replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`) + .replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`) + .replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`) + .replace(/"\{\{RICH_TEXT_DOC_ID\}\}"/g, `${formattedRichTextDocID}`), + ) + + await _payload.create({ + collection: usersSlug, + depth: 0, + data: { + email: devUser.email, + password: devUser.password, + }, + overrideAccess: true, + }) + + await _payload.create({ + collection: collapsibleFieldsSlug, + data: collapsibleDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: conditionalLogicSlug, + data: conditionalLogicDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: groupFieldsSlug, + data: groupDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: selectFieldsSlug, + data: selectsDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: radioFieldsSlug, + data: radiosDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: tabsFieldsSlug, + data: tabsDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: pointFieldsSlug, + data: pointDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: dateFieldsSlug, + data: dateDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: codeFieldsSlug, + data: codeDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: jsonFieldsSlug, + data: jsonDoc, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: blockFieldsSlug, + data: blocksDocWithRichText, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: lexicalFieldsSlug, + data: lexicalDocWithRelId, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: lexicalMigrateFieldsSlug, + data: lexicalMigrateDocWithRelId, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: numberFieldsSlug, + data: { number: 2 }, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: numberFieldsSlug, + data: { number: 3 }, + depth: 0, + overrideAccess: true, + }) + + await _payload.create({ + collection: numberFieldsSlug, + data: numberDoc, + depth: 0, + overrideAccess: true, }) } diff --git a/tsconfig.json b/tsconfig.json index 3009a940ca..5e34fd5bc9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -37,7 +37,7 @@ ], "paths": { "@payload-config": [ - "./test/fields-relationship/config.ts" + "./test/fields/config.ts" ], "@payloadcms/live-preview": [ "./packages/live-preview/src"