529 lines
16 KiB
JavaScript
529 lines
16 KiB
JavaScript
/**
|
|
* @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');
|
|
});
|
|
});
|
|
});
|