first
This commit is contained in:
580
tests/provider/appointment-scheduling.test.js
Normal file
580
tests/provider/appointment-scheduling.test.js
Normal file
@@ -0,0 +1,580 @@
|
||||
/**
|
||||
* @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');
|
||||
});
|
||||
});
|
||||
});
|
528
tests/provider/emr-patient-management.test.js
Normal file
528
tests/provider/emr-patient-management.test.js
Normal file
@@ -0,0 +1,528 @@
|
||||
/**
|
||||
* @fileoverview Tests for provider EMR and patient management MCP tools
|
||||
* Tests patient registration, updates, medical records, and HIPAA compliance
|
||||
*/
|
||||
|
||||
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
||||
import { mockFactory } from '../mocks/mockFactory.js';
|
||||
|
||||
describe('Provider EMR and Patient 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_emrregisterPatient', () => {
|
||||
test('should successfully register a new patient with complete data', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_emrregisterPatient';
|
||||
const parameters = {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
dateOfBirth: '1990-01-01',
|
||||
middleName: 'Michael',
|
||||
preferredName: 'Johnny',
|
||||
contactMethod: 'email',
|
||||
personalID: 'SSN123456789',
|
||||
sexatBirth: 'Male',
|
||||
genderIdentity: 'Male',
|
||||
race: 'Caucasian',
|
||||
pronoun: 'He/Him',
|
||||
ageGroup: 'Adult',
|
||||
timezone: 'America/New_York',
|
||||
preferredPhone: '555-0123',
|
||||
alternativePhone: '555-0124',
|
||||
textmsgNumber: '555-0123',
|
||||
address: '123 Main St',
|
||||
city: 'Test City',
|
||||
state: 'TS',
|
||||
zipcode: '12345',
|
||||
primaryPractitioner: 'Dr. Smith',
|
||||
primaryCarePhysician: 'Dr. Johnson',
|
||||
guardian: 'Jane Doe',
|
||||
emergencyContactNumber: '555-0125',
|
||||
emergencyContactNameRelation: 'Spouse - Jane Doe',
|
||||
patientMaritalStatus: 'Married',
|
||||
occupation: 'Engineer',
|
||||
referredBy: 'Dr. Wilson',
|
||||
patientNote: 'New patient registration',
|
||||
password: 'SecurePass123!',
|
||||
status: 'active',
|
||||
isportalAccess: true
|
||||
};
|
||||
|
||||
// Mock successful patient registration
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/register-patients', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
patient: {
|
||||
id: 'patient_123',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
dateOfBirth: '1990-01-01',
|
||||
status: 'active',
|
||||
isportalAccess: true
|
||||
},
|
||||
message: 'Patient registered successfully'
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.patient.firstName).toBe('John');
|
||||
expect(result.data.patient.email).toBe('john.doe@test.com');
|
||||
expect(result.data.patient.isportalAccess).toBe(true);
|
||||
});
|
||||
|
||||
test('should validate required patient registration fields', async () => {
|
||||
const toolName = 'provider_create_emrregisterPatient';
|
||||
|
||||
// Test missing required fields
|
||||
const requiredFields = ['firstName', 'lastName', 'email', 'dateOfBirth'];
|
||||
|
||||
for (const field of requiredFields) {
|
||||
const incompleteParams = {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john@test.com',
|
||||
dateOfBirth: '1990-01-01'
|
||||
};
|
||||
delete incompleteParams[field];
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, incompleteParams))
|
||||
.rejects.toThrow();
|
||||
}
|
||||
});
|
||||
|
||||
test('should handle HIPAA compliance for patient data', async () => {
|
||||
const toolName = 'provider_create_emrregisterPatient';
|
||||
const parameters = {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
dateOfBirth: '1990-01-01',
|
||||
personalID: 'SSN123456789' // Sensitive PHI data
|
||||
};
|
||||
|
||||
// Mock HIPAA-compliant response
|
||||
const mockPatient = mockFactory.healthcareMocks.createHIPAACompliantData('patient', 'provider', {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john.doe@test.com'
|
||||
});
|
||||
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/register-patients', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
patient: mockPatient,
|
||||
hipaaCompliant: true
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Verify HIPAA compliance
|
||||
expect(result.data.patient.hipaaMetadata).toBeDefined();
|
||||
expect(result.data.patient.hipaaMetadata.dataClassification).toBe('PHI');
|
||||
expect(result.data.patient.hipaaMetadata.encryptionStatus).toBe('encrypted');
|
||||
});
|
||||
});
|
||||
|
||||
describe('provider_create_emrupdatePatient', () => {
|
||||
test('should successfully update patient with comprehensive data', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_emrupdatePatient';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
firstName: 'John',
|
||||
lastName: 'Smith', // Changed last name
|
||||
fullName: 'John Michael Smith',
|
||||
email: 'john.smith@test.com',
|
||||
preferredPhone: '555-0126',
|
||||
address: '456 New St',
|
||||
city: 'New City',
|
||||
state: 'NS',
|
||||
zipcode: '54321',
|
||||
status: 'active',
|
||||
isportalAccess: true
|
||||
};
|
||||
|
||||
// Mock successful patient update
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/update-patient/patient_123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: {
|
||||
id: 'patient_123',
|
||||
firstName: 'John',
|
||||
lastName: 'Smith',
|
||||
email: 'john.smith@test.com',
|
||||
preferredPhone: '555-0126',
|
||||
updatedAt: new Date().toISOString()
|
||||
},
|
||||
message: 'Patient updated successfully'
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.patient.lastName).toBe('Smith');
|
||||
expect(result.data.patient.email).toBe('john.smith@test.com');
|
||||
});
|
||||
|
||||
test('should handle patient not found', async () => {
|
||||
const toolName = 'provider_create_emrupdatePatient';
|
||||
const parameters = {
|
||||
patient_id: 'nonexistent_patient',
|
||||
firstName: 'John'
|
||||
};
|
||||
|
||||
// Mock patient not found
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/update-patient/nonexistent_patient', null, true, {
|
||||
response: {
|
||||
status: 404,
|
||||
data: { error: 'Patient not found' }
|
||||
}
|
||||
});
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('provider_create_medicalRecordscreate', () => {
|
||||
test('should successfully create medical record', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_medicalRecordscreate';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
record_type: 'progress_note',
|
||||
diagnosis: 'Hypertension',
|
||||
treatment: 'Lisinopril 10mg daily',
|
||||
notes: 'Patient reports feeling well',
|
||||
vital_signs: {
|
||||
bloodPressure: '130/85',
|
||||
heartRate: 75,
|
||||
temperature: 98.6,
|
||||
weight: 180
|
||||
},
|
||||
allergies: ['Penicillin'],
|
||||
medications: ['Lisinopril 10mg']
|
||||
};
|
||||
|
||||
// Mock successful medical record creation
|
||||
const mockRecord = mockFactory.healthcareMocks.generateMockMedicalRecord({
|
||||
patientId: 'patient_123',
|
||||
type: 'progress_note',
|
||||
diagnosis: { primary: 'Hypertension' }
|
||||
});
|
||||
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/medical-records/create', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
medical_record: mockRecord,
|
||||
message: 'Medical record created successfully'
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.medical_record.patientId).toBe('patient_123');
|
||||
expect(result.data.medical_record.type).toBe('progress_note');
|
||||
});
|
||||
|
||||
test('should validate medical record data integrity', async () => {
|
||||
const toolName = 'provider_create_medicalRecordscreate';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
record_type: 'invalid_type', // Invalid record type
|
||||
diagnosis: 'Test diagnosis'
|
||||
};
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('provider_create_addVital', () => {
|
||||
test('should successfully add vital signs', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_addVital';
|
||||
const parameters = {
|
||||
patientId: 123,
|
||||
provider_id: 456,
|
||||
blood_presssure: '120/80',
|
||||
diastolic: '80',
|
||||
weight_lbs: 150,
|
||||
height_ft: 5,
|
||||
height_in: 8,
|
||||
temperature: 98.6,
|
||||
pulse: 72,
|
||||
respiratory_rate: 16,
|
||||
saturation: 98,
|
||||
waist_in: 32,
|
||||
headCircumference_in: 22,
|
||||
note: 'Normal vital signs',
|
||||
provider: 'Dr. Smith',
|
||||
weight_oz: 0,
|
||||
bmi: 22.8,
|
||||
bloodSugar: 95,
|
||||
fasting: true,
|
||||
neck_in: 15,
|
||||
shoulders_in: 18,
|
||||
chest_in: 38,
|
||||
hips_in: 36,
|
||||
lean_body_mass_lbs: 130,
|
||||
body_fat: 15,
|
||||
notes: 'Patient in good health',
|
||||
subjective_notes: 'Patient reports feeling well'
|
||||
};
|
||||
|
||||
// Mock successful vital signs addition
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/add-vital/123', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
vital_signs: {
|
||||
id: 'vital_789',
|
||||
patientId: 123,
|
||||
providerId: 456,
|
||||
bloodPressure: '120/80',
|
||||
weight: 150,
|
||||
temperature: 98.6,
|
||||
pulse: 72,
|
||||
bmi: 22.8,
|
||||
recordedAt: new Date().toISOString()
|
||||
},
|
||||
message: 'Vital signs recorded successfully'
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.vital_signs.patientId).toBe(123);
|
||||
expect(result.data.vital_signs.bloodPressure).toBe('120/80');
|
||||
expect(result.data.vital_signs.bmi).toBe(22.8);
|
||||
});
|
||||
|
||||
test('should validate vital signs data ranges', async () => {
|
||||
const toolName = 'provider_create_addVital';
|
||||
|
||||
// Test invalid vital signs
|
||||
const invalidVitals = [
|
||||
{ patientId: 123, provider_id: 456, temperature: 150 }, // Invalid temperature
|
||||
{ patientId: 123, provider_id: 456, pulse: 300 }, // Invalid pulse
|
||||
{ patientId: 123, provider_id: 456, saturation: 150 } // Invalid saturation
|
||||
];
|
||||
|
||||
for (const vitals of invalidVitals) {
|
||||
await expect(toolGenerator.executeTool(toolName, vitals))
|
||||
.rejects.toThrow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('provider_create_getPatientInfo', () => {
|
||||
test('should successfully retrieve patient information', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123
|
||||
};
|
||||
|
||||
// Mock patient information response
|
||||
const mockPatient = mockFactory.healthcareMocks.createHIPAACompliantData('patient', 'provider', {
|
||||
id: 'patient_123',
|
||||
firstName: 'John',
|
||||
lastName: 'Doe'
|
||||
});
|
||||
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: mockPatient
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.patient.id).toBe('patient_123');
|
||||
expect(result.data.patient.hipaaMetadata).toBeDefined();
|
||||
});
|
||||
|
||||
test('should handle unauthorized access to patient data', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123
|
||||
};
|
||||
|
||||
// Mock unauthorized access
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', null, true, {
|
||||
response: {
|
||||
status: 403,
|
||||
data: { error: 'Unauthorized access to patient data' }
|
||||
}
|
||||
});
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('provider_create_updatePatientInfo', () => {
|
||||
test('should successfully update patient information', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_updatePatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123,
|
||||
city: 'Updated City',
|
||||
state: 'UC',
|
||||
address: '789 Updated St',
|
||||
zip_code: '98765',
|
||||
dob: '1990-01-01',
|
||||
country: 'USA'
|
||||
};
|
||||
|
||||
// Mock successful update
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/update-patient-info/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: {
|
||||
id: 'patient_123',
|
||||
city: 'Updated City',
|
||||
state: 'UC',
|
||||
address: '789 Updated St',
|
||||
zipCode: '98765',
|
||||
updatedAt: new Date().toISOString()
|
||||
},
|
||||
message: 'Patient information updated successfully'
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.patient.city).toBe('Updated City');
|
||||
expect(result.data.patient.address).toBe('789 Updated St');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Provider Authentication and Security Tests', () => {
|
||||
test('should require provider authentication for patient operations', async () => {
|
||||
// Clear authentication
|
||||
mockFactory.authMocks.reset();
|
||||
|
||||
const toolName = 'provider_create_emrregisterPatient';
|
||||
const parameters = {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john@test.com',
|
||||
dateOfBirth: '1990-01-01'
|
||||
};
|
||||
|
||||
// Mock authentication failure
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/register-patients', null, true, {
|
||||
response: {
|
||||
status: 401,
|
||||
data: { error: 'Authentication required' }
|
||||
}
|
||||
});
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow();
|
||||
});
|
||||
|
||||
test('should validate provider permissions for patient access', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123
|
||||
};
|
||||
|
||||
// Mock insufficient permissions
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', null, true, {
|
||||
response: {
|
||||
status: 403,
|
||||
data: { error: 'Insufficient permissions' }
|
||||
}
|
||||
});
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow();
|
||||
});
|
||||
|
||||
test('should audit patient data access for HIPAA compliance', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123
|
||||
};
|
||||
|
||||
// Mock response with audit trail
|
||||
const mockPatient = mockFactory.healthcareMocks.createHIPAACompliantData('patient', 'provider');
|
||||
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: mockPatient,
|
||||
auditTrail: {
|
||||
accessedBy: 'provider_456',
|
||||
accessTime: new Date().toISOString(),
|
||||
purpose: 'patient_care'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Verify audit trail exists
|
||||
expect(result.data.auditTrail).toBeDefined();
|
||||
expect(result.data.auditTrail.accessedBy).toBeDefined();
|
||||
expect(result.data.auditTrail.purpose).toBe('patient_care');
|
||||
});
|
||||
});
|
||||
});
|
610
tests/provider/prescription-management.test.js
Normal file
610
tests/provider/prescription-management.test.js
Normal file
@@ -0,0 +1,610 @@
|
||||
/**
|
||||
* @fileoverview Tests for provider prescription and medication management MCP tools
|
||||
* Tests prescription creation, medication templates, and drug interaction checking
|
||||
*/
|
||||
|
||||
import { describe, test, expect, beforeEach, afterEach } from "@jest/globals";
|
||||
import { mockFactory } from "../mocks/mockFactory.js";
|
||||
|
||||
describe("Provider Prescription and Medication 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_prescriptionstore", () => {
|
||||
test("should successfully store prescription with complete medication data", async () => {
|
||||
// Setup
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Lisinopril",
|
||||
generic_name: "Lisinopril",
|
||||
strength: "10mg",
|
||||
form: "Tablet",
|
||||
dosage: "10mg",
|
||||
frequency: "Once daily",
|
||||
duration: "30 days",
|
||||
quantity: 30,
|
||||
refills: 2,
|
||||
instructions: "Take with food in the morning",
|
||||
prescriber_id: "provider_456",
|
||||
pharmacy_id: "pharmacy_789",
|
||||
ndc_number: "12345-678-90",
|
||||
dea_schedule: "Non-controlled",
|
||||
indication: "Hypertension",
|
||||
route: "Oral",
|
||||
start_date: "2025-07-09",
|
||||
end_date: "2025-08-08",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock successful prescription storage
|
||||
const mockPrescription =
|
||||
mockFactory.healthcareMocks.generateMockPrescription({
|
||||
patientId: "patient_123",
|
||||
medication: {
|
||||
name: "Lisinopril",
|
||||
strength: "10mg",
|
||||
form: "Tablet",
|
||||
},
|
||||
dosage: "10mg",
|
||||
frequency: "Once daily",
|
||||
duration: "30 days",
|
||||
});
|
||||
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
{
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
prescription: mockPrescription,
|
||||
message: "Prescription stored successfully",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.prescription.patientId).toBe("patient_123");
|
||||
expect(result.data.prescription.medication.name).toBe("Lisinopril");
|
||||
expect(result.data.prescription.dosage).toBe("10mg");
|
||||
expect(result.data.prescription.frequency).toBe("Once daily");
|
||||
});
|
||||
|
||||
test("should validate prescription data for drug safety", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
|
||||
// Test invalid dosage
|
||||
const invalidDosageParams = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Lisinopril",
|
||||
strength: "10mg",
|
||||
dosage: "invalid_dosage", // Invalid dosage format
|
||||
frequency: "Once daily",
|
||||
},
|
||||
};
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, invalidDosageParams)
|
||||
).rejects.toThrow();
|
||||
|
||||
// Test missing required fields
|
||||
const incompleteParams = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Lisinopril",
|
||||
// Missing required fields
|
||||
},
|
||||
};
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, incompleteParams)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("should check for drug interactions", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Warfarin",
|
||||
strength: "5mg",
|
||||
dosage: "5mg",
|
||||
frequency: "Once daily",
|
||||
current_medications: ["Aspirin", "Ibuprofen"], // Potential interactions
|
||||
},
|
||||
};
|
||||
|
||||
// Mock drug interaction warning
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
{
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
prescription:
|
||||
mockFactory.healthcareMocks.generateMockPrescription(),
|
||||
warnings: [
|
||||
{
|
||||
type: "drug_interaction",
|
||||
severity: "moderate",
|
||||
message: "Potential interaction between Warfarin and Aspirin",
|
||||
recommendation: "Monitor INR levels closely",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.warnings).toBeDefined();
|
||||
expect(result.data.warnings[0].type).toBe("drug_interaction");
|
||||
});
|
||||
|
||||
test("should handle controlled substance prescriptions", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Oxycodone",
|
||||
strength: "5mg",
|
||||
dosage: "5mg",
|
||||
frequency: "Every 6 hours as needed",
|
||||
dea_schedule: "Schedule II",
|
||||
quantity: 20,
|
||||
refills: 0, // No refills for Schedule II
|
||||
prescriber_dea: "AB1234567",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock controlled substance handling
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
{
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
prescription: {
|
||||
...mockFactory.healthcareMocks.generateMockPrescription(),
|
||||
controlledSubstance: true,
|
||||
deaSchedule: "Schedule II",
|
||||
refills: 0,
|
||||
specialHandling: {
|
||||
requiresDeaNumber: true,
|
||||
electronicPrescribingRequired: true,
|
||||
auditTrail: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.prescription.controlledSubstance).toBe(true);
|
||||
expect(result.data.prescription.refills).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("provider_create_add_medicine_template", () => {
|
||||
test("should successfully store medicine template", async () => {
|
||||
// Setup
|
||||
const toolName = "provider_create_add_medicine_template";
|
||||
const parameters = {
|
||||
template_data: {
|
||||
template_name: "Hypertension Standard Protocol",
|
||||
medication_name: "Lisinopril",
|
||||
default_strength: "10mg",
|
||||
default_dosage: "10mg",
|
||||
default_frequency: "Once daily",
|
||||
default_duration: "30 days",
|
||||
default_quantity: 30,
|
||||
default_refills: 2,
|
||||
default_instructions: "Take with food in the morning",
|
||||
indication: "Hypertension",
|
||||
contraindications: ["Pregnancy", "Angioedema history"],
|
||||
monitoring_requirements: ["Blood pressure", "Kidney function"],
|
||||
provider_id: "provider_456",
|
||||
specialty: "Internal Medicine",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock successful template storage
|
||||
mockFactory.httpMocks.mockRequest("POST", "/api/add_medicine_template", {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
template: {
|
||||
id: "template_123",
|
||||
templateName: "Hypertension Standard Protocol",
|
||||
medicationName: "Lisinopril",
|
||||
defaultStrength: "10mg",
|
||||
providerId: "provider_456",
|
||||
createdAt: new Date().toISOString(),
|
||||
},
|
||||
message: "Medicine template stored successfully",
|
||||
},
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.template.templateName).toBe(
|
||||
"Hypertension Standard Protocol"
|
||||
);
|
||||
expect(result.data.template.medicationName).toBe("Lisinopril");
|
||||
});
|
||||
|
||||
test("should validate template data completeness", async () => {
|
||||
const toolName = "provider_create_add_medicine_template";
|
||||
|
||||
// Test missing required template data
|
||||
const incompleteParams = {
|
||||
template_data: {
|
||||
template_name: "Incomplete Template",
|
||||
// Missing medication details
|
||||
},
|
||||
};
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, incompleteParams)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("provider_create_emrimportMedicine", () => {
|
||||
test("should successfully import medicines from Excel file", async () => {
|
||||
// Setup
|
||||
const toolName = "provider_create_emrimportMedicine";
|
||||
const parameters = {
|
||||
excel_file: new File(["mock excel content"], "medicines.xlsx", {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
}),
|
||||
};
|
||||
|
||||
// Mock successful import
|
||||
mockFactory.httpMocks.mockRequest("POST", "/api/emr/import-medicines", {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
imported_count: 150,
|
||||
skipped_count: 5,
|
||||
errors: [],
|
||||
summary: {
|
||||
total_rows: 155,
|
||||
successful_imports: 150,
|
||||
duplicates_skipped: 3,
|
||||
validation_errors: 2,
|
||||
},
|
||||
message: "Medicines imported successfully",
|
||||
},
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data.imported_count).toBe(150);
|
||||
expect(result.data.summary.total_rows).toBe(155);
|
||||
});
|
||||
|
||||
test("should handle import validation errors", async () => {
|
||||
const toolName = "provider_create_emrimportMedicine";
|
||||
const parameters = {
|
||||
excel_file: new File(["invalid content"], "invalid.xlsx", {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
}),
|
||||
};
|
||||
|
||||
// Mock import with validation errors
|
||||
mockFactory.httpMocks.mockRequest("POST", "/api/emr/import/medicine", {
|
||||
status: 200,
|
||||
data: {
|
||||
success: false,
|
||||
imported_count: 0,
|
||||
errors: [
|
||||
{
|
||||
row: 2,
|
||||
field: "medication_name",
|
||||
error: "Medication name is required",
|
||||
},
|
||||
{
|
||||
row: 3,
|
||||
field: "strength",
|
||||
error: "Invalid strength format",
|
||||
},
|
||||
],
|
||||
message: "Import completed with errors",
|
||||
},
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.data.errors.length).toBe(2);
|
||||
});
|
||||
|
||||
test("should validate file format", async () => {
|
||||
const toolName = "provider_create_emrimportMedicine";
|
||||
const parameters = {
|
||||
excel_file: new File(["not excel"], "medicines.txt", {
|
||||
type: "text/plain",
|
||||
}),
|
||||
};
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Prescription Security and Compliance Tests", () => {
|
||||
test("should require provider authentication for prescription operations", async () => {
|
||||
// Clear authentication
|
||||
mockFactory.authMocks.reset();
|
||||
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Lisinopril",
|
||||
strength: "10mg",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock authentication failure
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
response: {
|
||||
status: 401,
|
||||
data: { error: "Provider authentication required" },
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("should validate prescriber credentials for controlled substances", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Morphine",
|
||||
dea_schedule: "Schedule II",
|
||||
prescriber_dea: "invalid_dea",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock DEA validation failure
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
response: {
|
||||
status: 403,
|
||||
data: { error: "Invalid DEA number for controlled substance" },
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("should audit prescription activities for compliance", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Lisinopril",
|
||||
strength: "10mg",
|
||||
dosage: "10mg",
|
||||
frequency: "Once daily",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock response with audit trail
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
{
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
prescription:
|
||||
mockFactory.healthcareMocks.generateMockPrescription(),
|
||||
auditTrail: {
|
||||
prescriberId: "provider_456",
|
||||
prescribedAt: new Date().toISOString(),
|
||||
patientId: "patient_123",
|
||||
medicationName: "Lisinopril",
|
||||
action: "prescription_created",
|
||||
ipAddress: "127.0.0.1",
|
||||
userAgent: "Jest Test Suite",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.auditTrail).toBeDefined();
|
||||
expect(result.data.auditTrail.action).toBe("prescription_created");
|
||||
expect(result.data.auditTrail.prescriberId).toBe("provider_456");
|
||||
});
|
||||
|
||||
test("should handle prescription rate limiting", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Oxycodone",
|
||||
dea_schedule: "Schedule II",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock rate limiting for controlled substances
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
response: {
|
||||
status: 429,
|
||||
data: { error: "Too many controlled substance prescriptions" },
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("should validate patient eligibility for prescription", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "inactive_patient",
|
||||
medication_data: {
|
||||
medication_name: "Lisinopril",
|
||||
strength: "10mg",
|
||||
},
|
||||
};
|
||||
|
||||
// Mock patient eligibility check failure
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/inactive_patient",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
response: {
|
||||
status: 400,
|
||||
data: { error: "Patient is not eligible for prescriptions" },
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Medication Safety Tests", () => {
|
||||
test("should check for allergy contraindications", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "patient_123",
|
||||
medication_data: {
|
||||
medication_name: "Penicillin",
|
||||
strength: "500mg",
|
||||
patient_allergies: ["Penicillin"], // Patient allergic to prescribed medication
|
||||
},
|
||||
};
|
||||
|
||||
// Mock allergy contraindication
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/patient_123",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
response: {
|
||||
status: 400,
|
||||
data: {
|
||||
error: "Allergy contraindication detected",
|
||||
details: "Patient is allergic to Penicillin",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
|
||||
test("should validate dosage ranges for patient demographics", async () => {
|
||||
const toolName = "provider_create_prescriptionstore";
|
||||
const parameters = {
|
||||
patient_id: "pediatric_patient",
|
||||
medication_data: {
|
||||
medication_name: "Aspirin",
|
||||
strength: "325mg",
|
||||
dosage: "325mg",
|
||||
patient_age: 8, // Pediatric patient - aspirin contraindicated
|
||||
},
|
||||
};
|
||||
|
||||
// Mock pediatric contraindication
|
||||
mockFactory.httpMocks.mockRequest(
|
||||
"POST",
|
||||
"/api/emr/prescription/store/pediatric_patient",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
response: {
|
||||
status: 400,
|
||||
data: {
|
||||
error: "Age-related contraindication",
|
||||
details: "Aspirin not recommended for pediatric patients",
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
await expect(
|
||||
toolGenerator.executeTool(toolName, parameters)
|
||||
).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user