This commit is contained in:
nasir@endelospay.com
2025-07-11 20:22:12 +05:00
commit 8c74b0e23f
120 changed files with 206874 additions and 0 deletions

View File

@@ -0,0 +1,459 @@
/**
* @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();
});
});
});

352
tests/public/index.test.js Normal file
View File

@@ -0,0 +1,352 @@
/**
* @fileoverview Comprehensive test suite for all public MCP tools
* Runs all public tool tests and provides coverage reporting
*/
import { describe, test, expect, beforeAll, afterAll } from '@jest/globals';
import { mockFactory } from '../mocks/mockFactory.js';
describe('Public Tools Integration Tests', () => {
let mockEnv;
let toolGenerator;
beforeAll(async () => {
// Setup comprehensive mock environment
mockEnv = mockFactory.createMockEnvironment({
authTypes: ['public'],
enableHttpMocks: true,
enableAuthMocks: true,
enableHealthcareMocks: true
});
toolGenerator = mockEnv.toolGenerator;
// Setup all public endpoint mocks
setupPublicEndpointMocks();
});
afterAll(() => {
mockFactory.resetAllMocks();
});
/**
* Setup mock responses for all public endpoints
*/
function setupPublicEndpointMocks() {
// Login endpoints
const loginEndpoints = [
{ method: 'POST', path: '/api/login' },
{ method: 'POST', path: '/api/frontend/login' },
{ method: 'POST', path: '/api/admin/login' },
{ method: 'POST', path: '/api/login-partner-api' },
{ method: 'POST', path: '/api/affiliate-login-api' },
{ method: 'POST', path: '/api/network/login' },
{ method: 'POST', path: '/api/patient/login' },
{ method: 'POST', path: '/api/patient-login-api' },
{ method: 'POST', path: '/api/login-patient' }
];
loginEndpoints.forEach(endpoint => {
mockFactory.httpMocks.mockRequest(endpoint.method, endpoint.path, {
status: 200,
data: {
success: true,
token: `mock_token_${Date.now()}`,
user: { id: 'user_123', email: 'test@example.com' }
}
});
});
// Registration endpoints
const registrationEndpoints = [
{ method: 'POST', path: '/emr-api/provider-register' },
{ method: 'POST', path: '/api/register-patients' },
{ method: 'POST', path: '/api/register-patient' },
{ method: 'POST', path: '/api/affiliate-register-api' },
{ method: 'POST', path: '/api/partner-register-api' },
{ method: 'POST', path: '/api/network/register' },
{ method: 'POST', path: '/api/emr/provider/register' },
{ method: 'POST', path: '/api/patient/register-patient' }
];
registrationEndpoints.forEach(endpoint => {
mockFactory.httpMocks.mockRequest(endpoint.method, endpoint.path, {
status: 201,
data: {
success: true,
user: { id: 'new_user_123', email: 'newuser@example.com' },
message: 'Registration successful'
}
});
});
// Password management endpoints
const passwordEndpoints = [
{ method: 'POST', path: '/api/forgot-password' },
{ method: 'POST', path: '/api/frontend/forgot-password' },
{ method: 'POST', path: '/api/emr/provider/forgot-password' },
{ method: 'POST', path: '/api/password-reset' },
{ method: 'POST', path: '/api/frontend/reset-password' },
{ method: 'POST', path: '/api/emr/provider/reset-password' },
{ method: 'POST', path: '/api/set-password' },
{ method: 'POST', path: '/api/emr/set-password' },
{ method: 'POST', path: '/api/affiliate/set-password' },
{ method: 'POST', path: '/api/reset-password' }
];
passwordEndpoints.forEach(endpoint => {
mockFactory.httpMocks.mockRequest(endpoint.method, endpoint.path, {
status: 200,
data: {
success: true,
message: 'Password operation successful'
}
});
});
// Data access endpoints
mockFactory.httpMocks.mockRequest('POST', '/api/check-email', {
status: 200,
data: { available: true, email: 'test@example.com' }
});
mockFactory.httpMocks.mockRequest('POST', '/api/check-user', {
status: 200,
data: { exists: true, userType: 'provider' }
});
// Appointment endpoints
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' }
]
}
});
mockFactory.httpMocks.mockRequest('POST', '/api/patient-book-appointment', {
status: 201,
data: {
success: true,
appointment: { id: 'appointment_123', status: 'scheduled' }
}
});
// Verification endpoints
mockFactory.httpMocks.mockRequest('POST', '/api/public-manage-verify-email', {
status: 200,
data: { success: true, verified: true }
});
mockFactory.httpMocks.mockRequest('POST', '/api/public-manage-resend-verification', {
status: 200,
data: { success: true, message: 'Verification email sent' }
});
}
describe('Public Tools Coverage Test', () => {
test('should have all 77 public tools available', async () => {
const allTools = toolGenerator.generateAllTools();
const publicTools = allTools.filter(tool => tool.name.startsWith('public_'));
// Verify we have the expected number of public tools
expect(publicTools.length).toBeGreaterThanOrEqual(70); // Allow for some variance
// Verify tool naming convention
publicTools.forEach(tool => {
expect(tool.name).toMatch(/^public_[a-zA-Z]+_[a-zA-Z]+/);
expect(tool.description).toBeDefined();
expect(tool.inputSchema).toBeDefined();
});
});
test('should categorize public tools correctly', async () => {
const allTools = toolGenerator.generateAllTools();
const publicTools = allTools.filter(tool => tool.name.startsWith('public_'));
const categories = {
login: [],
registration: [],
password: [],
verification: [],
data: [],
appointment: [],
other: []
};
publicTools.forEach(tool => {
if (tool.name.includes('login') || tool.name.includes('Login')) {
categories.login.push(tool);
} else if (tool.name.includes('register') || tool.name.includes('Register')) {
categories.registration.push(tool);
} else if (tool.name.includes('password') || tool.name.includes('Password') || tool.name.includes('setPassword')) {
categories.password.push(tool);
} else if (tool.name.includes('verify') || tool.name.includes('Verify') || tool.name.includes('verification')) {
categories.verification.push(tool);
} else if (tool.name.includes('check') || tool.name.includes('Check') || tool.name.includes('get')) {
categories.data.push(tool);
} else if (tool.name.includes('appointment') || tool.name.includes('Appointment') || tool.name.includes('slot')) {
categories.appointment.push(tool);
} else {
categories.other.push(tool);
}
});
// Verify we have tools in each major category
expect(categories.login.length).toBeGreaterThan(5);
expect(categories.registration.length).toBeGreaterThan(5);
expect(categories.password.length).toBeGreaterThan(5);
console.log('Public Tools Distribution:');
Object.entries(categories).forEach(([category, tools]) => {
console.log(` ${category}: ${tools.length} tools`);
});
});
});
describe('Public Tools Parameter Validation', () => {
test('should validate required parameters for login tools', async () => {
const loginTools = [
'public_create_login',
'public_create_frontendlogin',
'public_create_adminlogin'
];
for (const toolName of loginTools) {
const tool = toolGenerator.getTool(toolName);
if (tool) {
expect(tool.inputSchema.required).toBeDefined();
expect(tool.inputSchema.required.length).toBeGreaterThan(0);
}
}
});
test('should validate required parameters for registration tools', async () => {
const registrationTools = [
'public_create_emrApiproviderRegister',
'public_create_registerPatient',
'public_create_affiliateRegisterApi'
];
for (const toolName of registrationTools) {
const tool = toolGenerator.getTool(toolName);
if (tool) {
expect(tool.inputSchema.required).toBeDefined();
expect(tool.inputSchema.required.length).toBeGreaterThan(1);
}
}
});
});
describe('Public Tools Error Handling', () => {
test('should handle network errors gracefully', async () => {
// Mock network error for all endpoints
mockFactory.httpMocks.setDefaultResponse('POST', null);
mockFactory.httpMocks.setDefaultResponse('GET', null);
const testTool = 'public_create_login';
const parameters = { username: 'test', password: 'test' };
// Should handle network errors without crashing
await expect(toolGenerator.executeTool(testTool, parameters))
.rejects.toThrow();
});
test('should handle malformed responses', async () => {
// Mock malformed response
mockFactory.httpMocks.mockRequest('POST', '/api/login', {
status: 200,
data: 'invalid json response'
});
const testTool = 'public_create_login';
const parameters = { username: 'test', password: 'test' };
await expect(toolGenerator.executeTool(testTool, parameters))
.rejects.toThrow();
});
});
describe('Public Tools Security Tests', () => {
test('should not expose sensitive information in logs', async () => {
const testTool = 'public_create_login';
const parameters = {
username: 'testuser',
password: 'supersecretpassword123!'
};
await toolGenerator.executeTool(testTool, parameters);
// Check request history doesn't contain password
const history = mockFactory.httpMocks.getRequestHistory();
const loginRequest = history.find(req => req.url === '/api/login');
if (loginRequest) {
const requestString = JSON.stringify(loginRequest);
expect(requestString).not.toContain('supersecretpassword123!');
}
});
test('should validate input sanitization', async () => {
const testTool = 'public_create_checkEmail';
const maliciousEmail = '<script>alert("xss")</script>@test.com';
await expect(toolGenerator.executeTool(testTool, { email: maliciousEmail }))
.rejects.toThrow();
});
});
describe('Public Tools Performance Tests', () => {
test('should complete tool execution within reasonable time', async () => {
const testTool = 'public_create_checkEmail';
const parameters = { email: 'test@example.com' };
const startTime = Date.now();
await toolGenerator.executeTool(testTool, parameters);
const endTime = Date.now();
const executionTime = endTime - startTime;
expect(executionTime).toBeLessThan(5000); // Should complete within 5 seconds
});
test('should handle concurrent tool executions', async () => {
const testTool = 'public_create_checkEmail';
const promises = [];
// Execute 10 concurrent requests
for (let i = 0; i < 10; i++) {
const parameters = { email: `test${i}@example.com` };
promises.push(toolGenerator.executeTool(testTool, parameters));
}
const results = await Promise.allSettled(promises);
// All requests should complete (either fulfilled or rejected)
expect(results.length).toBe(10);
results.forEach(result => {
expect(['fulfilled', 'rejected']).toContain(result.status);
});
});
});
describe('Public Tools Integration', () => {
test('should maintain consistent response format across tools', async () => {
const testTools = [
{ name: 'public_create_login', params: { username: 'test', password: 'test' } },
{ name: 'public_create_checkEmail', params: { email: 'test@example.com' } },
{ name: 'public_create_forgotPassword', params: { email: 'test@example.com' } }
];
for (const { name, params } of testTools) {
const result = await toolGenerator.executeTool(name, params);
// All tools should return consistent structure
expect(result).toHaveProperty('success');
expect(result).toHaveProperty('data');
expect(typeof result.success).toBe('boolean');
}
});
});
});

