chore: improve test suites, upgrade jest and playwright, add debug utilities for lexical (#4011)
* feat(richtext-lexical): 'bottom' position value for plugins * feat: TestRecorderFeature * chore: restructuring to seed and clear db before each test * chore: make sure all tests pass * chore: make sure indexes are created in seed.ts - this fixes one erroring test * chore: speed up test runs through db snapshots * chore: support drizzle when resetting db * chore: simplify seeding process, by moving boilerplate db reset / snapshot logic into a wrapper function * chore: add new seeding process to admin test suite * chore(deps): upgrade jest and playwright * chore: make sure mongoose-specific tests are not skipped * chore: fix point test, which was depending on another test (that's bad!) * chore: fix incorrect import * chore: remove unnecessary comments * chore: clearly label lexicalE2E test file as todo * chore: simplify seed logic * chore: move versions test suite to new seed system
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { arrayFieldsSlug } from '../../slugs'
|
||||
import { ArrayRowLabel } from './LabelComponent'
|
||||
|
||||
export const arrayDefaultValue = [{ text: 'row one' }, { text: 'row two' }]
|
||||
|
||||
export const arrayFieldsSlug = 'array-fields'
|
||||
|
||||
const ArrayFields: CollectionConfig = {
|
||||
slug: arrayFieldsSlug,
|
||||
admin: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
import type { BlockField } from '../../../../packages/payload/src/fields/config/types'
|
||||
|
||||
import { blockFieldsSlug } from '../../slugs'
|
||||
import { AddCustomBlocks } from './components/AddCustomBlocks'
|
||||
|
||||
export const getBlocksFieldSeedData = (prefix?: string): any => [
|
||||
@@ -149,7 +150,7 @@ export const getBlocksField = (prefix?: string): BlockField => ({
|
||||
})
|
||||
|
||||
const BlockFields: CollectionConfig = {
|
||||
slug: 'block-fields',
|
||||
slug: blockFieldsSlug,
|
||||
fields: [
|
||||
getBlocksField(),
|
||||
{
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { checkboxFieldsSlug } from '../../slugs'
|
||||
|
||||
const CheckboxFields: CollectionConfig = {
|
||||
slug: 'checkbox-fields',
|
||||
slug: checkboxFieldsSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'checkbox',
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
import type { CodeField } from '../../payload-types'
|
||||
|
||||
import { codeFieldsSlug } from '../../slugs'
|
||||
|
||||
const Code: CollectionConfig = {
|
||||
fields: [
|
||||
{
|
||||
@@ -39,7 +41,7 @@ const Code: CollectionConfig = {
|
||||
type: 'code',
|
||||
},
|
||||
],
|
||||
slug: 'code-fields',
|
||||
slug: codeFieldsSlug,
|
||||
}
|
||||
|
||||
export const codeDoc: Partial<CodeField> = {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { collapsibleFieldsSlug } from '../../slugs'
|
||||
import { CollapsibleLabelComponent } from './LabelComponent'
|
||||
import { collapsibleFieldsSlug } from './shared'
|
||||
|
||||
const CollapsibleFields: CollectionConfig = {
|
||||
slug: collapsibleFieldsSlug,
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export const collapsibleFieldsSlug = 'collapsible-fields'
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { conditionalLogicSlug } from '../../slugs'
|
||||
|
||||
const ConditionalLogic: CollectionConfig = {
|
||||
slug: 'conditional-logic',
|
||||
slug: conditionalLogicSlug,
|
||||
admin: {
|
||||
useAsTitle: 'text',
|
||||
},
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { dateFieldsSlug } from '../../slugs'
|
||||
|
||||
export const defaultText = 'default-text'
|
||||
|
||||
const DateFields: CollectionConfig = {
|
||||
slug: 'date-fields',
|
||||
slug: dateFieldsSlug,
|
||||
admin: {
|
||||
useAsTitle: 'default',
|
||||
},
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { groupFieldsSlug } from '../../slugs'
|
||||
|
||||
export const groupDefaultValue = 'set from parent'
|
||||
export const groupDefaultChild = 'child takes priority'
|
||||
export const groupFieldsSlug = 'group-fields'
|
||||
|
||||
const GroupFields: CollectionConfig = {
|
||||
slug: groupFieldsSlug,
|
||||
|
||||
@@ -4,6 +4,8 @@ import type {
|
||||
} from '../../../../packages/payload/src/collections/config/types'
|
||||
import type { IndexedField } from '../../payload-types'
|
||||
|
||||
import { indexedFieldsSlug } from '../../slugs'
|
||||
|
||||
const beforeDuplicate: BeforeDuplicate<IndexedField> = ({ data }) => {
|
||||
return {
|
||||
...data,
|
||||
@@ -22,7 +24,7 @@ const beforeDuplicate: BeforeDuplicate<IndexedField> = ({ data }) => {
|
||||
}
|
||||
|
||||
const IndexedFields: CollectionConfig = {
|
||||
slug: 'indexed-fields',
|
||||
slug: indexedFieldsSlug,
|
||||
// used to assert that versions also get indexes
|
||||
admin: {
|
||||
hooks: {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { jsonFieldsSlug } from '../../slugs'
|
||||
|
||||
type JSONField = {
|
||||
createdAt: string
|
||||
id: string
|
||||
@@ -17,7 +19,7 @@ const JSON: CollectionConfig = {
|
||||
type: 'json',
|
||||
},
|
||||
],
|
||||
slug: 'json-fields',
|
||||
slug: jsonFieldsSlug,
|
||||
versions: {
|
||||
maxPerDoc: 1,
|
||||
},
|
||||
|
||||
8
test/fields/collections/Lexical/data.ts
Normal file
8
test/fields/collections/Lexical/data.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { generateLexicalRichText } from './generateLexicalRichText'
|
||||
import { payloadPluginLexicalData } from './generatePayloadPluginLexicalData'
|
||||
|
||||
export const lexicalRichTextDoc = {
|
||||
title: 'Rich Text',
|
||||
richTextLexicalCustomFields: generateLexicalRichText(),
|
||||
richTextLexicalWithLexicalPluginData: payloadPluginLexicalData,
|
||||
}
|
||||
@@ -5,10 +5,12 @@ import {
|
||||
HTMLConverterFeature,
|
||||
LexicalPluginToLexicalFeature,
|
||||
LinkFeature,
|
||||
TestRecorderFeature,
|
||||
TreeviewFeature,
|
||||
UploadFeature,
|
||||
lexicalEditor,
|
||||
} from '../../../../packages/richtext-lexical/src'
|
||||
import { lexicalFieldsSlug } from '../../slugs'
|
||||
import {
|
||||
RelationshipBlock,
|
||||
RichTextBlock,
|
||||
@@ -21,7 +23,7 @@ import { generateLexicalRichText } from './generateLexicalRichText'
|
||||
import { payloadPluginLexicalData } from './generatePayloadPluginLexicalData'
|
||||
|
||||
export const LexicalFields: CollectionConfig = {
|
||||
slug: 'lexical-fields',
|
||||
slug: lexicalFieldsSlug,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
listSearchableFields: ['title', 'richTextLexicalCustomFields'],
|
||||
@@ -35,6 +37,27 @@ export const LexicalFields: CollectionConfig = {
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'richTextLexicalSimple',
|
||||
type: 'richText',
|
||||
editor: lexicalEditor({
|
||||
features: ({ defaultFeatures }) => [
|
||||
...defaultFeatures,
|
||||
TestRecorderFeature(),
|
||||
TreeviewFeature(),
|
||||
BlocksFeature({
|
||||
blocks: [
|
||||
RichTextBlock,
|
||||
TextBlock,
|
||||
UploadAndRichTextBlock,
|
||||
SelectFieldBlock,
|
||||
RelationshipBlock,
|
||||
SubBlockBlock,
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: 'richTextLexicalCustomFields',
|
||||
type: 'richText',
|
||||
@@ -42,6 +65,7 @@ export const LexicalFields: CollectionConfig = {
|
||||
editor: lexicalEditor({
|
||||
features: ({ defaultFeatures }) => [
|
||||
...defaultFeatures,
|
||||
TestRecorderFeature(),
|
||||
TreeviewFeature(),
|
||||
HTMLConverterFeature(),
|
||||
LinkFeature({
|
||||
@@ -126,9 +150,3 @@ export const LexicalFields: CollectionConfig = {
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const LexicalRichTextDoc = {
|
||||
title: 'Rich Text',
|
||||
richTextLexicalCustomFields: generateLexicalRichText(),
|
||||
richTextLexicalWithLexicalPluginData: payloadPluginLexicalData,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,958 @@
|
||||
export const payloadPluginLexicalData = {
|
||||
words: 49,
|
||||
preview:
|
||||
'paragraph text bold italic underline and all subscript superscript code internal link external link…',
|
||||
comments: [],
|
||||
characters: 493,
|
||||
jsonContent: {
|
||||
root: {
|
||||
type: 'root',
|
||||
format: '',
|
||||
indent: 0,
|
||||
version: 1,
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'paragraph text ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 1,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'bold',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 2,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'italic',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 8,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'underline',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' and ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 11,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'all',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 32,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'subscript',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 64,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'superscript',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 16,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'code',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'internal link',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'link',
|
||||
version: 2,
|
||||
attributes: {
|
||||
newTab: true,
|
||||
linkType: 'internal',
|
||||
doc: {
|
||||
value: '{{TEXT_DOC_ID}}',
|
||||
relationTo: 'text-fields',
|
||||
data: {}, // populated data
|
||||
},
|
||||
text: 'internal link',
|
||||
},
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'external link',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'link',
|
||||
version: 2,
|
||||
attributes: {
|
||||
newTab: true,
|
||||
nofollow: false,
|
||||
url: 'https://fewfwef.de',
|
||||
linkType: 'custom',
|
||||
text: 'external link',
|
||||
},
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: ' s. ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 4,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'strikethrough',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'heading 1',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'heading',
|
||||
version: 1,
|
||||
tag: 'h1',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'heading 2',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'heading',
|
||||
version: 1,
|
||||
tag: 'h2',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'bullet list ',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'item 2',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'item 3',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'list',
|
||||
version: 1,
|
||||
listType: 'bullet',
|
||||
start: 1,
|
||||
tag: 'ul',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'ordered list',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'item 2',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'item 3',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'list',
|
||||
version: 1,
|
||||
listType: 'number',
|
||||
start: 1,
|
||||
tag: 'ol',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'check list',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'item 2',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'item 3',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'listitem',
|
||||
version: 1,
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'list',
|
||||
version: 1,
|
||||
listType: 'check',
|
||||
start: 1,
|
||||
tag: 'ul',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'quoteeee',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'quote',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'code block line ',
|
||||
type: 'code-highlight',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '1',
|
||||
type: 'code-highlight',
|
||||
version: 1,
|
||||
highlightType: 'number',
|
||||
},
|
||||
{
|
||||
type: 'linebreak',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'code block line ',
|
||||
type: 'code-highlight',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '2',
|
||||
type: 'code-highlight',
|
||||
version: 1,
|
||||
highlightType: 'number',
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'code',
|
||||
version: 1,
|
||||
language: 'javascript',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'Upload:',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
type: 'upload',
|
||||
version: 1,
|
||||
rawImagePayload: {
|
||||
value: {
|
||||
id: '{{UPLOAD_DOC_ID}}',
|
||||
},
|
||||
relationTo: 'uploads',
|
||||
},
|
||||
caption: {
|
||||
editorState: {
|
||||
root: {
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'upload caption',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'root',
|
||||
version: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
showCaption: true,
|
||||
data: {}, // populated upload data
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '2x2 table top left',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'tablecell',
|
||||
version: 1,
|
||||
colSpan: 1,
|
||||
rowSpan: 1,
|
||||
backgroundColor: null,
|
||||
headerState: 3,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '2x2 table top right',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'tablecell',
|
||||
version: 1,
|
||||
colSpan: 1,
|
||||
rowSpan: 1,
|
||||
backgroundColor: null,
|
||||
headerState: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'tablerow',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '2x2 table bottom left',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'tablecell',
|
||||
version: 1,
|
||||
colSpan: 1,
|
||||
rowSpan: 1,
|
||||
backgroundColor: null,
|
||||
headerState: 2,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '2x2 table bottom right',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'tablecell',
|
||||
version: 1,
|
||||
colSpan: 1,
|
||||
rowSpan: 1,
|
||||
backgroundColor: null,
|
||||
headerState: 0,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'tablerow',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'table',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
rows: [
|
||||
{
|
||||
cells: [
|
||||
{
|
||||
colSpan: 1,
|
||||
id: 'kafuj',
|
||||
json: '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}',
|
||||
type: 'header',
|
||||
width: null,
|
||||
},
|
||||
{
|
||||
colSpan: 1,
|
||||
id: 'iussu',
|
||||
json: '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}',
|
||||
type: 'header',
|
||||
width: null,
|
||||
},
|
||||
],
|
||||
height: null,
|
||||
id: 'tnied',
|
||||
},
|
||||
{
|
||||
cells: [
|
||||
{
|
||||
colSpan: 1,
|
||||
id: 'hpnnv',
|
||||
json: '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}',
|
||||
type: 'header',
|
||||
width: null,
|
||||
},
|
||||
{
|
||||
colSpan: 1,
|
||||
id: 'ndteg',
|
||||
json: '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}',
|
||||
type: 'normal',
|
||||
width: null,
|
||||
},
|
||||
],
|
||||
height: null,
|
||||
id: 'rxyey',
|
||||
},
|
||||
{
|
||||
cells: [
|
||||
{
|
||||
colSpan: 1,
|
||||
id: 'rtueq',
|
||||
json: '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}',
|
||||
type: 'header',
|
||||
width: null,
|
||||
},
|
||||
{
|
||||
colSpan: 1,
|
||||
id: 'vrzoi',
|
||||
json: '{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}',
|
||||
type: 'normal',
|
||||
width: null,
|
||||
},
|
||||
],
|
||||
height: null,
|
||||
id: 'qzglv',
|
||||
},
|
||||
],
|
||||
type: 'tablesheet',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'youtube:',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
format: '',
|
||||
type: 'youtube',
|
||||
version: 1,
|
||||
videoID: '3Nwt3qu0_UY',
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
equation: '3+3',
|
||||
inline: true,
|
||||
type: 'equation',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'collapsible title',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'collapsible-title',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: 'collabsible conteent',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'collapsible-content',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'collapsible-container',
|
||||
version: 1,
|
||||
open: true,
|
||||
},
|
||||
{
|
||||
children: [],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
{
|
||||
type: 'horizontalrule',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: 'ltr',
|
||||
},
|
||||
},
|
||||
}
|
||||
73
test/fields/collections/LexicalMigrate/index.ts
Normal file
73
test/fields/collections/LexicalMigrate/index.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import {
|
||||
LexicalPluginToLexicalFeature,
|
||||
LinkFeature,
|
||||
TreeviewFeature,
|
||||
UploadFeature,
|
||||
lexicalEditor,
|
||||
} from '../../../../packages/richtext-lexical/src'
|
||||
import { lexicalMigrateFieldsSlug } from '../../slugs'
|
||||
import { payloadPluginLexicalData } from './generatePayloadPluginLexicalData'
|
||||
|
||||
export const LexicalMigrateFields: CollectionConfig = {
|
||||
slug: lexicalMigrateFieldsSlug,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
listSearchableFields: ['title', 'richTextLexicalCustomFields'],
|
||||
},
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'richTextLexicalWithLexicalPluginData',
|
||||
type: 'richText',
|
||||
editor: lexicalEditor({
|
||||
features: ({ defaultFeatures }) => [
|
||||
...defaultFeatures,
|
||||
LexicalPluginToLexicalFeature(),
|
||||
TreeviewFeature(),
|
||||
LinkFeature({
|
||||
fields: [
|
||||
{
|
||||
name: 'rel',
|
||||
label: 'Rel Attribute',
|
||||
type: 'select',
|
||||
hasMany: true,
|
||||
options: ['noopener', 'noreferrer', 'nofollow'],
|
||||
admin: {
|
||||
description:
|
||||
'The rel attribute defines the relationship between a linked resource and the current document. This is a custom link field.',
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
UploadFeature({
|
||||
collections: {
|
||||
uploads: {
|
||||
fields: [
|
||||
{
|
||||
name: 'caption',
|
||||
type: 'richText',
|
||||
editor: lexicalEditor(),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
}),
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const LexicalRichTextDoc = {
|
||||
title: 'Rich Text',
|
||||
richTextLexicalWithLexicalPluginData: payloadPluginLexicalData,
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { numberFieldsSlug } from '../../slugs'
|
||||
|
||||
export const defaultNumber = 5
|
||||
|
||||
const NumberFields: CollectionConfig = {
|
||||
slug: 'number-fields',
|
||||
slug: numberFieldsSlug,
|
||||
admin: {
|
||||
useAsTitle: 'number',
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
export const pointFieldsSlug = 'point-fields'
|
||||
import { pointFieldsSlug } from '../../slugs'
|
||||
|
||||
const PointFields: CollectionConfig = {
|
||||
slug: pointFieldsSlug,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { radioFieldsSlug } from '../../slugs'
|
||||
|
||||
const RadioFields: CollectionConfig = {
|
||||
slug: 'radio-fields',
|
||||
slug: radioFieldsSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'radio',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
export const relationshipFieldsSlug = 'relationship-fields'
|
||||
import { relationshipFieldsSlug } from '../../slugs'
|
||||
|
||||
const RelationshipFields: CollectionConfig = {
|
||||
fields: [
|
||||
|
||||
135
test/fields/collections/RichText/data.ts
Normal file
135
test/fields/collections/RichText/data.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
import { generateLexicalRichText } from './generateLexicalRichText'
|
||||
import { generateSlateRichText } from './generateSlateRichText'
|
||||
|
||||
export const richTextBlocks = [
|
||||
{
|
||||
blockType: 'textBlock',
|
||||
text: 'Regular text',
|
||||
},
|
||||
{
|
||||
blockType: 'richTextBlock',
|
||||
text: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'Rich text',
|
||||
},
|
||||
],
|
||||
type: 'h1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
export const richTextDoc = {
|
||||
title: 'Rich Text',
|
||||
selectHasMany: ['one', 'five'],
|
||||
richText: generateSlateRichText(),
|
||||
richTextReadOnly: generateSlateRichText(),
|
||||
richTextCustomFields: generateSlateRichText(),
|
||||
richTextLexicalCustomFields: generateLexicalRichText(),
|
||||
blocks: richTextBlocks,
|
||||
}
|
||||
|
||||
export const richTextBulletsDoc = {
|
||||
title: 'Bullets and Indentation',
|
||||
richTextLexicalCustomFields: generateLexicalRichText(),
|
||||
richText: [
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'I am semantically connected to my sub-bullets',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'I am sub-bullets that are semantically connected to the parent bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'Normal bullet',
|
||||
},
|
||||
],
|
||||
type: 'li',
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'I am the old style of sub-bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'Another normal bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'This text precedes a nested list',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'I am a sub-bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'And I am another sub-bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -10,12 +10,13 @@ import {
|
||||
} from '../../../../packages/richtext-lexical/src'
|
||||
import { lexicalHTML } from '../../../../packages/richtext-lexical/src/field/features/converters/html/field'
|
||||
import { slateEditor } from '../../../../packages/richtext-slate/src'
|
||||
import { richTextFieldsSlug } from '../../slugs'
|
||||
import { RelationshipBlock, SelectFieldBlock, TextBlock, UploadAndRichTextBlock } from './blocks'
|
||||
import { generateLexicalRichText } from './generateLexicalRichText'
|
||||
import { generateSlateRichText } from './generateSlateRichText'
|
||||
|
||||
const RichTextFields: CollectionConfig = {
|
||||
slug: 'rich-text-fields',
|
||||
slug: richTextFieldsSlug,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
@@ -317,137 +318,4 @@ const RichTextFields: CollectionConfig = {
|
||||
],
|
||||
}
|
||||
|
||||
export const richTextBulletsDoc = {
|
||||
title: 'Bullets and Indentation',
|
||||
richTextLexicalCustomFields: generateLexicalRichText(),
|
||||
richText: [
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'I am semantically connected to my sub-bullets',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'I am sub-bullets that are semantically connected to the parent bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'Normal bullet',
|
||||
},
|
||||
],
|
||||
type: 'li',
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'I am the old style of sub-bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'Another normal bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'This text precedes a nested list',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'ul',
|
||||
children: [
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'I am a sub-bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'li',
|
||||
children: [
|
||||
{
|
||||
text: 'And I am another sub-bullet',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
export const richTextBlocks = [
|
||||
{
|
||||
blockType: 'textBlock',
|
||||
text: 'Regular text',
|
||||
},
|
||||
{
|
||||
blockType: 'richTextBlock',
|
||||
text: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
text: 'Rich text',
|
||||
},
|
||||
],
|
||||
type: 'h1',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
export const richTextDoc = {
|
||||
title: 'Rich Text',
|
||||
selectHasMany: ['one', 'five'],
|
||||
richText: generateSlateRichText(),
|
||||
richTextReadOnly: generateSlateRichText(),
|
||||
richTextCustomFields: generateSlateRichText(),
|
||||
richTextLexicalCustomFields: generateLexicalRichText(),
|
||||
blocks: richTextBlocks,
|
||||
}
|
||||
|
||||
export default RichTextFields
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
export const rowFieldsSlug = 'row-fields'
|
||||
import { rowFieldsSlug } from '../../slugs'
|
||||
|
||||
const RowFields: CollectionConfig = {
|
||||
slug: rowFieldsSlug,
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { selectFieldsSlug } from '../../slugs'
|
||||
|
||||
const SelectFields: CollectionConfig = {
|
||||
slug: 'select-fields',
|
||||
slug: selectFieldsSlug,
|
||||
fields: [
|
||||
{
|
||||
name: 'select',
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
export const tabsSlug = 'tabs-fields'
|
||||
|
||||
export const namedTabText = 'Some text in a named tab'
|
||||
export const namedTabDefaultValue = 'default text inside of a named tab'
|
||||
export const localizedTextValue = 'localized text'
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/* eslint-disable no-param-reassign */
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { tabsFieldsSlug } from '../../slugs'
|
||||
import { getBlocksField, getBlocksFieldSeedData } from '../Blocks'
|
||||
import { UIField } from './UIField'
|
||||
import { localizedTextValue, namedTabDefaultValue, namedTabText, tabsSlug } from './constants'
|
||||
import { localizedTextValue, namedTabDefaultValue, namedTabText } from './constants'
|
||||
|
||||
const TabsFields: CollectionConfig = {
|
||||
slug: tabsSlug,
|
||||
slug: tabsFieldsSlug,
|
||||
access: {
|
||||
read: () => true,
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { textFieldsSlug } from '../../slugs'
|
||||
|
||||
export const defaultText = 'default-text'
|
||||
export const textFieldsSlug = 'text-fields'
|
||||
|
||||
const TextFields: CollectionConfig = {
|
||||
slug: textFieldsSlug,
|
||||
|
||||
@@ -2,8 +2,10 @@ import path from 'path'
|
||||
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { uploadsSlug } from '../../slugs'
|
||||
|
||||
const Uploads: CollectionConfig = {
|
||||
slug: 'uploads',
|
||||
slug: uploadsSlug,
|
||||
upload: {
|
||||
staticDir: path.resolve(__dirname, './uploads'),
|
||||
},
|
||||
@@ -15,7 +17,7 @@ const Uploads: CollectionConfig = {
|
||||
{
|
||||
type: 'upload',
|
||||
name: 'media',
|
||||
relationTo: 'uploads',
|
||||
relationTo: uploadsSlug,
|
||||
filterOptions: {
|
||||
mimeType: {
|
||||
equals: 'image/png',
|
||||
|
||||
@@ -2,8 +2,10 @@ import path from 'path'
|
||||
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { uploads2Slug } from '../../slugs'
|
||||
|
||||
const Uploads2: CollectionConfig = {
|
||||
slug: 'uploads2',
|
||||
slug: uploads2Slug,
|
||||
upload: {
|
||||
staticDir: path.resolve(__dirname, './uploads2'),
|
||||
},
|
||||
@@ -19,7 +21,7 @@ const Uploads2: CollectionConfig = {
|
||||
{
|
||||
type: 'upload',
|
||||
name: 'media',
|
||||
relationTo: 'uploads2',
|
||||
relationTo: uploads2Slug,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ import path from 'path'
|
||||
|
||||
import type { CollectionConfig } from '../../../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { uploads3Slug } from '../../slugs'
|
||||
|
||||
const Uploads3: CollectionConfig = {
|
||||
slug: 'uploads3',
|
||||
slug: uploads3Slug,
|
||||
upload: {
|
||||
staticDir: path.resolve(__dirname, './uploads3'),
|
||||
},
|
||||
@@ -18,7 +20,7 @@ const Uploads3: CollectionConfig = {
|
||||
{
|
||||
type: 'upload',
|
||||
name: 'media',
|
||||
relationTo: 'uploads3',
|
||||
relationTo: uploads3Slug,
|
||||
},
|
||||
{
|
||||
type: 'richText',
|
||||
|
||||
@@ -1,33 +1,75 @@
|
||||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
|
||||
import getFileByPath from '../../packages/payload/src/uploads/getFileByPath'
|
||||
import type { CollectionConfig } from '../../packages/payload/src/collections/config/types'
|
||||
|
||||
import { buildConfigWithDefaults } from '../buildConfigWithDefaults'
|
||||
import { devUser } from '../credentials'
|
||||
import ArrayFields, { arrayDoc } from './collections/Array'
|
||||
import BlockFields, { blocksDoc } from './collections/Blocks'
|
||||
import ArrayFields from './collections/Array'
|
||||
import BlockFields from './collections/Blocks'
|
||||
import CheckboxFields from './collections/Checkbox'
|
||||
import CodeFields, { codeDoc } from './collections/Code'
|
||||
import CollapsibleFields, { collapsibleDoc } from './collections/Collapsible'
|
||||
import ConditionalLogic, { conditionalLogicDoc } from './collections/ConditionalLogic'
|
||||
import DateFields, { dateDoc } from './collections/Date'
|
||||
import GroupFields, { groupDoc } from './collections/Group'
|
||||
import CodeFields from './collections/Code'
|
||||
import CollapsibleFields from './collections/Collapsible'
|
||||
import ConditionalLogic from './collections/ConditionalLogic'
|
||||
import DateFields from './collections/Date'
|
||||
import GroupFields from './collections/Group'
|
||||
import IndexedFields from './collections/Indexed'
|
||||
import JSONFields, { jsonDoc } from './collections/JSON'
|
||||
import { LexicalFields, LexicalRichTextDoc } from './collections/Lexical'
|
||||
import NumberFields, { numberDoc } from './collections/Number'
|
||||
import PointFields, { pointDoc } from './collections/Point'
|
||||
import RadioFields, { radiosDoc } from './collections/Radio'
|
||||
import JSONFields from './collections/JSON'
|
||||
import { LexicalFields } from './collections/Lexical'
|
||||
import { LexicalMigrateFields } from './collections/LexicalMigrate'
|
||||
import NumberFields from './collections/Number'
|
||||
import PointFields from './collections/Point'
|
||||
import RadioFields from './collections/Radio'
|
||||
import RelationshipFields from './collections/Relationship'
|
||||
import RichTextFields, { richTextBulletsDoc, richTextDoc } from './collections/RichText'
|
||||
import RichTextFields from './collections/RichText'
|
||||
import RowFields from './collections/Row'
|
||||
import SelectFields, { selectsDoc } from './collections/Select'
|
||||
import TabsFields, { tabsDoc } from './collections/Tabs'
|
||||
import TextFields, { textDoc, textFieldsSlug } from './collections/Text'
|
||||
import Uploads, { uploadsDoc } from './collections/Upload'
|
||||
import SelectFields from './collections/Select'
|
||||
import TabsFields from './collections/Tabs'
|
||||
import TextFields from './collections/Text'
|
||||
import Uploads from './collections/Upload'
|
||||
import Uploads2 from './collections/Upload2'
|
||||
import Uploads3 from './collections/Uploads3'
|
||||
import { clearAndSeedEverything } from './seed'
|
||||
|
||||
export const collectionSlugs: CollectionConfig[] = [
|
||||
LexicalFields,
|
||||
LexicalMigrateFields,
|
||||
{
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
auth: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'canViewConditionalField',
|
||||
defaultValue: true,
|
||||
type: 'checkbox',
|
||||
},
|
||||
],
|
||||
slug: 'users',
|
||||
},
|
||||
ArrayFields,
|
||||
BlockFields,
|
||||
CheckboxFields,
|
||||
CodeFields,
|
||||
CollapsibleFields,
|
||||
ConditionalLogic,
|
||||
DateFields,
|
||||
RadioFields,
|
||||
GroupFields,
|
||||
RowFields,
|
||||
IndexedFields,
|
||||
JSONFields,
|
||||
NumberFields,
|
||||
PointFields,
|
||||
RelationshipFields,
|
||||
RichTextFields,
|
||||
SelectFields,
|
||||
TabsFields,
|
||||
TextFields,
|
||||
Uploads,
|
||||
Uploads2,
|
||||
Uploads3,
|
||||
]
|
||||
|
||||
export default buildConfigWithDefaults({
|
||||
admin: {
|
||||
@@ -42,139 +84,13 @@ export default buildConfigWithDefaults({
|
||||
},
|
||||
}),
|
||||
},
|
||||
collections: [
|
||||
LexicalFields,
|
||||
{
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
auth: true,
|
||||
fields: [
|
||||
{
|
||||
name: 'canViewConditionalField',
|
||||
defaultValue: true,
|
||||
type: 'checkbox',
|
||||
},
|
||||
],
|
||||
slug: 'users',
|
||||
},
|
||||
ArrayFields,
|
||||
BlockFields,
|
||||
CheckboxFields,
|
||||
CodeFields,
|
||||
CollapsibleFields,
|
||||
ConditionalLogic,
|
||||
DateFields,
|
||||
RadioFields,
|
||||
GroupFields,
|
||||
RowFields,
|
||||
IndexedFields,
|
||||
JSONFields,
|
||||
NumberFields,
|
||||
PointFields,
|
||||
RelationshipFields,
|
||||
RichTextFields,
|
||||
SelectFields,
|
||||
TabsFields,
|
||||
TextFields,
|
||||
Uploads,
|
||||
Uploads2,
|
||||
Uploads3,
|
||||
],
|
||||
collections: collectionSlugs,
|
||||
localization: {
|
||||
defaultLocale: 'en',
|
||||
fallback: true,
|
||||
locales: ['en', 'es'],
|
||||
},
|
||||
onInit: async (payload) => {
|
||||
await payload.create({
|
||||
collection: 'users',
|
||||
data: {
|
||||
email: devUser.email,
|
||||
password: devUser.password,
|
||||
},
|
||||
})
|
||||
|
||||
const createdArrayDoc = await payload.create({ collection: 'array-fields', data: arrayDoc })
|
||||
await payload.create({ collection: 'collapsible-fields', data: collapsibleDoc })
|
||||
await payload.create({ collection: 'conditional-logic', data: conditionalLogicDoc })
|
||||
await payload.create({ collection: 'group-fields', data: groupDoc })
|
||||
await payload.create({ collection: 'select-fields', data: selectsDoc })
|
||||
await payload.create({ collection: 'radio-fields', data: radiosDoc })
|
||||
await payload.create({ collection: 'tabs-fields', data: tabsDoc })
|
||||
await payload.create({ collection: 'point-fields', data: pointDoc })
|
||||
await payload.create({ collection: 'date-fields', data: dateDoc })
|
||||
await payload.create({ collection: 'code-fields', data: codeDoc })
|
||||
await payload.create({ collection: 'json-fields', data: jsonDoc })
|
||||
|
||||
const createdTextDoc = await payload.create({ collection: textFieldsSlug, data: textDoc })
|
||||
|
||||
const uploadsDir = path.resolve(__dirname, './collections/Upload/uploads')
|
||||
|
||||
if (fs.existsSync(uploadsDir))
|
||||
fs.readdirSync(uploadsDir).forEach((f) => fs.rmSync(`${uploadsDir}/${f}`))
|
||||
|
||||
const pngPath = path.resolve(__dirname, './uploads/payload.png')
|
||||
const pngFile = await getFileByPath(pngPath)
|
||||
const createdPNGDoc = await payload.create({ collection: 'uploads', data: {}, file: pngFile })
|
||||
|
||||
const jpgPath = path.resolve(__dirname, './collections/Upload/payload.jpg')
|
||||
const jpgFile = await getFileByPath(jpgPath)
|
||||
const createdJPGDoc = await payload.create({
|
||||
collection: 'uploads',
|
||||
data: {
|
||||
...uploadsDoc,
|
||||
media: createdPNGDoc.id,
|
||||
},
|
||||
file: jpgFile,
|
||||
})
|
||||
|
||||
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(richTextDoc)
|
||||
.replace(/"\{\{ARRAY_DOC_ID\}\}"/g, formattedID)
|
||||
.replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, formattedJPGID)
|
||||
.replace(/"\{\{TEXT_DOC_ID\}\}"/g, formattedTextID),
|
||||
)
|
||||
const richTextBulletsDocWithRelId = JSON.parse(
|
||||
JSON.stringify(richTextBulletsDoc)
|
||||
.replace(/"\{\{ARRAY_DOC_ID\}\}"/g, formattedID)
|
||||
.replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, formattedJPGID)
|
||||
.replace(/"\{\{TEXT_DOC_ID\}\}"/g, formattedTextID),
|
||||
)
|
||||
|
||||
const lexicalRichTextDocWithRelId = JSON.parse(
|
||||
JSON.stringify(LexicalRichTextDoc)
|
||||
.replace(/"\{\{ARRAY_DOC_ID\}\}"/g, formattedID)
|
||||
.replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, formattedJPGID)
|
||||
.replace(/"\{\{TEXT_DOC_ID\}\}"/g, formattedTextID),
|
||||
)
|
||||
await payload.create({ collection: 'lexical-fields', data: lexicalRichTextDocWithRelId })
|
||||
|
||||
const richTextDocWithRelationship = { ...richTextDocWithRelId }
|
||||
|
||||
await payload.create({ collection: 'rich-text-fields', data: richTextBulletsDocWithRelId })
|
||||
await payload.create({ collection: 'rich-text-fields', data: richTextDocWithRelationship })
|
||||
|
||||
await payload.create({ collection: 'number-fields', data: { number: 2 } })
|
||||
await payload.create({ collection: 'number-fields', data: { number: 3 } })
|
||||
await payload.create({ collection: 'number-fields', data: numberDoc })
|
||||
|
||||
const blocksDocWithRichText = { ...blocksDoc }
|
||||
|
||||
// @ts-ignore
|
||||
blocksDocWithRichText.blocks[0].richText = richTextDocWithRelationship.richText
|
||||
// @ts-ignore
|
||||
blocksDocWithRichText.localizedBlocks[0].richText = richTextDocWithRelationship.richText
|
||||
|
||||
await payload.create({ collection: 'block-fields', data: blocksDocWithRichText })
|
||||
await clearAndSeedEverything(payload)
|
||||
},
|
||||
})
|
||||
|
||||
@@ -10,19 +10,25 @@ import { saveDocAndAssert, saveDocHotkeyAndAssert } from '../helpers'
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil'
|
||||
import { initPayloadE2E } from '../helpers/configHelpers'
|
||||
import { RESTClient } from '../helpers/rest'
|
||||
import { collapsibleFieldsSlug } from './collections/Collapsible/shared'
|
||||
import { jsonDoc } from './collections/JSON'
|
||||
import { numberDoc } from './collections/Number'
|
||||
import { pointFieldsSlug } from './collections/Point'
|
||||
import { relationshipFieldsSlug } from './collections/Relationship'
|
||||
import { tabsSlug } from './collections/Tabs/constants'
|
||||
import { textDoc, textFieldsSlug } from './collections/Text'
|
||||
import { textDoc } from './collections/Text'
|
||||
import { lexicalE2E } from './lexicalE2E'
|
||||
import { clearAndSeedEverything } from './seed'
|
||||
import {
|
||||
collapsibleFieldsSlug,
|
||||
pointFieldsSlug,
|
||||
relationshipFieldsSlug,
|
||||
tabsFieldsSlug,
|
||||
textFieldsSlug,
|
||||
} from './slugs'
|
||||
|
||||
const { afterEach, beforeAll, describe } = test
|
||||
const { afterEach, beforeAll, describe, beforeEach } = test
|
||||
|
||||
let client: RESTClient
|
||||
let page: Page
|
||||
let serverURL
|
||||
let serverURL: string
|
||||
// If we want to make this run in parallel: test.describe.configure({ mode: 'parallel' })
|
||||
|
||||
describe('fields', () => {
|
||||
beforeAll(async ({ browser }) => {
|
||||
@@ -34,7 +40,12 @@ describe('fields', () => {
|
||||
const context = await browser.newContext()
|
||||
page = await context.newPage()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await clearAndSeedEverything(payload)
|
||||
await client.logout()
|
||||
client = new RESTClient(null, { serverURL, defaultSlug: 'users' })
|
||||
await client.login()
|
||||
})
|
||||
describe('text', () => {
|
||||
let url: AdminUrlUtil
|
||||
beforeAll(() => {
|
||||
@@ -146,7 +157,7 @@ describe('fields', () => {
|
||||
|
||||
describe('indexed', () => {
|
||||
let url: AdminUrlUtil
|
||||
beforeAll(() => {
|
||||
beforeEach(() => {
|
||||
url = new AdminUrlUtil(serverURL, 'indexed-fields')
|
||||
})
|
||||
|
||||
@@ -162,13 +173,14 @@ describe('fields', () => {
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
await page.goto(url.create)
|
||||
|
||||
await page.locator('#field-text').fill('test')
|
||||
await page.locator('#field-uniqueText').fill(uniqueText)
|
||||
|
||||
// attempt to save
|
||||
await page.locator('#action-save').click()
|
||||
await page.click('#action-save', { delay: 100 })
|
||||
|
||||
// toast error
|
||||
await expect(page.locator('.Toastify')).toContainText(
|
||||
@@ -269,7 +281,7 @@ describe('fields', () => {
|
||||
let url: AdminUrlUtil
|
||||
let filledGroupPoint
|
||||
let emptyGroupPoint
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
url = new AdminUrlUtil(serverURL, pointFieldsSlug)
|
||||
filledGroupPoint = await payload.create({
|
||||
collection: pointFieldsSlug,
|
||||
@@ -682,7 +694,7 @@ describe('fields', () => {
|
||||
describe('tabs', () => {
|
||||
let url: AdminUrlUtil
|
||||
beforeAll(() => {
|
||||
url = new AdminUrlUtil(serverURL, tabsSlug)
|
||||
url = new AdminUrlUtil(serverURL, tabsFieldsSlug)
|
||||
})
|
||||
|
||||
test('should fill and retain a new value within a tab while switching tabs', async () => {
|
||||
@@ -750,7 +762,7 @@ describe('fields', () => {
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('lexical', lexicalE2E(client, page, serverURL))
|
||||
describe('richText', () => {
|
||||
async function navigateToRichTextFields() {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields')
|
||||
@@ -1473,7 +1485,7 @@ describe('fields', () => {
|
||||
url = new AdminUrlUtil(serverURL, 'uploads')
|
||||
})
|
||||
|
||||
test('should upload files', async () => {
|
||||
async function uploadImage() {
|
||||
await page.goto(url.create)
|
||||
|
||||
// create a jpg upload
|
||||
@@ -1484,10 +1496,15 @@ describe('fields', () => {
|
||||
await page.locator('#action-save').click()
|
||||
await wait(200)
|
||||
await expect(page.locator('.Toastify')).toContainText('successfully')
|
||||
}
|
||||
|
||||
test('should upload files', async () => {
|
||||
await uploadImage()
|
||||
})
|
||||
|
||||
// test that the image renders
|
||||
test('should render uploaded image', async () => {
|
||||
await uploadImage()
|
||||
await expect(page.locator('.file-field .file-details img')).toHaveAttribute(
|
||||
'src',
|
||||
'/uploads/payload-1.jpg',
|
||||
@@ -1495,6 +1512,7 @@ describe('fields', () => {
|
||||
})
|
||||
|
||||
test('should upload using the document drawer', async () => {
|
||||
await uploadImage()
|
||||
// Open the media drawer and create a png upload
|
||||
await page.locator('.field-type.upload .upload__toggler.doc-drawer__toggler').click()
|
||||
await page
|
||||
@@ -1521,10 +1539,20 @@ describe('fields', () => {
|
||||
})
|
||||
|
||||
test('should clear selected upload', async () => {
|
||||
await uploadImage()
|
||||
await page.locator('.field-type.upload .upload__toggler.doc-drawer__toggler').click()
|
||||
await page
|
||||
.locator('[id^=doc-drawer_uploads_1_] .file-field__upload input[type="file"]')
|
||||
.setInputFiles(path.resolve(__dirname, './uploads/payload.png'))
|
||||
await page.locator('[id^=doc-drawer_uploads_1_] #action-save').click()
|
||||
await wait(200)
|
||||
await expect(page.locator('.Toastify')).toContainText('successfully')
|
||||
await page.locator('.field-type.upload .file-details__remove').click()
|
||||
})
|
||||
|
||||
test('should select using the list drawer and restrict mimetype based on filterOptions', async () => {
|
||||
await uploadImage()
|
||||
|
||||
await page.locator('.field-type.upload .upload__toggler.list-drawer__toggler').click()
|
||||
await wait(200)
|
||||
const jpgImages = page.locator('[id^=list-drawer_1_] .upload-gallery img[src$=".jpg"]')
|
||||
|
||||
@@ -8,28 +8,24 @@ import type { RichTextField } from './payload-types'
|
||||
|
||||
import payload from '../../packages/payload/src'
|
||||
import { initPayloadTest } from '../helpers/configHelpers'
|
||||
import { isMongoose } from '../helpers/isMongoose'
|
||||
import { RESTClient } from '../helpers/rest'
|
||||
import configPromise from '../uploads/config'
|
||||
import { arrayDefaultValue, arrayFieldsSlug } from './collections/Array'
|
||||
import { arrayDefaultValue } from './collections/Array'
|
||||
import { blocksDoc } from './collections/Blocks'
|
||||
import { dateDoc } from './collections/Date'
|
||||
import {
|
||||
groupDefaultChild,
|
||||
groupDefaultValue,
|
||||
groupDoc,
|
||||
groupFieldsSlug,
|
||||
} from './collections/Group'
|
||||
import { groupDefaultChild, groupDefaultValue, groupDoc } from './collections/Group'
|
||||
import { defaultNumber, numberDoc } from './collections/Number'
|
||||
import { pointDoc } from './collections/Point'
|
||||
import { relationshipFieldsSlug } from './collections/Relationship'
|
||||
import { tabsDoc } from './collections/Tabs'
|
||||
import {
|
||||
localizedTextValue,
|
||||
namedTabDefaultValue,
|
||||
namedTabText,
|
||||
tabsSlug,
|
||||
} from './collections/Tabs/constants'
|
||||
import { defaultText } from './collections/Text'
|
||||
import { clearAndSeedEverything } from './seed'
|
||||
import { arrayFieldsSlug, groupFieldsSlug, relationshipFieldsSlug, tabsFieldsSlug } from './slugs'
|
||||
|
||||
let client
|
||||
let graphQLClient: GraphQLClient
|
||||
@@ -48,10 +44,16 @@ describe('Fields', () => {
|
||||
token = await client.login()
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
await clearAndSeedEverything(payload)
|
||||
client = new RESTClient(config, { defaultSlug: 'point-fields', serverURL })
|
||||
await client.login()
|
||||
})
|
||||
|
||||
describe('text', () => {
|
||||
let doc
|
||||
const text = 'text field'
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
doc = await payload.create({
|
||||
collection: 'text-fields',
|
||||
data: { text },
|
||||
@@ -86,7 +88,7 @@ describe('Fields', () => {
|
||||
const otherTextDocText = 'alt text'
|
||||
const relationshipText = 'relationship text'
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
textDoc = await payload.create({
|
||||
collection: 'text-fields',
|
||||
data: {
|
||||
@@ -193,7 +195,7 @@ describe('Fields', () => {
|
||||
describe('timestamps', () => {
|
||||
const tenMinutesAgo = new Date(Date.now() - 1000 * 60 * 10)
|
||||
let doc
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
doc = await payload.create({
|
||||
collection: 'date-fields',
|
||||
data: dateDoc,
|
||||
@@ -231,7 +233,7 @@ describe('Fields', () => {
|
||||
|
||||
describe('select', () => {
|
||||
let doc
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
const { id } = await payload.create({
|
||||
collection: 'select-fields',
|
||||
data: {
|
||||
@@ -273,7 +275,7 @@ describe('Fields', () => {
|
||||
|
||||
describe('number', () => {
|
||||
let doc
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
doc = await payload.create({
|
||||
collection: 'number-fields',
|
||||
data: numberDoc,
|
||||
@@ -375,13 +377,13 @@ describe('Fields', () => {
|
||||
})
|
||||
})
|
||||
|
||||
if (['mongoose'].includes(process.env.PAYLOAD_DATABASE)) {
|
||||
if (isMongoose(payload) || !['postgres'].includes(process.env.PAYLOAD_DATABASE)) {
|
||||
describe('indexes', () => {
|
||||
let indexes
|
||||
const definitions: Record<string, IndexDirection> = {}
|
||||
const options: Record<string, IndexOptions> = {}
|
||||
|
||||
beforeAll(() => {
|
||||
beforeEach(() => {
|
||||
indexes = (payload.db as MongooseAdapter).collections[
|
||||
'indexed-fields'
|
||||
].schema.indexes() as [Record<string, IndexDirection>, IndexOptions]
|
||||
@@ -434,7 +436,7 @@ describe('Fields', () => {
|
||||
const definitions: Record<string, IndexDirection> = {}
|
||||
const options: Record<string, IndexOptions> = {}
|
||||
|
||||
beforeAll(() => {
|
||||
beforeEach(() => {
|
||||
indexes = (payload.db as MongooseAdapter).versions['indexed-fields'].schema.indexes() as [
|
||||
Record<string, IndexDirection>,
|
||||
IndexOptions,
|
||||
@@ -458,7 +460,7 @@ describe('Fields', () => {
|
||||
const localized = [5, -2]
|
||||
const group = { point: [1, 9] }
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
const findDoc = await payload.find({
|
||||
collection: 'point-fields',
|
||||
pagination: false,
|
||||
@@ -495,6 +497,17 @@ describe('Fields', () => {
|
||||
})
|
||||
|
||||
it('should not create duplicate point when unique', async () => {
|
||||
// first create the point field
|
||||
doc = await payload.create({
|
||||
collection: 'point-fields',
|
||||
data: {
|
||||
group,
|
||||
localized,
|
||||
point,
|
||||
},
|
||||
})
|
||||
|
||||
// Now make sure we can't create a duplicate (since 'localized' is a unique field)
|
||||
await expect(() =>
|
||||
payload.create({
|
||||
collection: 'point-fields',
|
||||
@@ -546,7 +559,7 @@ describe('Fields', () => {
|
||||
let doc
|
||||
const collection = arrayFieldsSlug
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
doc = await payload.create({
|
||||
collection,
|
||||
data: {},
|
||||
@@ -611,7 +624,7 @@ describe('Fields', () => {
|
||||
describe('group', () => {
|
||||
let document
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
document = await payload.create({
|
||||
collection: groupFieldsSlug,
|
||||
data: {},
|
||||
@@ -627,9 +640,9 @@ describe('Fields', () => {
|
||||
describe('tabs', () => {
|
||||
let document
|
||||
|
||||
beforeAll(async () => {
|
||||
beforeEach(async () => {
|
||||
document = await payload.create({
|
||||
collection: tabsSlug,
|
||||
collection: tabsFieldsSlug,
|
||||
data: tabsDoc,
|
||||
})
|
||||
})
|
||||
@@ -649,7 +662,7 @@ describe('Fields', () => {
|
||||
it('should create with localized text inside a named tab', async () => {
|
||||
document = await payload.findByID({
|
||||
id: document.id,
|
||||
collection: tabsSlug,
|
||||
collection: tabsFieldsSlug,
|
||||
locale: 'all',
|
||||
})
|
||||
expect(document.localizedTab.en.text).toStrictEqual(localizedTextValue)
|
||||
@@ -658,7 +671,7 @@ describe('Fields', () => {
|
||||
it('should allow access control on a named tab', async () => {
|
||||
document = await payload.findByID({
|
||||
id: document.id,
|
||||
collection: tabsSlug,
|
||||
collection: tabsFieldsSlug,
|
||||
overrideAccess: false,
|
||||
})
|
||||
expect(document.accessControlTab).toBeUndefined()
|
||||
@@ -666,7 +679,7 @@ describe('Fields', () => {
|
||||
|
||||
it('should allow hooks on a named tab', async () => {
|
||||
const newDocument = await payload.create({
|
||||
collection: tabsSlug,
|
||||
collection: tabsFieldsSlug,
|
||||
data: tabsDoc,
|
||||
})
|
||||
expect(newDocument.hooksTab.beforeValidate).toBe(true)
|
||||
|
||||
27
test/fields/lexicalE2E.ts
Normal file
27
test/fields/lexicalE2E.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import type { Page } from '@playwright/test'
|
||||
|
||||
import { expect, test } from '@playwright/test'
|
||||
|
||||
import type { RESTClient } from '../helpers/rest'
|
||||
|
||||
import { AdminUrlUtil } from '../helpers/adminUrlUtil'
|
||||
|
||||
const { describe } = test
|
||||
|
||||
export const lexicalE2E = (client: RESTClient, page: Page, serverURL: string) => {
|
||||
async function navigateToRichTextFields() {
|
||||
const url: AdminUrlUtil = new AdminUrlUtil(serverURL, 'rich-text-fields')
|
||||
await page.goto(url.list)
|
||||
await page.locator('.row-1 .cell-title a').click()
|
||||
}
|
||||
|
||||
return () => {
|
||||
describe('todo', () => {
|
||||
test.skip('todo', async () => {
|
||||
await navigateToRichTextFields()
|
||||
|
||||
await page.locator('todo').first().click()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
147
test/fields/seed.ts
Normal file
147
test/fields/seed.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import path from 'path'
|
||||
|
||||
import { type Payload } from '../../packages/payload/src'
|
||||
import getFileByPath from '../../packages/payload/src/uploads/getFileByPath'
|
||||
import { devUser } from '../credentials'
|
||||
import { seedDB } from '../helpers/seed'
|
||||
import { arrayDoc } from './collections/Array'
|
||||
import { blocksDoc } from './collections/Blocks'
|
||||
import { codeDoc } from './collections/Code'
|
||||
import { collapsibleDoc } from './collections/Collapsible'
|
||||
import { conditionalLogicDoc } from './collections/ConditionalLogic'
|
||||
import { dateDoc } from './collections/Date'
|
||||
import { groupDoc } from './collections/Group'
|
||||
import { jsonDoc } from './collections/JSON'
|
||||
import { lexicalRichTextDoc } from './collections/Lexical/data'
|
||||
import { numberDoc } from './collections/Number'
|
||||
import { pointDoc } from './collections/Point'
|
||||
import { radiosDoc } from './collections/Radio'
|
||||
import { richTextBulletsDoc, richTextDoc } from './collections/RichText/data'
|
||||
import { selectsDoc } from './collections/Select'
|
||||
import { tabsDoc } from './collections/Tabs'
|
||||
import { textDoc } from './collections/Text'
|
||||
import { uploadsDoc } from './collections/Upload'
|
||||
import {
|
||||
blockFieldsSlug,
|
||||
codeFieldsSlug,
|
||||
collapsibleFieldsSlug,
|
||||
collectionSlugs,
|
||||
conditionalLogicSlug,
|
||||
dateFieldsSlug,
|
||||
groupFieldsSlug,
|
||||
jsonFieldsSlug,
|
||||
lexicalFieldsSlug,
|
||||
lexicalMigrateFieldsSlug,
|
||||
numberFieldsSlug,
|
||||
pointFieldsSlug,
|
||||
radioFieldsSlug,
|
||||
richTextFieldsSlug,
|
||||
selectFieldsSlug,
|
||||
tabsFieldsSlug,
|
||||
textFieldsSlug,
|
||||
uploadsSlug,
|
||||
usersSlug,
|
||||
} from './slugs'
|
||||
|
||||
export async function clearAndSeedEverything(_payload: Payload) {
|
||||
return await seedDB({
|
||||
snapshotKey: 'fieldsTest',
|
||||
shouldResetDB: true,
|
||||
collectionSlugs,
|
||||
_payload,
|
||||
uploadsDir: path.resolve(__dirname, './collections/Upload/uploads'),
|
||||
seedFunction: async (_payload) => {
|
||||
const jpgPath = path.resolve(__dirname, './collections/Upload/payload.jpg')
|
||||
const pngPath = path.resolve(__dirname, './uploads/payload.png')
|
||||
|
||||
// Get both files in parallel
|
||||
const [jpgFile, pngFile] = await Promise.all([getFileByPath(jpgPath), getFileByPath(pngPath)])
|
||||
|
||||
const [createdArrayDoc, createdTextDoc, createdPNGDoc] = await Promise.all([
|
||||
_payload.create({ collection: 'array-fields', data: arrayDoc }),
|
||||
_payload.create({ collection: textFieldsSlug, data: textDoc }),
|
||||
_payload.create({ collection: uploadsSlug, data: {}, file: pngFile }),
|
||||
])
|
||||
|
||||
const createdJPGDoc = await _payload.create({
|
||||
collection: uploadsSlug,
|
||||
data: {
|
||||
...uploadsDoc,
|
||||
media: createdPNGDoc.id,
|
||||
},
|
||||
file: jpgFile,
|
||||
})
|
||||
|
||||
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(richTextDoc)
|
||||
.replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`)
|
||||
.replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`)
|
||||
.replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`),
|
||||
)
|
||||
const richTextBulletsDocWithRelId = JSON.parse(
|
||||
JSON.stringify(richTextBulletsDoc)
|
||||
.replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`)
|
||||
.replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`)
|
||||
.replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`),
|
||||
)
|
||||
|
||||
const richTextDocWithRelationship = { ...richTextDocWithRelId }
|
||||
|
||||
const blocksDocWithRichText = { ...blocksDoc }
|
||||
|
||||
blocksDocWithRichText.blocks[0].richText = richTextDocWithRelationship.richText
|
||||
blocksDocWithRichText.localizedBlocks[0].richText = richTextDocWithRelationship.richText
|
||||
|
||||
const lexicalRichTextDocWithRelId = JSON.parse(
|
||||
JSON.stringify(lexicalRichTextDoc)
|
||||
.replace(/"\{\{ARRAY_DOC_ID\}\}"/g, `${formattedID}`)
|
||||
.replace(/"\{\{UPLOAD_DOC_ID\}\}"/g, `${formattedJPGID}`)
|
||||
.replace(/"\{\{TEXT_DOC_ID\}\}"/g, `${formattedTextID}`),
|
||||
)
|
||||
|
||||
await Promise.all([
|
||||
_payload.create({
|
||||
collection: usersSlug,
|
||||
data: {
|
||||
email: devUser.email,
|
||||
password: devUser.password,
|
||||
},
|
||||
}),
|
||||
_payload.create({ collection: collapsibleFieldsSlug, data: collapsibleDoc }),
|
||||
_payload.create({ collection: conditionalLogicSlug, data: conditionalLogicDoc }),
|
||||
_payload.create({ collection: groupFieldsSlug, data: groupDoc }),
|
||||
_payload.create({ collection: selectFieldsSlug, data: selectsDoc }),
|
||||
_payload.create({ collection: radioFieldsSlug, data: radiosDoc }),
|
||||
_payload.create({ collection: tabsFieldsSlug, data: tabsDoc }),
|
||||
_payload.create({ collection: pointFieldsSlug, data: pointDoc }),
|
||||
_payload.create({ collection: dateFieldsSlug, data: dateDoc }),
|
||||
_payload.create({ collection: codeFieldsSlug, data: codeDoc }),
|
||||
_payload.create({ collection: jsonFieldsSlug, data: jsonDoc }),
|
||||
|
||||
_payload.create({ collection: blockFieldsSlug, data: blocksDocWithRichText }),
|
||||
|
||||
_payload.create({ collection: lexicalFieldsSlug, data: lexicalRichTextDocWithRelId }),
|
||||
_payload.create({
|
||||
collection: lexicalMigrateFieldsSlug,
|
||||
data: lexicalRichTextDocWithRelId,
|
||||
}),
|
||||
|
||||
_payload.create({ collection: richTextFieldsSlug, data: richTextBulletsDocWithRelId }),
|
||||
_payload.create({ collection: richTextFieldsSlug, data: richTextDocWithRelationship }),
|
||||
|
||||
_payload.create({ collection: numberFieldsSlug, data: { number: 2 } }),
|
||||
_payload.create({ collection: numberFieldsSlug, data: { number: 3 } }),
|
||||
_payload.create({ collection: numberFieldsSlug, data: numberDoc }),
|
||||
])
|
||||
},
|
||||
})
|
||||
}
|
||||
52
test/fields/slugs.ts
Normal file
52
test/fields/slugs.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
export const usersSlug = 'users' as const
|
||||
export const arrayFieldsSlug = 'array-fields' as const
|
||||
export const blockFieldsSlug = 'block-fields' as const
|
||||
export const checkboxFieldsSlug = 'checkbox-fields' as const
|
||||
export const codeFieldsSlug = 'code-fields' as const
|
||||
export const collapsibleFieldsSlug = 'collapsible-fields' as const
|
||||
export const conditionalLogicSlug = 'conditional-logic' as const
|
||||
export const dateFieldsSlug = 'date-fields' as const
|
||||
export const groupFieldsSlug = 'group-fields' as const
|
||||
export const indexedFieldsSlug = 'indexed-fields' as const
|
||||
export const jsonFieldsSlug = 'json-fields' as const
|
||||
export const lexicalFieldsSlug = 'lexical-fields' as const
|
||||
export const lexicalMigrateFieldsSlug = 'lexical-migrate-fields' as const
|
||||
export const numberFieldsSlug = 'number-fields' as const
|
||||
export const pointFieldsSlug = 'point-fields' as const
|
||||
export const radioFieldsSlug = 'radio-fields' as const
|
||||
export const relationshipFieldsSlug = 'relationship-fields' as const
|
||||
export const richTextFieldsSlug = 'rich-text-fields' as const
|
||||
export const rowFieldsSlug = 'row-fields' as const
|
||||
export const selectFieldsSlug = 'select-fields' as const
|
||||
export const tabsFieldsSlug = 'tabs-fields' as const
|
||||
export const textFieldsSlug = 'text-fields' as const
|
||||
export const uploadsSlug = 'uploads' as const
|
||||
export const uploads2Slug = 'uploads2' as const
|
||||
export const uploads3Slug = 'uploads3' as const
|
||||
export const collectionSlugs = [
|
||||
usersSlug,
|
||||
arrayFieldsSlug,
|
||||
blockFieldsSlug,
|
||||
checkboxFieldsSlug,
|
||||
codeFieldsSlug,
|
||||
collapsibleFieldsSlug,
|
||||
conditionalLogicSlug,
|
||||
dateFieldsSlug,
|
||||
groupFieldsSlug,
|
||||
indexedFieldsSlug,
|
||||
jsonFieldsSlug,
|
||||
lexicalFieldsSlug,
|
||||
lexicalMigrateFieldsSlug,
|
||||
numberFieldsSlug,
|
||||
pointFieldsSlug,
|
||||
radioFieldsSlug,
|
||||
relationshipFieldsSlug,
|
||||
richTextFieldsSlug,
|
||||
rowFieldsSlug,
|
||||
selectFieldsSlug,
|
||||
tabsFieldsSlug,
|
||||
textFieldsSlug,
|
||||
uploadsSlug,
|
||||
uploads2Slug,
|
||||
uploads3Slug,
|
||||
]
|
||||
Reference in New Issue
Block a user