Files
atlas-seller-kit/apps/api/test/watermark-position.unit.test.ts
T

110 lines
4.9 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest';
import { createWatermarkTemplateRequestSchema } from '@atlas/contracts';
import { WatermarksService } from '../src/watermarks/watermarks.service.js';
const templateId = '46ea1f9c-28d0-4b32-92e1-3d4e74ad7757';
const templateRow = (x: number, y: number, position: string) => ({
id: templateId,
name: '测试水印',
kind: 'text' as const,
current_version: 1,
created_at: new Date('2026-09-25T00:00:00Z'),
updated_at: new Date('2026-09-25T00:00:00Z'),
revision: 1,
text_content: 'Atlas',
image_asset_id: null,
font_code: 'NotoSans',
font_size_px: 15,
opacity: '0.2600',
scale_ratio: null,
position,
position_x: x.toFixed(4),
position_y: y.toFixed(4),
});
describe('水印任意位置坐标', () => {
it('契约接收精确坐标、兼容旧位置,并拒绝创建时只给一个坐标', () => {
const base = {
name: '测试水印',
kind: 'text',
config: {
text_content: 'Atlas',
font_code: 'NotoSans',
font_size_px: 15,
opacity: '0.26',
},
};
expect(createWatermarkTemplateRequestSchema.safeParse({
...base, config: { ...base.config, position_x: 0.3737, position_y: 0.6161 },
}).success).toBe(true);
expect(createWatermarkTemplateRequestSchema.safeParse({
...base, config: { ...base.config, position: 'bottom_right' },
}).success).toBe(true);
expect(createWatermarkTemplateRequestSchema.safeParse({
...base, config: { ...base.config, position_x: 0.3737 },
}).success).toBe(false);
});
it('创建时保存精确坐标并在读取响应中返回,不吸附九宫格', async () => {
let insertedVersion: unknown[] = [];
const query = vi.fn(async (sql: string, args?: unknown[]) => {
if (sql.includes('SELECT code FROM atlas.watermark_fonts')) return { rows: [{ code: 'NotoSans' }] };
if (sql.includes('INSERT INTO atlas.watermark_templates')) return { rows: [{ id: templateId }] };
if (sql.includes('INSERT INTO atlas.watermark_template_versions')) {
insertedVersion = args ?? [];
return { rows: [] };
}
if (sql.includes('SELECT template.id')) return { rows: [templateRow(
Number(insertedVersion[9]), Number(insertedVersion[10]), String(insertedVersion[11]),
)] };
throw new Error(`未知 SQL: ${sql}`);
});
const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise<unknown>) =>
work({ query }));
const service = new WatermarksService(
{ run } as unknown as ConstructorParameters<typeof WatermarksService>[0],
{} as ConstructorParameters<typeof WatermarksService>[1],
);
const result = await service.create('workspace', 'user', 'key', {
name: '测试水印', kind: 'text',
config: {
text_content: 'Atlas', font_code: 'NotoSans', font_size_px: 15,
opacity: '0.26', position_x: 0.3737, position_y: 0.6161,
},
});
expect(insertedVersion.slice(9, 12)).toEqual([0.3737, 0.6161, 'center']);
expect(result).toMatchObject({
body: { data: { config: { position_x: 0.3737, position_y: 0.6161 } } },
});
});
it('旧版九宫格输入换算为精确坐标', async () => {
let insertedVersion: unknown[] = [];
const query = vi.fn(async (sql: string, args?: unknown[]) => {
if (sql.includes('SELECT code FROM atlas.watermark_fonts')) return { rows: [{ code: 'NotoSans' }] };
if (sql.includes('INSERT INTO atlas.watermark_templates')) return { rows: [{ id: templateId }] };
if (sql.includes('INSERT INTO atlas.watermark_template_versions')) {
insertedVersion = args ?? [];
return { rows: [] };
}
if (sql.includes('SELECT template.id')) return { rows: [templateRow(1, 0, 'top_right')] };
throw new Error(`未知 SQL: ${sql}`);
});
const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise<unknown>) =>
work({ query }));
const service = new WatermarksService(
{ run } as unknown as ConstructorParameters<typeof WatermarksService>[0],
{} as ConstructorParameters<typeof WatermarksService>[1],
);
await service.create('workspace', 'user', 'key', {
name: '测试水印', kind: 'text',
config: {
text_content: 'Atlas', font_code: 'NotoSans', font_size_px: 15,
opacity: '0.26', position: 'top_right',
},
});
expect(insertedVersion.slice(9, 12)).toEqual([1, 0, 'top_right']);
});
});