From 695ef32d1ee807a97c95c276637ba0d6a16ef18b Mon Sep 17 00:00:00 2001 From: Dan Ribbens Date: Tue, 30 Jul 2024 13:41:18 -0400 Subject: [PATCH] feat(db-*): add defaultValues to database schemas (#7368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Prior to this change, the `defaultValue` for fields have only been used in the application layer of Payload. With this change, you get the added benefit of having the database columns get the default also. This is especially helpful when adding new columns to postgres with existing data to avoid needing to write complex migrations. In MongoDB this change applies the default to the Mongoose model which is useful when calling payload.db.create() directly. This only works for statically defined values. 🙏 A big thanks to @r1tsuu for the feature and implementation idea as I lifted some code from PR https://github.com/payloadcms/payload/pull/6983 - [x] I have read and understand the [CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md) document in this repository. ## Type of change - [x] New feature (non-breaking change which adds functionality) - [x] This change requires a documentation update ## Checklist: - [x] I have added tests that prove my fix is effective or that my feature works - [x] Existing test suite passes locally with my changes - [x] I have made corresponding changes to the documentation --- docs/fields/overview.mdx | 4 +- packages/db-mongodb/src/models/buildSchema.ts | 22 +++++++--- packages/db-postgres/src/schema/build.ts | 1 - .../db-postgres/src/schema/traverseFields.ts | 27 ++++++------ .../db-postgres/src/schema/withDefault.ts | 17 ++++++++ .../db-sqlite/src/schema/traverseFields.ts | 16 +++---- packages/db-sqlite/src/schema/withDefault.ts | 17 ++++++++ packages/drizzle/src/count.ts | 5 +-- packages/drizzle/src/create.ts | 2 +- packages/drizzle/src/createGlobal.ts | 2 +- packages/drizzle/src/createGlobalVersion.ts | 2 +- packages/drizzle/src/createVersion.ts | 2 +- packages/drizzle/src/deleteMany.ts | 2 +- packages/drizzle/src/deleteOne.ts | 2 +- packages/drizzle/src/deleteVersions.ts | 2 +- packages/drizzle/src/update.ts | 2 +- packages/drizzle/src/updateGlobal.ts | 2 +- packages/drizzle/src/updateGlobalVersion.ts | 2 +- packages/drizzle/src/updateVersion.ts | 2 +- test/database/config.ts | 42 +++++++++++++++++++ test/database/int.spec.ts | 27 ++++++++++-- test/fields/e2e.spec.ts | 11 ++++- test/fields/int.spec.ts | 11 ++++- test/live-preview/fields/link.ts | 2 +- 24 files changed, 175 insertions(+), 49 deletions(-) create mode 100644 packages/db-postgres/src/schema/withDefault.ts create mode 100644 packages/db-sqlite/src/schema/withDefault.ts diff --git a/docs/fields/overview.mdx b/docs/fields/overview.mdx index bf02bbd50e..fcd346505c 100644 --- a/docs/fields/overview.mdx +++ b/docs/fields/overview.mdx @@ -205,7 +205,9 @@ export const MyField: Field = { } ``` -Default values can be defined as a static string or a function that returns a string. Functions are called with the following arguments: +Default values can be defined as a static value or a function that returns a value. When a `defaultValue` is defined statically, Payload's DB adapters will apply it to the database schema or models. + +Functions can be written to make use of the following argument properties: - `user` - the authenticated user object - `locale` - the currently selected locale string diff --git a/packages/db-mongodb/src/models/buildSchema.ts b/packages/db-mongodb/src/models/buildSchema.ts index 54388ecb90..f713f096a8 100644 --- a/packages/db-mongodb/src/models/buildSchema.ts +++ b/packages/db-mongodb/src/models/buildSchema.ts @@ -52,9 +52,19 @@ type FieldSchemaGenerator = ( buildSchemaOptions: BuildSchemaOptions, ) => void +/** + * get a field's defaultValue only if defined and not dynamic so that it can be set on the field schema + * @param field + */ +const formatDefaultValue = (field: FieldAffectingData) => + typeof field.defaultValue !== 'undefined' && typeof field.defaultValue !== 'function' + ? field.defaultValue + : undefined + const formatBaseSchema = (field: FieldAffectingData, buildSchemaOptions: BuildSchemaOptions) => { const { disableUnique, draftsEnabled, indexSortableFields } = buildSchemaOptions const schema: SchemaTypeOptions = { + default: formatDefaultValue(field), index: field.index || (!disableUnique && field.unique) || indexSortableFields || false, required: false, unique: (!disableUnique && field.unique) || false, @@ -159,7 +169,6 @@ const fieldToSchemaMap: Record = { }, }), ], - default: undefined, } schema.add({ @@ -174,7 +183,6 @@ const fieldToSchemaMap: Record = { ): void => { const fieldSchema = { type: [new mongoose.Schema({}, { _id: false, discriminatorKey: 'blockType' })], - default: undefined, } schema.add({ @@ -339,7 +347,7 @@ const fieldToSchemaMap: Record = { }, coordinates: { type: [Number], - default: field.defaultValue || undefined, + default: formatDefaultValue(field), required: false, }, } @@ -420,7 +428,9 @@ const fieldToSchemaMap: Record = { return { ...locales, - [locale]: field.hasMany ? { type: [localeSchema], default: undefined } : localeSchema, + [locale]: field.hasMany + ? { type: [localeSchema], default: formatDefaultValue(field) } + : localeSchema, } }, {}), localized: true, @@ -440,7 +450,7 @@ const fieldToSchemaMap: Record = { if (field.hasMany) { schemaToReturn = { type: [schemaToReturn], - default: undefined, + default: formatDefaultValue(field), } } } else { @@ -453,7 +463,7 @@ const fieldToSchemaMap: Record = { if (field.hasMany) { schemaToReturn = { type: [schemaToReturn], - default: undefined, + default: formatDefaultValue(field), } } } diff --git a/packages/db-postgres/src/schema/build.ts b/packages/db-postgres/src/schema/build.ts index f8391af768..0e814abff2 100644 --- a/packages/db-postgres/src/schema/build.ts +++ b/packages/db-postgres/src/schema/build.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-param-reassign */ import type { Relation } from 'drizzle-orm' import type { ForeignKeyBuilder, diff --git a/packages/db-postgres/src/schema/traverseFields.ts b/packages/db-postgres/src/schema/traverseFields.ts index be46f665c9..5d014495d4 100644 --- a/packages/db-postgres/src/schema/traverseFields.ts +++ b/packages/db-postgres/src/schema/traverseFields.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-param-reassign */ import type { Relation } from 'drizzle-orm' import type { IndexBuilder, PgColumnBuilder } from 'drizzle-orm/pg-core' import type { Field, TabAsField } from 'payload' @@ -35,6 +34,7 @@ import { buildTable } from './build.js' import { createIndex } from './createIndex.js' import { idToUUID } from './idToUUID.js' import { parentIDColumnMap } from './parentIDColumnMap.js' +import { withDefault } from './withDefault.js' type Args = { adapter: PostgresAdapter @@ -170,14 +170,14 @@ export const traverseFields = ({ ) } } else { - targetTable[fieldName] = varchar(columnName) + targetTable[fieldName] = withDefault(varchar(columnName), field) } break } case 'email': case 'code': case 'textarea': { - targetTable[fieldName] = varchar(columnName) + targetTable[fieldName] = withDefault(varchar(columnName), field) break } @@ -199,23 +199,26 @@ export const traverseFields = ({ ) } } else { - targetTable[fieldName] = numeric(columnName) + targetTable[fieldName] = withDefault(numeric(columnName), field) } break } case 'richText': case 'json': { - targetTable[fieldName] = jsonb(columnName) + targetTable[fieldName] = withDefault(jsonb(columnName), field) break } case 'date': { - targetTable[fieldName] = timestamp(columnName, { - mode: 'string', - precision: 3, - withTimezone: true, - }) + targetTable[fieldName] = withDefault( + timestamp(columnName, { + mode: 'string', + precision: 3, + withTimezone: true, + }), + field, + ) break } @@ -311,13 +314,13 @@ export const traverseFields = ({ }), ) } else { - targetTable[fieldName] = adapter.enums[enumName](fieldName) + targetTable[fieldName] = withDefault(adapter.enums[enumName](fieldName), field) } break } case 'checkbox': { - targetTable[fieldName] = boolean(columnName) + targetTable[fieldName] = withDefault(boolean(columnName), field) break } diff --git a/packages/db-postgres/src/schema/withDefault.ts b/packages/db-postgres/src/schema/withDefault.ts new file mode 100644 index 0000000000..1214c52e3a --- /dev/null +++ b/packages/db-postgres/src/schema/withDefault.ts @@ -0,0 +1,17 @@ +import type { PgColumnBuilder } from 'drizzle-orm/pg-core' +import type { FieldAffectingData } from 'payload' + +export const withDefault = ( + column: PgColumnBuilder, + field: FieldAffectingData, +): PgColumnBuilder => { + if (typeof field.defaultValue === 'undefined' || typeof field.defaultValue === 'function') + return column + + if (typeof field.defaultValue === 'string' && field.defaultValue.includes("'")) { + const escapedString = field.defaultValue.replaceAll("'", "''") + return column.default(escapedString) + } + + return column.default(field.defaultValue) +} diff --git a/packages/db-sqlite/src/schema/traverseFields.ts b/packages/db-sqlite/src/schema/traverseFields.ts index 2f4f95524d..5f6ff8841f 100644 --- a/packages/db-sqlite/src/schema/traverseFields.ts +++ b/packages/db-sqlite/src/schema/traverseFields.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-param-reassign */ import type { Relation } from 'drizzle-orm' import type { IndexBuilder, SQLiteColumnBuilder } from 'drizzle-orm/sqlite-core' import type { Field, TabAsField } from 'payload' @@ -30,6 +29,7 @@ import { buildTable } from './build.js' import { createIndex } from './createIndex.js' import { getIDColumn } from './getIDColumn.js' import { idToUUID } from './idToUUID.js' +import { withDefault } from './withDefault.js' type Args = { adapter: SQLiteAdapter @@ -166,14 +166,14 @@ export const traverseFields = ({ ) } } else { - targetTable[fieldName] = text(columnName) + targetTable[fieldName] = withDefault(text(columnName), field) } break } case 'email': case 'code': case 'textarea': { - targetTable[fieldName] = text(columnName) + targetTable[fieldName] = withDefault(text(columnName), field) break } @@ -195,19 +195,19 @@ export const traverseFields = ({ ) } } else { - targetTable[fieldName] = numeric(columnName) + targetTable[fieldName] = withDefault(numeric(columnName), field) } break } case 'richText': case 'json': { - targetTable[fieldName] = text(columnName, { mode: 'json' }) + targetTable[fieldName] = withDefault(text(columnName, { mode: 'json' }), field) break } case 'date': { - targetTable[fieldName] = text(columnName) + targetTable[fieldName] = withDefault(text(columnName), field) break } @@ -295,13 +295,13 @@ export const traverseFields = ({ }), ) } else { - targetTable[fieldName] = text(fieldName, { enum: options }) + targetTable[fieldName] = withDefault(text(fieldName, { enum: options }), field) } break } case 'checkbox': { - targetTable[fieldName] = integer(columnName, { mode: 'boolean' }) + targetTable[fieldName] = withDefault(integer(columnName, { mode: 'boolean' }), field) break } diff --git a/packages/db-sqlite/src/schema/withDefault.ts b/packages/db-sqlite/src/schema/withDefault.ts new file mode 100644 index 0000000000..beb974e043 --- /dev/null +++ b/packages/db-sqlite/src/schema/withDefault.ts @@ -0,0 +1,17 @@ +import type { SQLiteColumnBuilder } from 'drizzle-orm/sqlite-core' +import type { FieldAffectingData } from 'payload' + +export const withDefault = ( + column: SQLiteColumnBuilder, + field: FieldAffectingData, +): SQLiteColumnBuilder => { + if (typeof field.defaultValue === 'undefined' || typeof field.defaultValue === 'function') + return column + + if (typeof field.defaultValue === 'string' && field.defaultValue.includes("'")) { + const escapedString = field.defaultValue.replaceAll("'", "''") + return column.default(escapedString) + } + + return column.default(field.defaultValue) +} diff --git a/packages/drizzle/src/count.ts b/packages/drizzle/src/count.ts index 10d080d878..c2048d261c 100644 --- a/packages/drizzle/src/count.ts +++ b/packages/drizzle/src/count.ts @@ -1,5 +1,4 @@ -import type { Count } from 'payload' -import type { SanitizedCollectionConfig } from 'payload' +import type { Count , SanitizedCollectionConfig } from 'payload' import toSnakeCase from 'to-snake-case' @@ -15,7 +14,7 @@ export const count: Count = async function count( const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)) - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const { joins, where } = await buildQuery({ adapter: this, diff --git a/packages/drizzle/src/create.ts b/packages/drizzle/src/create.ts index 07048a28ee..7ab4679aec 100644 --- a/packages/drizzle/src/create.ts +++ b/packages/drizzle/src/create.ts @@ -10,7 +10,7 @@ export const create: Create = async function create( this: DrizzleAdapter, { collection: collectionSlug, data, req }, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config const tableName = this.tableNameMap.get(toSnakeCase(collection.slug)) diff --git a/packages/drizzle/src/createGlobal.ts b/packages/drizzle/src/createGlobal.ts index da3710ff4b..18b7dc7b88 100644 --- a/packages/drizzle/src/createGlobal.ts +++ b/packages/drizzle/src/createGlobal.ts @@ -10,7 +10,7 @@ export async function createGlobal>( this: DrizzleAdapter, { slug, data, req = {} as PayloadRequest }: CreateGlobalArgs, ): Promise { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const globalConfig = this.payload.globals.config.find((config) => config.slug === slug) const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug)) diff --git a/packages/drizzle/src/createGlobalVersion.ts b/packages/drizzle/src/createGlobalVersion.ts index a82b8559f7..810be5af68 100644 --- a/packages/drizzle/src/createGlobalVersion.ts +++ b/packages/drizzle/src/createGlobalVersion.ts @@ -12,7 +12,7 @@ export async function createGlobalVersion( this: DrizzleAdapter, { autosave, globalSlug, req = {} as PayloadRequest, versionData }: CreateGlobalVersionArgs, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const global = this.payload.globals.config.find(({ slug }) => slug === globalSlug) const tableName = this.tableNameMap.get(`_${toSnakeCase(global.slug)}${this.versionsSuffix}`) diff --git a/packages/drizzle/src/createVersion.ts b/packages/drizzle/src/createVersion.ts index afa12721d5..3e0c8c15bc 100644 --- a/packages/drizzle/src/createVersion.ts +++ b/packages/drizzle/src/createVersion.ts @@ -18,7 +18,7 @@ export async function createVersion( versionData, }: CreateVersionArgs, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config const defaultTableName = toSnakeCase(collection.slug) diff --git a/packages/drizzle/src/deleteMany.ts b/packages/drizzle/src/deleteMany.ts index 389f8bc301..7d0637fe34 100644 --- a/packages/drizzle/src/deleteMany.ts +++ b/packages/drizzle/src/deleteMany.ts @@ -11,7 +11,7 @@ export const deleteMany: DeleteMany = async function deleteMany( this: DrizzleAdapter, { collection, req = {} as PayloadRequest, where }, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collectionConfig = this.payload.collections[collection].config const tableName = this.tableNameMap.get(toSnakeCase(collectionConfig.slug)) diff --git a/packages/drizzle/src/deleteOne.ts b/packages/drizzle/src/deleteOne.ts index daee86249a..8a73eabf12 100644 --- a/packages/drizzle/src/deleteOne.ts +++ b/packages/drizzle/src/deleteOne.ts @@ -14,7 +14,7 @@ export const deleteOne: DeleteOne = async function deleteOne( this: DrizzleAdapter, { collection: collectionSlug, req = {} as PayloadRequest, where: whereArg }, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config const tableName = this.tableNameMap.get(toSnakeCase(collection.slug)) diff --git a/packages/drizzle/src/deleteVersions.ts b/packages/drizzle/src/deleteVersions.ts index 9d8320a745..69504bc235 100644 --- a/packages/drizzle/src/deleteVersions.ts +++ b/packages/drizzle/src/deleteVersions.ts @@ -12,7 +12,7 @@ export const deleteVersions: DeleteVersions = async function deleteVersion( this: DrizzleAdapter, { collection, locale, req = {} as PayloadRequest, where: where }, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const tableName = this.tableNameMap.get( diff --git a/packages/drizzle/src/update.ts b/packages/drizzle/src/update.ts index a3a8849a25..1e9e506c85 100644 --- a/packages/drizzle/src/update.ts +++ b/packages/drizzle/src/update.ts @@ -12,7 +12,7 @@ export const updateOne: UpdateOne = async function updateOne( this: DrizzleAdapter, { id, collection: collectionSlug, data, draft, locale, req, where: whereArg }, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collection = this.payload.collections[collectionSlug].config const tableName = this.tableNameMap.get(toSnakeCase(collection.slug)) const whereToUse = whereArg || { id: { equals: id } } diff --git a/packages/drizzle/src/updateGlobal.ts b/packages/drizzle/src/updateGlobal.ts index 974c1b13c7..ccb13d47a6 100644 --- a/packages/drizzle/src/updateGlobal.ts +++ b/packages/drizzle/src/updateGlobal.ts @@ -10,7 +10,7 @@ export async function updateGlobal>( this: DrizzleAdapter, { slug, data, req = {} as PayloadRequest }: UpdateGlobalArgs, ): Promise { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const globalConfig = this.payload.globals.config.find((config) => config.slug === slug) const tableName = this.tableNameMap.get(toSnakeCase(globalConfig.slug)) diff --git a/packages/drizzle/src/updateGlobalVersion.ts b/packages/drizzle/src/updateGlobalVersion.ts index 39e097bd6b..ff6352f211 100644 --- a/packages/drizzle/src/updateGlobalVersion.ts +++ b/packages/drizzle/src/updateGlobalVersion.ts @@ -25,7 +25,7 @@ export async function updateGlobalVersion( where: whereArg, }: UpdateGlobalVersionArgs, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const globalConfig: SanitizedGlobalConfig = this.payload.globals.config.find( ({ slug }) => slug === global, ) diff --git a/packages/drizzle/src/updateVersion.ts b/packages/drizzle/src/updateVersion.ts index 2a0f0f4836..5f922ec0a4 100644 --- a/packages/drizzle/src/updateVersion.ts +++ b/packages/drizzle/src/updateVersion.ts @@ -25,7 +25,7 @@ export async function updateVersion( where: whereArg, }: UpdateVersionArgs, ) { - const db = this.sessions[await req.transactionID]?.db || this.drizzle + const db = this.sessions[await req?.transactionID]?.db || this.drizzle const collectionConfig: SanitizedCollectionConfig = this.payload.collections[collection].config const whereToUse = whereArg || { id: { equals: id } } const tableName = this.tableNameMap.get( diff --git a/test/database/config.ts b/test/database/config.ts index 2685a1f841..a6c6d5631b 100644 --- a/test/database/config.ts +++ b/test/database/config.ts @@ -2,9 +2,17 @@ import { fileURLToPath } from 'node:url' import path from 'path' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) +import type { TextField } from 'payload' + import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js' import { devUser } from '../credentials.js' +const defaultValueField: TextField = { + name: 'defaultValue', + type: 'text', + defaultValue: 'default value from database', +} + export default buildConfigWithDefaults({ collections: [ { @@ -46,6 +54,40 @@ export default buildConfigWithDefaults({ ], }, }, + { + slug: 'default-values', + fields: [ + { + name: 'title', + type: 'text', + }, + defaultValueField, + { + name: 'array', + type: 'array', + // default array with one object to test subfield defaultValue properties for Mongoose + defaultValue: [{}], + fields: [defaultValueField], + }, + { + name: 'group', + type: 'group', + // we need to have to use as default in order to have subfield defaultValue properties directly for Mongoose + defaultValue: {}, + fields: [defaultValueField], + }, + { + name: 'select', + type: 'select', + defaultValue: 'default', + options: [ + { value: 'option0', label: 'Option 0' }, + { value: 'option1', label: 'Option 1' }, + { value: 'default', label: 'Default' }, + ], + }, + ], + }, { slug: 'relation-a', fields: [ diff --git a/test/database/int.spec.ts b/test/database/int.spec.ts index 2c969f16b3..a976034a5b 100644 --- a/test/database/int.spec.ts +++ b/test/database/int.spec.ts @@ -89,11 +89,10 @@ describe('database', () => { }) it('should allow createdAt to be set in create', async () => { - const createdAt = new Date('2021-01-01T00:00:00.000Z') + const createdAt = new Date('2021-01-01T00:00:00.000Z').toISOString() const result = await payload.create({ collection: 'posts', data: { - // TODO: createdAt should be optional on RequiredDataFromCollectionSlug createdAt, title: 'hello', }, @@ -104,8 +103,8 @@ describe('database', () => { collection: 'posts', }) - expect(result.createdAt).toStrictEqual(createdAt.toISOString()) - expect(doc.createdAt).toStrictEqual(createdAt.toISOString()) + expect(result.createdAt).toStrictEqual(createdAt) + expect(doc.createdAt).toStrictEqual(createdAt) }) it('updatedAt cannot be set in create', async () => { @@ -461,4 +460,24 @@ describe('database', () => { }) }) }) + + describe('defaultValue', () => { + it('should set default value from db.create', async () => { + // call the db adapter create directly to bypass Payload's default value assignment + const result = await payload.db.create({ + collection: 'default-values', + data: { + // for drizzle DBs, we need to pass an array of objects to test subfields + array: [{ id: 1 }], + title: 'hello', + }, + req: undefined, + }) + + expect(result.defaultValue).toStrictEqual('default value from database') + expect(result.array[0].defaultValue).toStrictEqual('default value from database') + expect(result.group.defaultValue).toStrictEqual('default value from database') + expect(result.select).toStrictEqual('default') + }) + }) }) diff --git a/test/fields/e2e.spec.ts b/test/fields/e2e.spec.ts index a013bab6f5..969eb76683 100644 --- a/test/fields/e2e.spec.ts +++ b/test/fields/e2e.spec.ts @@ -76,17 +76,26 @@ describe('fields', () => { // TODO - This test is flaky. Rarely, but sometimes it randomly fails. test('should display unique constraint error in ui', async () => { const uniqueText = 'uniqueText' - await payload.create({ + const doc = await payload.create({ collection: 'indexed-fields', data: { group: { unique: uniqueText, }, + localizedUniqueRequiredText: 'text', text: 'text', uniqueRequiredText: 'text', uniqueText, }, }) + await payload.update({ + id: doc.id, + collection: 'indexed-fields', + data: { + localizedUniqueRequiredText: 'es text', + }, + locale: 'es', + }) await page.goto(url.create) await page.waitForURL(url.create) diff --git a/test/fields/int.spec.ts b/test/fields/int.spec.ts index 1691ead079..1de61d01ee 100644 --- a/test/fields/int.spec.ts +++ b/test/fields/int.spec.ts @@ -700,10 +700,19 @@ describe('Fields', () => { uniqueRequiredText: 'a', // uniqueText omitted on purpose } - await payload.create({ + const doc = await payload.create({ collection: 'indexed-fields', data, }) + // Update spanish so we do not run into the unique constraint for other locales + await payload.update({ + id: doc.id, + collection: 'indexed-fields', + data: { + localizedUniqueRequiredText: 'es1', + }, + locale: 'es', + }) data.uniqueRequiredText = 'b' const result = await payload.create({ collection: 'indexed-fields', diff --git a/test/live-preview/fields/link.ts b/test/live-preview/fields/link.ts index aa7d00aa75..15bfbaf3f2 100644 --- a/test/live-preview/fields/link.ts +++ b/test/live-preview/fields/link.ts @@ -137,7 +137,7 @@ const link: LinkType = ({ appearances, disableLabel = false, overrides = {} } = linkResult.fields.push({ name: 'appearance', type: 'select', - defaultValue: 'default', + defaultValue: appearanceOptionsToUse[0].value, options: appearanceOptionsToUse, admin: { description: 'Choose how the link should be rendered.',