From 06f2a00eb561cf36c27c31ea86901ae8580e1c42 Mon Sep 17 00:00:00 2001 From: saileshwar-skyflow Date: Thu, 15 May 2025 00:37:54 +0530 Subject: [PATCH 1/2] SK-2048: fix detect tests --- test/vault/controller/detect.test.js | 901 ++++++++++++++++----------- 1 file changed, 523 insertions(+), 378 deletions(-) diff --git a/test/vault/controller/detect.test.js b/test/vault/controller/detect.test.js index ade596ee..30a53e0e 100644 --- a/test/vault/controller/detect.test.js +++ b/test/vault/controller/detect.test.js @@ -57,6 +57,11 @@ describe('DetectController', () => { deidentifyString: jest.fn(), reidentifyString: jest.fn(), }, + filesAPI: { + deidentifyPdf: jest.fn(), + deidentifyAudio: jest.fn(), + getRun: jest.fn(), + }, failureResponse: jest.fn().mockRejectedValue(new Error('API error')), vaultId: 'vault123', }; @@ -331,7 +336,7 @@ describe('reidentifyText', () => { }); }); -describe('DetectController - Files', () => { +describe('getDetectRun', () => { let mockVaultClient; let detectController; @@ -341,519 +346,659 @@ describe('DetectController - Files', () => { getCredentials: jest.fn().mockReturnValue({}), initAPI: jest.fn(), filesAPI: { - deidentifyText: jest.fn(), - deidentifyAudio: jest.fn(), - deidentifyPdf: jest.fn(), - deidentifyImage: jest.fn(), - deidentifyPresentation: jest.fn(), - deidentifySpreadsheet: jest.fn(), - deidentifyStructuredText: jest.fn(), - deidentifyDocument: jest.fn(), - deidentifyFile: jest.fn(), getRun: jest.fn(), }, failureResponse: jest.fn().mockRejectedValue(new Error('API error')), vaultId: 'vault123', }; + detectController = new DetectController(mockVaultClient); jest.clearAllMocks(); }); - const mockFile = new File(['test content'], 'test.txt', { type: 'text/plain' }); - const mockRequest = new DeidentifyFileRequest(mockFile); - const mockOptions = new DeidentifyFileOptions(); - mockOptions.setWaitTime(16); - - const mockPollResponse = { - status: 'SUCCESS', - output: [ - { - processedFile: 'mockProcessedFile', - processedFileType: 'text', - processedFileExtension: 'txt', - }, - ], - wordCharacterCount: { - wordCount: 100, - characterCount: 500, - }, - size: 1024, - duration: 0, - pages: 0, - slides: 0, - }; - - const setupPolling = () => { - mockVaultClient.filesAPI.getRun - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // First poll - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // Second poll - .mockResolvedValueOnce(mockPollResponse); // Final poll - }; - - test('should successfully deidentify an audio file', async () => { + test('should successfully get detect run and parse response', async () => { jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), + validateGetDetectRunRequest: jest.fn(), })); - validateDeidentifyFileRequest.mockImplementation(() => { + validateGetDetectRunRequest.mockImplementation(() => { // No validation error }); - detectController = new DetectController(mockVaultClient); - const audioFile = new File(['audio content'], 'test.mp3', { type: 'audio/mpeg' }); - const audioRequest = new DeidentifyFileRequest(audioFile); - - setupPolling(); + const mockRequest = { runId: 'mockRunId' }; + const mockResponseData = { + output: [ + { + processedFile: 'mockProcessedFile', + processedFileType: 'text', + processedFileExtension: 'txt', + }, + ], + wordCharacterCount: { + wordCount: 100, + characterCount: 500, + }, + size: 1024, + duration: 0, + pages: 1, + slides: 0, + run_id: 'mockRunId', + }; - mockVaultClient.filesAPI.deidentifyAudio.mockImplementation(() => ({ + mockVaultClient.filesAPI.getRun.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, + data: mockResponseData, rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, }), })); - const result = await detectController.deidentifyFile(audioRequest, mockOptions); + const result = await detectController.getDetectRun(mockRequest); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + expect(mockVaultClient.filesAPI.getRun).toHaveBeenCalledWith( + mockRequest.runId, + { vault_id: 'vault123' } + ); + }); + + test('should handle validation errors', async () => { + const mockRequest = { runId: 'mockRunId' }; + validateGetDetectRunRequest.mockImplementation(() => { + throw new Error('Validation error'); + }); + + await expect(detectController.getDetectRun(mockRequest)).rejects.toThrow('Validation error'); + expect(mockVaultClient.filesAPI.getRun).not.toHaveBeenCalled(); }); - test('should successfully deidentify a PDF file', async () => { + test('should handle API errors during getDetectRun', async () => { jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), + validateGetDetectRunRequest: jest.fn(), })); - validateDeidentifyFileRequest.mockImplementation(() => { + validateGetDetectRunRequest.mockImplementation(() => { // No validation error }); - detectController = new DetectController(mockVaultClient); - const pdfFile = new File(['pdf content'], 'test.pdf', { type: 'application/pdf' }); - const pdfRequest = new DeidentifyFileRequest(pdfFile); + const mockRequest = { runId: 'mockRunId' }; + mockVaultClient.filesAPI.getRun.mockImplementation(() => ({ + withRawResponse: jest.fn().mockRejectedValue(new Error('API error')), + })); - setupPolling(); + await expect(detectController.getDetectRun(mockRequest)).rejects.toThrow('API error'); + }); +}); - mockVaultClient.filesAPI.deidentifyPdf.mockImplementation(() => ({ - withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, - }), - })); +describe('deidentifyFile', () => { + let mockVaultClient; + let detectController; - const result = await detectController.deidentifyFile(pdfRequest, mockOptions); + beforeEach(() => { + jest.useFakeTimers(); + mockVaultClient = { + getLogLevel: jest.fn().mockReturnValue('DEBUG'), + getCredentials: jest.fn().mockReturnValue({}), + initAPI: jest.fn(), + filesAPI: { + deidentifyText: jest.fn(), + deidentifyAudio: jest.fn(), + deidentifyPdf: jest.fn(), + deidentifyImage: jest.fn(), + deidentifyPresentation: jest.fn(), + deidentifySpreadsheet: jest.fn(), + deidentifyStructuredText: jest.fn(), + deidentifyDocument: jest.fn(), + deidentifyFile: jest.fn(), + getRun: jest.fn(), + }, + failureResponse: jest.fn().mockRejectedValue(new Error('API error')), + vaultId: 'vault123', + }; + detectController = new DetectController(mockVaultClient); + jest.clearAllMocks(); + }); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + afterEach(() => { + jest.useRealTimers(); }); - test('should successfully deidentify a PDF file and save processed file to output directory', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - - detectController = new DetectController(mockVaultClient); - - const pdfFile = new File(['pdf content'], 'test.pdf', { type: 'application/pdf' }); - const pdfRequest = new DeidentifyFileRequest(pdfFile); - - const mockOptions = new DeidentifyFileOptions(); - mockOptions.setWaitTime(16); - mockOptions.setOutputDirectory('/mock/output/directory'); // Set the output directory - - // Mock the deidentifyPdf API call + test('should successfully deidentify a PDF file and poll until SUCCESS', async () => { + // Arrange + const file = new File(['dummy content'], 'test.pdf', { type: 'application/pdf' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); + options.setPixelDensity(300); + options.setMaxResolution(2000); + + // Mock PDF deidentify API to return a run_id mockVaultClient.filesAPI.deidentifyPdf.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, + data: { run_id: 'run123' }, rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, }), })); - - // Mock the getRun API call for polling - mockVaultClient.filesAPI.getRun = jest.fn() - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // First poll - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // Second poll - .mockResolvedValueOnce({ // Final poll + + // Polling: IN_PROGRESS twice, then SUCCESS + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ status: 'SUCCESS', output: [ { - processedFile: Buffer.from('mockProcessedFileContent').toString('base64'), // Base64-encoded content + processedFile: 'mockProcessedFile', processedFileType: 'pdf', processedFileExtension: 'pdf', }, ], wordCharacterCount: { - wordCount: 100, - characterCount: 500, + wordCount: 10, + characterCount: 100, }, - size: 1024, + size: 2048, duration: 0, - pages: 10, + pages: 2, slides: 0, + run_id: 'run123', }); - - // Mock the file system to avoid actual file writes - jest.spyOn(fs, 'existsSync').mockImplementation((path) => path === '/mock/output/directory'); - jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {}); - jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); - - const result = await detectController.deidentifyFile(pdfRequest, mockOptions); - - // Assertions for the response + + // Act + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + + // Fast-forward all timers and flush all microtasks + await jest.runAllTimersAsync(); + + const result = await promise; + + // Assert + expect(mockVaultClient.filesAPI.deidentifyPdf).toHaveBeenCalled(); + expect(mockVaultClient.filesAPI.getRun).toHaveBeenCalledTimes(3); + expect(result.file).toBe('mockProcessedFile'); + expect(result.type).toBe('pdf'); expect(result.extension).toBe('pdf'); - - // Assertions for processDeidentifyFileResponse - expect(fs.existsSync).toHaveBeenCalledWith('/mock/output/directory'); - expect(fs.writeFileSync).toHaveBeenCalledWith( - '/mock/output/directory/processed-test.pdf', - expect.any(Buffer) - ); + expect(result.wordCount).toBe(10); + expect(result.charCount).toBe(100); + expect(result.sizeInKb).toBe(2048); + expect(result.pageCount).toBe(2); + expect(result.runId).toBe('run123'); + expect(result.status).toBe('SUCCESS'); }); - test('should successfully deidentify an image file', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const imageFile = new File(['image content'], 'test.png', { type: 'image/png' }); - const imageRequest = new DeidentifyFileRequest(imageFile); - - setupPolling(); + test('should reject for PDF if polling returns FAILED', async () => { + const file = new File(['dummy content'], 'test.pdf', { type: 'application/pdf' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); - mockVaultClient.filesAPI.deidentifyImage.mockImplementation(() => ({ + mockVaultClient.filesAPI.deidentifyPdf.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, + data: { run_id: 'run123' }, rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, }), })); - const result = await detectController.deidentifyFile(imageRequest, mockOptions); + mockVaultClient.filesAPI.getRun.mockResolvedValue({ status: 'FAILED', message: 'Processing failed' }); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + await expect(detectController.deidentifyFile(deidentifyFileReq, options)).rejects.toThrow(); }); - test('should successfully deidentify a presentation file', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const pptFile = new File(['ppt content'], 'test.pptx', { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' }); - const pptRequest = new DeidentifyFileRequest(pptFile); + test('should reject for PDF if polling throws error', async () => { + const file = new File(['dummy content'], 'test.pdf', { type: 'application/pdf' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); - setupPolling(); - - mockVaultClient.filesAPI.deidentifyPresentation.mockImplementation(() => ({ + mockVaultClient.filesAPI.deidentifyPdf.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, + data: { run_id: 'run123' }, rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, }), })); - const result = await detectController.deidentifyFile(pptRequest, mockOptions); + mockVaultClient.filesAPI.getRun.mockRejectedValue(new Error('Polling error')); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + await expect(detectController.deidentifyFile(deidentifyFileReq, options)).rejects.toThrow('Polling error'); }); - test('should successfully deidentify a spreadsheet file', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), + test('should reject if deidentifyPdf throws error', async () => { + const file = new File(['dummy content'], 'test.pdf', { type: 'application/pdf' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); + + mockVaultClient.filesAPI.deidentifyPdf.mockImplementation(() => ({ + withRawResponse: jest.fn().mockRejectedValue(new Error('API error')), })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const spreadsheetFile = new File(['spreadsheet content'], 'test.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); - const spreadsheetRequest = new DeidentifyFileRequest(spreadsheetFile); - setupPolling(); + await expect(detectController.deidentifyFile(deidentifyFileReq, options)).rejects.toThrow('API error'); + }); - mockVaultClient.filesAPI.deidentifySpreadsheet.mockImplementation(() => ({ + test('should successfully deidentify an audio file and poll until SUCCESS', async () => { + const file = new File(['audio content'], 'test.mp3'); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); + + mockVaultClient.filesAPI.deidentifyAudio.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, + data: { run_id: 'audioRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-456') } }, }), })); - const result = await detectController.deidentifyFile(spreadsheetRequest, mockOptions); + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'audioProcessedFile', + processedFileType: 'mp3', + processedFileExtension: 'mp3', + }, + ], + wordCharacterCount: { + wordCount: 5, + characterCount: 50, + }, + size: 512, + duration: 10, + pages: 0, + slides: 0, + run_id: 'audioRunId', + }); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); - }); + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); - test('should successfully deidentify a structured text file', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const structuredTextFile = new File(['structured text content'], 'test.json', { type: 'application/json' }); - const structuredTextRequest = new DeidentifyFileRequest(structuredTextFile); + const result = await promise; + expect(mockVaultClient.filesAPI.deidentifyAudio).toHaveBeenCalled(); + }); - setupPolling(); + test('should successfully deidentify an image file and poll until SUCCESS', async () => { + const file = new File(['image content'], 'test.png', { type: 'image/png' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); - mockVaultClient.filesAPI.deidentifyStructuredText.mockImplementation(() => ({ + mockVaultClient.filesAPI.deidentifyImage.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, + data: { run_id: 'imgRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-789') } }, }), })); - const result = await detectController.deidentifyFile(structuredTextRequest, mockOptions); + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'imgProcessedFile', + processedFileType: 'png', + processedFileExtension: 'png', + }, + ], + wordCharacterCount: { + wordCount: 2, + characterCount: 20, + }, + size: 256, + duration: 0, + pages: 0, + slides: 0, + run_id: 'imgRunId', + }); + + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + const result = await promise; + expect(mockVaultClient.filesAPI.deidentifyImage).toHaveBeenCalled(); + expect(mockVaultClient.filesAPI.getRun).toHaveBeenCalledTimes(3); }); - test('should successfully deidentify a document file', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const documentFile = new File(['document content'], 'test.docx', { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); - const documentRequest = new DeidentifyFileRequest(documentFile); + test('should successfully deidentify a spreadsheet file and poll until SUCCESS', async () => { + const file = new File(['spreadsheet content'], 'test.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); - setupPolling(); - - mockVaultClient.filesAPI.deidentifyDocument.mockImplementation(() => ({ + mockVaultClient.filesAPI.deidentifySpreadsheet.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, + data: { run_id: 'sheetRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-321') } }, }), })); - const result = await detectController.deidentifyFile(documentRequest, mockOptions); + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'sheetProcessedFile', + processedFileType: 'xlsx', + processedFileExtension: 'xlsx', + }, + ], + wordCharacterCount: { + wordCount: 8, + characterCount: 80, + }, + size: 1024, + duration: 0, + pages: 0, + slides: 0, + run_id: 'sheetRunId', + }); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(mockVaultClient.filesAPI.deidentifySpreadsheet).toHaveBeenCalled(); + expect(result.file).toBe('sheetProcessedFile'); + expect(result.type).toBe('xlsx'); + expect(result.extension).toBe('xlsx'); + expect(result.wordCount).toBe(8); + expect(result.charCount).toBe(80); + expect(result.sizeInKb).toBe(1024); + expect(result.runId).toBe('sheetRunId'); + expect(result.status).toBe('SUCCESS'); }); - test('should successfully deidentify a generic file', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const genericFile = new File(['generic content'], 'test.zip', { type: 'application/zip' }); - const genericRequest = new DeidentifyFileRequest(genericFile); + test('should successfully deidentify a ppt file and poll until SUCCESS', async () => { + const file = new File(['ppt content'], 'test.pptx', { type: 'application/vnd.openxmlformats-officedocument.presentationml.presentation' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); - setupPolling(); - - mockVaultClient.filesAPI.deidentifyFile.mockImplementation(() => ({ + mockVaultClient.filesAPI.deidentifyPresentation.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, + data: { run_id: 'pptRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-654') } }, }), })); - const result = await detectController.deidentifyFile(genericRequest, mockOptions); + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'pptProcessedFile', + processedFileType: 'pptx', + processedFileExtension: 'pptx', + }, + ], + wordCharacterCount: { + wordCount: 3, + characterCount: 30, + }, + size: 2048, + duration: 0, + pages: 0, + slides: 5, + run_id: 'pptRunId', + }); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); - expect(result.extension).toBe('txt'); + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result.file).toBe('pptProcessedFile'); + expect(result.type).toBe('pptx'); + expect(result.extension).toBe('pptx'); + expect(result.wordCount).toBe(3); + expect(result.charCount).toBe(30); + expect(result.sizeInKb).toBe(2048); + expect(result.slideCount).toBe(5); + expect(result.runId).toBe('pptRunId'); + expect(result.status).toBe('SUCCESS'); }); - test('should throw validation error', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), + test('should successfully deidentify a structured text file and poll until SUCCESS', async () => { + const file = new File(['json content'], 'test.json', { type: 'application/json' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); + + mockVaultClient.filesAPI.deidentifyStructuredText.mockImplementation(() => ({ + withRawResponse: jest.fn().mockResolvedValue({ + data: { run_id: 'jsonRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-987') } }, + }), })); - validateDeidentifyFileRequest.mockImplementation(() => { - throw new Error("Validation error"); - }); - - // Initialize DetectController - detectController = new DetectController(mockVaultClient); - - // Create a generic file and request - const genericFile = new File(['generic content'], 'test.zip', { type: 'application/zip' }); - const genericRequest = new DeidentifyFileRequest(genericFile); - - // Assert that the deidentifyFile method throws the validation error - await expect(detectController.deidentifyFile(genericRequest, mockOptions)).rejects.toThrow("Validation error"); + + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'jsonProcessedFile', + processedFileType: 'json', + processedFileExtension: 'json', + }, + ], + wordCharacterCount: { + wordCount: 6, + characterCount: 60, + }, + size: 512, + duration: 0, + pages: 0, + slides: 0, + run_id: 'jsonRunId', + }); + + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result.file).toBe('jsonProcessedFile'); + expect(result.type).toBe('json'); + expect(result.extension).toBe('json'); + expect(result.wordCount).toBe(6); + expect(result.charCount).toBe(60); + expect(result.sizeInKb).toBe(512); + expect(result.runId).toBe('jsonRunId'); + expect(result.status).toBe('SUCCESS'); }); - test('should successfully deidentify a text file with processed file after polling', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - detectController = new DetectController(mockVaultClient); - const mockFile = new File(['test content'], 'test.txt', { type: 'text/plain' }); - const mockRequest = new DeidentifyFileRequest(mockFile); - const mockOptions = new DeidentifyFileOptions(); - mockOptions.setWaitTime(16); + test('should successfully deidentify a document file and poll until SUCCESS', async () => { + const file = new File(['doc content'], 'test.docx', { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); - mockVaultClient.filesAPI.deidentifyText.mockImplementation(() => ({ + mockVaultClient.filesAPI.deidentifyDocument.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, + data: { run_id: 'docRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-111') } }, }), })); - mockVaultClient.filesAPI.getRun = jest.fn() - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // First poll - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // Second poll - .mockResolvedValueOnce({ // Final poll - status: 'SUCCESS', - output: [ - { - processedFile: 'mockProcessedFile', - processedFileType: 'text', - processedFileExtension: 'txt', + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'docProcessedFile', + processedFileType: 'docx', + processedFileExtension: 'docx', + }, + ], + wordCharacterCount: { + wordCount: 7, + characterCount: 70, }, - ], - wordCharacterCount: { - wordCount: 100, - characterCount: 500, - }, - size: 1024, - duration: 0, - pages: 0, - slides: 0, - }); - + size: 1024, + duration: 0, + pages: 1, + slides: 0, + run_id: 'docRunId', + }); - const result = await detectController.deidentifyFile(mockRequest, mockOptions); - expect(result.file).toBe('mockProcessedFile'); - expect(result.type).toBe('text'); + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result.file).toBe('docProcessedFile'); + expect(result.type).toBe('docx'); + expect(result.extension).toBe('docx'); + expect(result.wordCount).toBe(7); + expect(result.charCount).toBe(70); + expect(result.sizeInKb).toBe(1024); + expect(result.pageCount).toBe(1); + expect(result.runId).toBe('docRunId'); + expect(result.status).toBe('SUCCESS'); }); - test('should handle error when getRun method rejects during polling', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateDeidentifyFileRequest: jest.fn(), - })); - validateDeidentifyFileRequest.mockImplementation(() => { - // No validation error - }); - - detectController = new DetectController(mockVaultClient); - const mockFile = new File(['test content'], 'test.txt', { type: 'text/plain' }); - const mockRequest = new DeidentifyFileRequest(mockFile); - const mockOptions = new DeidentifyFileOptions(); - mockOptions.setWaitTime(16); - + test('should successfully deidentify a text file and poll until SUCCESS', async () => { + const file = new File(['doc content'], 'test.txt'); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); + mockVaultClient.filesAPI.deidentifyText.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: { run_id: 'mockRunId' }, - rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, + data: { run_id: 'docRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-111') } }, }), })); - - // Simulate getRun method rejecting with an error - mockVaultClient.filesAPI.getRun = jest.fn() - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // First poll - .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) // Second poll - .mockRejectedValueOnce(new Error('Polling failed')); // Third poll rejects with an error - - await expect(detectController.deidentifyFile(mockRequest, mockOptions)).rejects.toThrow('Polling failed'); - }); - -}); + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'textProcessedFile', + processedFileType: 'text', + processedFileExtension: 'txt', + }, + ], + wordCharacterCount: { + wordCount: 7, + characterCount: 70, + }, + size: 1024, + duration: 0, + pages: 1, + slides: 0, + run_id: 'textRunId', + }); -describe('getDetectRun', () => { - let mockVaultClient; - let detectController; + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); - beforeEach(() => { - mockVaultClient = { - getLogLevel: jest.fn().mockReturnValue('DEBUG'), - getCredentials: jest.fn().mockReturnValue({}), - initAPI: jest.fn(), - filesAPI: { - getRun: jest.fn(), - }, - failureResponse: jest.fn().mockRejectedValue(new Error('API error')), - vaultId: 'vault123', - }; - detectController = new DetectController(mockVaultClient); - jest.clearAllMocks(); + const result = await promise; + expect(result.file).toBe('textProcessedFile'); + expect(result.extension).toBe('txt'); + expect(result.wordCount).toBe(7); + expect(result.charCount).toBe(70); + expect(result.sizeInKb).toBe(1024); + expect(result.pageCount).toBe(1); + expect(result.status).toBe('SUCCESS'); }); - test('should successfully get detect run and parse response', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateGetDetectRunRequest: jest.fn(), + test('should successfully deidentify a generic file and poll until SUCCESS', async () => { + const file = new File(['generic content'], 'test.abc', { type: 'application/octet-stream' }); + const deidentifyFileReq = new DeidentifyFileRequest(file); + const options = new DeidentifyFileOptions(); + + mockVaultClient.filesAPI.deidentifyFile.mockImplementation(() => ({ + withRawResponse: jest.fn().mockResolvedValue({ + data: { run_id: 'genRunId' }, + rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-222') } }, + }), })); - validateGetDetectRunRequest.mockImplementation(() => { - // No validation error - }); - const mockRequest = { runId: 'mockRunId' }; - const mockResponseData = { - output: [ - { - processedFile: 'mockProcessedFile', - processedFileType: 'text', - processedFileExtension: 'txt', + + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: 'genProcessedFile', + processedFileType: 'abc', + processedFileExtension: 'abc', + }, + ], + wordCharacterCount: { + wordCount: 4, + characterCount: 40, }, - ], - wordCharacterCount: { - wordCount: 100, - characterCount: 500, - }, - size: 1024, - duration: 0, - pages: 1, - slides: 0, - run_id: 'mockRunId', - }; + size: 256, + duration: 0, + pages: 0, + slides: 0, + run_id: 'genRunId', + }); - mockVaultClient.filesAPI.getRun.mockImplementation(() => ({ + const promise = detectController.deidentifyFile(deidentifyFileReq, options); + await jest.runAllTimersAsync(); + + const result = await promise; + expect(result.file).toBe('genProcessedFile'); + expect(result.type).toBe('abc'); + expect(result.extension).toBe('abc'); + expect(result.wordCount).toBe(4); + expect(result.charCount).toBe(40); + expect(result.sizeInKb).toBe(256); + expect(result.runId).toBe('genRunId'); + expect(result.status).toBe('SUCCESS'); + }); + + test('should successfully deidentify a PDF file and save processed file to output directory', async () => { + + const pdfFile = new File(['dummy content'], 'test.pdf', { type: 'application/pdf' }); + const pdfRequest = new DeidentifyFileRequest(pdfFile); + + const mockOptions = new DeidentifyFileOptions(); + mockOptions.setWaitTime(16); + mockOptions.setOutputDirectory('/mock/output/directory'); + + // Mock the deidentifyPdf API call + mockVaultClient.filesAPI.deidentifyPdf.mockImplementation(() => ({ withRawResponse: jest.fn().mockResolvedValue({ - data: mockResponseData, + data: { run_id: 'mockRunId' }, rawResponse: { headers: { get: jest.fn().mockReturnValue('request-id-123') } }, }), })); - const result = await detectController.getDetectRun(mockRequest); + // Mock the getRun API call for polling + mockVaultClient.filesAPI.getRun + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ status: 'IN_PROGRESS' }) + .mockResolvedValueOnce({ + status: 'SUCCESS', + output: [ + { + processedFile: Buffer.from('mockProcessedFileContent').toString('base64'), + processedFileType: 'pdf', + processedFileExtension: 'pdf', + }, + ], + wordCharacterCount: { + wordCount: 100, + characterCount: 500, + }, + size: 1024, + duration: 0, + pages: 10, + slides: 0, + }); - expect(mockVaultClient.filesAPI.getRun).toHaveBeenCalledWith( - mockRequest.runId, - { vault_id: 'vault123' } - ); - }); + // Mock the file system to avoid actual file writes + jest.spyOn(fs, 'existsSync').mockImplementation((path) => path === '/mock/output/directory'); + jest.spyOn(fs, 'mkdirSync').mockImplementation(() => {}); + jest.spyOn(fs, 'writeFileSync').mockImplementation(() => {}); - test('should handle validation errors', async () => { - const mockRequest = { runId: 'mockRunId' }; - validateGetDetectRunRequest.mockImplementation(() => { - throw new Error('Validation error'); - }); + const promise = detectController.deidentifyFile(pdfRequest, mockOptions); - await expect(detectController.getDetectRun(mockRequest)).rejects.toThrow('Validation error'); - expect(mockVaultClient.filesAPI.getRun).not.toHaveBeenCalled(); - }); + await jest.runAllTimersAsync(); - test('should handle API errors during getDetectRun', async () => { - jest.mock('../../../src/utils/validations', () => ({ - validateGetDetectRunRequest: jest.fn(), - })); - validateGetDetectRunRequest.mockImplementation(() => { - // No validation error - }); - const mockRequest = { runId: 'mockRunId' }; - mockVaultClient.filesAPI.getRun.mockImplementation(() => ({ - withRawResponse: jest.fn().mockRejectedValue(new Error('API error')), - })); + const result = await promise; + + // Assertions for the response + expect(result.extension).toBe('pdf'); - await expect(detectController.getDetectRun(mockRequest)).rejects.toThrow('API error'); + // Assertions for processDeidentifyFileResponse + expect(fs.existsSync).toHaveBeenCalledWith('/mock/output/directory'); + expect(fs.writeFileSync).toHaveBeenCalledWith( + '/mock/output/directory/processed-test.pdf', + expect.any(Buffer) + ); }); }); \ No newline at end of file From 8062dd95f3c990e51a9d1e1c721ec195867948b3 Mon Sep 17 00:00:00 2001 From: saileshwar-skyflow Date: Thu, 15 May 2025 00:52:13 +0530 Subject: [PATCH 2/2] SK-2048: fix client tests --- test/vault/client/client.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/vault/client/client.test.js b/test/vault/client/client.test.js index da9c622b..0bffa47f 100644 --- a/test/vault/client/client.test.js +++ b/test/vault/client/client.test.js @@ -94,7 +94,7 @@ describe('VaultClient', () => { }); test('should initialize Strings for DETECT', () => { - vaultClient.initAPI(authInfo, TYPES.DETECT); + vaultClient.initAPI(authInfo, TYPES.DEIDENTIFY_TEXT); expect(Strings).toHaveBeenCalled(); });