/** @jest-environment node */ import { mkdtemp, readFile, rm, writeFile } from 'fs/promises' import os from 'os' import path from 'path' import { existsSync } from 'fs' import { prepareOperationsGMaterialFiles } from '@/lib/material-access-scope-storage' import { downloadS3ObjectToFile } from '@/lib/s3' import { resolveStoredUploadPath } from '@/lib/upload-paths' jest.mock('@/lib/s3', () => ({ downloadS3ObjectToFile: jest.fn(), uploadToS3: jest.fn(), uploadFileToS3: jest.fn() })) let root: string const prior = { upload: process.env.UPLOAD_DIR, domain: process.env.S3_PUBLIC_DOMAIN, prefix: process.env.S3_FILE_PATH } beforeEach(async () => { root = await mkdtemp(path.join(os.tmpdir(), 'material-scope-storage-')) process.env.UPLOAD_DIR = root process.env.S3_PUBLIC_DOMAIN = 'https://storage.scope.local' process.env.S3_FILE_PATH = 'scope' jest.clearAllMocks() ;(downloadS3ObjectToFile as jest.Mock).mockImplementation(async (url: string, destination: string) => { await writeFile(destination, Buffer.from(`object:${url}`)) }) }) afterEach(async () => { for (const [key, value] of Object.entries({ UPLOAD_DIR: prior.upload, S3_PUBLIC_DOMAIN: prior.domain, S3_FILE_PATH: prior.prefix })) { if (value === undefined) delete process.env[key] else process.env[key] = value } expect(root.startsWith(path.join(os.tmpdir(), 'material-scope-storage-'))).toBe(true) await rm(root, { recursive: true, force: true }) }) test('更改范围时复制公开原件与预览,素材、资产和 SKU 共享同一份受保护文件', async () => { const preview = 'https://storage.scope.local/scope/preview.webp' const source = 'https://storage.scope.local/scope/source.zip' const result = await prepareOperationsGMaterialFiles({ id: 'material-1', previewUrl: preview, zipFilePath: source, zipFileName: 'source.zip', displayImages: [preview], }, [{ id: 'asset-1', fileUrl: preview }], [{ id: 'sku-1', filePath: source, previewUrl: preview }]) expect(downloadS3ObjectToFile).toHaveBeenCalledTimes(2) expect(result.assetFiles[0].fileUrl).toBe(result.materialFiles.previewUrl) expect(result.skuFiles[0].previewUrl).toBe(result.materialFiles.previewUrl) expect(result.skuFiles[0].filePath).toBe(result.materialFiles.zipFilePath) expect(result.publicUrls).toEqual([preview, source]) const stored = result.materialFiles.previewUrl as string expect(stored).toMatch(/^uploads\/materials\/material-1\/protected-display\//) expect(await readFile(resolveStoredUploadPath(stored), 'utf8')).toBe(`object:${preview}`) }) test('白底图的派生预览迁入可按原图定位的鉴权目录', async () => { const result = await prepareOperationsGMaterialFiles({ id: 'material-1' }, [{ id: 'asset-1', fileUrl: 'uploads/materials/material-1/white-background/sku-1/front.webp', }]) const expected = 'uploads/materials/material-1/protected-display/white-background/material-1/sku-1/front.webp' expect(existsSync(resolveStoredUploadPath(expected))).toBe(true) expect(result.publicUrls).toEqual(['https://storage.scope.local/scope/public-display/white-background/material-1/sku-1/front.webp']) expect(result.assetFiles).toEqual([]) })