project initialization
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
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
This commit is contained in:
336
backend/tests/contract/test_healthcare_appointments_get.py
Normal file
336
backend/tests/contract/test_healthcare_appointments_get.py
Normal file
@@ -0,0 +1,336 @@
|
||||
"""
|
||||
Contract test for GET /healthcare/appointments endpoint.
|
||||
This test MUST fail before implementation.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APIClient
|
||||
from rest_framework import status
|
||||
import json
|
||||
|
||||
|
||||
class HealthcareAppointmentsGetContractTest(TestCase):
|
||||
def setUp(self):
|
||||
self.client = APIClient()
|
||||
self.appointments_url = '/api/v1/healthcare/appointments/'
|
||||
|
||||
# Tenant authentication header
|
||||
self.tenant_auth = {'HTTP_AUTHORIZATION': 'Bearer tenant_token'}
|
||||
|
||||
def test_get_appointments_success(self):
|
||||
"""Test successful retrieval of appointments list."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
# This should fail before implementation
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
assert 'appointments' in data
|
||||
assert isinstance(data['appointments'], list)
|
||||
|
||||
# Check pagination structure
|
||||
assert 'pagination' in data
|
||||
pagination = data['pagination']
|
||||
assert 'page' in pagination
|
||||
assert 'limit' in pagination
|
||||
assert 'total' in pagination
|
||||
assert 'pages' in pagination
|
||||
|
||||
def test_get_appointments_unauthorized(self):
|
||||
"""Test appointments list retrieval without authentication."""
|
||||
response = self.client.get(self.appointments_url)
|
||||
|
||||
assert response.status_code == status.HTTP_401_UNAUTHORIZED
|
||||
|
||||
def test_get_appointments_with_pagination(self):
|
||||
"""Test appointments list retrieval with pagination parameters."""
|
||||
params = {
|
||||
'page': 2,
|
||||
'limit': 20
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
assert data['pagination']['page'] == 2
|
||||
assert data['pagination']['limit'] == 20
|
||||
|
||||
def test_get_appointments_with_search(self):
|
||||
"""Test appointments list retrieval with search parameter."""
|
||||
params = {
|
||||
'search': 'ahmad'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# All returned appointments should match search criteria
|
||||
for appointment in data['appointments']:
|
||||
search_match = (
|
||||
'ahmad' in appointment['patient_name'].lower() or
|
||||
'ahmad' in appointment['doctor_name'].lower() or
|
||||
'ahmad' in appointment['notes'].lower()
|
||||
)
|
||||
assert search_match
|
||||
|
||||
def test_get_appointments_filter_by_date_range(self):
|
||||
"""Test appointments list retrieval filtered by date range."""
|
||||
params = {
|
||||
'start_date': '2024-01-01',
|
||||
'end_date': '2024-01-31'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# All returned appointments should be within the date range
|
||||
for appointment in data['appointments']:
|
||||
appointment_date = appointment['appointment_datetime'].split('T')[0]
|
||||
assert '2024-01-01' <= appointment_date <= '2024-01-31'
|
||||
|
||||
def test_get_appointments_filter_by_status(self):
|
||||
"""Test appointments list retrieval filtered by status."""
|
||||
params = {
|
||||
'status': 'CONFIRMED'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# All returned appointments should have the specified status
|
||||
for appointment in data['appointments']:
|
||||
assert appointment['status'] == 'CONFIRMED'
|
||||
|
||||
def test_get_appointments_filter_by_doctor(self):
|
||||
"""Test appointments list retrieval filtered by doctor."""
|
||||
params = {
|
||||
'doctor_id': 'doctor-001'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# All returned appointments should be with the specified doctor
|
||||
for appointment in data['appointments']:
|
||||
assert appointment['doctor_id'] == 'doctor-001'
|
||||
|
||||
def test_get_appointments_filter_by_patient(self):
|
||||
"""Test appointments list retrieval filtered by patient."""
|
||||
params = {
|
||||
'patient_id': 'patient-001'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# All returned appointments should be for the specified patient
|
||||
for appointment in data['appointments']:
|
||||
assert appointment['patient_id'] == 'patient-001'
|
||||
|
||||
def test_get_appointments_data_structure(self):
|
||||
"""Test that appointment data structure matches the contract."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
if response.status_code == status.HTTP_200_OK and len(response.json()['appointments']) > 0:
|
||||
appointment = response.json()['appointments'][0]
|
||||
|
||||
# Required fields according to contract
|
||||
required_fields = [
|
||||
'id', 'patient_id', 'patient_name', 'doctor_id', 'doctor_name',
|
||||
'appointment_datetime', 'duration', 'status', 'type',
|
||||
'reason', 'notes', 'tenant_id', 'created_at', 'updated_at'
|
||||
]
|
||||
|
||||
for field in required_fields:
|
||||
assert field in appointment
|
||||
|
||||
# Field types and enums
|
||||
assert isinstance(appointment['id'], str)
|
||||
assert isinstance(appointment['patient_id'], str)
|
||||
assert isinstance(appointment['patient_name'], str)
|
||||
assert isinstance(appointment['doctor_id'], str)
|
||||
assert isinstance(appointment['doctor_name'], str)
|
||||
assert isinstance(appointment['appointment_datetime'], str)
|
||||
assert isinstance(appointment['duration'], int)
|
||||
assert appointment['status'] in ['SCHEDULED', 'CONFIRMED', 'IN_PROGRESS', 'COMPLETED', 'CANCELLED', 'NO_SHOW']
|
||||
assert appointment['type'] in ['CONSULTATION', 'FOLLOW_UP', 'PROCEDURE', 'EMERGENCY', 'CHECKUP']
|
||||
|
||||
def test_get_appointments_with_patient_details(self):
|
||||
"""Test that appointment data includes patient details."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data={'include_patient_details': 'true'},
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
if response.status_code == status.HTTP_200_OK and len(response.json()['appointments']) > 0:
|
||||
appointment = response.json()['appointments'][0]
|
||||
|
||||
# Should include patient details
|
||||
assert 'patient_details' in appointment
|
||||
patient_details = appointment['patient_details']
|
||||
|
||||
# Patient details should include relevant fields
|
||||
expected_patient_fields = ['ic_number', 'phone', 'email', 'age', 'gender']
|
||||
for field in expected_patient_fields:
|
||||
assert field in patient_details
|
||||
|
||||
def test_get_appointments_with_doctor_details(self):
|
||||
"""Test that appointment data includes doctor details."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data={'include_doctor_details': 'true'},
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
if response.status_code == status.HTTP_200_OK and len(response.json()['appointments']) > 0:
|
||||
appointment = response.json()['appointments'][0]
|
||||
|
||||
# Should include doctor details
|
||||
assert 'doctor_details' in appointment
|
||||
doctor_details = appointment['doctor_details']
|
||||
|
||||
# Doctor details should include relevant fields
|
||||
expected_doctor_fields = ['specialization', 'license_number', 'department']
|
||||
for field in expected_doctor_fields:
|
||||
assert field in doctor_details
|
||||
|
||||
def test_get_appointments_sorting(self):
|
||||
"""Test appointments list retrieval with sorting."""
|
||||
params = {
|
||||
'sort_by': 'appointment_datetime',
|
||||
'sort_order': 'asc'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# Appointments should be sorted by datetime in ascending order
|
||||
appointment_datetimes = [appointment['appointment_datetime'] for appointment in data['appointments']]
|
||||
assert appointment_datetimes == sorted(appointment_datetimes)
|
||||
|
||||
def test_get_appointments_tenant_isolation(self):
|
||||
"""Test that appointments are isolated by tenant."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
if response.status_code == status.HTTP_200_OK:
|
||||
data = response.json()
|
||||
# All returned appointments should belong to the authenticated tenant
|
||||
for appointment in data['appointments']:
|
||||
assert 'tenant_id' in appointment
|
||||
# This will be validated once implementation exists
|
||||
|
||||
def test_get_appointments_upcoming_only(self):
|
||||
"""Test appointments list retrieval for upcoming appointments only."""
|
||||
params = {
|
||||
'upcoming_only': 'true'
|
||||
}
|
||||
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data=params,
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
data = response.json()
|
||||
# All returned appointments should be in the future
|
||||
# This will be validated once implementation exists
|
||||
pass
|
||||
|
||||
def test_get_appointments_with_reminders(self):
|
||||
"""Test that appointment data includes reminder information."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data={'include_reminders': 'true'},
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
if response.status_code == status.HTTP_200_OK and len(response.json()['appointments']) > 0:
|
||||
appointment = response.json()['appointments'][0]
|
||||
|
||||
# Should include reminder information
|
||||
assert 'reminders' in appointment
|
||||
reminders = appointment['reminders']
|
||||
|
||||
# Should be a list
|
||||
assert isinstance(reminders, list)
|
||||
|
||||
if len(reminders) > 0:
|
||||
reminder = reminders[0]
|
||||
expected_reminder_fields = ['type', 'sent_at', 'status']
|
||||
for field in expected_reminder_fields:
|
||||
assert field in reminder
|
||||
|
||||
def test_get_appointments_with_virtual_info(self):
|
||||
"""Test that appointment data includes virtual consultation information."""
|
||||
response = self.client.get(
|
||||
self.appointments_url,
|
||||
data={'include_virtual_info': 'true'},
|
||||
**self.tenant_auth
|
||||
)
|
||||
|
||||
if response.status_code == status.HTTP_200_OK and len(response.json()['appointments']) > 0:
|
||||
appointment = response.json()['appointments'][0]
|
||||
|
||||
# Should include virtual consultation info if applicable
|
||||
if appointment.get('is_virtual', False):
|
||||
assert 'virtual_consultation' in appointment
|
||||
virtual_info = appointment['virtual_consultation']
|
||||
expected_virtual_fields = ['platform', 'link', 'instructions']
|
||||
for field in expected_virtual_fields:
|
||||
assert field in virtual_info
|
||||
Reference in New Issue
Block a user