kaauh_ats/conftest.py
2025-11-27 16:25:34 +03:00

395 lines
10 KiB
Python

"""
Pytest configuration and fixtures for the recruitment application tests.
"""
import os
import sys
import django
from pathlib import Path
# Setup Django
BASE_DIR = Path(__file__).resolve().parent
# Add the project root to sys.path
sys.path.append(str(BASE_DIR))
# Set the Django settings module
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NorahUniversity.settings')
# Configure Django
django.setup()
import pytest
from django.test import TestCase
from django.contrib.auth.models import User
from django.core.files.uploadedfile import SimpleUploadedFile
from django.utils import timezone
from datetime import datetime, time, timedelta, date
from recruitment.models import (
JobPosting, Candidate, ZoomMeeting, FormTemplate, FormStage, FormField,
FormSubmission, FieldResponse, BulkInterviewTemplate, ScheduledInterview,
TrainingMaterial, Source, HiringAgency, Profile, MeetingComment, JobPostingImage,
BreakTime
)
from recruitment.forms import (
JobPostingForm, CandidateForm, ZoomMeetingForm, MeetingCommentForm,
CandidateStageForm, BulkInterviewTemplateForm, BreakTimeFormSet
)
# Removed: django_db_setup fixture conflicts with Django TestCase
# Django TestCase handles its own database setup
@pytest.fixture
def user():
"""Create a regular user for testing"""
return User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpass123',
is_staff=False
)
@pytest.fixture
def staff_user():
"""Create a staff user for testing"""
return User.objects.create_user(
username='staffuser',
email='staff@example.com',
password='testpass123',
is_staff=True
)
@pytest.fixture
def profile(user):
"""Create a user profile"""
return Profile.objects.create(user=user)
@pytest.fixture
def job(staff_user):
"""Create a job posting for testing"""
return JobPosting.objects.create(
title='Software Engineer',
department='IT',
job_type='FULL_TIME',
workplace_type='REMOTE',
location_country='Saudi Arabia',
description='Job description',
qualifications='Job qualifications',
created_by=staff_user,
status='ACTIVE',
max_applications=100,
open_positions=1
)
@pytest.fixture
def candidate(job):
"""Create a candidate for testing"""
return Candidate.objects.create(
first_name='John',
last_name='Doe',
email='john@example.com',
phone='1234567890',
job=job,
stage='Applied'
)
@pytest.fixture
def zoom_meeting():
"""Create a Zoom meeting for testing"""
return ZoomMeeting.objects.create(
topic='Interview with John Doe',
start_time=timezone.now() + timedelta(hours=1),
duration=60,
timezone='UTC',
join_url='https://zoom.us/j/123456789',
meeting_id='123456789',
status='waiting'
)
@pytest.fixture
def form_template(staff_user, job):
"""Create a form template for testing"""
return FormTemplate.objects.create(
job=job,
name='Test Application Form',
description='Test form template',
created_by=staff_user,
is_active=True
)
@pytest.fixture
def form_stage(form_template):
"""Create a form stage for testing"""
return FormStage.objects.create(
template=form_template,
name='Personal Information',
order=0
)
@pytest.fixture
def form_field(form_stage):
"""Create a form field for testing"""
return FormField.objects.create(
stage=form_stage,
label='First Name',
field_type='text',
order=0,
required=True
)
@pytest.fixture
def form_submission(form_template):
"""Create a form submission for testing"""
return FormSubmission.objects.create(
template=form_template,
applicant_name='John Doe',
applicant_email='john@example.com'
)
@pytest.fixture
def field_response(form_submission, form_field):
"""Create a field response for testing"""
return FieldResponse.objects.create(
submission=form_submission,
field=form_field,
value='John'
)
@pytest.fixture
def interview_schedule(staff_user, job):
"""Create an interview schedule for testing"""
# Create candidates first
candidates = []
for i in range(3):
candidate = Candidate.objects.create(
first_name=f'Candidate{i}',
last_name=f'Test{i}',
email=f'candidate{i}@example.com',
phone=f'12345678{i}',
job=job,
stage='Interview'
)
candidates.append(candidate)
return BulkInterviewTemplate.objects.create(
job=job,
created_by=staff_user,
start_date=date.today() + timedelta(days=1),
end_date=date.today() + timedelta(days=7),
working_days=[0, 1, 2, 3, 4], # Mon-Fri
start_time=time(9, 0),
end_time=time(17, 0),
interview_duration=60,
buffer_time=15,
break_start_time=time(12, 0),
break_end_time=time(13, 0)
)
@pytest.fixture
def scheduled_interview(candidate, job, zoom_meeting):
"""Create a scheduled interview for testing"""
return ScheduledInterview.objects.create(
candidate=candidate,
job=job,
zoom_meeting=zoom_meeting,
interview_date=timezone.now().date(),
interview_time=time(10, 0),
status='scheduled'
)
@pytest.fixture
def meeting_comment(user, zoom_meeting):
"""Create a meeting comment for testing"""
return MeetingComment.objects.create(
meeting=zoom_meeting,
author=user,
content='This is a test comment'
)
@pytest.fixture
def file_content():
"""Create test file content"""
return b'%PDF-1.4\n% ... test content ...'
@pytest.fixture
def uploaded_file(file_content):
"""Create an uploaded file for testing"""
return SimpleUploadedFile(
'test_file.pdf',
file_content,
content_type='application/pdf'
)
@pytest.fixture
def job_form_data():
"""Basic job posting form data for testing"""
return {
'title': 'Test Job Title',
'department': 'IT',
'job_type': 'FULL_TIME',
'workplace_type': 'REMOTE',
'location_city': 'Riyadh',
'location_state': 'Riyadh',
'location_country': 'Saudi Arabia',
'description': 'Job description',
'qualifications': 'Job qualifications',
'salary_range': '5000-7000',
'application_deadline': '2025-12-31',
'max_applications': '100',
'open_positions': '1',
'hash_tags': '#hiring, #jobopening'
}
@pytest.fixture
def candidate_form_data(job):
"""Basic candidate form data for testing"""
return {
'job': job.id,
'first_name': 'John',
'last_name': 'Doe',
'phone': '1234567890',
'email': 'john@example.com'
}
@pytest.fixture
def zoom_meeting_form_data():
"""Basic Zoom meeting form data for testing"""
start_time = timezone.now() + timedelta(hours=1)
return {
'topic': 'Test Meeting',
'start_time': start_time.strftime('%Y-%m-%dT%H:%M'),
'duration': 60
}
@pytest.fixture
def interview_schedule_form_data(job):
"""Basic interview schedule form data for testing"""
# Create candidates first
candidates = []
for i in range(2):
candidate = Candidate.objects.create(
first_name=f'Interview{i}',
last_name=f'Candidate{i}',
email=f'interview{i}@example.com',
phone=f'12345678{i}',
job=job,
stage='Interview'
)
candidates.append(candidate)
return {
'candidates': [c.pk for c in candidates],
'start_date': (date.today() + timedelta(days=1)).isoformat(),
'end_date': (date.today() + timedelta(days=7)).isoformat(),
'working_days': [0, 1, 2, 3, 4],
'start_time': '09:00',
'end_time': '17:00',
'interview_duration': '60',
'buffer_time': '15'
}
@pytest.fixture
def client():
"""Django test client"""
from django.test import Client
return Client()
@pytest.fixture
def authenticated_client(client, user):
"""Authenticated Django test client"""
client.force_login(user)
return client
@pytest.fixture
def authenticated_staff_client(client, staff_user):
"""Authenticated staff Django test client"""
client.force_login(staff_user)
return client
@pytest.fixture
def mock_zoom_api():
"""Mock Zoom API responses"""
with pytest.MonkeyPatch().context() as m:
m.setattr('recruitment.utils.create_zoom_meeting', lambda *args, **kwargs: {
'status': 'success',
'meeting_details': {
'meeting_id': '123456789',
'join_url': 'https://zoom.us/j/123456789',
'password': 'meeting123'
},
'zoom_gateway_response': {'status': 'waiting'}
})
yield
@pytest.fixture
def mock_time_slots():
"""Mock available time slots for interview scheduling"""
return [
{'date': date.today() + timedelta(days=1), 'time': '10:00'},
{'date': date.today() + timedelta(days=1), 'time': '11:00'},
{'date': date.today() + timedelta(days=1), 'time': '14:00'},
{'date': date.today() + timedelta(days=2), 'time': '09:00'},
{'date': date.today() + timedelta(days=2), 'time': '15:00'}
]
# Test markers
def pytest_configure(config):
"""Configure custom markers"""
config.addinivalue_line(
"markers", "slow: marks tests as slow (deselect with '-m \"not slow\"')"
)
config.addinivalue_line(
"markers", "integration: marks tests as integration tests"
)
config.addinivalue_line(
"markers", "unit: marks tests as unit tests"
)
config.addinivalue_line(
"markers", "security: marks tests as security tests"
)
config.addinivalue_line(
"markers", "api: marks tests as API tests"
)
# Pytest hooks for better test output
# Note: HTML reporting hooks are commented out to avoid plugin validation issues
# def pytest_html_report_title(report):
# """Set the HTML report title"""
# report.title = "Recruitment Application Test Report"
# def pytest_runtest_logreport(report):
# """Customize test output"""
# if report.when == 'call' and report.failed:
# # Add custom information for failed tests
# pass