|
| 1 | +jest.mock('@/utils/CopilotAPI', () => ({ CopilotAPI: class {} })) |
| 2 | +jest.mock('@/lib/db', () => ({ __esModule: true, default: { getInstance: () => ({}) } })) |
| 3 | +jest.mock('@/app/api/attachments/public/public.serializer', () => ({ |
| 4 | + PublicAttachmentSerializer: { serializeAttachments: jest.fn(async () => []) }, |
| 5 | +})) |
| 6 | +jest.mock('@/utils/santizeContents', () => ({ sanitizeHtml: (value: string) => value })) |
| 7 | +jest.mock('@/utils/signedUrlReplacer', () => ({ |
| 8 | + replaceMediaSources: jest.fn(async (value: string) => value), |
| 9 | + replaceImageSrc: jest.fn(async (value: string) => value), |
| 10 | +})) |
| 11 | +jest.mock('@/utils/signUrl', () => ({ getSignedUrl: jest.fn(async (value: string) => value) })) |
| 12 | +jest.mock('@/utils/signedTemplateUrlReplacer', () => ({ |
| 13 | + copyTemplateMediaToTask: jest.fn(async (_workspaceId: string, value: string) => value), |
| 14 | +})) |
| 15 | + |
| 16 | +import { PublicTaskSerializer, TaskWithWorkflowStateAndAttachments } from './public.serializer' |
| 17 | + |
| 18 | +const IU_ID = '22222222-2222-2222-2222-222222222222' |
| 19 | + |
| 20 | +const makeTask = (overrides: Partial<TaskWithWorkflowStateAndAttachments> = {}): TaskWithWorkflowStateAndAttachments => |
| 21 | + ({ |
| 22 | + id: '11111111-1111-1111-1111-111111111111', |
| 23 | + title: 'A task', |
| 24 | + body: null, |
| 25 | + parentId: null, |
| 26 | + dueDate: null, |
| 27 | + label: '', |
| 28 | + templateId: null, |
| 29 | + createdById: IU_ID, |
| 30 | + completedAt: null, |
| 31 | + createdAt: new Date('2026-01-01T00:00:00.000Z'), |
| 32 | + isArchived: false, |
| 33 | + lastArchivedDate: null, |
| 34 | + archivedBy: null, |
| 35 | + deletedAt: null, |
| 36 | + source: 'api', |
| 37 | + deletedBy: null, |
| 38 | + completedBy: null, |
| 39 | + completedByUserType: null, |
| 40 | + internalUserId: IU_ID, |
| 41 | + clientId: null, |
| 42 | + companyId: null, |
| 43 | + associations: [], |
| 44 | + isShared: false, |
| 45 | + workflowState: { type: 'started' }, |
| 46 | + attachments: [], |
| 47 | + ...overrides, |
| 48 | + }) as unknown as TaskWithWorkflowStateAndAttachments |
| 49 | + |
| 50 | +// OUT-4029: label generation was removed but the public API keeps the `label` |
| 51 | +// field for backward compatibility — empty string for new tasks, the stored |
| 52 | +// value for pre-existing ones. These lock that contract so a future change |
| 53 | +// can't silently drop the field again. |
| 54 | +describe('PublicTaskSerializer — label backward compatibility', () => { |
| 55 | + it('returns an empty-string label for tasks created after label generation was removed', async () => { |
| 56 | + const result = await PublicTaskSerializer.serializeUnsafe(makeTask({ label: '' })) |
| 57 | + expect(result.label).toBe('') |
| 58 | + }) |
| 59 | + |
| 60 | + it('preserves the pre-existing generated label for older tasks', async () => { |
| 61 | + const result = await PublicTaskSerializer.serializeUnsafe(makeTask({ label: 'OUT-001' })) |
| 62 | + expect(result.label).toBe('OUT-001') |
| 63 | + }) |
| 64 | + |
| 65 | + it('keeps label in the schema-validated public DTO', async () => { |
| 66 | + const result = await PublicTaskSerializer.serialize(makeTask({ label: 'OUT-001' })) |
| 67 | + expect(result.label).toBe('OUT-001') |
| 68 | + }) |
| 69 | +}) |
0 commit comments