Some checks failed
ci / changes (push) Has been cancelled
ci / lint (push) Has been cancelled
ci / build (push) Has been cancelled
ci / tests-unit (push) Has been cancelled
ci / tests-types (push) Has been cancelled
ci / int-cosmosdb (push) Has been cancelled
ci / int-documentdb (push) Has been cancelled
ci / int-firestore (push) Has been cancelled
ci / int-mongodb (push) Has been cancelled
ci / int-postgres (push) Has been cancelled
ci / int-postgres-custom-schema (push) Has been cancelled
ci / int-postgres-uuid (push) Has been cancelled
ci / int-sqlite (push) Has been cancelled
ci / int-sqlite-uuid (push) Has been cancelled
ci / int-supabase (push) Has been cancelled
ci / e2e-_community (push) Has been cancelled
ci / e2e-access-control (push) Has been cancelled
ci / e2e-admin-bar (push) Has been cancelled
ci / e2e-admin-root (push) Has been cancelled
ci / e2e-admin__e2e__document-view (push) Has been cancelled
ci / e2e-admin__e2e__general (push) Has been cancelled
ci / e2e-admin__e2e__list-view (push) Has been cancelled
ci / e2e-auth (push) Has been cancelled
ci / e2e-auth-basic (push) Has been cancelled
ci / e2e-bulk-edit (push) Has been cancelled
ci / e2e-field-error-states (push) Has been cancelled
ci / e2e-fields-relationship (push) Has been cancelled
ci / e2e-fields__collections__Array (push) Has been cancelled
ci / e2e-fields__collections__Blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-fields__collections__Blocks (push) Has been cancelled
ci / e2e-fields__collections__Checkbox (push) Has been cancelled
ci / e2e-fields__collections__Collapsible (push) Has been cancelled
ci / e2e-fields__collections__ConditionalLogic (push) Has been cancelled
ci / e2e-fields__collections__CustomID (push) Has been cancelled
ci / e2e-fields__collections__Date (push) Has been cancelled
ci / e2e-fields__collections__Email (push) Has been cancelled
ci / e2e-fields__collections__Indexed (push) Has been cancelled
ci / e2e-fields__collections__JSON (push) Has been cancelled
ci / e2e-fields__collections__Number (push) Has been cancelled
ci / e2e-fields__collections__Point (push) Has been cancelled
ci / e2e-fields__collections__Radio (push) Has been cancelled
ci / e2e-fields__collections__Relationship (push) Has been cancelled
ci / e2e-fields__collections__Row (push) Has been cancelled
ci / e2e-fields__collections__Select (push) Has been cancelled
ci / e2e-fields__collections__Tabs (push) Has been cancelled
ci / e2e-fields__collections__Tabs2 (push) Has been cancelled
ci / e2e-fields__collections__Text (push) Has been cancelled
ci / e2e-fields__collections__UI (push) Has been cancelled
ci / e2e-fields__collections__Upload (push) Has been cancelled
ci / e2e-folders (push) Has been cancelled
ci / e2e-form-state (push) Has been cancelled
ci / e2e-group-by (push) Has been cancelled
ci / e2e-hooks (push) Has been cancelled
ci / e2e-i18n (push) Has been cancelled
ci / e2e-joins (push) Has been cancelled
ci / e2e-lexical__collections__LexicalHeadingFeature (push) Has been cancelled
ci / e2e-lexical__collections__LexicalJSXConverter (push) Has been cancelled
ci / e2e-lexical__collections__LexicalLinkFeature (push) Has been cancelled
ci / e2e-lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-lexical__collections__Lexical__e2e__blocks (push) Has been cancelled
ci / e2e-lexical__collections__Lexical__e2e__main (push) Has been cancelled
ci / e2e-lexical__collections__OnDemandForm (push) Has been cancelled
ci / e2e-lexical__collections__RichText (push) Has been cancelled
ci / e2e-lexical__collections___LexicalFullyFeatured (push) Has been cancelled
ci / e2e-lexical__collections___LexicalFullyFeatured__db (push) Has been cancelled
ci / e2e-live-preview (push) Has been cancelled
ci / e2e-localization (push) Has been cancelled
ci / e2e-locked-documents (push) Has been cancelled
ci / e2e-plugin-cloud-storage (push) Has been cancelled
ci / e2e-plugin-form-builder (push) Has been cancelled
ci / e2e-plugin-import-export (push) Has been cancelled
ci / e2e-plugin-multi-tenant (push) Has been cancelled
ci / e2e-plugin-nested-docs (push) Has been cancelled
ci / e2e-plugin-seo (push) Has been cancelled
ci / e2e-query-presets (push) Has been cancelled
ci / e2e-sort (push) Has been cancelled
ci / e2e-trash (push) Has been cancelled
ci / e2e-uploads (push) Has been cancelled
ci / e2e-versions (push) Has been cancelled
ci / e2e-turbo-_community (push) Has been cancelled
ci / e2e-turbo-access-control (push) Has been cancelled
ci / e2e-turbo-admin-bar (push) Has been cancelled
ci / e2e-turbo-admin-root (push) Has been cancelled
ci / e2e-turbo-admin__e2e__document-view (push) Has been cancelled
ci / e2e-turbo-admin__e2e__general (push) Has been cancelled
ci / e2e-turbo-admin__e2e__list-view (push) Has been cancelled
ci / e2e-turbo-auth (push) Has been cancelled
ci / e2e-turbo-auth-basic (push) Has been cancelled
ci / e2e-turbo-bulk-edit (push) Has been cancelled
ci / e2e-turbo-field-error-states (push) Has been cancelled
ci / e2e-turbo-fields-relationship (push) Has been cancelled
ci / e2e-turbo-fields__collections__Array (push) Has been cancelled
ci / e2e-turbo-fields__collections__Blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-turbo-fields__collections__Blocks (push) Has been cancelled
ci / e2e-turbo-fields__collections__Checkbox (push) Has been cancelled
ci / e2e-turbo-fields__collections__Collapsible (push) Has been cancelled
ci / e2e-turbo-fields__collections__ConditionalLogic (push) Has been cancelled
ci / e2e-turbo-fields__collections__CustomID (push) Has been cancelled
ci / e2e-turbo-fields__collections__Date (push) Has been cancelled
ci / e2e-turbo-fields__collections__Email (push) Has been cancelled
ci / e2e-turbo-fields__collections__Indexed (push) Has been cancelled
ci / e2e-turbo-fields__collections__JSON (push) Has been cancelled
ci / e2e-turbo-fields__collections__Number (push) Has been cancelled
ci / e2e-turbo-fields__collections__Point (push) Has been cancelled
ci / e2e-turbo-fields__collections__Radio (push) Has been cancelled
ci / e2e-turbo-fields__collections__Relationship (push) Has been cancelled
ci / e2e-turbo-fields__collections__Row (push) Has been cancelled
ci / e2e-turbo-fields__collections__Select (push) Has been cancelled
ci / e2e-turbo-fields__collections__Tabs (push) Has been cancelled
ci / e2e-turbo-fields__collections__Tabs2 (push) Has been cancelled
ci / e2e-turbo-fields__collections__Text (push) Has been cancelled
ci / e2e-turbo-fields__collections__UI (push) Has been cancelled
ci / e2e-turbo-fields__collections__Upload (push) Has been cancelled
ci / e2e-turbo-folders (push) Has been cancelled
ci / e2e-turbo-form-state (push) Has been cancelled
ci / e2e-turbo-group-by (push) Has been cancelled
ci / e2e-turbo-hooks (push) Has been cancelled
ci / e2e-turbo-i18n (push) Has been cancelled
ci / e2e-turbo-joins (push) Has been cancelled
ci / e2e-turbo-lexical__collections__LexicalHeadingFeature (push) Has been cancelled
ci / e2e-turbo-lexical__collections__LexicalJSXConverter (push) Has been cancelled
ci / e2e-turbo-lexical__collections__LexicalLinkFeature (push) Has been cancelled
ci / e2e-turbo-lexical__collections__Lexical__e2e__blocks#config.blockreferences.ts (push) Has been cancelled
ci / e2e-turbo-lexical__collections__Lexical__e2e__blocks (push) Has been cancelled
ci / e2e-turbo-lexical__collections__Lexical__e2e__main (push) Has been cancelled
ci / e2e-turbo-lexical__collections__OnDemandForm (push) Has been cancelled
ci / e2e-turbo-lexical__collections__RichText (push) Has been cancelled
ci / e2e-turbo-lexical__collections___LexicalFullyFeatured (push) Has been cancelled
ci / e2e-turbo-lexical__collections___LexicalFullyFeatured__db (push) Has been cancelled
ci / e2e-turbo-live-preview (push) Has been cancelled
ci / e2e-turbo-localization (push) Has been cancelled
ci / e2e-turbo-locked-documents (push) Has been cancelled
ci / e2e-turbo-plugin-cloud-storage (push) Has been cancelled
ci / e2e-turbo-plugin-form-builder (push) Has been cancelled
ci / e2e-turbo-plugin-import-export (push) Has been cancelled
ci / e2e-turbo-plugin-multi-tenant (push) Has been cancelled
ci / e2e-turbo-plugin-nested-docs (push) Has been cancelled
ci / e2e-turbo-plugin-seo (push) Has been cancelled
ci / e2e-turbo-query-presets (push) Has been cancelled
ci / e2e-turbo-sort (push) Has been cancelled
ci / e2e-turbo-trash (push) Has been cancelled
ci / e2e-turbo-uploads (push) Has been cancelled
ci / e2e-turbo-versions (push) Has been cancelled
ci / build-template-blank-mongodb (push) Has been cancelled
ci / build-template-website-mongodb (push) Has been cancelled
ci / build-template-with-payload-cloud-mongodb (push) Has been cancelled
ci / build-template-with-vercel-mongodb-mongodb (push) Has been cancelled
ci / build-template-plugin- (push) Has been cancelled
ci / build-template-with-postgres-postgres (push) Has been cancelled
ci / build-template-with-vercel-postgres-postgres (push) Has been cancelled
ci / tests-type-generation (push) Has been cancelled
ci / All Green (push) Has been cancelled
ci / Publish Canary (push) Has been cancelled
ci / analyze (push) Has been cancelled
publish-prerelease / publish-prerelease-${{ github.ref_name }}-${{ github.sha }} (push) Has been cancelled
lock-issues / lock_issues (push) Has been cancelled
stale / stale (push) Has been cancelled
audit-dependencies / audit (push) Has been cancelled
activity-notifications / run (push) Has been cancelled
252 lines
6.6 KiB
TypeScript
252 lines
6.6 KiB
TypeScript
/* eslint-disable jest/require-top-level-describe */
|
|
import type { Payload } from 'tbsh-cms'
|
|
|
|
import path from 'path'
|
|
import { assert } from 'ts-essentials'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
import type { Point, Post } from './payload-types.js'
|
|
|
|
import { initPayloadInt } from '../helpers/initPayloadInt.js'
|
|
|
|
let payload: Payload
|
|
|
|
const filename = fileURLToPath(import.meta.url)
|
|
const dirname = path.dirname(filename)
|
|
|
|
const describePostgres = process.env.PAYLOAD_DATABASE === 'postgres' ? describe : describe.skip
|
|
|
|
describePostgres('Select - with postgres logs', () => {
|
|
// --__--__--__--__--__--__--__--__--__
|
|
// Boilerplate test setup/teardown
|
|
// --__--__--__--__--__--__--__--__--__
|
|
beforeAll(async () => {
|
|
const initialized = await initPayloadInt(
|
|
dirname,
|
|
undefined,
|
|
undefined,
|
|
'config.postgreslogs.ts',
|
|
)
|
|
assert(initialized.payload)
|
|
assert(initialized.restClient)
|
|
;({ payload } = initialized)
|
|
})
|
|
|
|
afterAll(async () => {
|
|
await payload.destroy()
|
|
})
|
|
|
|
describe('Local API - Base', () => {
|
|
let post: Post
|
|
let postId: number | string
|
|
|
|
let point: Point
|
|
let pointId: number | string
|
|
|
|
beforeEach(async () => {
|
|
post = await createPost()
|
|
postId = post.id
|
|
|
|
point = await createPoint()
|
|
pointId = point.id
|
|
})
|
|
|
|
// Clean up to safely mutate in each test
|
|
afterEach(async () => {
|
|
await payload.delete({ id: postId, collection: 'posts' })
|
|
await payload.delete({ id: pointId, collection: 'points' })
|
|
})
|
|
|
|
it('ensure optimized db update is still used when using select', async () => {
|
|
const post = await createPost()
|
|
|
|
// Count every console log
|
|
const consoleCount = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
const res = removeEmptyAndUndefined(
|
|
(await payload.db.updateOne({
|
|
collection: 'posts',
|
|
id: post.id,
|
|
data: {
|
|
text: 'new text',
|
|
},
|
|
select: { text: true, number: true },
|
|
})) as any,
|
|
)
|
|
|
|
expect(consoleCount).toHaveBeenCalledTimes(1) // Should be 1 single sql call if the optimization is used. If not, this would be 2 calls
|
|
consoleCount.mockRestore()
|
|
|
|
expect(res.number).toEqual(1)
|
|
expect(res.text).toEqual('new text')
|
|
expect(res.id).toEqual(post.id)
|
|
expect(Object.keys(res)).toHaveLength(3)
|
|
})
|
|
|
|
// This verifies that select actually improves performance of simple updates for complex collections.
|
|
// This is possible as no `with` is returned by buildFindManyArgs for the blocks field, only if we have a select that does not select that blocks field.
|
|
it('ensure simple update of complex collection uses optimized upsertRow with optimized returning() if only simple fields are selected', async () => {
|
|
const page = await payload.create({
|
|
collection: 'pages',
|
|
data: {
|
|
slug: 'test-page',
|
|
additional: 'value',
|
|
blocks: [
|
|
{
|
|
id: '123',
|
|
blockType: 'some',
|
|
other: 'value',
|
|
title: 'Test Block',
|
|
},
|
|
],
|
|
},
|
|
})
|
|
|
|
// Count every console log
|
|
const consoleCount = jest.spyOn(console, 'log').mockImplementation(() => {})
|
|
|
|
const res = removeEmptyAndUndefined(
|
|
(await payload.db.updateOne({
|
|
collection: 'pages',
|
|
id: page.id,
|
|
select: {
|
|
slug: true,
|
|
additional: true,
|
|
},
|
|
data: {
|
|
slug: 'new-slug',
|
|
},
|
|
})) as any,
|
|
)
|
|
|
|
expect(consoleCount).toHaveBeenCalledTimes(1) // Should be 1 single sql call if the optimization is used. If not, this would be 2 calls
|
|
consoleCount.mockRestore()
|
|
|
|
expect(res.slug).toEqual('new-slug')
|
|
expect(res.additional).toEqual('value')
|
|
expect(res.id).toEqual(page.id)
|
|
expect(Object.keys(res)).toHaveLength(3)
|
|
|
|
// Do full find without select just to ensure that the update worked
|
|
const fullPage: any = await payload.findByID({
|
|
collection: 'pages',
|
|
id: page.id,
|
|
})
|
|
|
|
delete fullPage.createdAt
|
|
delete fullPage.updatedAt
|
|
delete fullPage.array
|
|
delete fullPage.content
|
|
|
|
expect(fullPage).toEqual({
|
|
id: page.id,
|
|
slug: 'new-slug',
|
|
additional: 'value',
|
|
relatedPage: null,
|
|
blocks: [
|
|
{
|
|
id: '123',
|
|
blockType: 'some',
|
|
blockName: null,
|
|
other: 'value',
|
|
title: 'Test Block',
|
|
},
|
|
],
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
function removeEmptyAndUndefined(obj: any): any {
|
|
if (Array.isArray(obj)) {
|
|
const cleanedArray = obj
|
|
.map(removeEmptyAndUndefined)
|
|
.filter(
|
|
(item) =>
|
|
item !== undefined && !(typeof item === 'object' && Object.keys(item).length === 0),
|
|
)
|
|
|
|
return cleanedArray.length > 0 ? cleanedArray : undefined
|
|
}
|
|
|
|
if (obj !== null && typeof obj === 'object') {
|
|
const cleanedEntries = Object.entries(obj)
|
|
.map(([key, value]) => [key, removeEmptyAndUndefined(value)])
|
|
.filter(([, value]) => {
|
|
return (
|
|
value !== undefined &&
|
|
value !== null &&
|
|
!(
|
|
typeof value === 'object' &&
|
|
(Array.isArray(value) ? value.length === 0 : Object.keys(value).length === 0)
|
|
)
|
|
)
|
|
})
|
|
|
|
return cleanedEntries.length > 0 ? Object.fromEntries(cleanedEntries) : undefined
|
|
}
|
|
|
|
return obj
|
|
}
|
|
async function createPost() {
|
|
const upload = await payload.create({
|
|
collection: 'upload',
|
|
data: {},
|
|
filePath: path.resolve(dirname, 'image.jpg'),
|
|
})
|
|
|
|
const relation = await payload.create({
|
|
depth: 0,
|
|
collection: 'rels',
|
|
data: {},
|
|
})
|
|
|
|
return payload.create({
|
|
collection: 'posts',
|
|
depth: 0,
|
|
data: {
|
|
number: 1,
|
|
text: 'text',
|
|
select: 'a',
|
|
selectMany: ['a'],
|
|
group: {
|
|
number: 1,
|
|
text: 'text',
|
|
},
|
|
hasMany: [relation],
|
|
hasManyUpload: [upload],
|
|
hasOne: relation,
|
|
hasManyPoly: [{ relationTo: 'rels', value: relation }],
|
|
hasOnePoly: { relationTo: 'rels', value: relation },
|
|
blocks: [
|
|
{
|
|
blockType: 'cta',
|
|
ctaText: 'cta-text',
|
|
text: 'text',
|
|
},
|
|
{
|
|
blockType: 'intro',
|
|
introText: 'intro-text',
|
|
text: 'text',
|
|
},
|
|
],
|
|
array: [
|
|
{
|
|
text: 'text',
|
|
number: 1,
|
|
},
|
|
],
|
|
tab: {
|
|
text: 'text',
|
|
number: 1,
|
|
},
|
|
unnamedTabNumber: 2,
|
|
unnamedTabText: 'text2',
|
|
},
|
|
})
|
|
}
|
|
|
|
function createPoint() {
|
|
return payload.create({ collection: 'points', data: { text: 'some', point: [10, 20] } })
|
|
}
|