import { describe, expect, it } from "vitest"; import { bulkBackgroundTask, decodeBackgroundTaskCursor, documentBackgroundTask, encodeBackgroundTaskCursor, sourceBackgroundTask, } from "./background-task"; import type { BulkOperation } from "./bulk-operation"; import type { BulkOperationSummary } from "./bulk-operation-summary"; import type { DocumentProcessingTask } from "./document-processing-task-repository"; import type { SourceWorkflowRun } from "./source-product-workflow"; const SPACE_ID = "018f0d60-7a49-7cc2-9c1b-5b36f18f2c40"; const CREATED_AT = "2026-07-23T12:00:00.000Z"; const UPDATED_AT = "2026-07-23T12:01:00.000Z"; describe("background task DTOs", () => { it("maps document terminal states to retry and cancel controls", () => { expect( documentBackgroundTask( documentTask({ completedAt: UPDATED_AT, errorCode: "PARSER_FAILED", errorMessage: "Parser failed", progressPercent: 20, state: "failed", }), ), ).toMatchObject({ canCancel: false, canRetry: true, errorCode: "DOCUMENT_PARSER_UNAVAILABLE", errorMessage: "The document parser is temporarily unavailable.", failure: { action: "retry", category: "dependency", code: "DOCUMENT_PARSER_UNAVAILABLE", retryPolicy: "automatic", }, operation: "document_processing", progressFailed: 1, state: "failed", taskKind: "document", }); expect(documentBackgroundTask(documentTask({ state: "retry_wait" }))).toMatchObject({ canCancel: true, canRetry: false, state: "queued", }); expect( documentBackgroundTask( documentTask({ errorCode: "MODEL_SELECTION_NOT_FOUND", errorMessage: "provider credential and endpoint detail", phase: "outline_summary", state: "failed", }), ), ).toMatchObject({ canRetry: false, errorMessage: "The selected model is no longer available in this workspace. Select another model before retrying.", failure: { action: "configure_model", code: "MODEL_SELECTION_NOT_FOUND", retryPolicy: "after_configuration", stage: "outline_summary", }, }); }); it("forwards additive document compilation and graph progress metadata", () => { expect( documentBackgroundTask( documentTask({ activeOperations: ["chunk", "fts_index", "embedding"], phase: "chunking_indexing", semanticEnrichment: { nodesCompleted: 32, nodesTotal: 80, state: "running", }, }), ), ).toMatchObject({ activeOperations: ["chunk", "fts_index", "embedding"], phase: "chunking_indexing", semanticEnrichment: { nodesCompleted: 32, nodesTotal: 80, state: "running", }, }); }); it.each([ ["succeeded", "completed", 1, false, false], ["canceled", "canceled", 0, false, true], ["superseded", "canceled", 0, false, true], ["running", "running", 0, true, false], ] as const)( "maps document state %s to public state %s", (state, publicState, progressCompleted, canCancel, canRetry) => { expect(documentBackgroundTask(documentTask({ state }))).toMatchObject({ canCancel, canRetry, progressCompleted, state: publicState, }); }, ); it("maps bulk and source task progress without treating canceled work as failed", () => { const operation: BulkOperation = { capabilityGrantId: "11111111-1111-4111-8111-111111111111", createdAt: CREATED_AT, id: "22222222-2222-4222-8222-222222222222", items: [], knowledgeSpaceId: SPACE_ID, tenantId: "tenant-1", type: "document_reindex", updatedAt: UPDATED_AT, }; const summary: BulkOperationSummary = { canceledItems: 1, completedItems: 2, createdAt: CREATED_AT, failedItemIds: [], failedItems: 0, id: operation.id, knowledgeSpaceId: SPACE_ID, status: "canceled", totalItems: 3, type: operation.type, updatedAt: UPDATED_AT, }; expect(bulkBackgroundTask(operation, summary)).toMatchObject({ canCancel: false, canRetry: true, progressCompleted: 2, progressFailed: 0, progressPercent: 100, state: "canceled", taskKind: "document_bulk", }); expect( sourceBackgroundTask( sourceRun({ progressCompleted: 4, progressFailed: 1, progressSkipped: 1, progressTotal: 8, state: "syncing", }), ), ).toMatchObject({ canCancel: true, canRetry: false, operation: "source_sync", progressCompleted: 4, progressFailed: 1, progressPercent: 75, progressTotal: 8, state: "running", taskKind: "source", }); }); it("maps empty bulk operations and every source terminal state", () => { const operation: BulkOperation = { createdAt: CREATED_AT, id: "22222222-2222-4222-8222-222222222222", items: [], knowledgeSpaceId: SPACE_ID, permissionSnapshot: { accessChannel: "interactive", id: "11111111-1111-4111-8111-111111111111", revision: 2, }, requestedBySubjectId: "member-a", tenantId: "tenant-1", type: "document_upload", updatedAt: UPDATED_AT, }; expect( bulkBackgroundTask(operation, { canceledItems: 0, completedItems: 0, createdAt: CREATED_AT, failedItemIds: [], failedItems: 0, id: operation.id, knowledgeSpaceId: SPACE_ID, status: "completed", totalItems: 0, type: operation.type, updatedAt: UPDATED_AT, }), ).toMatchObject({ canCancel: false, canRetry: false, completedAt: UPDATED_AT, operation: "document_upload", progressPercent: 100, state: "completed", }); expect( sourceBackgroundTask( sourceRun({ kind: "crawl-import", lastErrorCode: "SOURCE_FAILED", lastErrorMessage: "Source failed", progressTotal: 0, sourceId: undefined, state: "failed", }), ), ).toMatchObject({ canRetry: true, errorCode: "SOURCE_OPERATION_FAILED", errorMessage: "The source operation could not be completed.", failure: { action: "retry", code: "SOURCE_OPERATION_FAILED", retryPolicy: "manual", }, operation: "source_crawl_import", progressPercent: 100, state: "failed", }); expect( sourceBackgroundTask( sourceRun({ kind: "crawl-preview", progressTotal: 2, state: "completed" }), ), ).toMatchObject({ operation: "source_crawl_preview", progressCompleted: 2, state: "completed", }); expect( sourceBackgroundTask(sourceRun({ kind: "online-document-import", state: "zero_results" })), ).toMatchObject({ operation: "source_online_document_import", state: "completed", }); expect( sourceBackgroundTask(sourceRun({ kind: "online-drive-import", state: "preview_ready" })), ).toMatchObject({ operation: "source_online_drive_import", state: "completed", }); expect(sourceBackgroundTask(sourceRun({ kind: "bulk", state: "canceled" }))).toMatchObject({ canRetry: true, operation: "source_bulk", state: "canceled", }); expect(sourceBackgroundTask(sourceRun({ state: "queued" }))).toMatchObject({ canCancel: true, state: "queued", }); }); it("replaces raw bulk item diagnostics with the registered public failure", () => { const operation: BulkOperation = { createdAt: CREATED_AT, id: "22222222-2222-4222-8222-222222222222", items: [], knowledgeSpaceId: SPACE_ID, tenantId: "tenant-1", type: "document_reindex", updatedAt: UPDATED_AT, }; const task = bulkBackgroundTask(operation, { canceledItems: 0, completedItems: 0, createdAt: CREATED_AT, failedItemIds: ["document-1"], failedItems: 1, failures: [ { documentId: "document-1", errorCode: "MODEL_CREDENTIAL_INVALID", errorMessage: "Authorization: Bearer secret", }, ], id: operation.id, knowledgeSpaceId: SPACE_ID, status: "failed", totalItems: 1, type: operation.type, updatedAt: UPDATED_AT, }); expect(task).toMatchObject({ canRetry: false, errorMessage: "The selected model credentials are invalid. Ask an administrator to update the model provider configuration.", failures: [ { errorCode: "MODEL_CREDENTIAL_INVALID", errorMessage: "The selected model credentials are invalid. Ask an administrator to update the model provider configuration.", failure: { action: "configure_model", code: "MODEL_CREDENTIAL_INVALID", retryPolicy: "after_configuration", }, }, ], }); expect(JSON.stringify(task)).not.toContain("Bearer secret"); }); it("round-trips opaque composite cursors and rejects malformed values", () => { const cursor = { bulk: { createdAt: CREATED_AT, id: "bulk-1" }, document: { createdAt: UPDATED_AT, id: "document-1" }, version: 1 as const, }; expect(decodeBackgroundTaskCursor(encodeBackgroundTaskCursor(cursor))).toEqual(cursor); expect(() => decodeBackgroundTaskCursor("not-a-cursor")).toThrow( "Invalid background task cursor", ); expect(() => decodeBackgroundTaskCursor( Buffer.from( JSON.stringify({ document: { createdAt: "bad", id: "x" }, version: 1 }), ).toString("base64url"), ), ).toThrow("Invalid background task cursor"); }); it("validates every cursor component and preserves a source-only cursor", () => { const sourceOnly = { source: { createdAt: CREATED_AT, id: "source-1" }, version: 1 as const, }; expect(decodeBackgroundTaskCursor(encodeBackgroundTaskCursor(sourceOnly))).toEqual(sourceOnly); for (const value of [ null, [], { version: 2 }, { document: null, version: 1 }, { bulk: [], version: 1 }, { source: { createdAt: CREATED_AT, extra: true, id: "source-1" }, version: 1 }, { source: { createdAt: 1, id: "source-1" }, version: 1 }, { source: { createdAt: "not-a-date", id: "source-1" }, version: 1 }, { source: { createdAt: CREATED_AT, id: 1 }, version: 1 }, { source: { createdAt: CREATED_AT, id: "" }, version: 1 }, ]) { expect(() => decodeBackgroundTaskCursor(Buffer.from(JSON.stringify(value)).toString("base64url")), ).toThrow("Invalid background task cursor"); } }); }); function documentTask(patch: Partial = {}): DocumentProcessingTask { return { createdAt: CREATED_AT, documentId: "33333333-3333-4333-8333-333333333333", documentRevision: 2, id: "44444444-4444-4444-8444-444444444444", knowledgeSpaceId: SPACE_ID, progressPercent: 0, stage: "queued", state: "queued", updatedAt: UPDATED_AT, ...patch, }; } function sourceRun(patch: Partial = {}): SourceWorkflowRun { return { checkpoint: "queued", createdAt: CREATED_AT, executionAttempts: 1, id: "55555555-5555-4555-8555-555555555555", idempotencyKey: "sync-1", knowledgeSpaceId: SPACE_ID, kind: "sync", maxExecutionAttempts: 5, payload: {}, progressCompleted: 0, progressFailed: 0, progressSkipped: 0, rowVersion: 1, sourceId: "66666666-6666-4666-8666-666666666666", state: "queued", tenantId: "tenant-1", updatedAt: UPDATED_AT, ...patch, }; }