chore: tests: uploads dir: delete and restore snapshot between tests (#5560)
* chore: tests: uploads dir: delete and restore snapshot between tests * chore: add missing creation of uploads dir cache folder * fix logic
This commit is contained in:
@@ -1,10 +1,11 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import * as os from 'node:os'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { type Payload } from 'payload'
|
import { type Payload } from 'payload'
|
||||||
|
|
||||||
import { isMongoose } from './isMongoose.js'
|
import { isMongoose } from './isMongoose.js'
|
||||||
import { resetDB } from './reset.js'
|
import { resetDB } from './reset.js'
|
||||||
import { createSnapshot, dbSnapshot, restoreFromSnapshot } from './snapshot.js'
|
import { createSnapshot, dbSnapshot, restoreFromSnapshot, uploadsDirCache } from './snapshot.js'
|
||||||
|
|
||||||
type SeedFunction = (_payload: Payload) => Promise<void>
|
type SeedFunction = (_payload: Payload) => Promise<void>
|
||||||
|
|
||||||
@@ -14,8 +15,13 @@ export async function seedDB({
|
|||||||
seedFunction,
|
seedFunction,
|
||||||
snapshotKey,
|
snapshotKey,
|
||||||
uploadsDir,
|
uploadsDir,
|
||||||
|
/**
|
||||||
|
* Always seeds, instead of restoring from snapshot for consecutive test runs
|
||||||
|
*/
|
||||||
|
alwaysSeed = false,
|
||||||
}: {
|
}: {
|
||||||
_payload: Payload
|
_payload: Payload
|
||||||
|
alwaysSeed?: boolean
|
||||||
collectionSlugs: string[]
|
collectionSlugs: string[]
|
||||||
seedFunction: SeedFunction
|
seedFunction: SeedFunction
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +34,25 @@ export async function seedDB({
|
|||||||
* Reset database
|
* Reset database
|
||||||
*/
|
*/
|
||||||
await resetDB(_payload, collectionSlugs)
|
await resetDB(_payload, collectionSlugs)
|
||||||
|
/**
|
||||||
|
* Delete uploads directory if it exists
|
||||||
|
*/
|
||||||
|
if (uploadsDir) {
|
||||||
|
try {
|
||||||
|
// Attempt to clear the uploads directory if it exists
|
||||||
|
await fs.promises.access(uploadsDir)
|
||||||
|
const files = await fs.promises.readdir(uploadsDir)
|
||||||
|
for (const file of files) {
|
||||||
|
await fs.promises.rm(path.join(uploadsDir, file))
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code !== 'ENOENT') {
|
||||||
|
// If the error is not because the directory doesn't exist
|
||||||
|
console.error('Error in operation (deleting uploads dir):', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mongoose & Postgres: Restore snapshot of old data if available
|
* Mongoose & Postgres: Restore snapshot of old data if available
|
||||||
@@ -36,8 +61,40 @@ export async function seedDB({
|
|||||||
* 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
|
* 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
|
let restored = false
|
||||||
if (dbSnapshot[snapshotKey] && Object.keys(dbSnapshot[snapshotKey]).length) {
|
if (!alwaysSeed && dbSnapshot[snapshotKey] && Object.keys(dbSnapshot[snapshotKey]).length) {
|
||||||
await restoreFromSnapshot(_payload, snapshotKey, collectionSlugs)
|
await restoreFromSnapshot(_payload, snapshotKey, collectionSlugs)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore uploads dir if it exists
|
||||||
|
*/
|
||||||
|
if (uploadsDir && fs.existsSync(uploadsDirCache.path)) {
|
||||||
|
// move all files from inside uploadsDirCacheFolder to uploadsDir
|
||||||
|
await fs.promises
|
||||||
|
.readdir(uploadsDirCache.path, { withFileTypes: true })
|
||||||
|
.then(async (files) => {
|
||||||
|
for (const file of files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
await fs.promises.mkdir(path.join(uploadsDir, file.name), {
|
||||||
|
recursive: true,
|
||||||
|
})
|
||||||
|
await fs.promises.copyFile(
|
||||||
|
path.join(uploadsDirCache.path, file.name),
|
||||||
|
path.join(uploadsDir, file.name),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
await fs.promises.copyFile(
|
||||||
|
path.join(uploadsDirCache.path, file.name),
|
||||||
|
path.join(uploadsDir, file.name),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Error in operation (restoring uploads dir):', err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
restored = true
|
restored = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +106,7 @@ export async function seedDB({
|
|||||||
if (isMongoose(_payload)) {
|
if (isMongoose(_payload)) {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
...collectionSlugs.map(async (collectionSlug) => {
|
...collectionSlugs.map(async (collectionSlug) => {
|
||||||
|
// @ts-expect-error TODO: Type this better
|
||||||
await _payload.db.collections[collectionSlug].createIndexes()
|
await _payload.db.collections[collectionSlug].createIndexes()
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
@@ -61,33 +119,53 @@ export async function seedDB({
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete uploads directory only if no snapshot was restored.
|
|
||||||
* The snapshot restoration only restores the database state, not the uploads directory.
|
|
||||||
* If we ran it after or before restoring the snapshot, we would have NO upload files anymore, as they are not restored from the snapshot. And after snapshot
|
|
||||||
* restoration the seed process is not run again
|
|
||||||
*/
|
|
||||||
if (uploadsDir) {
|
|
||||||
try {
|
|
||||||
// Attempt to clear the uploads directory if it exists
|
|
||||||
await fs.promises.access(uploadsDir)
|
|
||||||
const files = await fs.promises.readdir(uploadsDir)
|
|
||||||
for (const file of files) {
|
|
||||||
await fs.promises.rm(path.join(uploadsDir, file))
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (error.code !== 'ENOENT') {
|
|
||||||
// If the error is not because the directory doesn't exist
|
|
||||||
console.error('Error in operation:', error)
|
|
||||||
throw error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Seed the database with data and save it to a snapshot
|
* Seed the database with data and save it to a snapshot
|
||||||
**/
|
**/
|
||||||
await seedFunction(_payload)
|
await seedFunction(_payload)
|
||||||
|
|
||||||
await createSnapshot(_payload, snapshotKey, collectionSlugs)
|
if (!alwaysSeed) {
|
||||||
|
await createSnapshot(_payload, snapshotKey, collectionSlugs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache uploads dir to a cache folder if uploadsDir exists
|
||||||
|
*/
|
||||||
|
if (!alwaysSeed && uploadsDir && fs.existsSync(uploadsDir)) {
|
||||||
|
if (!uploadsDirCache.path) {
|
||||||
|
// Define new cache folder path to the OS temp directory (well a random folder inside it)
|
||||||
|
uploadsDirCache.path = path.join(os.tmpdir(), `payload-e2e-tests-uploads-cache`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the cache folder if it exists
|
||||||
|
if (fs.existsSync(uploadsDirCache.path)) {
|
||||||
|
await fs.promises.rm(uploadsDirCache.path, { recursive: true })
|
||||||
|
}
|
||||||
|
await fs.promises.mkdir(uploadsDirCache.path, { recursive: true })
|
||||||
|
// recursively move all files and directories from uploadsDir to uploadsDirCacheFolder
|
||||||
|
await fs.promises
|
||||||
|
.readdir(uploadsDir, { withFileTypes: true })
|
||||||
|
.then(async (files) => {
|
||||||
|
for (const file of files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
await fs.promises.mkdir(path.join(uploadsDirCache.path, file.name), {
|
||||||
|
recursive: true,
|
||||||
|
})
|
||||||
|
await fs.promises.copyFile(
|
||||||
|
path.join(uploadsDir, file.name),
|
||||||
|
path.join(uploadsDirCache.path, file.name),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
await fs.promises.copyFile(
|
||||||
|
path.join(uploadsDir, file.name),
|
||||||
|
path.join(uploadsDirCache.path, file.name),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('Error in operation (creating snapshot of uploads dir):', err)
|
||||||
|
throw err
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ import { sql } from 'drizzle-orm'
|
|||||||
|
|
||||||
import { isMongoose } from './isMongoose.js'
|
import { isMongoose } from './isMongoose.js'
|
||||||
|
|
||||||
|
export const uploadsDirCache: {
|
||||||
|
path: null | string
|
||||||
|
} = {
|
||||||
|
path: null,
|
||||||
|
}
|
||||||
export const dbSnapshot = {}
|
export const dbSnapshot = {}
|
||||||
|
|
||||||
async function createMongooseSnapshot(collectionsObj, snapshotKey: string) {
|
async function createMongooseSnapshot(collectionsObj, snapshotKey: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user