""" 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.contrib.auth.models import User from django.core.files.uploadedfile import SimpleUploadedFile from django.utils import timezone from datetime import time, timedelta, date from recruitment.models import ( JobPosting, Candidate, ZoomMeeting, FormTemplate, FormStage, FormField, FormSubmission, FieldResponse, BulkInterviewTemplate, ScheduledInterview,Profile, MeetingComment, ) # 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