first
This commit is contained in:
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