Files
photo-live/apps/admin/e2e/seed-fixture.cjs
T

108 lines
3.5 KiB
JavaScript
Raw Normal View History

// e2e 数据种子夹具(Node 直跑,Playwright 用例内按需调用)。
// 为什么不用 API 造数:目标照片需要 published/processing_failed 等终态,
// 真实链路要 worker 处理流水线;e2e 只验证管理页展示与操作,直插 DB 行
// (uploadedAt 置位即可入管理列表,见 services/api listAlbumPhotos 过滤条件)。
// 依赖经 PHOTO_DB_CN 环境变量注入 @photo/db-cn 绝对路径(apps/admin 不依赖
// 该包,node 从文件位置解析不到;services/api 的 node_modules 里有现成链接)。
// 用法:
// node seed-fixture.cjs staff <account> <displayName>
// node seed-fixture.cjs photos <albumId> <uploaderAccount>
// 幂等:账号存在即跳过;照片按 objectKey upsert(同相册重复种不重复建行)。
const db_cn = process.env.PHOTO_DB_CN
const databaseUrl = process.env.DATABASE_URL_CN
if (!db_cn || !databaseUrl) {
console.error('seed-fixture: PHOTO_DB_CN and DATABASE_URL_CN env vars are required')
process.exit(1)
}
// CommonJS(node 直跑,无构建步骤):动态 require 经环境变量注入的包路径
// eslint-disable-next-line @typescript-eslint/no-require-imports
const { PrismaClient } = require(db_cn)
const prisma = new PrismaClient({ datasources: { db: { url: databaseUrl } } })
async function seedStaff(account, displayName) {
const existing = await prisma.users.findUnique({ where: { account } })
if (existing) {
console.log(`seed-fixture: staff "${account}" exists, skipping`)
return
}
// passwordHash 占位(不可登录):e2e 只经账号查询邀请该用户,从不登录
await prisma.users.create({
data: {
account,
passwordHash: 'seeded-no-login',
displayName: displayName || account,
role: 'staff',
credentialStatus: 'active'
}
})
console.log(`seed-fixture: staff "${account}" created`)
}
async function seedPhotos(albumId, uploaderAccount) {
const uploader = await prisma.users.findUnique({ where: { account: uploaderAccount } })
if (!uploader) {
throw new Error(`seed-fixture: uploader "${uploaderAccount}" not found`)
}
const now = new Date()
const rows = [
{
suffix: 'published',
visibility: 'published',
processingState: 'ready',
width: 1200,
height: 800,
publishedAt: now,
errorCode: null
},
{
suffix: 'failed',
visibility: 'unpublished',
processingState: 'processing_failed',
width: null,
height: null,
publishedAt: null,
errorCode: 'DECODE_FAILED'
}
]
for (const row of rows) {
const objectKey = `e2e-seed/albums/${albumId}/${row.suffix}.jpg`
await prisma.photos.upsert({
where: { objectKey },
update: {},
create: {
albumId,
uploaderId: uploader.id,
objectKey,
bytes: 2048,
width: row.width,
height: row.height,
uploadedAt: now,
publishedAt: row.publishedAt,
processingState: row.processingState,
errorCode: row.errorCode,
visibility: row.visibility
}
})
}
console.log(`seed-fixture: 2 photos seeded for album ${albumId}`)
}
async function main() {
const [mode, argA, argB] = process.argv.slice(2)
if (mode === 'staff') {
await seedStaff(argA, argB)
} else if (mode === 'photos') {
await seedPhotos(argA, argB)
} else {
throw new Error(`seed-fixture: unknown mode "${mode}"`)
}
}
main()
.catch((error) => {
console.error(error)
process.exitCode = 1
})
.finally(() => prisma.$disconnect())