349
tests/public/login.test.js Normal file
View File

@@ -0,0 +1,349 @@
/**
* @fileoverview Tests for public login MCP tools
* Tests all public authentication and login endpoints
*/
import { describe, test, expect, beforeEach, afterEach } from "@jest/globals";
import { mockFactory } from "../mocks/mockFactory.js";
import { ToolGenerator } from "../../src/tools/ToolGenerator.js";
describe("Public Login Tools", () => {
let mockEnv;
let toolGenerator;
beforeEach(() => {
// Create mock environment
mockEnv = mockFactory.createMockEnvironment({
authTypes: ["public"],
enableHttpMocks: true,
enableAuthMocks: true,
});
toolGenerator = mockEnv.toolGenerator;
});
afterEach(() => {
mockFactory.resetAllMocks();
});
describe("public_create_login", () => {
test("should successfully login with valid credentials", async () => {
// Setup
const toolName = "public_create_login";
const parameters = {
username: "validuser",
password: "validpassword",
};
// Mock successful login response
mockFactory.httpMocks.mockRequest("POST", "/api/login", {
status: 200,
data: {
success: true,
token: "mock_login_token_123",
user: {
id: "user_123",
username: "validuser",
email: "test@example.com",
},
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data).toBeDefined();
// Verify HTTP request was made
const requestHistory = mockFactory.httpMocks.getRequestHistory();
const loginRequest = requestHistory.find(
(req) => req.method === "POST" && req.url === "/api/login"
);
expect(loginRequest).toBeDefined();
});
test("should fail with invalid credentials", async () => {
// Setup
const toolName = "public_create_login";
const parameters = {
username: "invaliduser",
password: "wrongpassword",
};
// Mock failed login response
mockFactory.httpMocks.mockRequest("POST", "/api/login", null, true, {
response: {
status: 401,
data: { error: "Invalid credentials" },
},
});
// Execute & Assert
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should validate required parameters", async () => {
const toolName = "public_create_login";
// Test missing username
await expect(
toolGenerator.executeTool(toolName, { password: "test" })
).rejects.toThrow();
// Test missing password
await expect(
toolGenerator.executeTool(toolName, { username: "test" })
).rejects.toThrow();
// Test empty parameters
await expect(toolGenerator.executeTool(toolName, {})).rejects.toThrow();
});
});
describe("public_create_frontendlogin", () => {
test("should successfully login patient", async () => {
// Setup
const toolName = "public_create_frontendlogin";
const parameters = {
email: "patient@test.com",
password: "patientpassword",
};
// Mock successful patient login
mockFactory.httpMocks.mockRequest("POST", "/api/frontend/login", {
status: 200,
data: {
success: true,
token: "mock_patient_token_456",
user: {
id: "patient_456",
email: "patient@test.com",
role: "patient",
},
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.user.role).toBe("patient");
});
test("should validate email format", async () => {
const toolName = "public_create_frontendlogin";
const parameters = {
email: "invalid-email",
password: "password",
};
// Execute & Assert
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
});
describe("public_create_adminlogin", () => {
test("should successfully login admin", async () => {
// Setup
const toolName = "public_create_adminlogin";
const parameters = {
email: "admin@test.com",
password: "adminpassword",
};
// Mock successful admin login
mockFactory.httpMocks.mockRequest("POST", "/api/admin/login", {
status: 200,
data: {
success: true,
token: "mock_admin_token_789",
user: {
id: "admin_789",
email: "admin@test.com",
role: "admin",
},
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.user.role).toBe("admin");
});
});
describe("public_create_loginPartnerApi", () => {
test("should successfully login partner", async () => {
// Setup
const toolName = "public_create_loginPartnerApi";
const parameters = {
email: "partner@test.com",
password: "partnerpassword",
};
// Mock successful partner login
mockFactory.httpMocks.mockRequest("POST", "/api/login-partner-api", {
status: 200,
data: {
success: true,
token: "mock_partner_token_101",
user: {
id: "partner_101",
email: "partner@test.com",
role: "partner",
},
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.user.role).toBe("partner");
});
});
describe("public_create_affiliateLoginApi", () => {
test("should successfully login affiliate", async () => {
// Setup
const toolName = "public_create_affiliateLoginApi";
const parameters = {
email: "affiliate@test.com",
password: "affiliatepassword",
};
// Mock successful affiliate login
mockFactory.httpMocks.mockRequest("POST", "/api/affiliate-login-api", {
status: 200,
data: {
success: true,
token: "mock_affiliate_token_202",
user: {
id: "affiliate_202",
email: "affiliate@test.com",
role: "affiliate",
},
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.user.role).toBe("affiliate");
});
});
describe("public_create_networklogin", () => {
test("should successfully login network user", async () => {
// Setup
const toolName = "public_create_networklogin";
const parameters = {
email: "network@test.com",
password: "networkpassword",
};
// Mock successful network login
mockFactory.httpMocks.mockRequest("POST", "/api/network/login", {
status: 200,
data: {
success: true,
token: "mock_network_token_303",
user: {
id: "network_303",
email: "network@test.com",
role: "network",
},
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.user.role).toBe("network");
});
});
describe("Login Security Tests", () => {
test("should handle rate limiting", async () => {
const toolName = "public_create_login";
const parameters = {
username: "testuser",
password: "testpassword",
};
// Mock rate limit response
mockFactory.httpMocks.mockRequest("POST", "/api/login", null, true, {
response: {
status: 429,
data: { error: "Too many login attempts" },
},
});
// Execute & Assert
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should handle server errors gracefully", async () => {
const toolName = "public_create_login";
const parameters = {
username: "testuser",
password: "testpassword",
};
// Mock server error
mockFactory.httpMocks.mockRequest("POST", "/api/login", null, true, {
response: {
status: 500,
data: { error: "Internal server error" },
},
});
// Execute & Assert
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should not log sensitive information", async () => {
const toolName = "public_create_login";
const parameters = {
username: "testuser",
password: "secretpassword",
};
// Mock successful login
mockFactory.httpMocks.mockRequest("POST", "/api/login", {
status: 200,
data: { success: true, token: "token123" },
});
// Execute
await toolGenerator.executeTool(toolName, parameters);
// Verify password is not in request history
const requestHistory = mockFactory.httpMocks.getRequestHistory();
const loginRequest = requestHistory.find(
(req) => req.method === "POST" && req.url === "/api/login"
);
// Password should be redacted or not logged in plain text
expect(JSON.stringify(loginRequest)).not.toContain("secretpassword");
});
});
});

View File

@@ -0,0 +1,455 @@
/**
* @fileoverview Tests for public password management MCP tools
* Tests password reset, forgot password, and set password functionality
*/
import { describe, test, expect, beforeEach, afterEach } from "@jest/globals";
import { mockFactory } from "../mocks/mockFactory.js";
describe("Public Password Management Tools", () => {
let mockEnv;
let toolGenerator;
beforeEach(() => {
mockEnv = mockFactory.createMockEnvironment({
authTypes: ["public"],
enableHttpMocks: true,
});
toolGenerator = mockEnv.toolGenerator;
});
afterEach(() => {
mockFactory.resetAllMocks();
});
describe("public_create_forgotPassword", () => {
test("should successfully initiate password reset", async () => {
// Setup
const toolName = "public_create_forgotPassword";
const parameters = {
email: "user@test.com",
};
// Mock successful forgot password response
mockFactory.httpMocks.mockRequest("POST", "/api/forgot-password", {
status: 200,
data: {
success: true,
message: "Password reset email sent successfully",
email: "user@test.com",
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("Password reset email sent");
});
test("should validate email format", async () => {
const toolName = "public_create_forgotPassword";
const parameters = {
email: "invalid-email-format",
};
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should handle non-existent email gracefully", async () => {
const toolName = "public_create_forgotPassword";
const parameters = {
email: "nonexistent@test.com",
};
// Mock response for non-existent email (should still return success for security)
mockFactory.httpMocks.mockRequest("POST", "/api/forgot-password", {
status: 200,
data: {
success: true,
message: "If the email exists, a reset link has been sent",
},
});
const result = await toolGenerator.executeTool(toolName, parameters);
expect(result.success).toBe(true);
});
});
describe("public_create_frontendforgotPassword", () => {
test("should successfully initiate patient password reset", async () => {
// Setup
const toolName = "public_create_frontendforgotPassword";
const parameters = {
email: "patient@test.com",
};
// Mock successful patient forgot password response
mockFactory.httpMocks.mockRequest(
"POST",
"/api/frontend/forgot-password",
{
status: 200,
data: {
success: true,
message: "Patient password reset email sent",
email: "patient@test.com",
},
}
);
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("Patient password reset");
});
});
describe("public_create_providerforgotPassword", () => {
test("should successfully initiate provider password reset", async () => {
// Setup
const toolName = "public_create_providerforgotPassword";
const parameters = {
email: "provider@test.com",
};
// Mock successful provider forgot password response
mockFactory.httpMocks.mockRequest(
"POST",
"/api/emr/provider/forgot-password",
{
status: 200,
data: {
success: true,
message: "Provider password reset email sent",
email: "provider@test.com",
},
}
);
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("Provider password reset");
});
});
describe("public_create_passwordReset", () => {
test("should successfully reset password with valid token", async () => {
// Setup
const toolName = "public_create_passwordReset";
const parameters = {
token: "valid_reset_token_123",
email: "user@test.com",
password: "NewSecurePass123!",
password_confirmation: "NewSecurePass123!",
};
// Mock successful password reset
mockFactory.httpMocks.mockRequest("POST", "/api/password-reset", {
status: 200,
data: {
success: true,
message: "Password reset successfully",
email: "user@test.com",
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("Password reset successfully");
});
test("should validate password confirmation match", async () => {
const toolName = "public_create_passwordReset";
const parameters = {
token: "valid_reset_token_123",
email: "user@test.com",
password: "NewSecurePass123!",
password_confirmation: "DifferentPassword123!",
};
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should handle invalid reset token", async () => {
const toolName = "public_create_passwordReset";
const parameters = {
token: "invalid_token",
email: "user@test.com",
password: "NewSecurePass123!",
password_confirmation: "NewSecurePass123!",
};
// Mock invalid token response
mockFactory.httpMocks.mockRequest(
"POST",
"/api/password-reset",
null,
true,
{
response: {
status: 400,
data: { error: "Invalid or expired reset token" },
},
}
);
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should handle expired reset token", async () => {
const toolName = "public_create_passwordReset";
const parameters = {
token: "expired_token_456",
email: "user@test.com",
password: "NewSecurePass123!",
password_confirmation: "NewSecurePass123!",
};
// Mock expired token response
mockFactory.httpMocks.mockRequest(
"POST",
"/api/password-reset",
null,
true,
{
response: {
status: 410,
data: { error: "Reset token has expired" },
},
}
);
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
});
describe("public_create_frontendresetPassword", () => {
test("should successfully reset patient password", async () => {
// Setup
const toolName = "public_create_frontendresetPassword";
const parameters = {
email: "patient@test.com",
password: "NewPatientPass123!",
password_confirmation: "NewPatientPass123!",
token: "patient_reset_token_789",
};
// Mock successful patient password reset
mockFactory.httpMocks.mockRequest(
"POST",
"/api/frontend/reset-password",
{
status: 200,
data: {
success: true,
message: "Patient password reset successfully",
email: "patient@test.com",
},
}
);
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("Patient password reset");
});
});
describe("public_create_setPassword", () => {
test("should successfully set password with valid token", async () => {
// Setup
const toolName = "public_create_setPassword";
const parameters = {
password: "NewPassword123!",
password_confirmation: "NewPassword123!",
token: "set_password_token_101",
};
// Mock successful password set
mockFactory.httpMocks.mockRequest("POST", "/api/set-password", {
status: 200,
data: {
success: true,
message: "Password set successfully",
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("Password set successfully");
});
test("should validate password strength requirements", async () => {
const toolName = "public_create_setPassword";
// Test weak passwords
const weakPasswords = [
"123", // Too short
"password", // No numbers/special chars
"12345678", // Only numbers
"PASSWORD", // Only uppercase
"password123", // No special characters
];
for (const weakPassword of weakPasswords) {
const parameters = {
password: weakPassword,
password_confirmation: weakPassword,
token: "valid_token",
};
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
}
});
});
describe("public_create_emrsetPassword", () => {
test("should successfully set EMR password", async () => {
// Setup
const toolName = "public_create_emrsetPassword";
const parameters = {
password: "EMRPassword123!",
password_confirmation: "EMRPassword123!",
token: "emr_token_202",
};
// Mock successful EMR password set
mockFactory.httpMocks.mockRequest("POST", "/api/emr/set-password", {
status: 200,
data: {
success: true,
message: "EMR password set successfully",
},
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.message).toContain("EMR password set");
});
});
describe("Password Security Tests", () => {
test("should enforce password complexity requirements", async () => {
const toolName = "public_create_passwordReset";
// Test various password requirements
const testCases = [
{
password: "short",
description: "too short",
},
{
password: "nouppercase123!",
description: "no uppercase",
},
{
password: "NOLOWERCASE123!",
description: "no lowercase",
},
{
password: "NoNumbers!",
description: "no numbers",
},
{
password: "NoSpecialChars123",
description: "no special characters",
},
];
for (const testCase of testCases) {
const parameters = {
token: "valid_token",
email: "test@test.com",
password: testCase.password,
password_confirmation: testCase.password,
};
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
}
});
test("should handle rate limiting for password reset attempts", async () => {
const toolName = "public_create_forgotPassword";
const parameters = {
email: "ratelimited@test.com",
};
// Mock rate limit response
mockFactory.httpMocks.mockRequest(
"POST",
"/api/forgot-password",
null,
true,
{
response: {
status: 429,
data: { error: "Too many password reset attempts" },
},
}
);
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow();
});
test("should not expose sensitive information in error messages", async () => {
const toolName = "public_create_passwordReset";
const parameters = {
token: "invalid_token",
email: "user@test.com",
password: "ValidPass123!",
password_confirmation: "ValidPass123!",
};
// Mock generic error response
mockFactory.httpMocks.mockRequest(
"POST",
"/api/password-reset",
null,
true,
{
response: {
status: 400,
data: { error: "Invalid request" }, // Generic error message
},
}
);
await expect(
toolGenerator.executeTool(toolName, parameters)
).rejects.toThrow("Invalid request");
});
});
});

View File

@@ -0,0 +1,385 @@
/**
* @fileoverview Tests for public registration MCP tools
* Tests all public registration endpoints for different user types
*/
import { describe, test, expect, beforeEach, afterEach } from '@jest/globals';
import { mockFactory } from '../mocks/mockFactory.js';
describe('Public Registration Tools', () => {
let mockEnv;
let toolGenerator;
beforeEach(() => {
mockEnv = mockFactory.createMockEnvironment({
authTypes: ['public'],
enableHttpMocks: true,
enableHealthcareMocks: true
});
toolGenerator = mockEnv.toolGenerator;
});
afterEach(() => {
mockFactory.resetAllMocks();
});
describe('public_create_emrApiproviderRegister', () => {
test('should successfully register a new provider', async () => {
// Setup
const toolName = 'public_create_emrApiproviderRegister';
const parameters = {
firstName: 'Dr. John',
lastName: 'Smith',
username: 'drsmith',
emailAddress: 'dr.smith@test.com',
textMessageNumber: '555-0123',
newUserPassword: 'SecurePass123!',
company_name: 'Test Medical Center',
on_your_domain: true
};
// Mock successful registration
mockFactory.httpMocks.mockRequest('POST', '/emr-api/provider-register', {
status: 201,
data: {
success: true,
provider: {
id: 'provider_123',
firstName: 'Dr. John',
lastName: 'Smith',
emailAddress: 'dr.smith@test.com',
username: 'drsmith'
},
message: 'Provider registered successfully'
}
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.provider.firstName).toBe('Dr. John');
expect(result.data.provider.emailAddress).toBe('dr.smith@test.com');
});
test('should validate required provider registration fields', async () => {
const toolName = 'public_create_emrApiproviderRegister';
// Test missing required fields
const requiredFields = [
'firstName', 'lastName', 'username', 'emailAddress',
'textMessageNumber', 'newUserPassword', 'company_name'
];
for (const field of requiredFields) {
const incompleteParams = {
firstName: 'Dr. John',
lastName: 'Smith',
username: 'drsmith',
emailAddress: 'dr.smith@test.com',
textMessageNumber: '555-0123',
newUserPassword: 'SecurePass123!',
company_name: 'Test Medical Center'
};
delete incompleteParams[field];
await expect(toolGenerator.executeTool(toolName, incompleteParams))
.rejects.toThrow();
}
});
test('should handle duplicate email registration', async () => {
const toolName = 'public_create_emrApiproviderRegister';
const parameters = {
firstName: 'Dr. John',
lastName: 'Smith',
username: 'drsmith',
emailAddress: 'existing@test.com',
textMessageNumber: '555-0123',
newUserPassword: 'SecurePass123!',
company_name: 'Test Medical Center'
};
// Mock duplicate email error
mockFactory.httpMocks.mockRequest('POST', '/emr-api/provider-register', null, true, {
response: {
status: 409,
data: { error: 'Email already exists' }
}
});
await expect(toolGenerator.executeTool(toolName, parameters))
.rejects.toThrow();
});
});
describe('public_create_registerPatient', () => {
test('should successfully register a new patient', async () => {
// Setup
const toolName = 'public_create_registerPatient';
const parameters = {
first_name: 'Jane',
last_name: 'Doe',
email: 'jane.doe@test.com',
phone_no: '555-0456',
dob: '1990-01-01',
gender: 'Female',
provider_id: 123,
preferredPhone: '555-0456',
password: 'PatientPass123!',
username: 'janedoe',
isportalAccess: true
};
// Mock successful patient registration
mockFactory.httpMocks.mockRequest('POST', '/api/register-patients', {
status: 201,
data: {
success: true,
patient: {
id: 'patient_456',
first_name: 'Jane',
last_name: 'Doe',
email: 'jane.doe@test.com',
isportalAccess: true
},
message: 'Patient registered successfully'
}
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.patient.first_name).toBe('Jane');
expect(result.data.patient.email).toBe('jane.doe@test.com');
expect(result.data.patient.isportalAccess).toBe(true);
});
test('should validate patient data format', async () => {
const toolName = 'public_create_registerPatient';
// Test invalid email format
const invalidEmailParams = {
first_name: 'Jane',
last_name: 'Doe',
email: 'invalid-email',
phone_no: '555-0456',
dob: '1990-01-01',
gender: 'Female',
password: 'PatientPass123!'
};
await expect(toolGenerator.executeTool(toolName, invalidEmailParams))
.rejects.toThrow();
// Test invalid date format
const invalidDateParams = {
first_name: 'Jane',
last_name: 'Doe',
email: 'jane@test.com',
phone_no: '555-0456',
dob: 'invalid-date',
gender: 'Female',
password: 'PatientPass123!'
};
await expect(toolGenerator.executeTool(toolName, invalidDateParams))
.rejects.toThrow();
});
});
describe('public_create_affiliateRegisterApi', () => {
test('should successfully register a new affiliate', async () => {
// Setup
const toolName = 'public_create_affiliateRegisterApi';
const parameters = {
first_name: 'Alice',
last_name: 'Johnson',
phone_no: '555-0789',
email: 'alice.johnson@test.com',
dob: '1985-05-15',
gender: 'Female',
partner_email: 'partner@test.com'
};
// Mock successful affiliate registration
mockFactory.httpMocks.mockRequest('POST', '/api/affiliate-register-api', {
status: 201,
data: {
success: true,
affiliate: {
id: 'affiliate_789',
first_name: 'Alice',
last_name: 'Johnson',
email: 'alice.johnson@test.com'
},
message: 'Affiliate registered successfully'
}
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.affiliate.first_name).toBe('Alice');
expect(result.data.affiliate.email).toBe('alice.johnson@test.com');
});
});
describe('public_create_partnerRegisterApi', () => {
test('should successfully register a new partner', async () => {
// Setup
const toolName = 'public_create_partnerRegisterApi';
const parameters = {
first_name: 'Bob',
last_name: 'Wilson',
phone_no: '555-0321',
email: 'bob.wilson@test.com',
dob: '1980-12-10',
gender: 'Male',
password: 'PartnerPass123!'
};
// Mock successful partner registration
mockFactory.httpMocks.mockRequest('POST', '/api/partner-register-api', {
status: 201,
data: {
success: true,
partner: {
id: 'partner_321',
first_name: 'Bob',
last_name: 'Wilson',
email: 'bob.wilson@test.com'
},
message: 'Partner registered successfully'
}
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.partner.first_name).toBe('Bob');
expect(result.data.partner.email).toBe('bob.wilson@test.com');
});
});
describe('public_create_networkregister', () => {
test('should successfully register a new network user', async () => {
// Setup
const toolName = 'public_create_networkregister';
const parameters = {
first_name: 'Carol',
last_name: 'Davis',
phone_no: '555-0654',
email: 'carol.davis@test.com',
dob: '1992-03-20',
gender: 'Female',
password: 'NetworkPass123!',
partner_id: 'partner_123'
};
// Mock successful network registration
mockFactory.httpMocks.mockRequest('POST', '/api/network/register', {
status: 201,
data: {
success: true,
network_user: {
id: 'network_654',
first_name: 'Carol',
last_name: 'Davis',
email: 'carol.davis@test.com'
},
message: 'Network user registered successfully'
}
});
// Execute
const result = await toolGenerator.executeTool(toolName, parameters);
// Assert
expect(result.success).toBe(true);
expect(result.data.network_user.first_name).toBe('Carol');
expect(result.data.network_user.email).toBe('carol.davis@test.com');
});
});
describe('Registration Security Tests', () => {
test('should validate password strength', async () => {
const toolName = 'public_create_emrApiproviderRegister';
const weakPasswordParams = {
firstName: 'Dr. John',
lastName: 'Smith',
username: 'drsmith',
emailAddress: 'dr.smith@test.com',
textMessageNumber: '555-0123',
newUserPassword: '123', // Weak password
company_name: 'Test Medical Center'
};
await expect(toolGenerator.executeTool(toolName, weakPasswordParams))
.rejects.toThrow();
});
test('should sanitize input data', async () => {
const toolName = 'public_create_registerPatient';
const maliciousParams = {
first_name: '<script>alert("xss")</script>',
last_name: 'Doe',
email: 'test@test.com',
phone_no: '555-0456',
dob: '1990-01-01',
gender: 'Female',
password: 'ValidPass123!'
};
// Mock successful registration (input should be sanitized)
mockFactory.httpMocks.mockRequest('POST', '/api/register-patients', {
status: 201,
data: {
success: true,
patient: {
id: 'patient_123',
first_name: 'alert("xss")', // Sanitized
email: 'test@test.com'
}
}
});
const result = await toolGenerator.executeTool(toolName, maliciousParams);
// Verify XSS attempt was sanitized
expect(result.data.patient.first_name).not.toContain('<script>');
});
test('should handle registration rate limiting', async () => {
const toolName = 'public_create_registerPatient';
const parameters = {
first_name: 'Jane',
last_name: 'Doe',
email: 'jane@test.com',
phone_no: '555-0456',
dob: '1990-01-01',
gender: 'Female',
password: 'ValidPass123!'
};
// Mock rate limit response
mockFactory.httpMocks.mockRequest('POST', '/api/register-patients', null, true, {
response: {
status: 429,
data: { error: 'Too many registration attempts' }
}
});
await expect(toolGenerator.executeTool(toolName, parameters))
.rejects.toThrow();
});
});
});