Files
atlas-seller-kit/apps/api/test/media-import.unit.test.ts
T

101 lines
3.9 KiB
TypeScript

import { createHash } from 'node:crypto';
import { describe, expect, it, vi } from 'vitest';
import { MediaService } from '../src/media/media.service.js';
vi.mock('../src/media/product-image-download.js', async (importOriginal) => {
const original =
await importOriginal<
typeof import('../src/media/product-image-download.js')
>();
return {
...original,
downloadProductImage: vi.fn(async () => ({
bytes: Buffer.from('validated-image'),
contentType: 'image/png',
width: 800,
height: 800,
})),
};
});
describe('网络商品图片导入', () => {
it('复用同工作空间素材并返回正式 ID 与短时预览地址', async () => {
const assetId = '7c910684-7070-4f36-8a7b-b10bd91acd79';
const bytes = Buffer.from('validated-image');
const checksum = createHash('sha256').update(bytes).digest('hex');
const query = vi.fn(async (sql: string, args?: unknown[]) => {
if (sql.includes('WHERE checksum_sha256 = $1')) {
expect(args).toEqual([checksum]);
return { rows: [{ id: assetId }] };
}
if (sql.includes('INSERT INTO atlas.product_image_imports')) {
expect(args?.[0]).toBe('https://example.com/photo.png');
expect(args?.[1]).toBe(assetId);
return { rows: [] };
}
if (sql.includes('SELECT id, content_type')) {
return {
rows: [
{
id: assetId,
content_type: 'image/png',
byte_size: '15',
width_px: 800,
height_px: 800,
created_at: new Date('2026-09-24T00:00:00Z'),
},
],
};
}
if (sql.includes('SELECT bucket, object_key')) {
return {
rows: [
{
bucket: 'test',
object_key: 'product-imports/existing.png',
},
],
};
}
throw new Error(`未知 SQL: ${sql}`);
});
const run = vi.fn(
async (
request: { path: string; key: string },
callback: (tx: { query: typeof query }) => Promise<unknown>,
) => {
expect(request.path).toBe('/api/media-assets/product-imports');
expect(request.key).toBe('idempotency-key');
return callback({ query });
},
);
const service = new MediaService(
{ run } as unknown as ConstructorParameters<typeof MediaService>[0],
{} as ConstructorParameters<typeof MediaService>[1],
{
OBJECT_STORAGE_ENDPOINT: 'http://127.0.0.1:9000',
OBJECT_STORAGE_BUCKET: 'test',
objectStorageForcePathStyle: true,
objectStorageAccessKey: 'test',
objectStorageSecretKey: 'test',
} as ConstructorParameters<typeof MediaService>[2],
);
const result = await service.importProductImage(
'workspace-id',
'user-id',
'idempotency-key',
{ url: 'https://example.com/photo.png' },
);
const body = result.body as {
data: { id: string; source_url: string; preview_url: string };
};
expect(result.status).toBe(201);
expect(body.data).toMatchObject({
id: assetId,
source_url: 'https://example.com/photo.png',
});
expect(body.data.preview_url).toContain('product-imports/existing.png');
expect(query).toHaveBeenCalledTimes(4);
});
});