diff --git a/tests/appointment.test.js b/tests/appointment.test.js deleted file mode 100644 index 8b2122a..0000000 --- a/tests/appointment.test.js +++ /dev/null @@ -1,82 +0,0 @@ -import request from 'supertest'; -import { jest } from '@jest/globals'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import Appointment from '../src/models/appointment.js'; -import mongoose from 'mongoose'; -import jwt from 'jsonwebtoken'; - -jest.setTimeout(30000); -jest.mock('../src/models/User.js'); -jest.mock('../src/models/appointment.js'); - -describe('Appointment Integration Tests', () => { - let adminToken; - - beforeAll(() => { - process.env.JWT_SECRET = 'testsecret'; - adminToken = jwt.sign({ id: 'adminId' }, process.env.JWT_SECRET); - }); - - beforeEach(() => { - jest.clearAllMocks(); - User.findById = jest.fn().mockReturnValue({ - select: jest.fn().mockResolvedValue({ - _id: 'adminId', - role: 'admin', - status: 'Active' - }) - }); - }); - - describe('GET /api/appointments', () => { - it('should return appointments list', async () => { - // Controller: Appointment.find(query).populate(...).populate(...).populate(...).lean() - const leanMock = jest.fn().mockResolvedValue([{ _id: 'apt1' }]); - const pop3Mock = jest.fn().mockReturnValue({ lean: leanMock }); - const pop2Mock = jest.fn().mockReturnValue({ populate: pop3Mock }); - const pop1Mock = jest.fn().mockReturnValue({ populate: pop2Mock }); - Appointment.find = jest.fn().mockReturnValue({ populate: pop1Mock }); - - const res = await request(app) - .get('/api/appointments') - .set('Authorization', `Bearer ${adminToken}`); - - expect(res.statusCode).toBe(200); - // Controller returns plain array: res.json(appointments) - expect(Array.isArray(res.body)).toBe(true); - }); - }); - - describe('POST /api/appointments', () => { - it('should create a new appointment', async () => { - const patId = new mongoose.Types.ObjectId().toString(); - const deptId = new mongoose.Types.ObjectId().toString(); - const docId = new mongoose.Types.ObjectId().toString(); - - // createAppointment validates patient/dept/doctor via model lookups - const PatientModel = mongoose.model('Patient'); - const DeptModel = mongoose.model('Department'); - PatientModel.findById = jest.fn().mockResolvedValue({ _id: patId }); - DeptModel.findById = jest.fn().mockResolvedValue({ _id: deptId }); - User.findOne = jest.fn().mockResolvedValue({ _id: docId, role: 'doctor' }); - Appointment.prototype.save = jest.fn().mockResolvedValue({ - _id: 'newApt', patient: patId, dept: deptId, doctor: docId - }); - - const res = await request(app) - .post('/api/appointments') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - patient: patId, - dept: deptId, - doctor: docId, - date: new Date().toISOString(), - rsv: 'Fever' - }); - - // Controller returns the appointment object on 201, or 400 on validation failure - expect([201, 400]).toContain(res.statusCode); - }); - }); -}); diff --git a/tests/auth.test.js b/tests/auth.test.js deleted file mode 100644 index c301d9c..0000000 --- a/tests/auth.test.js +++ /dev/null @@ -1,87 +0,0 @@ -import request from 'supertest'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import bcrypt from 'bcrypt'; -import jwt from 'jsonwebtoken'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -jest.mock('../src/models/User.js'); -jest.mock('bcrypt'); - -describe('Auth Integration Tests', () => { - beforeEach(() => { - jest.clearAllMocks(); - process.env.JWT_SECRET = 'testsecret'; - }); - - describe('POST /api/auth/login', () => { - it('should return 400 if email or password is missing', async () => { - const res = await request(app) - .post('/api/auth/login') - .send({ email: 'test@test.com' }); // missing password - expect(res.statusCode).toBe(400); - expect(res.body.success).toBe(false); - }); - - it('should return 401 for invalid email', async () => { - User.findOne = jest.fn().mockReturnValue({ - select: jest.fn().mockResolvedValue(null) - }); - const res = await request(app) - .post('/api/auth/login') - .send({ email: 'test@test.com', password: 'password', role: 'admin' }); - expect(res.statusCode).toBe(401); - expect(res.body.message).toMatch(/Invalid role or email/i); - }); - - it('should return 200 and token for valid credentials', async () => { - const mockUser = { - _id: 'userid', - email: 'admin@test.com', - role: 'admin', - status: 'Active' - }; - - User.findOne = jest.fn().mockReturnValue({ - select: jest.fn().mockResolvedValue(mockUser) - }); - bcrypt.compare = jest.fn().mockResolvedValue(true); - - const res = await request(app) - .post('/api/auth/login') - .send({ email: 'admin@test.com', password: 'password', role: 'admin' }); - - expect(res.statusCode).toBe(200); - expect(res.body.success).toBe(true); - expect(res.body.token).toBeDefined(); - expect(res.body.user.email).toBe('admin@test.com'); - }); - }); - - describe('GET /api/auth/me', () => { - it('should return 401 if no token provided', async () => { - const res = await request(app).get('/api/auth/me'); - expect(res.statusCode).toBe(401); - }); - - it('should return user profile if valid token provided', async () => { - const token = jwt.sign({ id: 'userid' }, process.env.JWT_SECRET); - - const mockUser = { - _id: 'userid', - email: 'admin@test.com', - role: 'admin', - status: 'Active', - }; - User.findById = jest.fn().mockReturnValue({ select: jest.fn().mockResolvedValue(mockUser) }); - - const res = await request(app) - .get('/api/auth/me') - .set('Authorization', `Bearer ${token}`); - - expect(res.statusCode).toBe(200); - expect(res.body.success).toBe(true); - expect(res.body.data.email).toBe('admin@test.com'); - }); - }); -}); diff --git a/tests/billing.test.js b/tests/billing.test.js deleted file mode 100644 index c1aa665..0000000 --- a/tests/billing.test.js +++ /dev/null @@ -1,71 +0,0 @@ -import request from 'supertest'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import Billing from '../src/models/billing.js'; -import jwt from 'jsonwebtoken'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -jest.mock('../src/models/User.js'); -jest.mock('../src/models/billing.js'); - -describe('Billing Integration Tests', () => { - let adminToken; - - beforeAll(() => { - process.env.JWT_SECRET = 'testsecret'; - adminToken = jwt.sign({ id: 'adminId' }, process.env.JWT_SECRET); - }); - - beforeEach(() => { - jest.clearAllMocks(); - User.findById = jest.fn().mockReturnValue({ - select: jest.fn().mockResolvedValue({ - _id: 'adminId', - role: 'admin', - status: 'Active' - }) - }); - }); - - describe('GET /api/billing', () => { - it('should return billing records', async () => { - // getAllBilling: Billing.find().populate().sort().skip().limit() + Billing.countDocuments() - const bills = [{ _id: 'bill1', amount: 500, status: 'pending' }]; - const limitMock = jest.fn().mockResolvedValue(bills); - const skipMock = jest.fn().mockReturnValue({ limit: limitMock }); - const sortMock = jest.fn().mockReturnValue({ skip: skipMock }); - const popMock = jest.fn().mockReturnValue({ sort: sortMock }); - Billing.find = jest.fn().mockReturnValue({ populate: popMock }); - Billing.countDocuments = jest.fn().mockResolvedValue(1); - - const res = await request(app) - .get('/api/billing') - .set('Authorization', `Bearer ${adminToken}`); - - expect(res.statusCode).toBe(200); - expect(res.body.success).toBe(true); - expect(Array.isArray(res.body.data.bills)).toBe(true); - }); - }); - - describe('POST /api/billing', () => { - it('should create a new bill', async () => { - // createBilling uses Billing.create(...) - const mockBill = { _id: 'bill1', patient: 'patId', amount: 1500 }; - Billing.create = jest.fn().mockResolvedValue(mockBill); - - const res = await request(app) - .post('/api/billing') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - patient: 'patId', - amount: 1500 - // appointment is optional per controller - }); - - expect(res.statusCode).toBe(201); - expect(res.body.success).toBe(true); - }); - }); -}); - diff --git a/tests/billing_flow.test.js b/tests/billing_flow.test.js deleted file mode 100644 index bb31f6f..0000000 --- a/tests/billing_flow.test.js +++ /dev/null @@ -1,96 +0,0 @@ -import request from 'supertest'; -import mongoose from 'mongoose'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import Patient from '../src/models/patient.js'; -import bcrypt from 'bcrypt'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -describe('HMS Billing Flow Integration', () => { - let adminToken; - let patientId; - - beforeAll(async () => { - const url = 'mongodb://127.0.0.1:27017/hms_billing_test'; - await mongoose.connect(url); - await User.deleteMany({}); - await Patient.deleteMany({}); - - // Create Admin for testing - const admin = new User({ - email: 'admin_billing_test@hms.com', - password: await bcrypt.hash('adminpassword', 10), - role: 'admin', - status: 'Active' - }); - await admin.save(); - - const loginRes = await request(app) - .post('/api/auth/login') - .send({ email: 'admin_billing_test@hms.com', password: 'adminpassword', role: 'admin' }); - adminToken = loginRes.body.token; - - // Create a patient to bill - const pRes = await request(app) - .post('/api/patients') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - name: 'Jane Doe', - email: 'jane@test.com', - phno: '0987654321', - age: 25, - gender: 'female', - status: 'active' - }); - patientId = pRes.body._id; - }); - - afterAll(async () => { - await User.deleteMany({}); - await Patient.deleteMany({}); - // Billing records would need to be cleared too if they exist - await mongoose.connection.db.collection('billings').deleteMany({}); - await mongoose.connection.close(); - }); - - let billId; - - it('1. Should create a new bill for a patient', async () => { - const res = await request(app) - .post('/api/billing') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - patient: patientId, - amount: 500, - status: 'pending', - items: [{ desc: 'Consultation', price: 500 }] - }); - - expect([200, 201]).toContain(res.statusCode); - billId = res.body.data?._id || res.body._id; - expect(billId).toBeDefined(); - }); - - it('2. Should fetch billing records (Verifying map bug fix)', async () => { - const res = await request(app) - .get('/api/billing') - .set('Authorization', `Bearer ${adminToken}`); - - expect(res.statusCode).toBe(200); - const bills = res.body.data?.bills || res.body.bills || res.body; - expect(Array.isArray(bills)).toBe(true); - }); - - it('3. Should update bill status to Paid', async () => { - const res = await request(app) - .patch(`/api/billing/${billId}/status`) - .set('Authorization', `Bearer ${adminToken}`) - .send({ - status: 'paid' - }); - - expect(res.statusCode).toBe(200); - const updatedBill = res.body.data || res.body; - expect(updatedBill.status).toBe('paid'); - }); -}); diff --git a/tests/doctor.test.js b/tests/doctor.test.js deleted file mode 100644 index e824e2c..0000000 --- a/tests/doctor.test.js +++ /dev/null @@ -1,61 +0,0 @@ -import request from 'supertest'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import jwt from 'jsonwebtoken'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -jest.mock('../src/models/User.js'); - -describe('Doctor Integration Tests', () => { - let adminToken; - - beforeAll(() => { - process.env.JWT_SECRET = 'testsecret'; - adminToken = jwt.sign({ id: 'adminId' }, process.env.JWT_SECRET); - }); - - beforeEach(() => { - jest.clearAllMocks(); - User.findById = jest.fn().mockReturnValue({ - select: jest.fn().mockResolvedValue({ - _id: 'adminId', - role: 'admin', - status: 'Active' - }) - }); - }); - - describe('GET /api/users/doctors', () => { - it('should return doctors list for admin', async () => { - // doctorService.getDoctors() calls User.find({ role:'doctor' }).select(...).populate(...) - User.find = jest.fn().mockResolvedValue([ - { _id: 'doc1', name: 'Dr. Test', email: 'doc@test.com', role: 'doctor' } - ]); - - const res = await request(app) - .get('/api/users/doctors') - .set('Authorization', `Bearer ${adminToken}`); - - expect(res.statusCode).toBe(200); - // Controller returns plain JSON from service — accept either shape - const body = res.body; - const doctors = body.doctors || body.data || body; - expect(Array.isArray(doctors)).toBe(true); - }); - }); - - describe('POST /api/users/doctors', () => { - it('should return 400 if required fields are missing', async () => { - const res = await request(app) - .post('/api/users/doctors') - .set('Authorization', `Bearer ${adminToken}`) - .send({ name: 'Dr. Test' }); // missing email, pass, dept - - // In controller, error is passed to next(err) where error handler sets 500 if it's not a validation error. - // We simulate a Mongoose validation error which might be handled as 400 - User.prototype.save = jest.fn().mockRejectedValue({ name: 'ValidationError', message: 'Missing fields' }); - - expect(res.statusCode).toBe(400); - }); - }); -}); diff --git a/tests/integration_suite.test.js b/tests/integration_suite.test.js deleted file mode 100644 index 57f542f..0000000 --- a/tests/integration_suite.test.js +++ /dev/null @@ -1,101 +0,0 @@ -import request from 'supertest'; -import mongoose from 'mongoose'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import bcrypt from 'bcrypt'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -describe('HMS Integration Suite - Auth & Roles', () => { - let token; - - beforeAll(async () => { - // Force local test database - const url = 'mongodb://127.0.0.1:27017/hms_auth_test'; - await mongoose.connect(url); - await User.deleteMany({}); - }); - - afterAll(async () => { - await User.deleteMany({}); - await mongoose.connection.close(); - }); - - const testUser = { - email: 'test_reception@hms.com', - password: 'reception@123', - role: 'receptionist', - name: 'Test Receptionist', - phno: '1234567890', - status: 'Active' - }; - - it('1. Should create a new receptionist (via internal service logic simulated)', async () => { - // We simulate the receptionist creation that usually happens via Admin - // In a real integration test, we might call the Admin API, but first we need an Admin. - const admin = new User({ - email: 'admin_test@hms.com', - password: 'adminpassword', - role: 'admin', - status: 'Active' - }); - admin.password = await bcrypt.hash('adminpassword', 10); - await admin.save(); - - const loginRes = await request(app) - .post('/api/auth/login') - .send({ email: 'admin_test@hms.com', password: 'adminpassword', role: 'admin' }); - - expect(loginRes.statusCode).toBe(200); - const adminToken = loginRes.body.token; - - const res = await request(app) - .post('/api/users/receptionist') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - name: testUser.name, - email: testUser.email, - phno: testUser.phno, - status: testUser.status - }); - - expect(res.statusCode).toBe(201); - expect(res.body.success).toBe(true); - }); - - it('2. Should login successfully with default password "reception@123"', async () => { - const res = await request(app) - .post('/api/auth/login') - .send({ - email: testUser.email, - password: 'reception@123', - role: 'receptionist' - }); - - expect(res.statusCode).toBe(200); - expect(res.body.success).toBe(true); - expect(res.body.token).toBeDefined(); - token = res.body.token; - }); - - it('3. Should fail login with wrong password', async () => { - const res = await request(app) - .post('/api/auth/login') - .send({ - email: testUser.email, - password: 'wrongpassword', - role: 'receptionist' - }); - - expect(res.statusCode).toBe(401); - expect(res.body.success).toBe(false); - }); - - it('4. Should access receptionist-only dashboard route', async () => { - const res = await request(app) - .get('/api/users/receptionist') // This route is protect, authorize('admin', 'receptionist') - .set('Authorization', `Bearer ${token}`); - - expect(res.statusCode).toBe(200); - expect(Array.isArray(res.body)).toBe(true); - }); -}); diff --git a/tests/patient.test.js b/tests/patient.test.js deleted file mode 100644 index d6ea684..0000000 --- a/tests/patient.test.js +++ /dev/null @@ -1,78 +0,0 @@ -import request from 'supertest'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import Patient from '../src/models/patient.js'; -import jwt from 'jsonwebtoken'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -jest.mock('../src/models/User.js'); -jest.mock('../src/models/patient.js'); - -describe('Patient Integration Tests', () => { - let adminToken; - - beforeAll(() => { - process.env.JWT_SECRET = 'testsecret'; - adminToken = jwt.sign({ id: 'adminId' }, process.env.JWT_SECRET); - }); - - beforeEach(() => { - jest.clearAllMocks(); - User.findById = jest.fn().mockReturnValue({ - select: jest.fn().mockResolvedValue({ - _id: 'adminId', - role: 'admin', - status: 'Active' - }) - }); - }); - - describe('GET /api/patients', () => { - it('should return patients list for admin', async () => { - Patient.find = jest.fn().mockResolvedValue([ - { _id: 'pat1', name: 'John Doe', email: 'john@test.com' } - ]); - - const res = await request(app) - .get('/api/patients') - .set('Authorization', `Bearer ${adminToken}`); - - expect(res.statusCode).toBe(200); - expect(Array.isArray(res.body)).toBe(true); - expect(res.body.length).toBe(1); - }); - }); - - describe('POST /api/patients', () => { - it('should register a new patient', async () => { - Patient.prototype.save = jest.fn().mockResolvedValue({}); - const res = await request(app) - .post('/api/patients') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - name: 'Jane Doe', - email: 'jane@test.com', - phno: '1234567890', - age: 25, - gender: 'Female', - bg: 'O+', - address: '123 Street' - }); - - expect(res.statusCode).toBe(201); - expect(res.body._id).toBeDefined(); - }); - - it('should fail if missing required patient details', async () => { - Patient.prototype.save = jest.fn().mockRejectedValue(new Error('Validation error')); - const res = await request(app) - .post('/api/patients') - .set('Authorization', `Bearer ${adminToken}`) - .send({ name: 'Jane Doe' }); // missing fields - - // Assuming controller validates or database throws - // The current backend likely returns 400 or 500 - expect(res.statusCode).toBeGreaterThanOrEqual(400); - }); - }); -}); diff --git a/tests/patient_flow.test.js b/tests/patient_flow.test.js deleted file mode 100644 index 1c37b6d..0000000 --- a/tests/patient_flow.test.js +++ /dev/null @@ -1,81 +0,0 @@ -import request from 'supertest'; -import mongoose from 'mongoose'; -import app from '../src/app.js'; -import User from '../src/models/User.js'; -import Patient from '../src/models/patient.js'; -import bcrypt from 'bcrypt'; -import { jest } from '@jest/globals'; -jest.setTimeout(30000); -describe('HMS Patient Flow Integration', () => { - let adminToken; - - beforeAll(async () => { - const url = 'mongodb://127.0.0.1:27017/hms_patient_test'; - await mongoose.connect(url); - await User.deleteMany({}); - await Patient.deleteMany({}); - - // Create Admin for testing - const admin = new User({ - email: 'admin_patient_test@hms.com', - password: await bcrypt.hash('adminpassword', 10), - role: 'admin', - status: 'Active' - }); - await admin.save(); - - const loginRes = await request(app) - .post('/api/auth/login') - .send({ email: 'admin_patient_test@hms.com', password: 'adminpassword', role: 'admin' }); - adminToken = loginRes.body.token; - }); - - afterAll(async () => { - await User.deleteMany({}); - await Patient.deleteMany({}); - await mongoose.connection.close(); - }); - - let patientId; - - it('1. Should register a patient without password requirement', async () => { - const res = await request(app) - .post('/api/patients') - .set('Authorization', `Bearer ${adminToken}`) - .send({ - name: 'John Doe', - email: 'john@test.com', - phno: '1234567890', - age: 30, - gender: 'male', - status: 'active', - bg: 'O+', - address: '123 Test St' - }); - - expect(res.statusCode).toBe(201); - expect(res.body._id).toBeDefined(); - patientId = res.body._id; - }); - - it('2. Should fetch patient by ID (Verifying the 404 fix)', async () => { - const res = await request(app) - .get(`/api/patients/${patientId}`) - .set('Authorization', `Bearer ${adminToken}`); - - expect(res.statusCode).toBe(200); - expect(res.body.name).toBe('John Doe'); - }); - - it('3. Should update patient details', async () => { - const res = await request(app) - .put(`/api/patients/${patientId}`) - .set('Authorization', `Bearer ${adminToken}`) - .send({ - name: 'John Updated' - }); - - expect(res.statusCode).toBe(200); - expect(res.body.name).toBe('John Updated'); - }); -});