Esempio n. 1
0
    def test_lti_id_model_logic(self):
        # Test if a single lTI id can only be coupled to a singular assignment
        ltiAssignment1 = factory.LtiAssignment()
        ltiAssignment2 = factory.LtiAssignment()
        assert ltiAssignment1.active_lti_id != ltiAssignment2.active_lti_id, \
            'LTI ids of generated assignments should be unique.'

        ltiAssignment2.active_lti_id = ltiAssignment1.active_lti_id
        self.assertRaises(
            ValidationError,
            ltiAssignment2.save,
            msg=
            'lti_id_set and assignment should be unique together for each arrayfield value'
        )

        assert ltiAssignment2.active_lti_id in ltiAssignment2.lti_id_set, \
            'LTI ids added to the assignment should als be added to the lti_id_set'

        journal = factory.Journal(assignment=ltiAssignment1)
        journal.grade_url = 'Not None'
        journal.sourcedid = 'Not None'
        journal.save()
        ltiAssignment1.active_lti_id = 'new lti id'
        ltiAssignment1.save()
        # Refresh the journal instance after the assignment update
        journal = Journal.objects.get(pk=journal.pk)

        assert journal.grade_url is None and journal.sourcedid is None, \
            'Updating the active LTI id of an assignment should reset the grade_url and sourcedid of all nested ' \
            'journals'
