Source code for matching.tests

# Run from /backend with: python manage.py test matching
import json

from django.test import TestCase
from django.urls import reverse

from matching.models import Score
from matching.utils import UNMATCH_CONFIRMATION
from users.models import User


[docs] class MatchingAPITests(TestCase):
[docs] def setUp(self): # Create a verified mentee and two mentors self.password = 'testpassword123' self.mentee = User.objects.create_user(email="mentee@ucla.edu", password=self.password, role='MENTEE', is_verified=True) self.mentor1 = User.objects.create_user(email="mentor1@ucla.edu", password=self.password, role='MENTOR', is_verified=True) self.mentor2 = User.objects.create_user(email="mentor2@ucla.edu", password=self.password, role='MENTOR', is_verified=True) # Set up mandatory profile data so they appear in matches for u in [self.mentee, self.mentor1, self.mentor2]: u.major = ["Computer Science"] u.year = "2" u.save() Score.objects.update_or_create( mentee_email=self.mentee.email, mentor_email=self.mentor1.email, defaults={'score': 85.0} ) Score.objects.update_or_create( mentee_email=self.mentee.email, mentor_email=self.mentor2.email, defaults={'score': 70.0} )
[docs] def test_get_mentor_matches_ranked(self): """Ensures mentee receives mentors sorted by high score first""" self.client.login(email=self.mentee.email, password=self.password) response = self.client.get(reverse('mentor_matches')) self.assertEqual(response.status_code, 200) data = response.json() self.assertEqual(data['total'], 2) # Verify mentor1 (score 85) is listed before mentor2 (score 70) self.assertEqual(data['matches'][0]['email'], self.mentor1.email)
[docs] def test_select_mentor_success(self): """Ensures a mentee can successfully match with a mentor""" self.client.login(email=self.mentee.email, password=self.password) payload = {'mentor_email': self.mentor1.email} response = self.client.post(reverse('select_mentor'), data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 200) self.mentee.refresh_from_db() self.assertTrue(self.mentee.isMatched) self.assertEqual(self.mentee.matchedMentorEmail, self.mentor1.email)
[docs] def test_mentor_capacity_limit(self): """Ensures a mentor with 2 mentees is rejected""" # Manually fill mentor1's slots self.mentor1.current_mentees = ["student1@ucla.edu", "student2@ucla.edu"] self.mentor1.save() self.client.login(email=self.mentee.email, password=self.password) payload = {'mentor_email': self.mentor1.email} response = self.client.post(reverse('select_mentor'), data=json.dumps(payload), content_type='application/json') # Should return 409 Conflict as mentor is full self.assertEqual(response.status_code, 409)
[docs] def test_unauthorized_role_blocked(self): """Ensures a mentor cannot access mentee-only matching endpoints""" self.client.login(email=self.mentor1.email, password=self.password) response = self.client.get(reverse('mentor_matches')) # Should return 403 Forbidden self.assertEqual(response.status_code, 403)
[docs] def test_incomplete_profile_no_matches(self): """Ensures users without major/year see 0 matches""" # Create a user with no major or year new_mentee = User.objects.create_user( email="incomplete@ucla.edu", password=self.password, role='MENTEE', is_verified=True ) self.client.login(email=new_mentee.email, password=self.password) response = self.client.get(reverse('mentor_matches')) self.assertEqual(response.status_code, 200) data = response.json() # Should be 0 because Score signals don't fire for incomplete profiles self.assertEqual(data['total'], 0)
[docs] def test_unmatch_lifecycle(self): """Verifies unmatching clears state and blacklists the mentor""" # First, establish a match self.mentee.isMatched = True self.mentee.matchedMentorEmail = self.mentor1.email self.mentee.save() self.mentor1.current_mentees = [self.mentee.email] self.mentor1.save() self.client.login(email=self.mentee.email, password=self.password) # The unmatch endpoint requires a confirmation string payload = { 'mentor_email': self.mentor1.email, 'confirmation': UNMATCH_CONFIRMATION } response = self.client.post(reverse('unmatch'), data=json.dumps(payload), content_type='application/json') self.assertEqual(response.status_code, 200) self.mentee.refresh_from_db() self.mentor1.refresh_from_db() # Verify relationship is cleared self.assertFalse(self.mentee.isMatched) self.assertEqual(self.mentee.matchedMentorEmail, '') self.assertNotIn(self.mentee.email, self.mentor1.current_mentees) # Verify mentor is blacklisted so they don't show up in matches again self.assertIn(self.mentor1.email, self.mentee.blacklisted_mentors)
[docs] def test_deleted_user_cannot_match(self): """Ensures users pending deletion are blocked from matching""" self.mentee.request_deletion() # Sets is_deleted=True self.client.login(email=self.mentee.email, password=self.password) response = self.client.get(reverse('mentor_matches')) # Should return 403 or specific error defined in require_not_deleted self.assertEqual(response.status_code, 403) self.assertIn('Account pending deletion', response.json()['error'])
[docs] def test_rematch_endpoint_logic(self): """Verifies the rematch endpoint returns the same ranked data""" self.client.login(email=self.mentee.email, password=self.password) response = self.client.get(reverse('rematch')) self.assertEqual(response.status_code, 200) self.assertEqual(response.json()['total'], 2)