import { describe, expect, it, vi } from 'vitest'; import { WatermarksService } from '../src/watermarks/watermarks.service.js'; const templateId = '46ea1f9c-28d0-4b32-92e1-3d4e74ad7757'; const templateRow = (isDefault: boolean) => ({ id: templateId, name: '品牌水印', kind: 'text' as const, is_default: isDefault, 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, image_size_px: null, border_radius_px: 0, position: 'center', position_x: '0.5000', position_y: '0.5000', }); describe('工作空间默认水印', () => { it('切换默认后返回新状态,重复设置不会再写入', async () => { let isDefault = false; const statements: string[] = []; const query = vi.fn(async (sql: string) => { statements.push(sql); if (sql.includes('SELECT id FROM atlas.workspaces')) return { rows: [{ id: 'workspace' }] }; if (sql.includes('SELECT template.id')) return { rows: [templateRow(isDefault)] }; if (sql.includes('SET is_default = false')) return { rows: [] }; if (sql.includes('SET is_default = true')) { isDefault = true; return { rows: [] }; } throw new Error(`未知 SQL: ${sql}`); }); const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise) => work({ query })); const service = new WatermarksService( { run } as unknown as ConstructorParameters[0], {} as ConstructorParameters[1], ); const first = await service.setDefault('workspace', 'user', templateId, 'key-1'); expect(first).toMatchObject({ status: 200, body: { data: { id: templateId, is_default: true } } }); expect(statements.filter((sql) => sql.includes('SET is_default'))).toHaveLength(2); expect(statements[0]).toContain('FOR UPDATE'); const second = await service.setDefault('workspace', 'user', templateId, 'key-2'); expect(second).toMatchObject({ status: 200, body: { data: { is_default: true } } }); expect(statements.filter((sql) => sql.includes('SET is_default'))).toHaveLength(2); expect(run).toHaveBeenCalledWith(expect.objectContaining({ method: 'PUT', path: `/api/watermark-templates/${templateId}/default`, }), expect.any(Function)); }); it('未设置默认时返回 null', async () => { const query = vi.fn(async () => ({ rows: [] })); const workspaceTransaction = vi.fn(async (_workspaceId: string, work: (tx: { query: typeof query }) => Promise) => work({ query })); const service = new WatermarksService( {} as ConstructorParameters[0], { workspaceTransaction } as unknown as ConstructorParameters[1], ); expect(await service.getDefault('workspace')).toBeNull(); expect(query.mock.calls).toHaveLength(1); expect(workspaceTransaction).toHaveBeenCalledWith('workspace', expect.any(Function)); }); it('删除默认模板时同时清除默认标记', async () => { const query = vi.fn(async (sql: string) => { if (sql.includes('SELECT template.id')) return { rows: [templateRow(true)] }; return { rows: [] }; }); const run = vi.fn(async (_input: unknown, work: (tx: { query: typeof query }) => Promise) => work({ query })); const service = new WatermarksService( { run } as unknown as ConstructorParameters[0], {} as ConstructorParameters[1], ); expect(await service.remove('workspace', 'user', templateId, 'key')).toEqual({ status: 204, body: null }); expect(query.mock.calls.some(([sql]) => sql.includes("status = 'archived'") && sql.includes('is_default = false'))).toBe(true); }); });