Skip to main content
Glama
PSPDFKit

Nutrient Document Engine MCP Server

by PSPDFKit
createRedaction.test.ts12.9 kB
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { createRedaction } from '../../../src/tools/annotations/createRedaction.js'; import { createMockClient, type MockedDocumentEngineClient } from '../../utils/mockTypes.js'; // Mock the logger to prevent console output during tests vi.mock('../../../src/utils/Logger.js', () => ({ logger: { error: vi.fn(), info: vi.fn(), debug: vi.fn(), warn: vi.fn(), }, })); describe('createRedaction', () => { let mockClient: MockedDocumentEngineClient; const mockDate = new Date('2023-01-01T12:00:00Z'); beforeEach(() => { mockClient = createMockClient(); // Mock Date.now and Math.random for consistent redaction IDs Date.now = vi.fn(() => mockDate.getTime()); Math.random = vi.fn(() => 0.123456789); }); afterEach(() => { // Restore original functions vi.restoreAllMocks(); }); describe('successful scenarios', () => { it('should create a regex redaction successfully', async () => { // Mock create-document-redactions response with matches const mockResponse = { data: { data: { annotations: [ { id: '123ABC', pageIndex: 0, bbox: [100, 200, 50, 30] }, { id: '456ABC', pageIndex: 0, bbox: [300, 400, 50, 30] }, { id: '789ABC', pageIndex: 2, bbox: [150, 250, 50, 30] }, ], }, }, }; mockClient['create-document-redactions'].mockResolvedValue(mockResponse); // Call the function const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, redaction_type: 'regex', pattern: '\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b', // Email pattern }); // Verify create-document-redactions was called with the correct parameters expect(mockClient['create-document-redactions']).toHaveBeenCalledWith( { documentId: 'doc_123' }, { strategy: 'regex', strategyOptions: { regex: '\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b', }, } ); // Verify the result contains the expected markdown expect(result.markdown).toContain('# Redaction Creation Complete'); // Check for redaction ID pattern (starts with 'red_' followed by numbers and letters) expect(result.markdown).toMatch(/🔍 \*\*Redaction IDs:\*\* \[[A-Za-z0-9, ]+\]/); expect(result.markdown).toContain('**Matches Found:** 3 instances'); expect(result.markdown).toContain('**Pages Affected:** 1, 3'); expect(result.markdown).toContain('**Preview Available:** Yes'); expect(result.markdown).toContain('## Redaction Summary'); expect(result.markdown).toContain('**Type:** Custom Regex'); expect(result.markdown).toContain( '**Pattern:** \\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b' ); expect(result.markdown).toContain('**Matches:** 3 instances'); expect(result.markdown).toContain('### 📍 Locations Found'); expect(result.markdown).toContain('- **Page 1:** 2 matches detected'); expect(result.markdown).toContain('- **Page 3:** 1 match detected'); expect(result.markdown).toContain('## ⚠️ Important Notes'); expect(result.markdown).toContain( '**Preview mode:** No content has been permanently redacted yet' ); expect(result.markdown).toContain('## Processing Summary'); expect(result.markdown).toContain('**Document ID:** doc_123'); }); it('should create a preset redaction successfully', async () => { // Mock create-document-redactions response with matches const mockResponse = { data: { data: { annotations: [{ pageIndex: 1, bbox: [100, 200, 50, 30] }], }, }, }; mockClient['create-document-redactions'].mockResolvedValue(mockResponse); // Call the function const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, redaction_type: 'preset', preset: 'credit-card-number', }); // Verify create-document-redactions was called with the correct parameters expect(mockClient['create-document-redactions']).toHaveBeenCalledWith( { documentId: 'doc_123' }, { strategy: 'preset', strategyOptions: { preset: 'credit-card-number', }, } ); // Verify the result contains the expected markdown expect(result.markdown).toContain('# Redaction Creation Complete'); expect(result.markdown).toContain('**Matches Found:** 1 instance'); expect(result.markdown).toContain('**Pages Affected:** 2'); expect(result.markdown).toContain('**Type:** Preset'); expect(result.markdown).toContain('**Pattern:** credit-card-number'); expect(result.markdown).toContain('Preset: Credit Card Number'); }); it('should create a text redaction successfully', async () => { // Mock create-document-redactions response with matches const mockResponse = { data: { data: { annotations: [ { pageIndex: 0, bbox: [100, 200, 50, 30] }, { pageIndex: 3, bbox: [300, 400, 50, 30] }, ], }, }, }; mockClient['create-document-redactions'].mockResolvedValue(mockResponse); // Call the function const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, redaction_type: 'text', text: 'CONFIDENTIAL', }); // Verify create-document-redactions was called with the correct parameters expect(mockClient['create-document-redactions']).toHaveBeenCalledWith( { documentId: 'doc_123' }, { strategy: 'text', strategyOptions: { text: 'CONFIDENTIAL', }, } ); // Verify the result contains the expected markdown expect(result.markdown).toContain('# Redaction Creation Complete'); expect(result.markdown).toContain('**Matches Found:** 2 instances'); expect(result.markdown).toContain('**Pages Affected:** 1, 4'); expect(result.markdown).toContain('**Type:** Text Match'); expect(result.markdown).toContain('**Pattern:** CONFIDENTIAL'); expect(result.markdown).toContain('Text: CONFIDENTIAL'); }); it('should handle no matches found', async () => { // Mock create-document-redactions response with no matches const mockResponse = { data: { data: { annotations: [], }, }, }; mockClient['create-document-redactions'].mockResolvedValue(mockResponse); // Call the function const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, redaction_type: 'regex', pattern: '\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b', }); // Verify the result contains the expected markdown expect(result.markdown).toContain('# Redaction Creation Complete'); expect(result.markdown).toContain('**Matches Found:** 0 instances'); expect(result.markdown).toContain('**Pages Affected:** None'); expect(result.markdown).toContain('## No Matches Found'); expect(result.markdown).toContain('**Pattern:** Custom Pattern:'); expect(result.markdown).toContain('**Suggestion:** Try adjusting your pattern'); }); it('should work with layers', async () => { // Mock create-document-redactions response with matches const mockResponse = { data: { data: { annotations: [ { id: '123LAYER', pageIndex: 0, bbox: [100, 200, 50, 30] }, { id: '456LAYER', pageIndex: 1, bbox: [300, 400, 50, 30] }, ], }, }, }; mockClient['create-document-layer-redactions'].mockResolvedValue(mockResponse); // Call the function with layer const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123', layer: 'review-layer', }, redaction_type: 'text', text: 'CONFIDENTIAL', }); // Verify the layer-specific endpoint was called expect(mockClient['create-document-layer-redactions']).toHaveBeenCalledWith( { documentId: 'doc_123', layerName: 'review-layer', }, { strategy: 'text', strategyOptions: { text: 'CONFIDENTIAL', }, } ); // Verify the default endpoint was NOT called expect(mockClient['create-document-redactions']).not.toHaveBeenCalled(); // Verify the result contains layer information expect(result.markdown).toContain('# Redaction Creation Complete'); expect(result.markdown).toContain('**Redaction IDs:** [123LAYER, 456LAYER]'); expect(result.markdown).toContain('**Matches Found:** 2 instances'); expect(result.markdown).toContain('**Pages Affected:** 1, 2'); expect(result.markdown).toContain('**Document ID:** doc_123'); expect(result.markdown).toContain('**Layer:** review-layer'); expect(result.markdown).toContain('Text: CONFIDENTIAL'); }); }); describe('error scenarios', () => { it('should handle API errors from create-document-redactions', async () => { // Mock create-document-redactions to throw an error const errorMessage = 'API Error: Failed to create redaction'; mockClient['create-document-redactions'].mockRejectedValue(new Error(errorMessage)); // Call the function const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, redaction_type: 'regex', pattern: '\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b', }); // Verify the result contains the error message expect(result.markdown).toContain('# Error Creating Redaction'); expect(result.markdown).toContain( `An error occurred while trying to create redaction analysis: ${errorMessage}` ); expect(result.markdown).toContain('**Document ID:** doc_123'); expect(result.markdown).toContain('**Redaction Type:** regex'); expect(result.markdown).toContain( '**Pattern:** \\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b' ); expect(result.markdown).toContain('## Troubleshooting Tips'); }); it('should handle validation errors for missing required fields', async () => { // Call the function with missing required fields const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, redaction_type: 'regex', // Missing pattern field // eslint-disable-next-line @typescript-eslint/no-explicit-any } as any); // Testing missing required fields for validation // Verify the result contains the validation error expect(result.markdown).toContain('# Error Creating Redaction'); expect(result.markdown).toContain( 'An error occurred while trying to create redaction analysis:' ); expect(result.markdown).toContain( 'Invalid redaction configuration: missing required fields for redaction type' ); }); it('should handle validation errors for invalid redaction type', async () => { // Call the function with invalid redaction type const result = await createRedaction(mockClient, { document_fingerprint: { document_id: 'doc_123' }, // eslint-disable-next-line @typescript-eslint/no-explicit-any redaction_type: 'invalid' as any, // Testing invalid redaction type for validation pattern: 'test', }); // Verify the result contains the validation error expect(result.markdown).toContain('# Error Creating Redaction'); expect(result.markdown).toContain( 'An error occurred while trying to create redaction analysis:' ); expect(result.markdown).toContain('invalid_enum_value'); }); it('should handle validation errors for empty document_id', async () => { // Call the function with empty document_id const result = await createRedaction(mockClient, { document_fingerprint: { document_id: '' }, redaction_type: 'regex', pattern: 'test', }); // Verify the result contains the validation error expect(result.markdown).toContain('# Error Creating Redaction'); expect(result.markdown).toContain( 'An error occurred while trying to create redaction analysis:' ); expect(result.markdown).toContain('Document ID is required'); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/PSPDFKit/nutrient-document-engine-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server