from unittest.mock import call, patch from django.db.models.signals import pre_save from django.dispatch import Signal from django.test import TestCase from vbv_lernwelt.core.constants import ( TEST_COURSE_SESSION_BERN_ID, TEST_COURSE_SESSION_ZURICH_ID, TEST_STUDENT1_USER_ID, TEST_STUDENT2_USER_ID, TEST_SUPERVISOR1_USER_ID, TEST_TRAINER1_USER_ID, ) from vbv_lernwelt.core.create_default_users import create_default_users from vbv_lernwelt.core.models import User from vbv_lernwelt.course.consts import COURSE_TEST_ID from vbv_lernwelt.course.creators.test_course import create_test_course from vbv_lernwelt.course.creators.test_utils import ( add_course_session_user, create_course, create_course_session, create_user, ) from vbv_lernwelt.course.models import Course, CourseSessionUser from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.learning_mentor.models import LearningMentor from vbv_lernwelt.sso.signals import update_sso_roles_in_cs class CourseSessionUserTests(TestCase): def setUp(self): create_default_users() create_test_course(include_uk=True, with_sessions=True) self.student1 = User.objects.get(id=TEST_STUDENT1_USER_ID) self.csu1_student1 = CourseSessionUser.objects.get( user=self.student1, course_session__id=TEST_COURSE_SESSION_BERN_ID ) self.student2 = User.objects.get(id=TEST_STUDENT2_USER_ID) self.csu1_student2 = CourseSessionUser.objects.get( user=self.student2, course_session__id=TEST_COURSE_SESSION_ZURICH_ID ) # Disconnect the actual signal handler to avoid side effects during testing pre_save.disconnect(receiver=update_sso_roles_in_cs, sender=CourseSessionUser) # Connect a mock signal handler self.mock_pre_save_signal = Signal() self.mock_pre_save_signal.connect( receiver=update_sso_roles_in_cs, sender=CourseSessionUser ) @patch("vbv_lernwelt.sso.signals.remove_roles_from_user") def test_remove_roles_for_single_role_in_cs(self, mock_remove_roles_from_user): mock_remove_roles_from_user.return_value = None self.csu1_student1.delete() self.assertEqual(mock_remove_roles_from_user.call_count, 1) mock_remove_roles_from_user.assert_called_with( self.student1, [(self.csu1_student1.course_session.course.slug, "MEMBER")] ) @patch("vbv_lernwelt.sso.signals.remove_roles_from_user") def test_dont_remove_roles_for_multiple_roles_in_cs( self, mock_remove_roles_from_user ): mock_remove_roles_from_user.return_value = None self.csu1_student2.delete() self.assertFalse(mock_remove_roles_from_user.called) @patch("vbv_lernwelt.sso.signals.add_roles_to_user") def test_add_role_for_user_on_creation(self, mock_add_roles_from_user): mock_add_roles_from_user.return_value = None self.csu1_student1.delete() csu = CourseSessionUser.objects.create( user=self.student1, course_session=self.csu1_student1.course_session, role="MEMBER", ) self.mock_pre_save_signal.send(sender=CourseSessionUser, instance=csu) self.assertEqual(mock_add_roles_from_user.call_count, 1) mock_add_roles_from_user.assert_called_with( self.student1, [(self.csu1_student1.course_session.course.slug, "MEMBER")] ) @patch("vbv_lernwelt.sso.signals.update_roles_for_user") def test_update_role_for_user_on_update_with_role_change( self, mock_update_roles_for_user ): mock_update_roles_for_user.return_value = None self.csu1_student1.role = "TRAINER" self.mock_pre_save_signal.send( sender=CourseSessionUser, instance=self.csu1_student1 ) self.assertEqual(mock_update_roles_for_user.call_count, 1) mock_update_roles_for_user.assert_called_with( self.student1, add_course_roles=[ (self.csu1_student1.course_session.course.slug, "TRAINER") ], remove_course_roles=[ (self.csu1_student1.course_session.course.slug, "MEMBER") ], ) @patch("vbv_lernwelt.sso.signals.update_roles_for_user") def test_update_role_for_user_on_update_with_course_change( self, mock_update_roles_for_user ): mock_update_roles_for_user.return_value = None course, self.course_page = create_course("Test Course") course_session = create_course_session(course=course, title="Test VV") old_course_slug = self.csu1_student1.course_session.course.slug self.csu1_student1.course_session = course_session self.mock_pre_save_signal.send( sender=CourseSessionUser, instance=self.csu1_student1 ) self.assertEqual(mock_update_roles_for_user.call_count, 1) mock_update_roles_for_user.assert_called_with( self.student1, add_course_roles=[ (self.csu1_student1.course_session.course.slug, "MEMBER") ], remove_course_roles=[(old_course_slug, "MEMBER")], ) @patch("vbv_lernwelt.sso.signals.update_roles_for_user") def test_dont_update_role_for_user_on_update(self, mock_update_roles_for_user): mock_update_roles_for_user.return_value = None self.csu1_student1.role = "MEMBER" self.mock_pre_save_signal.send( sender=CourseSessionUser, instance=self.csu1_student1 ) self.assertEqual(mock_update_roles_for_user.call_count, 0) class CourseSessionGroupTests(TestCase): def setUp(self): create_default_users() create_test_course(include_uk=True, with_sessions=True) self.csg = CourseSessionGroup.objects.get( name="Region 1", ) course = Course.objects.get(id=COURSE_TEST_ID) self.slug = course.slug self.trainer = User.objects.get(id=TEST_TRAINER1_USER_ID) self.supervisor = User.objects.get(id=TEST_SUPERVISOR1_USER_ID) @patch("vbv_lernwelt.sso.signals.remove_roles_from_user") def test_remove_roles_for_csg_supervisors(self, mock_remove_roles_from_user): mock_remove_roles_from_user.return_value = None self.csg.supervisor.set([self.trainer, self.supervisor]) self.csg.delete() expected_calls = [ call(self.supervisor, [(self.slug, "SUPERVISOR")]), call(self.trainer, [(self.slug, "SUPERVISOR")]), ] mock_remove_roles_from_user.assert_has_calls(expected_calls, any_order=True) self.assertEqual(mock_remove_roles_from_user.call_count, 2) @patch("vbv_lernwelt.sso.signals.remove_roles_from_user") @patch("vbv_lernwelt.sso.signals.add_roles_to_user") def test_add_supervisors_to_csg( self, mock_add_roles_to_user, mock_remove_roles_from_user ): mock_remove_roles_from_user.return_value = None mock_add_roles_to_user.return_value = None self.csg.supervisor.add(self.trainer) self.assertEqual(mock_add_roles_to_user.call_count, 1) self.assertEqual(mock_remove_roles_from_user.call_count, 0) mock_add_roles_to_user.assert_called_with( self.trainer, [(self.slug, "SUPERVISOR")] ) @patch("vbv_lernwelt.sso.signals.remove_roles_from_user") @patch("vbv_lernwelt.sso.signals.add_roles_to_user") def test_remove_supervisors_to_csg( self, mock_add_roles_to_user, mock_remove_roles_from_user ): mock_remove_roles_from_user.return_value = None mock_add_roles_to_user.return_value = None self.csg.supervisor.remove(self.supervisor) self.assertEqual(mock_add_roles_to_user.call_count, 0) self.assertEqual(mock_remove_roles_from_user.call_count, 1) mock_remove_roles_from_user.assert_called_with( self.supervisor, [(self.slug, "SUPERVISOR")] ) class LearningMentorTests(TestCase): def setUp(self): self.course, self.course_page = create_course("Test Course") self.course_session = create_course_session(course=self.course, title="Test VV") self.user = create_user("mentor") self.mentor = LearningMentor.objects.create( mentor=self.user, course_session=self.course_session ) @patch("vbv_lernwelt.sso.signals.remove_roles_from_user") def test_remove_roles_for_learning_mentor_on_delete( self, mock_remove_roles_from_user ): mock_remove_roles_from_user.return_value = None self.mentor.delete() self.assertEqual(mock_remove_roles_from_user.call_count, 1) mock_remove_roles_from_user.assert_called_with( self.user, [(self.course.slug, "LEARNING_MENTOR")] ) @patch("vbv_lernwelt.sso.signals.add_roles_to_user") def test_add_roles_for_learning_mentor_on_create(self, mock_add_roles_from_user): mock_add_roles_from_user.return_value = None self.mentor.delete() LearningMentor.objects.create( mentor=self.user, course_session=self.course_session ) self.assertEqual(mock_add_roles_from_user.call_count, 1) mock_add_roles_from_user.assert_called_with( self.user, [(self.course.slug, "LEARNING_MENTOR")] ) @patch("vbv_lernwelt.sso.signals.add_roles_to_user") def test_no_add_roles_for_learning_mentor_on_update(self, mock_add_roles_from_user): mock_add_roles_from_user.return_value = None participant_1 = add_course_session_user( self.course_session, create_user("participant_1"), role=CourseSessionUser.Role.MEMBER, ) mock_add_roles_from_user.reset_mock() self.mentor.participants.set([participant_1]) self.assertEqual(mock_add_roles_from_user.call_count, 0)