first
This commit is contained in:
561
tests/healthcare-specific/clinical-workflows.test.js
Normal file
561
tests/healthcare-specific/clinical-workflows.test.js
Normal file
@@ -0,0 +1,561 @@
|
||||
/**
|
||||
* @fileoverview Tests for clinical workflows and medical data validation
|
||||
* Tests clinical decision support, medical coding, drug interactions, and care coordination
|
||||
*/
|
||||
|
||||
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
||||
import { mockFactory } from '../mocks/mockFactory.js';
|
||||
|
||||
describe('Clinical Workflows and Medical Data Validation Tests', () => {
|
||||
let mockEnv;
|
||||
let toolGenerator;
|
||||
|
||||
beforeEach(() => {
|
||||
mockEnv = mockFactory.createMockEnvironment({
|
||||
authTypes: ['provider'],
|
||||
enableHttpMocks: true,
|
||||
enableAuthMocks: true,
|
||||
enableHealthcareMocks: true
|
||||
});
|
||||
|
||||
toolGenerator = mockEnv.toolGenerator;
|
||||
|
||||
// Setup provider authentication
|
||||
mockFactory.authMocks.setMockCredentials('provider', {
|
||||
username: 'test_provider',
|
||||
password: 'test_password'
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFactory.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('Clinical Decision Support System (CDSS)', () => {
|
||||
test('should provide drug interaction alerts', async () => {
|
||||
const toolName = 'provider_create_prescriptionstore';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
medication_data: {
|
||||
medication_name: 'Warfarin',
|
||||
strength: '5mg',
|
||||
dosage: '5mg daily',
|
||||
current_medications: ['Aspirin 81mg', 'Ibuprofen 400mg']
|
||||
}
|
||||
};
|
||||
|
||||
// Mock drug interaction alert
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/prescription/store/patient_123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
prescription: mockFactory.healthcareMocks.generateMockPrescription(),
|
||||
clinical_alerts: [
|
||||
{
|
||||
type: 'drug_interaction',
|
||||
severity: 'major',
|
||||
interaction: 'Warfarin + Aspirin',
|
||||
description: 'Increased risk of bleeding',
|
||||
recommendation: 'Monitor INR closely, consider alternative antiplatelet therapy',
|
||||
evidence_level: 'high',
|
||||
references: ['Clinical Pharmacology Database']
|
||||
},
|
||||
{
|
||||
type: 'drug_interaction',
|
||||
severity: 'moderate',
|
||||
interaction: 'Warfarin + Ibuprofen',
|
||||
description: 'Increased anticoagulant effect',
|
||||
recommendation: 'Avoid concurrent use or monitor INR',
|
||||
evidence_level: 'moderate'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.clinical_alerts).toHaveLength(2);
|
||||
expect(result.data.clinical_alerts[0].severity).toBe('major');
|
||||
expect(result.data.clinical_alerts[0].recommendation).toContain('Monitor INR');
|
||||
});
|
||||
|
||||
test('should provide allergy contraindication alerts', async () => {
|
||||
const toolName = 'provider_create_prescriptionstore';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
medication_data: {
|
||||
medication_name: 'Penicillin',
|
||||
strength: '500mg',
|
||||
patient_allergies: ['Penicillin', 'Sulfa drugs']
|
||||
}
|
||||
};
|
||||
|
||||
// Mock allergy alert
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/prescription/store/patient_123', null, true, {
|
||||
response: {
|
||||
status: 400,
|
||||
data: {
|
||||
error: 'Allergy contraindication detected',
|
||||
clinical_alerts: [
|
||||
{
|
||||
type: 'allergy_contraindication',
|
||||
severity: 'critical',
|
||||
allergen: 'Penicillin',
|
||||
reaction_type: 'anaphylaxis',
|
||||
recommendation: 'DO NOT PRESCRIBE - Use alternative antibiotic',
|
||||
override_required: true,
|
||||
override_justification_required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow('Allergy contraindication detected');
|
||||
});
|
||||
|
||||
test('should provide dosage adjustment recommendations', async () => {
|
||||
const toolName = 'provider_create_prescriptionstore';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
medication_data: {
|
||||
medication_name: 'Digoxin',
|
||||
strength: '0.25mg',
|
||||
dosage: '0.25mg daily',
|
||||
patient_age: 85,
|
||||
kidney_function: 'moderate_impairment'
|
||||
}
|
||||
};
|
||||
|
||||
// Mock dosage adjustment recommendation
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/prescription/store/patient_123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
prescription: mockFactory.healthcareMocks.generateMockPrescription(),
|
||||
clinical_alerts: [
|
||||
{
|
||||
type: 'dosage_adjustment',
|
||||
severity: 'moderate',
|
||||
reason: 'renal_impairment_elderly',
|
||||
current_dose: '0.25mg daily',
|
||||
recommended_dose: '0.125mg daily',
|
||||
adjustment_factor: 0.5,
|
||||
monitoring_required: ['serum_digoxin_levels', 'kidney_function'],
|
||||
rationale: 'Reduced clearance in elderly patients with renal impairment'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.clinical_alerts[0].type).toBe('dosage_adjustment');
|
||||
expect(result.data.clinical_alerts[0].recommended_dose).toBe('0.125mg daily');
|
||||
expect(result.data.clinical_alerts[0].monitoring_required).toContain('serum_digoxin_levels');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Medical Coding and Documentation', () => {
|
||||
test('should validate ICD-10 diagnosis codes', async () => {
|
||||
const toolName = 'provider_create_medicalRecordscreate';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
record_type: 'progress_note',
|
||||
diagnosis_codes: ['E11.9', 'I10', 'Z00.00'],
|
||||
primary_diagnosis: 'E11.9'
|
||||
};
|
||||
|
||||
// Mock ICD-10 validation
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/medical-records/create', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
medical_record: mockFactory.healthcareMocks.generateMockMedicalRecord(),
|
||||
coding_validation: {
|
||||
icd10_codes: [
|
||||
{
|
||||
code: 'E11.9',
|
||||
description: 'Type 2 diabetes mellitus without complications',
|
||||
valid: true,
|
||||
billable: true,
|
||||
specificity: 'high'
|
||||
},
|
||||
{
|
||||
code: 'I10',
|
||||
description: 'Essential (primary) hypertension',
|
||||
valid: true,
|
||||
billable: true,
|
||||
specificity: 'medium'
|
||||
},
|
||||
{
|
||||
code: 'Z00.00',
|
||||
description: 'Encounter for general adult medical examination without abnormal findings',
|
||||
valid: true,
|
||||
billable: false,
|
||||
specificity: 'high'
|
||||
}
|
||||
],
|
||||
coding_accuracy: 100,
|
||||
billing_compliance: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.coding_validation.coding_accuracy).toBe(100);
|
||||
expect(result.data.coding_validation.icd10_codes[0].valid).toBe(true);
|
||||
expect(result.data.coding_validation.billing_compliance).toBe(true);
|
||||
});
|
||||
|
||||
test('should validate CPT procedure codes', async () => {
|
||||
const toolName = 'provider_create_procedureDocumentation';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
procedure_codes: ['99213', '93000', '36415'],
|
||||
procedure_date: '2025-07-09'
|
||||
};
|
||||
|
||||
// Mock CPT validation
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/procedure-documentation', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
procedure_record: {
|
||||
id: 'procedure_123',
|
||||
patient_id: 'patient_123',
|
||||
procedure_date: '2025-07-09'
|
||||
},
|
||||
cpt_validation: {
|
||||
codes: [
|
||||
{
|
||||
code: '99213',
|
||||
description: 'Office visit, established patient, level 3',
|
||||
valid: true,
|
||||
modifier_required: false,
|
||||
documentation_requirements: ['history', 'examination', 'medical_decision_making']
|
||||
},
|
||||
{
|
||||
code: '93000',
|
||||
description: 'Electrocardiogram, routine ECG with interpretation',
|
||||
valid: true,
|
||||
bundling_rules: 'separate_billable'
|
||||
},
|
||||
{
|
||||
code: '36415',
|
||||
description: 'Collection of venous blood by venipuncture',
|
||||
valid: true,
|
||||
bundling_rules: 'included_in_lab_panel'
|
||||
}
|
||||
],
|
||||
billing_compliance: true,
|
||||
documentation_complete: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.cpt_validation.billing_compliance).toBe(true);
|
||||
expect(result.data.cpt_validation.codes[0].documentation_requirements).toContain('history');
|
||||
});
|
||||
|
||||
test('should enforce clinical documentation requirements', async () => {
|
||||
const toolName = 'provider_create_medicalRecordscreate';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
record_type: 'progress_note',
|
||||
chief_complaint: 'Chest pain',
|
||||
history_present_illness: 'Patient reports chest pain for 2 hours',
|
||||
// Missing required fields for complete documentation
|
||||
};
|
||||
|
||||
// Mock documentation validation
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emr/medical-records/create', null, true, {
|
||||
response: {
|
||||
status: 400,
|
||||
data: {
|
||||
error: 'Incomplete clinical documentation',
|
||||
documentation_requirements: {
|
||||
missing_fields: ['physical_examination', 'assessment', 'plan'],
|
||||
required_for_billing: ['medical_decision_making'],
|
||||
compliance_level: 'insufficient',
|
||||
recommendations: [
|
||||
'Complete physical examination documentation',
|
||||
'Provide clinical assessment',
|
||||
'Document treatment plan'
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await expect(toolGenerator.executeTool(toolName, parameters))
|
||||
.rejects.toThrow('Incomplete clinical documentation');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Care Coordination and Workflow Management', () => {
|
||||
test('should manage care team coordination', async () => {
|
||||
const toolName = 'provider_create_careTeamAssignment';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
care_team: [
|
||||
{
|
||||
provider_id: 'provider_456',
|
||||
role: 'primary_care_physician',
|
||||
responsibilities: ['overall_care', 'medication_management']
|
||||
},
|
||||
{
|
||||
provider_id: 'provider_789',
|
||||
role: 'cardiologist',
|
||||
responsibilities: ['cardiac_care', 'specialist_consultation']
|
||||
},
|
||||
{
|
||||
provider_id: 'nurse_101',
|
||||
role: 'care_coordinator',
|
||||
responsibilities: ['patient_education', 'follow_up_scheduling']
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Mock care team coordination
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/care-team-assignment', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
care_team: {
|
||||
patient_id: 'patient_123',
|
||||
team_members: [
|
||||
{
|
||||
provider_id: 'provider_456',
|
||||
role: 'primary_care_physician',
|
||||
status: 'active',
|
||||
communication_preferences: ['secure_messaging', 'phone']
|
||||
},
|
||||
{
|
||||
provider_id: 'provider_789',
|
||||
role: 'cardiologist',
|
||||
status: 'active',
|
||||
next_appointment: '2025-07-20'
|
||||
}
|
||||
],
|
||||
coordination_plan: {
|
||||
communication_protocol: 'weekly_updates',
|
||||
shared_care_plan: true,
|
||||
medication_reconciliation: 'monthly'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.care_team.team_members).toHaveLength(2);
|
||||
expect(result.data.care_team.coordination_plan.shared_care_plan).toBe(true);
|
||||
});
|
||||
|
||||
test('should manage clinical task workflows', async () => {
|
||||
const toolName = 'provider_create_addTask';
|
||||
const parameters = {
|
||||
patient_id: 123,
|
||||
task_title: 'Follow-up lab results review',
|
||||
task_body: 'Review CBC and metabolic panel results, adjust medications if needed',
|
||||
task_due_date: '2025-07-15',
|
||||
task_assigned_to: 456,
|
||||
task_priority: 'high',
|
||||
task_watchers: [789, 101],
|
||||
clinical_context: {
|
||||
related_diagnosis: 'E11.9',
|
||||
lab_orders: ['CBC', 'CMP'],
|
||||
medication_review_required: true
|
||||
}
|
||||
};
|
||||
|
||||
// Mock clinical task creation
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/add-task/123', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
task: {
|
||||
id: 'task_123',
|
||||
patient_id: 123,
|
||||
title: 'Follow-up lab results review',
|
||||
priority: 'high',
|
||||
assigned_to: 456,
|
||||
due_date: '2025-07-15',
|
||||
status: 'pending',
|
||||
clinical_flags: ['medication_review', 'lab_follow_up'],
|
||||
workflow_stage: 'review_required'
|
||||
},
|
||||
workflow_automation: {
|
||||
reminders_scheduled: true,
|
||||
escalation_rules: 'notify_supervisor_if_overdue',
|
||||
integration_triggers: ['lab_result_notification']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.task.clinical_flags).toContain('medication_review');
|
||||
expect(result.data.workflow_automation.reminders_scheduled).toBe(true);
|
||||
});
|
||||
|
||||
test('should handle clinical handoff procedures', async () => {
|
||||
const toolName = 'provider_create_clinicalHandoff';
|
||||
const parameters = {
|
||||
patient_id: 'patient_123',
|
||||
from_provider: 'provider_456',
|
||||
to_provider: 'provider_789',
|
||||
handoff_type: 'shift_change',
|
||||
clinical_summary: {
|
||||
current_condition: 'stable',
|
||||
active_issues: ['diabetes management', 'hypertension monitoring'],
|
||||
pending_tasks: ['lab_review', 'medication_adjustment'],
|
||||
critical_alerts: ['allergy_to_penicillin']
|
||||
}
|
||||
};
|
||||
|
||||
// Mock clinical handoff
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/clinical-handoff', {
|
||||
status: 201,
|
||||
data: {
|
||||
success: true,
|
||||
handoff: {
|
||||
id: 'handoff_123',
|
||||
patient_id: 'patient_123',
|
||||
from_provider: 'provider_456',
|
||||
to_provider: 'provider_789',
|
||||
handoff_time: new Date().toISOString(),
|
||||
status: 'completed',
|
||||
acknowledgment_required: true
|
||||
},
|
||||
communication_record: {
|
||||
sbar_format: {
|
||||
situation: 'Patient stable, routine monitoring',
|
||||
background: 'Type 2 diabetes, hypertension',
|
||||
assessment: 'Stable condition, medications effective',
|
||||
recommendation: 'Continue current treatment, review labs'
|
||||
},
|
||||
critical_information_highlighted: true,
|
||||
read_back_completed: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.handoff.acknowledgment_required).toBe(true);
|
||||
expect(result.data.communication_record.sbar_format).toBeDefined();
|
||||
expect(result.data.communication_record.read_back_completed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Quality Measures and Clinical Indicators', () => {
|
||||
test('should track clinical quality measures', async () => {
|
||||
const toolName = 'provider_get_qualityMeasures';
|
||||
const parameters = {
|
||||
provider_id: 'provider_456',
|
||||
measure_set: 'diabetes_care',
|
||||
reporting_period: '2025-Q2'
|
||||
};
|
||||
|
||||
// Mock quality measures
|
||||
mockFactory.httpMocks.mockRequest('GET', '/api/quality-measures/provider_456', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
quality_measures: {
|
||||
diabetes_care: {
|
||||
hba1c_testing: {
|
||||
numerator: 85,
|
||||
denominator: 100,
|
||||
percentage: 85.0,
|
||||
benchmark: 90.0,
|
||||
status: 'below_benchmark'
|
||||
},
|
||||
blood_pressure_control: {
|
||||
numerator: 78,
|
||||
denominator: 100,
|
||||
percentage: 78.0,
|
||||
benchmark: 80.0,
|
||||
status: 'below_benchmark'
|
||||
},
|
||||
eye_exam_screening: {
|
||||
numerator: 92,
|
||||
denominator: 100,
|
||||
percentage: 92.0,
|
||||
benchmark: 85.0,
|
||||
status: 'above_benchmark'
|
||||
}
|
||||
},
|
||||
improvement_opportunities: [
|
||||
'Increase HbA1c testing frequency',
|
||||
'Improve blood pressure management protocols'
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.quality_measures.diabetes_care.hba1c_testing.percentage).toBe(85.0);
|
||||
expect(result.data.quality_measures.diabetes_care.eye_exam_screening.status).toBe('above_benchmark');
|
||||
expect(result.data.improvement_opportunities).toContain('Increase HbA1c testing frequency');
|
||||
});
|
||||
|
||||
test('should monitor patient safety indicators', async () => {
|
||||
const toolName = 'provider_get_safetyIndicators';
|
||||
const parameters = {
|
||||
facility_id: 'facility_123',
|
||||
indicator_type: 'medication_safety',
|
||||
time_period: 'last_30_days'
|
||||
};
|
||||
|
||||
// Mock safety indicators
|
||||
mockFactory.httpMocks.mockRequest('GET', '/api/safety-indicators/facility_123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
safety_indicators: {
|
||||
medication_errors: {
|
||||
total_incidents: 3,
|
||||
severity_breakdown: {
|
||||
low: 2,
|
||||
moderate: 1,
|
||||
high: 0,
|
||||
critical: 0
|
||||
},
|
||||
error_types: {
|
||||
dosing_error: 1,
|
||||
wrong_medication: 1,
|
||||
timing_error: 1
|
||||
},
|
||||
trend: 'decreasing'
|
||||
},
|
||||
adverse_drug_events: {
|
||||
total_events: 1,
|
||||
preventable: 0,
|
||||
severity: 'moderate',
|
||||
reporting_rate: 100
|
||||
},
|
||||
near_miss_events: {
|
||||
total_reports: 5,
|
||||
categories: ['prescription_clarity', 'drug_interaction_alerts'],
|
||||
learning_opportunities: 3
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.safety_indicators.medication_errors.total_incidents).toBe(3);
|
||||
expect(result.data.safety_indicators.medication_errors.trend).toBe('decreasing');
|
||||
expect(result.data.safety_indicators.near_miss_events.learning_opportunities).toBe(3);
|
||||
});
|
||||
});
|
||||
});
|
||||
498
tests/healthcare-specific/hipaa-compliance.test.js
Normal file
498
tests/healthcare-specific/hipaa-compliance.test.js
Normal file
@@ -0,0 +1,498 @@
|
||||
/**
|
||||
* @fileoverview Tests for HIPAA compliance and healthcare-specific security requirements
|
||||
* Tests PHI handling, audit trails, access controls, and healthcare data protection
|
||||
*/
|
||||
|
||||
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
||||
import { mockFactory } from '../mocks/mockFactory.js';
|
||||
|
||||
describe('HIPAA Compliance and Healthcare Security Tests', () => {
|
||||
let mockEnv;
|
||||
let toolGenerator;
|
||||
|
||||
beforeEach(() => {
|
||||
mockEnv = mockFactory.createMockEnvironment({
|
||||
authTypes: ['provider', 'patient'],
|
||||
enableHttpMocks: true,
|
||||
enableAuthMocks: true,
|
||||
enableHealthcareMocks: true
|
||||
});
|
||||
|
||||
toolGenerator = mockEnv.toolGenerator;
|
||||
|
||||
// Setup healthcare authentication
|
||||
mockFactory.authMocks.setMockCredentials('provider', {
|
||||
username: 'test_provider',
|
||||
password: 'test_password'
|
||||
});
|
||||
mockFactory.authMocks.setMockCredentials('patient', {
|
||||
username: 'test_patient',
|
||||
password: 'test_password'
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockFactory.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('PHI (Protected Health Information) Handling', () => {
|
||||
test('should properly encrypt PHI data in transit and at rest', async () => {
|
||||
// Setup
|
||||
const toolName = 'provider_create_emrregisterPatient';
|
||||
const parameters = {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
email: 'john.doe@test.com',
|
||||
dateOfBirth: '1990-01-01',
|
||||
personalID: 'SSN123456789', // Sensitive PHI
|
||||
medicalHistory: 'Diabetes, Hypertension' // Sensitive medical 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,
|
||||
encryption: {
|
||||
algorithm: 'AES-256-GCM',
|
||||
keyRotation: 'enabled',
|
||||
transitEncryption: 'TLS 1.3'
|
||||
},
|
||||
hipaaCompliant: true
|
||||
}
|
||||
});
|
||||
|
||||
// Execute
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
// Assert HIPAA compliance
|
||||
expect(result.data.hipaaCompliant).toBe(true);
|
||||
expect(result.data.patient.hipaaMetadata).toBeDefined();
|
||||
expect(result.data.patient.hipaaMetadata.dataClassification).toBe('PHI');
|
||||
expect(result.data.patient.hipaaMetadata.encryptionStatus).toBe('encrypted');
|
||||
expect(result.data.encryption.algorithm).toBe('AES-256-GCM');
|
||||
});
|
||||
|
||||
test('should implement minimum necessary standard for PHI access', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123,
|
||||
requestedFields: ['firstName', 'lastName', 'dateOfBirth'], // Limited fields
|
||||
accessPurpose: 'treatment'
|
||||
};
|
||||
|
||||
// Mock minimum necessary response
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: {
|
||||
firstName: 'John',
|
||||
lastName: 'Doe',
|
||||
dateOfBirth: '1990-01-01'
|
||||
// Other sensitive fields excluded based on minimum necessary
|
||||
},
|
||||
accessControl: {
|
||||
minimumNecessary: true,
|
||||
fieldsProvided: ['firstName', 'lastName', 'dateOfBirth'],
|
||||
fieldsExcluded: ['personalID', 'medicalHistory'],
|
||||
accessPurpose: 'treatment'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.accessControl.minimumNecessary).toBe(true);
|
||||
expect(result.data.accessControl.fieldsExcluded).toContain('personalID');
|
||||
});
|
||||
|
||||
test('should handle PHI de-identification for research purposes', async () => {
|
||||
const toolName = 'provider_get_researchData';
|
||||
const parameters = {
|
||||
dataset: 'diabetes_study',
|
||||
deidentification_level: 'safe_harbor'
|
||||
};
|
||||
|
||||
// Mock de-identified data response
|
||||
mockFactory.httpMocks.mockRequest('GET', '/api/research-data/diabetes_study', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
research_data: [
|
||||
{
|
||||
patient_id: 'DEIDENT_001', // De-identified ID
|
||||
age_range: '30-35',
|
||||
gender: 'M',
|
||||
diagnosis: 'Type 2 Diabetes',
|
||||
treatment_response: 'Positive'
|
||||
// No direct identifiers
|
||||
}
|
||||
],
|
||||
deidentification: {
|
||||
method: 'safe_harbor',
|
||||
identifiers_removed: [
|
||||
'names', 'addresses', 'dates', 'phone_numbers',
|
||||
'email_addresses', 'ssn', 'medical_record_numbers'
|
||||
],
|
||||
certification: 'HIPAA_compliant',
|
||||
expert_determination: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.deidentification.method).toBe('safe_harbor');
|
||||
expect(result.data.deidentification.identifiers_removed).toContain('ssn');
|
||||
expect(result.data.research_data[0].patient_id).toMatch(/^DEIDENT_/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Access Controls and Authorization', () => {
|
||||
test('should implement role-based access control (RBAC)', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123
|
||||
};
|
||||
|
||||
// Mock RBAC response
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: mockFactory.healthcareMocks.createHIPAACompliantData('patient', 'provider'),
|
||||
accessControl: {
|
||||
userRole: 'provider',
|
||||
permissions: ['read:patient_data', 'write:patient_data', 'read:medical_records'],
|
||||
restrictions: ['no_billing_access'],
|
||||
accessLevel: 'full_clinical_access'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.accessControl.userRole).toBe('provider');
|
||||
expect(result.data.accessControl.permissions).toContain('read:patient_data');
|
||||
expect(result.data.accessControl.restrictions).toContain('no_billing_access');
|
||||
});
|
||||
|
||||
test('should enforce break-glass emergency access procedures', async () => {
|
||||
const toolName = 'provider_emergency_patientAccess';
|
||||
const parameters = {
|
||||
patientId: 123,
|
||||
emergencyCode: 'EMERGENCY_001',
|
||||
justification: 'Patient in critical condition, immediate access required',
|
||||
emergencyType: 'life_threatening'
|
||||
};
|
||||
|
||||
// Mock emergency access response
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/emergency-access/patient/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: mockFactory.healthcareMocks.createHIPAACompliantData('patient', 'provider'),
|
||||
emergencyAccess: {
|
||||
granted: true,
|
||||
emergencyCode: 'EMERGENCY_001',
|
||||
accessLevel: 'full_emergency_access',
|
||||
timeLimit: '4 hours',
|
||||
requiresReview: true,
|
||||
auditFlag: 'emergency_access'
|
||||
},
|
||||
complianceNote: 'Emergency access granted under HIPAA emergency provisions'
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.emergencyAccess.granted).toBe(true);
|
||||
expect(result.data.emergencyAccess.requiresReview).toBe(true);
|
||||
expect(result.data.emergencyAccess.auditFlag).toBe('emergency_access');
|
||||
});
|
||||
|
||||
test('should implement patient consent verification', async () => {
|
||||
const toolName = 'provider_create_sharePatientData';
|
||||
const parameters = {
|
||||
patientId: 123,
|
||||
recipientProvider: 'specialist_456',
|
||||
dataTypes: ['medical_records', 'lab_results'],
|
||||
purpose: 'specialist_consultation'
|
||||
};
|
||||
|
||||
// Mock consent verification
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/share-patient-data', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
sharing_authorized: true,
|
||||
consent_verification: {
|
||||
consent_obtained: true,
|
||||
consent_date: '2025-01-15',
|
||||
consent_type: 'written_authorization',
|
||||
expiration_date: '2026-01-15',
|
||||
scope: ['medical_records', 'lab_results'],
|
||||
purpose: 'specialist_consultation'
|
||||
},
|
||||
sharing_details: {
|
||||
recipient: 'specialist_456',
|
||||
shared_at: new Date().toISOString(),
|
||||
tracking_id: 'SHARE_789'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.consent_verification.consent_obtained).toBe(true);
|
||||
expect(result.data.consent_verification.scope).toContain('medical_records');
|
||||
expect(result.data.sharing_details.tracking_id).toBe('SHARE_789');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Audit Trails and Logging', () => {
|
||||
test('should maintain comprehensive audit trails for all PHI access', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 123
|
||||
};
|
||||
|
||||
// Mock comprehensive audit trail
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/123', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
patient: mockFactory.healthcareMocks.createHIPAACompliantData('patient', 'provider'),
|
||||
auditTrail: {
|
||||
accessId: 'AUDIT_12345',
|
||||
userId: 'provider_456',
|
||||
userRole: 'provider',
|
||||
patientId: 123,
|
||||
action: 'patient_data_access',
|
||||
timestamp: new Date().toISOString(),
|
||||
ipAddress: '192.168.1.100',
|
||||
userAgent: 'Healthcare Portal v2.1',
|
||||
sessionId: 'SESSION_789',
|
||||
accessPurpose: 'patient_care',
|
||||
dataAccessed: ['demographics', 'medical_history'],
|
||||
accessMethod: 'direct_lookup',
|
||||
workstation: 'WS_001',
|
||||
location: 'Main Clinic - Room 101'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
const audit = result.data.auditTrail;
|
||||
expect(audit.accessId).toBeDefined();
|
||||
expect(audit.userId).toBe('provider_456');
|
||||
expect(audit.action).toBe('patient_data_access');
|
||||
expect(audit.dataAccessed).toContain('demographics');
|
||||
expect(audit.workstation).toBe('WS_001');
|
||||
});
|
||||
|
||||
test('should log failed access attempts for security monitoring', async () => {
|
||||
const toolName = 'provider_create_getPatientInfo';
|
||||
const parameters = {
|
||||
patientId: 999 // Non-existent patient
|
||||
};
|
||||
|
||||
// Mock failed access with audit
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/get-patient-info/999', null, true, {
|
||||
response: {
|
||||
status: 404,
|
||||
data: {
|
||||
error: 'Patient not found',
|
||||
auditTrail: {
|
||||
accessId: 'AUDIT_FAIL_001',
|
||||
userId: 'provider_456',
|
||||
action: 'failed_patient_access',
|
||||
timestamp: new Date().toISOString(),
|
||||
failureReason: 'patient_not_found',
|
||||
attemptedPatientId: 999,
|
||||
securityFlag: 'potential_unauthorized_access'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await toolGenerator.executeTool(toolName, parameters);
|
||||
} catch (error) {
|
||||
// Verify audit trail exists even for failed attempts
|
||||
expect(error.response?.data?.auditTrail).toBeDefined();
|
||||
expect(error.response.data.auditTrail.action).toBe('failed_patient_access');
|
||||
expect(error.response.data.auditTrail.securityFlag).toBe('potential_unauthorized_access');
|
||||
}
|
||||
});
|
||||
|
||||
test('should implement audit log integrity protection', async () => {
|
||||
const toolName = 'admin_get_auditLogs';
|
||||
const parameters = {
|
||||
date_range: {
|
||||
start: '2025-07-01',
|
||||
end: '2025-07-09'
|
||||
}
|
||||
};
|
||||
|
||||
// Mock audit log response with integrity protection
|
||||
mockFactory.httpMocks.mockRequest('GET', '/api/admin/audit-logs', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
audit_logs: [
|
||||
{
|
||||
id: 'AUDIT_001',
|
||||
timestamp: '2025-07-09T10:00:00Z',
|
||||
action: 'patient_data_access',
|
||||
userId: 'provider_456',
|
||||
checksum: 'SHA256:abc123def456',
|
||||
signature: 'RSA_SIGNATURE_HERE'
|
||||
}
|
||||
],
|
||||
integrity: {
|
||||
total_logs: 1,
|
||||
verified_checksums: 1,
|
||||
tamper_detected: false,
|
||||
last_integrity_check: new Date().toISOString(),
|
||||
protection_method: 'cryptographic_hash_chain'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.integrity.tamper_detected).toBe(false);
|
||||
expect(result.data.integrity.verified_checksums).toBe(1);
|
||||
expect(result.data.audit_logs[0].checksum).toMatch(/^SHA256:/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Data Breach Prevention and Response', () => {
|
||||
test('should detect and prevent potential data breaches', async () => {
|
||||
const toolName = 'provider_bulk_patientExport';
|
||||
const parameters = {
|
||||
patient_ids: Array.from({length: 1000}, (_, i) => i + 1), // Large bulk export
|
||||
export_format: 'csv'
|
||||
};
|
||||
|
||||
// Mock breach prevention response
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/bulk-export-patients', null, true, {
|
||||
response: {
|
||||
status: 403,
|
||||
data: {
|
||||
error: 'Potential data breach detected',
|
||||
breach_prevention: {
|
||||
trigger: 'bulk_export_threshold_exceeded',
|
||||
threshold: 100,
|
||||
requested_count: 1000,
|
||||
risk_level: 'high',
|
||||
action_taken: 'request_blocked',
|
||||
incident_id: 'INCIDENT_001'
|
||||
},
|
||||
required_approvals: ['security_officer', 'privacy_officer'],
|
||||
compliance_note: 'Large data exports require additional authorization'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
await toolGenerator.executeTool(toolName, parameters);
|
||||
} catch (error) {
|
||||
expect(error.response.data.breach_prevention.trigger).toBe('bulk_export_threshold_exceeded');
|
||||
expect(error.response.data.breach_prevention.risk_level).toBe('high');
|
||||
expect(error.response.data.required_approvals).toContain('security_officer');
|
||||
}
|
||||
});
|
||||
|
||||
test('should implement automatic breach notification procedures', async () => {
|
||||
const toolName = 'system_security_incident';
|
||||
const parameters = {
|
||||
incident_type: 'unauthorized_access_detected',
|
||||
affected_records: 50,
|
||||
incident_details: 'Suspicious login patterns detected'
|
||||
};
|
||||
|
||||
// Mock breach notification response
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/security-incident', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
incident: {
|
||||
id: 'BREACH_001',
|
||||
type: 'unauthorized_access_detected',
|
||||
severity: 'medium',
|
||||
affected_records: 50,
|
||||
notification_required: true
|
||||
},
|
||||
breach_response: {
|
||||
immediate_actions: [
|
||||
'affected_accounts_locked',
|
||||
'security_team_notified',
|
||||
'audit_log_preserved'
|
||||
],
|
||||
notification_timeline: {
|
||||
internal_notification: 'immediate',
|
||||
patient_notification: 'within_60_days',
|
||||
regulatory_notification: 'within_60_days'
|
||||
},
|
||||
compliance_requirements: [
|
||||
'HIPAA_breach_notification_rule',
|
||||
'state_breach_notification_laws'
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.incident.notification_required).toBe(true);
|
||||
expect(result.data.breach_response.immediate_actions).toContain('security_team_notified');
|
||||
expect(result.data.breach_response.compliance_requirements).toContain('HIPAA_breach_notification_rule');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Business Associate Agreements (BAA)', () => {
|
||||
test('should verify BAA compliance for third-party integrations', async () => {
|
||||
const toolName = 'provider_integrate_thirdPartyService';
|
||||
const parameters = {
|
||||
service_name: 'Lab Results API',
|
||||
service_provider: 'LabCorp',
|
||||
integration_type: 'api_connection'
|
||||
};
|
||||
|
||||
// Mock BAA verification
|
||||
mockFactory.httpMocks.mockRequest('POST', '/api/integrate-third-party', {
|
||||
status: 200,
|
||||
data: {
|
||||
success: true,
|
||||
integration_approved: true,
|
||||
baa_compliance: {
|
||||
baa_signed: true,
|
||||
baa_date: '2025-01-01',
|
||||
baa_expiration: '2026-01-01',
|
||||
service_provider: 'LabCorp',
|
||||
compliance_verified: true,
|
||||
permitted_uses: ['lab_result_transmission', 'patient_data_processing'],
|
||||
safeguards_required: ['encryption', 'access_controls', 'audit_logging']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const result = await toolGenerator.executeTool(toolName, parameters);
|
||||
|
||||
expect(result.data.baa_compliance.baa_signed).toBe(true);
|
||||
expect(result.data.baa_compliance.compliance_verified).toBe(true);
|
||||
expect(result.data.baa_compliance.safeguards_required).toContain('encryption');
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user