Esempio n. 2
0
    def test_get_lti_params_from_valid_test_user(self):
        course = factory.LtiCourse()
        assignment = factory.LtiAssignment(courses=[course])
        test_student = factory.TestUser()
        get_jwt(
            self,
            user=test_student,
            status=200,
            request_body={
                'user_id': test_student.lti_id,
                'custom_course_id': course.active_lti_id,
                'custom_assignment_id': assignment.active_lti_id
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a course and assign linked, a test student should be forwarded to finish state.'
        )

        test_student2 = factory.TestUser()
        get_jwt(
            self,
            user=test_student2,
            status=200,
            request_body={
                'user_id': test_student2.lti_id,
                'custom_course_id': course.active_lti_id,
                'custom_assignment_id': assignment.active_lti_id
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a course and assign linked, a test student should be forwarded to finish state.'
        )
        assert not User.objects.filter(lti_id=test_student.lti_id).exists(
        ), 'Max of 1 test student per course.'

        course2 = factory.LtiCourse()
        assignment2 = factory.LtiAssignment(courses=[course2])

        test_student3 = factory.TestUser()
        get_jwt(
            self,
            user=test_student3,
            status=200,
            request_body={
                'user_id': test_student3.lti_id,
                'custom_course_id': course2.active_lti_id,
                'custom_assignment_id': assignment2.active_lti_id
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a course and assign linked, a test student should be forwarded to finish state.'
        )
        assert User.objects.filter(lti_id=test_student2.lti_id).exists(), \
            'Linking a test user to one course should not delete test users of a different course.'
Esempio n. 3
0
    def test_get_lti_params_from_jwt_old_assignment_teacher(self):
        course = factory.LtiCourse(author=self.teacher,
                                   name=REQUEST['custom_course_name'])
        assignment = factory.LtiAssignment(
            author=self.teacher,
            courses=[course],
            name=REQUEST['custom_assignment_title'])
        old_id = assignment.active_lti_id
        assignment.active_lti_id = assignment.active_lti_id + '_new'
        assignment.save()

        response = get_jwt(
            self,
            user=self.teacher,
            status=200,
            request_body={
                'user_id': self.teacher.lti_id,
                'roles': 'Instructor',
                'custom_course_id': course.active_lti_id,
                'custom_assignment_id': old_id
            },
            response_value=lti_view.LTI_STATES.FINISH_T.value,
            assert_msg=
            'When a teacher joins via a no longer active lti assignment, he should still be normally'
            + ' forwarded.')
        assert response['params'][
            'jID'] is None, 'A teacher should receive no journal id'
Esempio n. 4
0
 def test_lti_delete(self):
     assignment = factory.LtiAssignment()
     course = assignment.courses.first()
     assert assignment.active_lti_id in course.assignment_lti_id_set, \
         'assignment lti_id should be in assignment_lti_id_set of course before anything is deleted'
     # Test if deletion is possible to delete assignment if it has only one lti id
     api.delete(self,
                'assignments',
                params={
                    'pk': assignment.pk,
                    'course_id': course.pk
                },
                user=factory.Admin())
     assert assignment.active_lti_id not in Course.objects.get(pk=course.pk).assignment_lti_id_set, \
         'assignment lti_id should get removed from the assignment_lti_id_set from the course'
     assignment = factory.LtiAssignment()
     course = assignment.courses.first()
     course2 = factory.LtiCourse()
     assignment.courses.add(course2)
     assignment.lti_id_set.append('second' + assignment.active_lti_id)
     assignment.save()
     # Test is deletion is not possible from connected LTI course
     api.delete(self,
                'assignments',
                params={
                    'pk': assignment.pk,
                    'course_id': course.pk
                },
                user=factory.Admin(),
                status=400)
     # Test is deletion is possible from other course
     api.delete(self,
                'assignments',
                params={
                    'pk': assignment.pk,
                    'course_id': course2.pk
                },
                user=factory.Admin())
Esempio n. 5
0
 def setUp(self):
     """Setup."""
     self.student = factory.Student()
     self.teacher = factory.Teacher()
     self.course = factory.LtiCourse(author=self.teacher)
     self.assignment = factory.LtiAssignment(author=self.teacher,
                                             courses=[self.course])
     self.journal = factory.Journal(
         assignment=self.assignment,
         user=self.student,
         sourcedid='f6d552',
         grade_url=
         'https://uvadlo-tes.instructure.com/api/lti/v1/tools/267/grade_passback'
     )
Esempio n. 6
0
    def test_legit_student_from_old_uplink_update_passback(self):
        course = factory.LtiCourse(author=self.teacher,
                                   name=REQUEST['custom_course_name'])
        assignment = factory.LtiAssignment(
            author=self.teacher,
            courses=[course],
            name=REQUEST['custom_assignment_title'])
        student = factory.LtiStudent()
        journal = factory.Journal(user=student)
        assignment = journal.assignment

        journal_exists = Journal.objects.filter(user=student,
                                                assignment=assignment)
        journal_exists = journal_exists.count(
        ) == 1 and journal.pk == journal_exists.first().pk
        assert journal_exists, "The student is assumed to have a single nested journal beforehand"

        journal.grade_url = 'before'
        journal.sourcedid = 'before'
        course.active_lti_id = 'new'
        assignment.active_lti_id = 'new'
        course.save()
        assignment.save()
        journal.save()

        get_jwt(
            self,
            user=student,
            status=200,
            request_body={
                'user_id': student.lti_id,
                'custom_course_id': 'new',
                'custom_assignment_id': 'new',
                'lis_outcome_service_url': REQUEST['lis_outcome_service_url'],
                'lis_result_sourcedid': REQUEST['lis_result_sourcedid'],
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a setup assignment, a legitimate student jwt connection should return FINISH_S state',
        )

        journal = Journal.objects.get(user=student, assignment=assignment)
        assert journal.sourcedid == REQUEST['lis_result_sourcedid'], \
            'A legitimate student jwt route should set a journal sourcedid.'
        assert journal.grade_url == REQUEST['lis_outcome_service_url'], \
            'A legitimate student jwt route should set a journal grade_url.'
Esempio n. 7
0
 def test_get_lti_params_from_jwt_journal_student(self):
     course = factory.LtiCourse(author=self.teacher,
                                name=REQUEST['custom_course_name'])
     assignment = factory.LtiAssignment(
         author=self.teacher,
         courses=[course],
         name=REQUEST['custom_assignment_title'])
     get_jwt(
         self,
         user=self.student,
         status=200,
         request_body={
             'user_id': self.student.lti_id,
             'custom_course_id': course.active_lti_id,
             'custom_assignment_id': assignment.active_lti_id
         },
         response_value=lti_view.LTI_STATES.FINISH_S.value,
         assert_msg=
         'When after assignment is created it should return the FINISH_S state for students'
     )
Esempio n. 8
0
    def test_legit_student_new_journal_update_passback(self):
        course = factory.LtiCourse(author=self.teacher,
                                   name=REQUEST['custom_course_name'])
        assignment = factory.LtiAssignment(
            author=self.teacher,
            courses=[course],
            name=REQUEST['custom_assignment_title'])
        student = factory.LtiStudent()
        journal_exists = Journal.objects.filter(
            user=student, assignment=assignment).exists()
        assert not journal_exists, "The student is assumed to have no journal beforehand"

        get_jwt(
            self,
            user=student,
            status=200,
            request_body={
                'user_id': student.lti_id,
                'custom_course_id': course.active_lti_id,
                'custom_assignment_id': assignment.active_lti_id,
                'lis_outcome_service_url': REQUEST['lis_outcome_service_url'],
                'lis_result_sourcedid': REQUEST['lis_result_sourcedid'],
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a setup assignment, a legitimate student jwt connection should return FINISH_S state'
        )

        journal_qry = Journal.objects.filter(user=student,
                                             assignment=assignment)
        assert journal_qry.count(
        ) == 1, 'A legitimate student jwt connection should create a single journal.'
        journal = journal_qry.first()
        assert journal.sourcedid == REQUEST['lis_result_sourcedid'], \
            'A legitimate student jwt route should set a journal sourcedid.'
        assert journal.grade_url == REQUEST['lis_outcome_service_url'], \
            'A legitimate student jwt route should set a journal grade_url.'
Esempio n. 9
0
 def test_get_lti_params_from_jwt_old_assignment_student_with_journal(self):
     course = factory.LtiCourse(author=self.teacher,
                                name=REQUEST['custom_course_name'])
     assignment = factory.LtiAssignment(
         author=self.teacher,
         courses=[course],
         name=REQUEST['custom_assignment_title'])
     get_jwt(
         self,
         user=self.student,
         status=200,
         request_body={
             'user_id': self.student.lti_id,
             'custom_course_id': course.active_lti_id,
             'custom_assignment_id': assignment.active_lti_id
         },
         response_value=lti_view.LTI_STATES.FINISH_S.value,
         assert_msg=
         'When after assignment is created it should return the FINISH_S state for students'
     )
     old_id = assignment.active_lti_id
     assignment.active_lti_id = assignment.active_lti_id + '_new'
     assignment.save()
     get_jwt(
         self,
         user=self.student,
         status=200,
         request_body={
             'user_id': self.student.lti_id,
             'roles': 'Student',
             'custom_course_id': course.active_lti_id,
             'custom_assignment_id': old_id
         },
         response_value=lti_view.LTI_STATES.FINISH_S.value,
         assert_msg=
         'When a student with journal joins via an old LTI connection, he should still be normally '
         + 'forwarded (FINISH_S state)')
Esempio n. 10
0
    def test_lti_flow_test_user(self):
        course = factory.LtiCourse()
        assignment = factory.LtiAssignment(courses=[course])
        test_user_params = factory.JWTTestUserParams(user_id=get_new_lti_id())

        resp = lti_launch(
            request_body=test_user_params,
            response_value=lti_view.LTI_STATES.LOGGED_IN.value,
            assert_msg=
            'A test user should directly be created on lti launch if not exist.',
        )
        test_student = User.objects.get(lti_id=test_user_params['user_id'])
        assert test_student.is_test_student, 'A new test user should be created and flagged accordingly.'
        total_users = User.objects.count()

        get_jwt(
            self,
            user=test_student,
            status=200,
            access=lti_launch_response_to_access_token(resp),
            request_body={
                **test_user_params, 'custom_course_id': course.active_lti_id,
                'custom_assignment_id': assignment.active_lti_id
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a course and assign linked, a fresh test student should be forwarded to finish state.'
        )

        resp = lti_launch(
            request_body=test_user_params,
            response_value=lti_view.LTI_STATES.LOGGED_IN.value,
            assert_msg=
            'A reused test user can launch succesfully after being created.',
        )

        get_jwt(
            self,
            user=test_student,
            status=200,
            access=lti_launch_response_to_access_token(resp),
            request_body={
                **test_user_params, 'custom_course_id': course.active_lti_id,
                'custom_assignment_id': assignment.active_lti_id
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'With a course and assign linked, a reused test student should be forwarded to finish state.'
        )

        assert total_users == User.objects.count(
        ), 'Launching and relaunching should create no additional users.'

        # Test the flow of another test user part of the same course and assignment
        test_user_params2 = factory.JWTTestUserParams(user_id=get_new_lti_id())

        resp = lti_launch(request_body=test_user_params2,
                          response_value=lti_view.LTI_STATES.LOGGED_IN.value)
        test_student2 = User.objects.get(lti_id=test_user_params2['user_id'])
        get_jwt(
            self,
            user=test_student2,
            status=200,
            access=lti_launch_response_to_access_token(resp),
            request_body={
                **test_user_params2, 'custom_course_id': course.active_lti_id,
                'custom_assignment_id': assignment.active_lti_id
            },
            response_value=lti_view.LTI_STATES.FINISH_S.value,
            assert_msg=
            'A second fresh test student from the same course and assign should be forwarded to finish state'
        )
        assert User.objects.filter(lti_id=test_user_params2['user_id']).exists(
        ), 'Second test user should be created.'
        assert not User.objects.filter(lti_id=test_student.lti_id).exists(
        ), 'Can only be one test student per course.'
Esempio n. 11
0
 def test_check_if_need_VLE_publish_no_journals(self):
     """Hopefully doesnt crash."""
     course = factory.LtiCourse()
     factory.LtiAssignment(courses=[course])
     lti_beats.check_if_need_VLE_publish()