94 lines
3.1 KiB
TypeScript
94 lines
3.1 KiB
TypeScript
/** @jest-environment node */
|
|
|
|
import { generatePreviewImages, resolveUniqueZipEntryName } from '@/lib/task-material-processor'
|
|
import { uploadPublicDisplayToS3 } from '@/lib/public-display'
|
|
import { uploadToS3 } from '@/lib/s3'
|
|
import { compressImage } from '@/lib/image-processor'
|
|
|
|
jest.mock('fs/promises', () => ({
|
|
readFile: jest.fn(),
|
|
mkdir: jest.fn(),
|
|
unlink: jest.fn(),
|
|
rm: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/upload-sessions', () => ({
|
|
getUploadedFile: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/upload-sessions-redis', () => ({
|
|
deleteUploadSession: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/image-processor', () => ({
|
|
compressImage: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/public-display', () => ({
|
|
...jest.requireActual('@/lib/public-display'),
|
|
uploadPublicDisplayToS3: jest.fn(),
|
|
}))
|
|
|
|
jest.mock('@/lib/s3', () => ({
|
|
uploadToS3: jest.fn(),
|
|
deleteFromS3: jest.fn(),
|
|
}))
|
|
|
|
describe('task-material-processor', () => {
|
|
const fsPromises = jest.requireMock('fs/promises') as {
|
|
readFile: jest.Mock
|
|
}
|
|
const { getUploadedFile } = jest.requireMock('@/lib/upload-sessions') as {
|
|
getUploadedFile: jest.Mock
|
|
}
|
|
let dateNowSpy: jest.SpyInstance
|
|
let mathRandomSpy: jest.SpyInstance
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks()
|
|
fsPromises.readFile.mockResolvedValue(Buffer.from('source-image'))
|
|
getUploadedFile.mockResolvedValue('/tmp/uploaded/image.png')
|
|
;(compressImage as jest.Mock).mockResolvedValue(Buffer.from('compressed-image'))
|
|
;(uploadPublicDisplayToS3 as jest.Mock).mockResolvedValue(
|
|
'https://s3.jiansun.vip/gongxiangpan/public-display/materials/preview-123.webp',
|
|
)
|
|
;(uploadToS3 as jest.Mock).mockResolvedValue(
|
|
'https://s3.jiansun.vip/gongxiangpan/product-package/preview-123.webp',
|
|
)
|
|
dateNowSpy = jest.spyOn(Date, 'now').mockReturnValue(1711111111111)
|
|
mathRandomSpy = jest.spyOn(Math, 'random').mockReturnValue(0.123456789)
|
|
})
|
|
|
|
afterEach(() => {
|
|
dateNowSpy.mockRestore()
|
|
mathRandomSpy.mockRestore()
|
|
})
|
|
|
|
test('generatePreviewImages 应将任务类预览图写入 public-display materials 前缀', async () => {
|
|
const result = await generatePreviewImages(
|
|
[{ uploadId: 'upload-1', fileName: 'origin.png' }],
|
|
'任务-3D原图',
|
|
)
|
|
|
|
expect(result).toEqual([
|
|
'https://s3.jiansun.vip/gongxiangpan/public-display/materials/preview-123.webp',
|
|
])
|
|
expect(uploadPublicDisplayToS3).toHaveBeenCalledWith(
|
|
Buffer.from('compressed-image'),
|
|
expect.stringMatching(/^materials\/preview-1711111111111-0-[a-z0-9]+\.webp$/),
|
|
'image/webp',
|
|
)
|
|
expect(uploadToS3).not.toHaveBeenCalled()
|
|
})
|
|
|
|
test('resolveUniqueZipEntryName 应避免同名文件在解压时互相覆盖', () => {
|
|
const usedNames = new Set<string>()
|
|
|
|
expect(resolveUniqueZipEntryName('01.jpg', 0, usedNames)).toBe('01.jpg')
|
|
expect(resolveUniqueZipEntryName('01.jpg', 1, usedNames)).toBe('01-2.jpg')
|
|
expect(resolveUniqueZipEntryName('01.JPG', 2, usedNames)).toBe('01-3.JPG')
|
|
expect(resolveUniqueZipEntryName('主图/01.jpg', 3, usedNames)).toBe('主图_01.jpg')
|
|
expect(resolveUniqueZipEntryName('', 4, usedNames)).toBe('file-005')
|
|
})
|
|
})
|