Some checks failed
System Monitoring / Health Checks (push) Has been cancelled
System Monitoring / Performance Monitoring (push) Has been cancelled
System Monitoring / Database Monitoring (push) Has been cancelled
System Monitoring / Cache Monitoring (push) Has been cancelled
System Monitoring / Log Monitoring (push) Has been cancelled
System Monitoring / Resource Monitoring (push) Has been cancelled
System Monitoring / Uptime Monitoring (push) Has been cancelled
System Monitoring / Backup Monitoring (push) Has been cancelled
System Monitoring / Security Monitoring (push) Has been cancelled
System Monitoring / Monitoring Dashboard (push) Has been cancelled
System Monitoring / Alerting (push) Has been cancelled
Security Scanning / Dependency Scanning (push) Has been cancelled
Security Scanning / Code Security Scanning (push) Has been cancelled
Security Scanning / Secrets Scanning (push) Has been cancelled
Security Scanning / Container Security Scanning (push) Has been cancelled
Security Scanning / Compliance Checking (push) Has been cancelled
Security Scanning / Security Dashboard (push) Has been cancelled
Security Scanning / Security Remediation (push) Has been cancelled
323 lines
12 KiB
Python
323 lines
12 KiB
Python
"""
|
|
Unit tests for Healthcare Models
|
|
|
|
Tests for healthcare module models:
|
|
- Patient
|
|
- Appointment
|
|
|
|
Author: Claude
|
|
"""
|
|
|
|
import pytest
|
|
from django.test import TestCase
|
|
from django.contrib.auth import get_user_model
|
|
from django.utils import timezone
|
|
from decimal import Decimal
|
|
from datetime import date, time, timedelta
|
|
|
|
from backend.src.core.models.tenant import Tenant
|
|
from backend.src.core.models.user import User
|
|
from backend.src.modules.healthcare.models.patient import Patient
|
|
from backend.src.modules.healthcare.models.appointment import Appointment
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class PatientModelTest(TestCase):
|
|
"""Test cases for Patient model"""
|
|
|
|
def setUp(self):
|
|
self.tenant = Tenant.objects.create(
|
|
name='Test Healthcare Sdn Bhd',
|
|
schema_name='test_healthcare',
|
|
domain='testhealthcare.com',
|
|
business_type='healthcare'
|
|
)
|
|
|
|
self.user = User.objects.create_user(
|
|
username='doctor',
|
|
email='doctor@test.com',
|
|
password='test123',
|
|
tenant=self.tenant,
|
|
role='staff'
|
|
)
|
|
|
|
self.patient_data = {
|
|
'tenant': self.tenant,
|
|
'patient_id': 'P2024010001',
|
|
'first_name': 'John',
|
|
'last_name': 'Doe',
|
|
'ic_number': '000101-01-0001',
|
|
'passport_number': '',
|
|
'nationality': 'Malaysian',
|
|
'gender': 'male',
|
|
'date_of_birth': date(1990, 1, 1),
|
|
'blood_type': 'O+',
|
|
'email': 'john.doe@test.com',
|
|
'phone': '+60123456789',
|
|
'emergency_contact_name': 'Jane Doe',
|
|
'emergency_contact_phone': '+60123456788',
|
|
'emergency_contact_relationship': 'Spouse',
|
|
'address': '123 Test Street',
|
|
'city': 'Kuala Lumpur',
|
|
'state': 'KUL',
|
|
'postal_code': '50000',
|
|
'medical_history': 'No significant medical history',
|
|
'allergies': 'None known',
|
|
'current_medications': 'None',
|
|
'chronic_conditions': 'None',
|
|
'last_visit_date': None,
|
|
'is_active': True,
|
|
'created_by': self.user
|
|
}
|
|
|
|
def test_create_patient(self):
|
|
"""Test creating a new patient"""
|
|
patient = Patient.objects.create(**self.patient_data)
|
|
self.assertEqual(patient.tenant, self.tenant)
|
|
self.assertEqual(patient.patient_id, self.patient_data['patient_id'])
|
|
self.assertEqual(patient.first_name, self.patient_data['first_name'])
|
|
self.assertEqual(patient.last_name, self.patient_data['last_name'])
|
|
self.assertEqual(patient.ic_number, self.patient_data['ic_number'])
|
|
self.assertEqual(patient.gender, self.patient_data['gender'])
|
|
self.assertEqual(patient.blood_type, self.patient_data['blood_type'])
|
|
self.assertTrue(patient.is_active)
|
|
|
|
def test_patient_string_representation(self):
|
|
"""Test patient string representation"""
|
|
patient = Patient.objects.create(**self.patient_data)
|
|
self.assertEqual(str(patient), f"{patient.first_name} {patient.last_name} ({patient.patient_id})")
|
|
|
|
def test_patient_full_name(self):
|
|
"""Test patient full name property"""
|
|
patient = Patient.objects.create(**self.patient_data)
|
|
self.assertEqual(patient.full_name, f"{patient.first_name} {patient.last_name}")
|
|
|
|
def test_patient_age(self):
|
|
"""Test patient age calculation"""
|
|
patient = Patient.objects.create(**self.patient_data)
|
|
|
|
# Age should be calculated based on date of birth
|
|
today = date.today()
|
|
expected_age = today.year - patient.date_of_birth.year
|
|
if today.month < patient.date_of_birth.month or (today.month == patient.date_of_birth.month and today.day < patient.date_of_birth.day):
|
|
expected_age -= 1
|
|
|
|
self.assertEqual(patient.age, expected_age)
|
|
|
|
def test_patient_malaysian_ic_validation(self):
|
|
"""Test Malaysian IC number validation"""
|
|
# Valid IC number
|
|
patient = Patient.objects.create(**self.patient_data)
|
|
self.assertEqual(patient.ic_number, self.patient_data['ic_number'])
|
|
|
|
# Invalid IC number format
|
|
invalid_data = self.patient_data.copy()
|
|
invalid_data['ic_number'] = '123'
|
|
with self.assertRaises(Exception):
|
|
Patient.objects.create(**invalid_data)
|
|
|
|
def test_patient_gender_choices(self):
|
|
"""Test patient gender validation"""
|
|
invalid_data = self.patient_data.copy()
|
|
invalid_data['gender'] = 'invalid_gender'
|
|
|
|
with self.assertRaises(Exception):
|
|
Patient.objects.create(**invalid_data)
|
|
|
|
def test_patient_blood_type_choices(self):
|
|
"""Test patient blood type validation"""
|
|
invalid_data = self.patient_data.copy()
|
|
invalid_data['blood_type'] = 'Z+'
|
|
|
|
with self.assertRaises(Exception):
|
|
Patient.objects.create(**invalid_data)
|
|
|
|
def test_patient_phone_validation(self):
|
|
"""Test Malaysian phone number validation"""
|
|
# Valid Malaysian phone number
|
|
patient = Patient.objects.create(**self.patient_data)
|
|
self.assertEqual(patient.phone, self.patient_data['phone'])
|
|
|
|
# Invalid phone number
|
|
invalid_data = self.patient_data.copy()
|
|
invalid_data['phone'] = '12345'
|
|
with self.assertRaises(Exception):
|
|
Patient.objects.create(**invalid_data)
|
|
|
|
def test_patient_medical_info_validation(self):
|
|
"""Test patient medical information validation"""
|
|
# Test with medical conditions
|
|
data = self.patient_data.copy()
|
|
data['chronic_conditions'] = 'Diabetes, Hypertension'
|
|
data['allergies'] = 'Penicillin, Sulfa drugs'
|
|
|
|
patient = Patient.objects.create(**data)
|
|
self.assertEqual(patient.chronic_conditions, 'Diabetes, Hypertension')
|
|
self.assertEqual(patient.allergies, 'Penicillin, Sulfa drugs')
|
|
|
|
|
|
class AppointmentModelTest(TestCase):
|
|
"""Test cases for Appointment model"""
|
|
|
|
def setUp(self):
|
|
self.tenant = Tenant.objects.create(
|
|
name='Test Healthcare Sdn Bhd',
|
|
schema_name='test_healthcare',
|
|
domain='testhealthcare.com',
|
|
business_type='healthcare'
|
|
)
|
|
|
|
self.doctor = User.objects.create_user(
|
|
username='doctor',
|
|
email='doctor@test.com',
|
|
password='test123',
|
|
tenant=self.tenant,
|
|
role='staff'
|
|
)
|
|
|
|
self.patient = Patient.objects.create(
|
|
tenant=self.tenant,
|
|
patient_id='P2024010001',
|
|
first_name='John',
|
|
last_name='Doe',
|
|
ic_number='000101-01-0001',
|
|
gender='male',
|
|
date_of_birth=date(1990, 1, 1),
|
|
blood_type='O+',
|
|
phone='+60123456789',
|
|
created_by=self.doctor
|
|
)
|
|
|
|
self.appointment_data = {
|
|
'tenant': self.tenant,
|
|
'patient': self.patient,
|
|
'doctor': self.doctor,
|
|
'appointment_number': 'APT-2024010001',
|
|
'appointment_date': date.today() + timedelta(days=1),
|
|
'appointment_time': time(10, 0),
|
|
'end_time': time(10, 30),
|
|
'appointment_type': 'consultation',
|
|
'status': 'scheduled',
|
|
'reason': 'General checkup',
|
|
'notes': '',
|
|
'is_telemedicine': False,
|
|
'telemedicine_link': '',
|
|
'reminder_sent': False,
|
|
'created_by': self.doctor
|
|
}
|
|
|
|
def test_create_appointment(self):
|
|
"""Test creating a new appointment"""
|
|
appointment = Appointment.objects.create(**self.appointment_data)
|
|
self.assertEqual(appointment.tenant, self.tenant)
|
|
self.assertEqual(appointment.patient, self.patient)
|
|
self.assertEqual(appointment.doctor, self.doctor)
|
|
self.assertEqual(appointment.appointment_number, self.appointment_data['appointment_number'])
|
|
self.assertEqual(appointment.status, self.appointment_data['status'])
|
|
self.assertEqual(appointment.appointment_type, self.appointment_data['appointment_type'])
|
|
self.assertFalse(appointment.is_telemedicine)
|
|
|
|
def test_appointment_string_representation(self):
|
|
"""Test appointment string representation"""
|
|
appointment = Appointment.objects.create(**self.appointment_data)
|
|
expected = f"{self.patient.full_name} - {appointment.appointment_date} at {appointment.appointment_time}"
|
|
self.assertEqual(str(appointment), expected)
|
|
|
|
def test_appointment_duration(self):
|
|
"""Test appointment duration calculation"""
|
|
appointment = Appointment.objects.create(**self.appointment_data)
|
|
|
|
# Duration should be 30 minutes
|
|
self.assertEqual(appointment.duration, 30)
|
|
|
|
def test_appointment_is_upcoming(self):
|
|
"""Test appointment upcoming status"""
|
|
# Future appointment
|
|
appointment = Appointment.objects.create(**self.appointment_data)
|
|
self.assertTrue(appointment.is_upcoming)
|
|
|
|
# Past appointment
|
|
appointment.appointment_date = date.today() - timedelta(days=1)
|
|
appointment.save()
|
|
self.assertFalse(appointment.is_upcoming)
|
|
|
|
def test_appointment_status_choices(self):
|
|
"""Test appointment status validation"""
|
|
invalid_data = self.appointment_data.copy()
|
|
invalid_data['status'] = 'invalid_status'
|
|
|
|
with self.assertRaises(Exception):
|
|
Appointment.objects.create(**invalid_data)
|
|
|
|
def test_appointment_type_choices(self):
|
|
"""Test appointment type validation"""
|
|
invalid_data = self.appointment_data.copy()
|
|
invalid_data['appointment_type'] = 'invalid_type'
|
|
|
|
with self.assertRaises(Exception):
|
|
Appointment.objects.create(**invalid_data)
|
|
|
|
def test_appointment_time_validation(self):
|
|
"""Test appointment time validation"""
|
|
# Valid time range
|
|
appointment = Appointment.objects.create(**self.appointment_data)
|
|
self.assertEqual(appointment.appointment_time, self.appointment_data['appointment_time'])
|
|
self.assertEqual(appointment.end_time, self.appointment_data['end_time'])
|
|
|
|
# Invalid time range (end before start)
|
|
invalid_data = self.appointment_data.copy()
|
|
invalid_data['appointment_time'] = time(11, 0)
|
|
invalid_data['end_time'] = time(10, 30)
|
|
|
|
with self.assertRaises(Exception):
|
|
Appointment.objects.create(**invalid_data)
|
|
|
|
def test_appointment_conflict_detection(self):
|
|
"""Test appointment conflict detection"""
|
|
# Create first appointment
|
|
appointment1 = Appointment.objects.create(**self.appointment_data)
|
|
|
|
# Try to create conflicting appointment
|
|
conflict_data = self.appointment_data.copy()
|
|
conflict_data['appointment_number'] = 'APT-2024010002'
|
|
conflict_data['appointment_time'] = time(10, 15)
|
|
conflict_data['end_time'] = time(10, 45)
|
|
|
|
# This should not raise an exception but conflict detection should be available
|
|
appointment2 = Appointment.objects.create(**conflict_data)
|
|
|
|
# Check if there's a conflict
|
|
self.assertTrue(
|
|
appointment1.appointment_date == appointment2.appointment_date and
|
|
appointment1.doctor == appointment2.doctor and
|
|
(
|
|
(appointment1.appointment_time <= appointment2.appointment_time < appointment1.end_time) or
|
|
(appointment2.appointment_time <= appointment1.appointment_time < appointment2.end_time)
|
|
)
|
|
)
|
|
|
|
def test_telemedicine_appointment(self):
|
|
"""Test telemedicine appointment features"""
|
|
data = self.appointment_data.copy()
|
|
data['is_telemedicine'] = True
|
|
data['telemedicine_link'] = 'https://meet.test.com/room/12345'
|
|
|
|
appointment = Appointment.objects.create(**data)
|
|
self.assertTrue(appointment.is_telemedicine)
|
|
self.assertEqual(appointment.telemedicine_link, data['telemedicine_link'])
|
|
|
|
def test_appointment_reminder_features(self):
|
|
"""Test appointment reminder features"""
|
|
appointment = Appointment.objects.create(**self.appointment_data)
|
|
|
|
# Initially no reminder sent
|
|
self.assertFalse(appointment.reminder_sent)
|
|
|
|
# Mark reminder as sent
|
|
appointment.reminder_sent = True
|
|
appointment.reminder_sent_at = timezone.now()
|
|
appointment.save()
|
|
|
|
self.assertTrue(appointment.reminder_sent)
|
|
self.assertIsNotNone(appointment.reminder_sent_at) |