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
229 lines
7.1 KiB
TypeScript
229 lines
7.1 KiB
TypeScript
import fs from 'fs'
|
|
import * as os from 'node:os'
|
|
import path from 'path'
|
|
import { type Payload } from 'tbsh-cms'
|
|
|
|
import { isErrorWithCode } from './isErrorWithCode.js'
|
|
import { isMongoose } from './isMongoose.js'
|
|
import { resetDB } from './reset.js'
|
|
import { createSnapshot, dbSnapshot, restoreFromSnapshot, uploadsDirCache } from './snapshot.js'
|
|
|
|
type SeedFunction = (_payload: Payload) => Promise<void> | void
|
|
|
|
export async function seedDB({
|
|
_payload,
|
|
collectionSlugs,
|
|
seedFunction,
|
|
snapshotKey,
|
|
uploadsDir,
|
|
/**
|
|
* Always seeds, instead of restoring from snapshot for consecutive test runs
|
|
*/
|
|
alwaysSeed = false,
|
|
deleteOnly,
|
|
}: {
|
|
_payload: Payload
|
|
alwaysSeed?: boolean
|
|
collectionSlugs: string[]
|
|
deleteOnly?: boolean
|
|
seedFunction: SeedFunction
|
|
/**
|
|
* Key to uniquely identify the kind of snapshot. Each test suite should pass in a unique key
|
|
*/
|
|
snapshotKey: string
|
|
uploadsDir?: string | string[]
|
|
}) {
|
|
/**
|
|
* Reset database
|
|
*/
|
|
try {
|
|
await resetDB(_payload, collectionSlugs)
|
|
} catch (error) {
|
|
console.error('Error in operation (resetting database):', error)
|
|
}
|
|
/**
|
|
* Delete uploads directory if it exists
|
|
*/
|
|
if (uploadsDir) {
|
|
const uploadsDirs = Array.isArray(uploadsDir) ? uploadsDir : [uploadsDir]
|
|
for (const dir of uploadsDirs) {
|
|
try {
|
|
await fs.promises.access(dir)
|
|
const files = await fs.promises.readdir(dir)
|
|
for (const file of files) {
|
|
const filePath = path.join(dir, file)
|
|
await fs.promises.rm(filePath, { recursive: true, force: true })
|
|
}
|
|
} catch (error) {
|
|
if (isErrorWithCode(error, 'ENOENT')) {
|
|
// Directory does not exist - that's okay, skip it
|
|
continue
|
|
} else {
|
|
// Some other error occurred - rethrow it
|
|
console.error('Error in operation (deleting uploads dir):', dir, error)
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mongoose & Postgres: Restore snapshot of old data if available
|
|
*
|
|
* Note for postgres: For postgres, this needs to happen AFTER the tables were created.
|
|
* This does not work if I run payload.db.init or payload.db.connect anywhere. Thus, when resetting the database, we are not dropping the schema, but are instead only deleting the table values
|
|
*/
|
|
let restored = false
|
|
if (
|
|
!alwaysSeed &&
|
|
dbSnapshot[snapshotKey] &&
|
|
Object.keys(dbSnapshot[snapshotKey]).length &&
|
|
!deleteOnly
|
|
) {
|
|
await restoreFromSnapshot(_payload, snapshotKey, collectionSlugs)
|
|
|
|
/**
|
|
* Restore uploads dir if it exists
|
|
*/
|
|
if (uploadsDirCache[snapshotKey]) {
|
|
for (const cache of uploadsDirCache[snapshotKey]) {
|
|
if (cache.originalDir && fs.existsSync(cache.cacheDir)) {
|
|
// move all files from inside uploadsDirCacheFolder to uploadsDir
|
|
await fs.promises
|
|
.readdir(cache.cacheDir, { withFileTypes: true })
|
|
.then(async (files) => {
|
|
for (const file of files) {
|
|
if (file.isDirectory()) {
|
|
await fs.promises.mkdir(path.join(cache.originalDir, file.name), {
|
|
recursive: true,
|
|
})
|
|
await fs.promises.copyFile(
|
|
path.join(cache.cacheDir, file.name),
|
|
path.join(cache.originalDir, file.name),
|
|
)
|
|
} else {
|
|
await fs.promises.copyFile(
|
|
path.join(cache.cacheDir, file.name),
|
|
path.join(cache.originalDir, file.name),
|
|
)
|
|
}
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
console.error('Error in operation (restoring uploads dir):', err)
|
|
throw err
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
restored = true
|
|
}
|
|
|
|
/**
|
|
* Mongoose: Re-create indexes
|
|
* Postgres: No need for any action here, since we only delete the table data and no schemas
|
|
*/
|
|
// Dropping the db breaks indexes (on mongoose - did not test extensively on postgres yet), so we recreate them here
|
|
try {
|
|
if (isMongoose(_payload)) {
|
|
await Promise.all([
|
|
...collectionSlugs
|
|
.filter(
|
|
(collectionSlug) =>
|
|
['payload-migrations', 'payload-preferences', 'payload-locked-documents'].indexOf(
|
|
collectionSlug,
|
|
) === -1,
|
|
)
|
|
.map(async (collectionSlug) => {
|
|
await _payload.db.collections[collectionSlug]?.createIndexes({
|
|
// Blocks writes (doesn't matter here) but faster
|
|
background: false,
|
|
})
|
|
}),
|
|
])
|
|
}
|
|
} catch (e) {
|
|
console.error('Error in operation (re-creating indexes):', e)
|
|
}
|
|
|
|
/**
|
|
* If a snapshot was restored, we don't need to seed the database
|
|
*/
|
|
if (restored || deleteOnly) {
|
|
return
|
|
}
|
|
|
|
/**
|
|
* Seed the database with data and save it to a snapshot
|
|
**/
|
|
if (typeof seedFunction === 'function') {
|
|
await seedFunction(_payload)
|
|
}
|
|
|
|
if (!alwaysSeed) {
|
|
await createSnapshot(_payload, snapshotKey, collectionSlugs)
|
|
}
|
|
|
|
/**
|
|
* Cache uploads dir to a cache folder if uploadsDir exists
|
|
*/
|
|
if (!alwaysSeed && uploadsDir) {
|
|
const uploadsDirs = Array.isArray(uploadsDir) ? uploadsDir : [uploadsDir]
|
|
for (const dir of uploadsDirs) {
|
|
if (dir && fs.existsSync(dir)) {
|
|
if (!uploadsDirCache[snapshotKey]) {
|
|
uploadsDirCache[snapshotKey] = []
|
|
}
|
|
let newObj: {
|
|
cacheDir: string
|
|
originalDir: string
|
|
} | null = null
|
|
if (!uploadsDirCache[snapshotKey].find((cache) => cache.originalDir === dir)) {
|
|
// Define new cache folder path to the OS temp directory (well a random folder inside it)
|
|
newObj = {
|
|
originalDir: dir,
|
|
cacheDir: path.join(os.tmpdir(), `${snapshotKey}`, `payload-e2e-tests-uploads-cache`),
|
|
}
|
|
}
|
|
if (!newObj) {
|
|
continue
|
|
}
|
|
|
|
// delete the cache folder if it exists
|
|
if (fs.existsSync(newObj.cacheDir)) {
|
|
await fs.promises.rm(newObj.cacheDir, { recursive: true })
|
|
}
|
|
await fs.promises.mkdir(newObj.cacheDir, { recursive: true })
|
|
// recursively move all files and directories from uploadsDir to uploadsDirCacheFolder
|
|
|
|
try {
|
|
const files = await fs.promises.readdir(newObj.originalDir, { withFileTypes: true })
|
|
|
|
for (const file of files) {
|
|
if (file.isDirectory()) {
|
|
await fs.promises.mkdir(path.join(newObj.cacheDir, file.name), {
|
|
recursive: true,
|
|
})
|
|
await fs.promises.copyFile(
|
|
path.join(newObj.originalDir, file.name),
|
|
path.join(newObj.cacheDir, file.name),
|
|
)
|
|
} else {
|
|
await fs.promises.copyFile(
|
|
path.join(newObj.originalDir, file.name),
|
|
path.join(newObj.cacheDir, file.name),
|
|
)
|
|
}
|
|
}
|
|
|
|
uploadsDirCache[snapshotKey].push(newObj)
|
|
} catch (e) {
|
|
console.error('Error in operation (creating snapshot of uploads dir):', e)
|
|
throw e
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|