/** * @fileoverview Tests for provider appointment and scheduling management MCP tools * Tests appointment creation, scheduling, cancellation, and availability management */ import { describe, test, expect, beforeEach, afterEach } from '@jest/globals'; import { mockFactory } from '../mocks/mockFactory.js'; describe('Provider Appointment and Scheduling Management Tools', () => { let mockEnv; let toolGenerator; let mockToken; beforeEach(() => { mockEnv = mockFactory.createMockEnvironment({ authTypes: ['provider'], enableHttpMocks: true, enableAuthMocks: true, enableHealthcareMocks: true }); toolGenerator = mockEnv.toolGenerator; // Setup provider authentication mockToken = 'provider_token_123'; mockFactory.authMocks.setMockCredentials('provider', { username: 'test_provider', password: 'test_password' }); }); afterEach(() => { mockFactory.resetAllMocks(); }); describe('provider_create_emrcreateAppointment', () => { test('should successfully create appointment with complete scheduling data', async () => { // Setup const toolName = 'provider_create_emrcreateAppointment'; const parameters = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2025-07-15', appointment_time: '10:00', duration: 30, appointment_type: 'consultation', reason: 'Annual physical examination', notes: 'Patient reports feeling well', location_id: 'location_789', status: 'scheduled' }; // Mock successful appointment creation const mockAppointment = mockFactory.healthcareMocks.generateMockAppointment({ patientId: 'patient_123', providerId: 'provider_456', date: '2025-07-15', time: '10:00', type: 'consultation', status: 'scheduled' }); mockFactory.httpMocks.mockRequest('POST', '/api/emr/create-appointment', { status: 201, data: { success: true, appointment: mockAppointment, message: 'Appointment created successfully' } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.appointment.patientId).toBe('patient_123'); expect(result.data.appointment.providerId).toBe('provider_456'); expect(result.data.appointment.date).toBe('2025-07-15'); expect(result.data.appointment.time).toBe('10:00'); expect(result.data.appointment.status).toBe('scheduled'); }); test('should validate required appointment fields', async () => { const toolName = 'provider_create_emrcreateAppointment'; // Test missing required fields const requiredFields = ['patient_id', 'practitioner_id', 'appointment_date', 'appointment_time']; for (const field of requiredFields) { const incompleteParams = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2025-07-15', appointment_time: '10:00' }; delete incompleteParams[field]; await expect(toolGenerator.executeTool(toolName, incompleteParams)) .rejects.toThrow(); } }); test('should handle scheduling conflicts', async () => { const toolName = 'provider_create_emrcreateAppointment'; const parameters = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2025-07-15', appointment_time: '10:00' // Conflicting time slot }; // Mock scheduling conflict mockFactory.httpMocks.mockRequest('POST', '/api/emr/create-appointment', null, true, { response: { status: 409, data: { error: 'Scheduling conflict detected', conflicting_appointment: { id: 'appointment_existing', time: '10:00', patient: 'Another Patient' } } } }); await expect(toolGenerator.executeTool(toolName, parameters)) .rejects.toThrow(); }); test('should validate appointment date and time', async () => { const toolName = 'provider_create_emrcreateAppointment'; // Test past date const pastDateParams = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2020-01-01', // Past date appointment_time: '10:00' }; await expect(toolGenerator.executeTool(toolName, pastDateParams)) .rejects.toThrow(); // Test invalid time format const invalidTimeParams = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2025-07-15', appointment_time: '25:00' // Invalid time }; await expect(toolGenerator.executeTool(toolName, invalidTimeParams)) .rejects.toThrow(); }); }); describe('provider_create_bookAppointment', () => { test('should successfully book appointment', async () => { // Setup const toolName = 'provider_create_bookAppointment'; const parameters = { telemed_pros_id: 123, patient_id: 456, doctor_id: 789, appointment_id: 101, appointment_time: '2025-07-15 10:00:00' }; // Mock successful booking mockFactory.httpMocks.mockRequest('POST', '/api/book-appointment', { status: 201, data: { success: true, appointment: { id: 101, patientId: 456, doctorId: 789, appointmentTime: '2025-07-15 10:00:00', status: 'booked', telemedProsId: 123 }, message: 'Appointment booked successfully' } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.appointment.status).toBe('booked'); expect(result.data.appointment.patientId).toBe(456); }); }); describe('provider_create_appointmentcancel', () => { test('should successfully cancel appointment', async () => { // Setup const toolName = 'provider_create_appointmentcancel'; const parameters = { id: 123 }; // Mock successful cancellation mockFactory.httpMocks.mockRequest('POST', '/api/emr/appointment/123/cancel', { status: 200, data: { success: true, appointment: { id: 123, status: 'cancelled', cancelledAt: new Date().toISOString(), cancelledBy: 'provider_456' }, message: 'Appointment cancelled successfully' } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.appointment.status).toBe('cancelled'); expect(result.data.appointment.cancelledBy).toBe('provider_456'); }); test('should handle cancellation of non-existent appointment', async () => { const toolName = 'provider_create_appointmentcancel'; const parameters = { id: 999 // Non-existent appointment }; // Mock appointment not found mockFactory.httpMocks.mockRequest('POST', '/api/emr/appointment/999/cancel', null, true, { response: { status: 404, data: { error: 'Appointment not found' } } }); await expect(toolGenerator.executeTool(toolName, parameters)) .rejects.toThrow(); }); test('should handle cancellation of already cancelled appointment', async () => { const toolName = 'provider_create_appointmentcancel'; const parameters = { id: 123 }; // Mock already cancelled appointment mockFactory.httpMocks.mockRequest('POST', '/api/emr/appointment/123/cancel', null, true, { response: { status: 400, data: { error: 'Appointment is already cancelled' } } }); await expect(toolGenerator.executeTool(toolName, parameters)) .rejects.toThrow(); }); }); describe('provider_create_appointmentqueue', () => { test('should successfully add patient to appointment queue', async () => { // Setup const toolName = 'provider_create_appointmentqueue'; const parameters = { patientId: 123 }; // Mock successful queue addition mockFactory.httpMocks.mockRequest('POST', '/api/emr/appointment/queue/123', { status: 200, data: { success: true, queue_position: 3, estimated_wait_time: '15 minutes', patient: { id: 123, name: 'John Doe', queuedAt: new Date().toISOString() }, message: 'Patient added to queue successfully' } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.queue_position).toBe(3); expect(result.data.estimated_wait_time).toBe('15 minutes'); }); }); describe('provider_create_availableSlot', () => { test('should successfully get available appointment slots', async () => { // Setup const toolName = 'provider_create_availableSlot'; const parameters = { date: '2025-07-15' }; // Mock available slots response mockFactory.httpMocks.mockRequest('POST', '/api/available-slots/2025-07-15', { status: 200, data: { date: '2025-07-15', available_slots: [ { time: '09:00', duration: 30, provider_id: 'provider_456', provider_name: 'Dr. Smith', location: 'Room 101' }, { time: '10:30', duration: 30, provider_id: 'provider_456', provider_name: 'Dr. Smith', location: 'Room 101' }, { time: '14:00', duration: 60, provider_id: 'provider_789', provider_name: 'Dr. Johnson', location: 'Room 102' } ], total_slots: 3 } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.available_slots).toHaveLength(3); expect(result.data.date).toBe('2025-07-15'); expect(result.data.available_slots[0].time).toBe('09:00'); }); test('should handle no available slots', async () => { const toolName = 'provider_create_availableSlot'; const parameters = { date: '2025-12-25' // Holiday - no slots }; // Mock no slots response mockFactory.httpMocks.mockRequest('POST', '/api/available-slots/2025-12-25', { status: 200, data: { date: '2025-12-25', available_slots: [], total_slots: 0, message: 'No available slots for this date' } }); const result = await toolGenerator.executeTool(toolName, parameters); expect(result.success).toBe(true); expect(result.data.available_slots).toHaveLength(0); }); }); describe('provider_create_providerAddAvailability', () => { test('should successfully store provider availability', async () => { // Setup const toolName = 'provider_create_providerAddAvailability'; const parameters = { title: 'Morning Clinic Hours', start: '2025-07-15 09:00:00', end: '2025-07-15 12:00:00', type: 'available', comment: 'Regular morning clinic hours', practitioner_id: 456 }; // Mock successful availability storage mockFactory.httpMocks.mockRequest('POST', '/api/provider-add-availability', { status: 201, data: { success: true, availability: { id: 'availability_123', title: 'Morning Clinic Hours', start: '2025-07-15 09:00:00', end: '2025-07-15 12:00:00', type: 'available', practitionerId: 456, createdAt: new Date().toISOString() }, message: 'Provider availability stored successfully' } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.availability.title).toBe('Morning Clinic Hours'); expect(result.data.availability.type).toBe('available'); expect(result.data.availability.practitionerId).toBe(456); }); test('should validate availability time ranges', async () => { const toolName = 'provider_create_providerAddAvailability'; // Test end time before start time const invalidTimeParams = { title: 'Invalid Time Range', start: '2025-07-15 12:00:00', end: '2025-07-15 09:00:00', // End before start type: 'available' }; await expect(toolGenerator.executeTool(toolName, invalidTimeParams)) .rejects.toThrow(); }); }); describe('provider_create_getAppointmentList', () => { test('should successfully get appointments list', async () => { // Setup const toolName = 'provider_create_getAppointmentList'; const parameters = {}; // Mock appointments list response mockFactory.httpMocks.mockRequest('POST', '/api/get-appointment-list', { status: 200, data: { appointments: [ mockFactory.healthcareMocks.generateMockAppointment({ id: 'appointment_1', date: '2025-07-15', time: '09:00' }), mockFactory.healthcareMocks.generateMockAppointment({ id: 'appointment_2', date: '2025-07-15', time: '10:30' }) ], total_count: 2, page: 1, per_page: 10 } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.appointments).toHaveLength(2); expect(result.data.total_count).toBe(2); }); }); describe('provider_create_getAppointmentListDate', () => { test('should successfully get appointments by date', async () => { // Setup const toolName = 'provider_create_getAppointmentListDate'; const parameters = { date: '2025-07-15', practitioner_id: 456 }; // Mock date-filtered appointments mockFactory.httpMocks.mockRequest('POST', '/api/get-appointment-list-date', { status: 200, data: { date: '2025-07-15', practitioner_id: 456, appointments: [ mockFactory.healthcareMocks.generateMockAppointment({ date: '2025-07-15', providerId: 'provider_456' }) ], total_count: 1 } }); // Execute const result = await toolGenerator.executeTool(toolName, parameters); // Assert expect(result.success).toBe(true); expect(result.data.date).toBe('2025-07-15'); expect(result.data.appointments).toHaveLength(1); }); }); describe('Appointment Security and Compliance Tests', () => { test('should require provider authentication for appointment operations', async () => { // Clear authentication mockFactory.authMocks.reset(); const toolName = 'provider_create_emrcreateAppointment'; const parameters = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2025-07-15', appointment_time: '10:00' }; // Mock authentication failure mockFactory.httpMocks.mockRequest('POST', '/api/emr/create-appointment', null, true, { response: { status: 401, data: { error: 'Provider authentication required' } } }); await expect(toolGenerator.executeTool(toolName, parameters)) .rejects.toThrow(); }); test('should validate provider permissions for appointment management', async () => { const toolName = 'provider_create_appointmentcancel'; const parameters = { id: 123 }; // Mock insufficient permissions mockFactory.httpMocks.mockRequest('POST', '/api/emr/appointment/123/cancel', null, true, { response: { status: 403, data: { error: 'Insufficient permissions to cancel this appointment' } } }); await expect(toolGenerator.executeTool(toolName, parameters)) .rejects.toThrow(); }); test('should audit appointment activities for compliance', async () => { const toolName = 'provider_create_emrcreateAppointment'; const parameters = { patient_id: 'patient_123', practitioner_id: 'provider_456', appointment_date: '2025-07-15', appointment_time: '10:00' }; // Mock response with audit trail mockFactory.httpMocks.mockRequest('POST', '/api/emr/create-appointment', { status: 201, data: { success: true, appointment: mockFactory.healthcareMocks.generateMockAppointment(), auditTrail: { createdBy: 'provider_456', createdAt: new Date().toISOString(), action: 'appointment_created', patientId: 'patient_123', ipAddress: '127.0.0.1' } } }); const result = await toolGenerator.executeTool(toolName, parameters); expect(result.data.auditTrail).toBeDefined(); expect(result.data.auditTrail.action).toBe('appointment_created'); expect(result.data.auditTrail.createdBy).toBe('provider_456'); }); }); });