82 lines
4.3 KiB
TypeScript
82 lines
4.3 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
import { AspectRatioDerivativeService } from '../src/media/aspect-ratio-derivative.service.js';
|
|
|
|
const workspaceId = '30cf54b7-06a3-4e5f-a5fc-d74165115094';
|
|
const sourceAssetId = '664d0d73-3d39-4a98-ac0a-5c0e521d8998';
|
|
const derivativeId = '68db226f-3fcb-4579-ab9e-4932b1d84067';
|
|
const productId = '733d0d73-3d39-4a98-ac0a-5c0e521d8998';
|
|
|
|
describe('一键 3:4 派生任务', () => {
|
|
it('在同一个租户事务写入派生记录、操作进度和 Outbox', async () => {
|
|
const statements: string[] = [];
|
|
const query = vi.fn(async (sql: string) => {
|
|
statements.push(sql);
|
|
if (sql.includes('SELECT id FROM atlas.media_assets')) return { rows: [{ id: sourceAssetId }] };
|
|
if (sql.includes('RETURNING id')) return { rows: [{ id: derivativeId }] };
|
|
return { rows: [] };
|
|
});
|
|
const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise<unknown>) =>
|
|
work({ query }));
|
|
const service = new AspectRatioDerivativeService(
|
|
{} as ConstructorParameters<typeof AspectRatioDerivativeService>[0],
|
|
{ run } as unknown as ConstructorParameters<typeof AspectRatioDerivativeService>[1],
|
|
{} as ConstructorParameters<typeof AspectRatioDerivativeService>[2],
|
|
);
|
|
const result = await service.create(
|
|
workspaceId,
|
|
'user-id',
|
|
sourceAssetId,
|
|
'idempotency-key',
|
|
{ preset: '3:4', fit: 'contain' },
|
|
);
|
|
expect(result).toMatchObject({
|
|
status: 202,
|
|
body: { data: { id: derivativeId, status: 'queued', source_asset_id: sourceAssetId } },
|
|
});
|
|
expect(run).toHaveBeenCalledOnce();
|
|
expect(statements.some((sql) => sql.includes('INSERT INTO atlas.media_aspect_ratio_derivatives'))).toBe(true);
|
|
expect(statements.some((sql) => sql.includes('INSERT INTO atlas.operations'))).toBe(true);
|
|
expect(statements.some((sql) => sql.includes('INSERT INTO atlas.outbox_events'))).toBe(true);
|
|
});
|
|
|
|
it('缺少或跨工作空间的源素材不会创建任务', async () => {
|
|
const query = vi.fn(async () => ({ rows: [] }));
|
|
const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise<unknown>) =>
|
|
work({ query }));
|
|
const service = new AspectRatioDerivativeService(
|
|
{} as ConstructorParameters<typeof AspectRatioDerivativeService>[0],
|
|
{ run } as unknown as ConstructorParameters<typeof AspectRatioDerivativeService>[1],
|
|
{} as ConstructorParameters<typeof AspectRatioDerivativeService>[2],
|
|
);
|
|
await expect(service.create(
|
|
workspaceId,
|
|
'user-id',
|
|
sourceAssetId,
|
|
'idempotency-key',
|
|
{ preset: '3:4', fit: 'contain' },
|
|
)).rejects.toMatchObject({ status: 404 });
|
|
expect(query).toHaveBeenCalledOnce();
|
|
});
|
|
|
|
it('将当前工作空间的商品关联到新派生任务', async () => {
|
|
const query = vi.fn(async (sql: string, values?: unknown[]) => {
|
|
if (sql.includes('SELECT id FROM atlas.media_assets')) return { rows: [{ id: sourceAssetId }] };
|
|
if (sql.includes('SELECT id FROM atlas.products')) return { rows: [{ id: productId }] };
|
|
if (sql.includes('INSERT INTO atlas.media_aspect_ratio_derivatives')) {
|
|
expect(values).toEqual([productId, sourceAssetId, 'user-id']);
|
|
return { rows: [{ id: derivativeId }] };
|
|
}
|
|
return { rows: [] };
|
|
});
|
|
const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise<unknown>) => work({ query }));
|
|
const service = new AspectRatioDerivativeService(
|
|
{} as ConstructorParameters<typeof AspectRatioDerivativeService>[0],
|
|
{ run } as unknown as ConstructorParameters<typeof AspectRatioDerivativeService>[1],
|
|
{} as ConstructorParameters<typeof AspectRatioDerivativeService>[2],
|
|
);
|
|
await service.create(workspaceId, 'user-id', sourceAssetId, 'key',
|
|
{ preset: '3:4', fit: 'contain', product_id: productId });
|
|
expect(query.mock.calls.some(([sql]) => String(sql).includes('INSERT INTO atlas.media_aspect_ratio_derivatives'))).toBe(true);
|
|
});
|
|
});
|