460 lines
13 KiB
JavaScript
460 lines
13 KiB
JavaScript
/**
|
|
* @fileoverview Tests for public data access MCP tools
|
|
* Tests email checking, user validation, and public data endpoints
|
|
*/
|
|
|
|
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
|
|
import { mockFactory } from '../mocks/mockFactory.js';
|
|
|
|
describe('Public Data Access Tools', () => {
|
|
let mockEnv;
|
|
let toolGenerator;
|
|
|
|
beforeEach(() => {
|
|
mockEnv = mockFactory.createMockEnvironment({
|
|
authTypes: ['public'],
|
|
enableHttpMocks: true,
|
|
enableHealthcareMocks: true
|
|
});
|
|
|
|
toolGenerator = mockEnv.toolGenerator;
|
|
});
|
|
|
|
afterEach(() => {
|
|
mockFactory.resetAllMocks();
|
|
});
|
|
|
|
describe('public_create_checkEmail', () => {
|
|
test('should check if email is available', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_checkEmail';
|
|
const parameters = {
|
|
email: 'newuser@test.com'
|
|
};
|
|
|
|
// Mock email availability response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/check-email', {
|
|
status: 200,
|
|
data: {
|
|
available: true,
|
|
email: 'newuser@test.com',
|
|
message: 'Email is available'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.available).toBe(true);
|
|
expect(result.data.email).toBe('newuser@test.com');
|
|
});
|
|
|
|
test('should detect existing email', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_checkEmail';
|
|
const parameters = {
|
|
email: 'existing@test.com'
|
|
};
|
|
|
|
// Mock existing email response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/check-email', {
|
|
status: 200,
|
|
data: {
|
|
available: false,
|
|
email: 'existing@test.com',
|
|
message: 'Email is already in use'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.available).toBe(false);
|
|
});
|
|
|
|
test('should validate email format', async () => {
|
|
const toolName = 'public_create_checkEmail';
|
|
const parameters = {
|
|
email: 'invalid-email-format'
|
|
};
|
|
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('public_create_checkUser', () => {
|
|
test('should check if provider exists', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_checkUser';
|
|
const parameters = {
|
|
email: 'provider@test.com'
|
|
};
|
|
|
|
// Mock provider exists response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/check-user', {
|
|
status: 200,
|
|
data: {
|
|
exists: true,
|
|
email: 'provider@test.com',
|
|
userType: 'provider',
|
|
message: 'Provider found'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.exists).toBe(true);
|
|
expect(result.data.userType).toBe('provider');
|
|
});
|
|
|
|
test('should handle non-existent user', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_checkUser';
|
|
const parameters = {
|
|
email: 'nonexistent@test.com'
|
|
};
|
|
|
|
// Mock user not found response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/check-user', {
|
|
status: 200,
|
|
data: {
|
|
exists: false,
|
|
email: 'nonexistent@test.com',
|
|
message: 'User not found'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.exists).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('public_get_appointmentParticipant', () => {
|
|
test('should get appointment participants', async () => {
|
|
// Setup
|
|
const toolName = 'public_get_appointmentParticipant';
|
|
const parameters = {
|
|
appointmentId: 'appointment_123'
|
|
};
|
|
|
|
// Mock appointment participants response
|
|
mockFactory.httpMocks.mockRequest('GET', '/api/appointment-participants/appointment_123', {
|
|
status: 200,
|
|
data: {
|
|
appointmentId: 'appointment_123',
|
|
participants: [
|
|
{
|
|
id: 'participant_1',
|
|
name: 'Dr. Smith',
|
|
role: 'provider',
|
|
email: 'dr.smith@test.com'
|
|
},
|
|
{
|
|
id: 'participant_2',
|
|
name: 'John Doe',
|
|
role: 'patient',
|
|
email: 'john.doe@test.com'
|
|
}
|
|
]
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.participants).toHaveLength(2);
|
|
expect(result.data.participants[0].role).toBe('provider');
|
|
expect(result.data.participants[1].role).toBe('patient');
|
|
});
|
|
|
|
test('should handle invalid appointment ID', async () => {
|
|
// Setup
|
|
const toolName = 'public_get_appointmentParticipant';
|
|
const parameters = {
|
|
appointmentId: 'invalid_appointment'
|
|
};
|
|
|
|
// Mock not found response
|
|
mockFactory.httpMocks.mockRequest('GET', '/api/appointment-participants/invalid_appointment', null, true, {
|
|
response: {
|
|
status: 404,
|
|
data: { error: 'Appointment not found' }
|
|
}
|
|
});
|
|
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('public_create_patientavailableSlot', () => {
|
|
test('should get available appointment slots', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_patientavailableSlot';
|
|
const parameters = {
|
|
date: '2025-07-15'
|
|
};
|
|
|
|
// Mock available slots response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/patient/available-slots/2025-07-15', {
|
|
status: 200,
|
|
data: {
|
|
date: '2025-07-15',
|
|
availableSlots: [
|
|
{
|
|
time: '09:00',
|
|
duration: 30,
|
|
providerId: 'provider_123',
|
|
providerName: 'Dr. Smith'
|
|
},
|
|
{
|
|
time: '10:30',
|
|
duration: 30,
|
|
providerId: 'provider_123',
|
|
providerName: 'Dr. Smith'
|
|
},
|
|
{
|
|
time: '14:00',
|
|
duration: 60,
|
|
providerId: 'provider_456',
|
|
providerName: 'Dr. Johnson'
|
|
}
|
|
]
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.availableSlots).toHaveLength(3);
|
|
expect(result.data.date).toBe('2025-07-15');
|
|
});
|
|
|
|
test('should validate date format', async () => {
|
|
const toolName = 'public_create_patientavailableSlot';
|
|
const parameters = {
|
|
date: 'invalid-date'
|
|
};
|
|
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
|
|
test('should handle no available slots', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_patientavailableSlot';
|
|
const parameters = {
|
|
date: '2025-12-25' // Holiday - no slots
|
|
};
|
|
|
|
// Mock no slots response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/patient/available-slots/2025-12-25', {
|
|
status: 200,
|
|
data: {
|
|
date: '2025-12-25',
|
|
availableSlots: [],
|
|
message: 'No available slots for this date'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.availableSlots).toHaveLength(0);
|
|
});
|
|
});
|
|
|
|
describe('public_create_patientBookAppointment', () => {
|
|
test('should successfully book appointment', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_patientBookAppointment';
|
|
const parameters = {
|
|
patient_id: 'patient_123',
|
|
start_time: '09:00',
|
|
end_time: '09:30',
|
|
practitioner_id: 'provider_456',
|
|
appointment_date: '2025-07-15',
|
|
appointment_time: '09:00',
|
|
notes: 'Annual checkup',
|
|
order_id: 789
|
|
};
|
|
|
|
// Mock successful booking response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/patient-book-appointment', {
|
|
status: 201,
|
|
data: {
|
|
success: true,
|
|
appointment: {
|
|
id: 'appointment_789',
|
|
patientId: 'patient_123',
|
|
practitionerId: 'provider_456',
|
|
date: '2025-07-15',
|
|
time: '09:00',
|
|
status: 'scheduled'
|
|
},
|
|
message: 'Appointment booked successfully'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.appointment.status).toBe('scheduled');
|
|
expect(result.data.appointment.date).toBe('2025-07-15');
|
|
});
|
|
|
|
test('should handle scheduling conflicts', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_patientBookAppointment';
|
|
const parameters = {
|
|
patient_id: 'patient_123',
|
|
start_time: '09:00',
|
|
end_time: '09:30',
|
|
practitioner_id: 'provider_456',
|
|
appointment_date: '2025-07-15',
|
|
appointment_time: '09:00'
|
|
};
|
|
|
|
// Mock conflict response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/patient-book-appointment', null, true, {
|
|
response: {
|
|
status: 409,
|
|
data: { error: 'Time slot is no longer available' }
|
|
}
|
|
});
|
|
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('Email Verification Tools', () => {
|
|
describe('public_create_publicManageVerifyEmail', () => {
|
|
test('should successfully verify email', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_publicManageVerifyEmail';
|
|
const parameters = {
|
|
token: 'verification_token_123',
|
|
email: 'user@test.com'
|
|
};
|
|
|
|
// Mock successful verification
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/public-manage-verify-email', {
|
|
status: 200,
|
|
data: {
|
|
success: true,
|
|
email: 'user@test.com',
|
|
verified: true,
|
|
message: 'Email verified successfully'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.verified).toBe(true);
|
|
});
|
|
|
|
test('should handle invalid verification token', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_publicManageVerifyEmail';
|
|
const parameters = {
|
|
token: 'invalid_token',
|
|
email: 'user@test.com'
|
|
};
|
|
|
|
// Mock invalid token response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/public-manage-verify-email', null, true, {
|
|
response: {
|
|
status: 400,
|
|
data: { error: 'Invalid verification token' }
|
|
}
|
|
});
|
|
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
});
|
|
|
|
describe('public_create_publicManageResendVerification', () => {
|
|
test('should successfully resend verification email', async () => {
|
|
// Setup
|
|
const toolName = 'public_create_publicManageResendVerification';
|
|
const parameters = {
|
|
email: 'user@test.com'
|
|
};
|
|
|
|
// Mock successful resend
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/public-manage-resend-verification', {
|
|
status: 200,
|
|
data: {
|
|
success: true,
|
|
email: 'user@test.com',
|
|
message: 'Verification email sent'
|
|
}
|
|
});
|
|
|
|
// Execute
|
|
const result = await toolGenerator.executeTool(toolName, parameters);
|
|
|
|
// Assert
|
|
expect(result.success).toBe(true);
|
|
expect(result.data.message).toContain('Verification email sent');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Data Access Security Tests', () => {
|
|
test('should handle rate limiting for email checks', async () => {
|
|
const toolName = 'public_create_checkEmail';
|
|
const parameters = {
|
|
email: 'test@test.com'
|
|
};
|
|
|
|
// Mock rate limit response
|
|
mockFactory.httpMocks.mockRequest('POST', '/api/check-email', null, true, {
|
|
response: {
|
|
status: 429,
|
|
data: { error: 'Too many requests' }
|
|
}
|
|
});
|
|
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
|
|
test('should sanitize input parameters', async () => {
|
|
const toolName = 'public_create_checkEmail';
|
|
const parameters = {
|
|
email: '<script>alert("xss")</script>@test.com'
|
|
};
|
|
|
|
// Should reject malicious input
|
|
await expect(toolGenerator.executeTool(toolName, parameters))
|
|
.rejects.toThrow();
|
|
});
|
|
});
|
|
});
|