135 lines
3.9 KiB
TypeScript
135 lines
3.9 KiB
TypeScript
/** @jest-environment node */
|
|
|
|
import { POST } from '@/app/api/admin/regenerate-preview/route'
|
|
import { getServerSession } from 'next-auth'
|
|
import { prisma } from '@/lib/prisma'
|
|
import { uploadPublicDisplayToS3 } from '@/lib/public-display'
|
|
|
|
jest.mock('next-auth', () => ({
|
|
getServerSession: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/auth', () => ({
|
|
authOptions: {},
|
|
}))
|
|
|
|
jest.mock('fs/promises', () => ({
|
|
readFile: jest.fn(),
|
|
unlink: jest.fn(),
|
|
mkdir: jest.fn(),
|
|
rm: jest.fn(),
|
|
readdir: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/prisma', () => ({
|
|
prisma: {
|
|
material: {
|
|
findUnique: jest.fn(),
|
|
update: jest.fn(),
|
|
},
|
|
materialAsset: {
|
|
findMany: jest.fn(),
|
|
deleteMany: jest.fn(),
|
|
createMany: jest.fn(),
|
|
},
|
|
},
|
|
}))
|
|
|
|
jest.mock('sharp', () =>
|
|
jest.fn(() => ({
|
|
metadata: jest.fn().mockResolvedValue({ width: 1200, height: 2400 }),
|
|
})),
|
|
)
|
|
|
|
jest.mock('@/lib/image-processor', () => ({
|
|
sliceImage: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/public-display', () => ({
|
|
...jest.requireActual('@/lib/public-display'),
|
|
uploadPublicDisplayToS3: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('adm-zip', () =>
|
|
jest.fn().mockImplementation(() => ({
|
|
extractAllTo: jest.fn(),
|
|
})),
|
|
)
|
|
|
|
describe('admin regenerate-preview route', () => {
|
|
const fsPromises = jest.requireMock('fs/promises') as {
|
|
readFile: jest.Mock
|
|
mkdir: jest.Mock
|
|
rm: jest.Mock
|
|
readdir: jest.Mock
|
|
}
|
|
const { sliceImage } = jest.requireMock('@/lib/image-processor') as {
|
|
sliceImage: jest.Mock
|
|
}
|
|
let dateNowSpy: jest.SpyInstance
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
;(getServerSession as jest.Mock).mockResolvedValue({
|
|
user: { id: 'admin-1' },
|
|
})
|
|
;(prisma.material.findUnique as jest.Mock).mockResolvedValue({
|
|
id: 'material-1',
|
|
})
|
|
;(prisma.materialAsset.findMany as jest.Mock).mockResolvedValue([
|
|
{
|
|
materialId: 'material-1',
|
|
assetType: 'detail',
|
|
fileUrl: 'uploads/materials/detail.zip',
|
|
},
|
|
])
|
|
;(prisma.materialAsset.deleteMany as jest.Mock).mockResolvedValue({ count: 2 })
|
|
;(prisma.materialAsset.createMany as jest.Mock).mockResolvedValue({ count: 2 })
|
|
;(prisma.material.update as jest.Mock).mockResolvedValue(undefined)
|
|
fsPromises.mkdir.mockResolvedValue(undefined)
|
|
fsPromises.rm.mockResolvedValue(undefined)
|
|
fsPromises.readdir.mockResolvedValue(['detail.png'])
|
|
fsPromises.readFile.mockResolvedValue(Buffer.from('detail-image'))
|
|
sliceImage.mockResolvedValue([Buffer.from('slice-1'), Buffer.from('slice-2')])
|
|
;(uploadPublicDisplayToS3 as jest.Mock)
|
|
.mockResolvedValueOnce('https://s3.jiansun.vip/gongxiangpan/public-display/task-detail/material-1/detail/detail-preview-1.webp')
|
|
.mockResolvedValueOnce('https://s3.jiansun.vip/gongxiangpan/public-display/task-detail/material-1/detail/detail-preview-2.webp')
|
|
dateNowSpy = jest.spyOn(Date, 'now').mockReturnValue(1712222222222)
|
|
})
|
|
|
|
afterEach(() => {
|
|
dateNowSpy.mockRestore()
|
|
})
|
|
|
|
test('管理员重建详情预览时应写入 public-display task-detail 前缀', async () => {
|
|
const request = {
|
|
json: jest.fn().mockResolvedValue({ materialId: 'material-1' }),
|
|
} as any
|
|
|
|
const response = await POST(request)
|
|
const body = await response.json()
|
|
|
|
expect(response.status).toBe(200)
|
|
expect(body.success).toBe(true)
|
|
expect(uploadPublicDisplayToS3).toHaveBeenNthCalledWith(
|
|
1,
|
|
Buffer.from('slice-1'),
|
|
'task-detail/material-1/detail/detail-preview-1712222222222-0-slice0.webp',
|
|
'image/webp',
|
|
)
|
|
expect(uploadPublicDisplayToS3).toHaveBeenNthCalledWith(
|
|
2,
|
|
Buffer.from('slice-2'),
|
|
'task-detail/material-1/detail/detail-preview-1712222222222-1-slice1.webp',
|
|
'image/webp',
|
|
)
|
|
expect(prisma.material.update).toHaveBeenCalledWith({
|
|
where: { id: 'material-1' },
|
|
data: {
|
|
previewUrl:
|
|
'https://s3.jiansun.vip/gongxiangpan/public-display/task-detail/material-1/detail/detail-preview-1.webp',
|
|
},
|
|
})
|
|
})
|
|
})
|