def test_edit_exam_teacher_others_exams(self): """Teachers cannot modify others teachers exams""" teacher1 = Teacher.query.order_by(Teacher.id).first() teacher2 = Teacher.query.order_by(Teacher.id.desc()).first() exam1 = Exam.query.filter(Exam.author_id == teacher1.id).first() exam2 = Exam.query.filter(Exam.author_id == teacher2.id).first() token1 = generate_user_token(teacher1.username, TEACHER_PERMISSIONS) token2 = generate_user_token(teacher2.username, TEACHER_PERMISSIONS) test_set = [(teacher1, token1, exam2), (teacher2, token2, exam1)] for teacher, token, exam in test_set: res = self.client.patch(f'/api/v1/exams/{exam.id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}, json={}) self.assertEqual(res.status_code, 403, res.get_json())
def test_edit_exam_teacher(self): """Teacher edit their exam properly""" exam = Exam.query.first() teacher = Teacher.get_by_id(exam.author_id) # Generate a header for a teacher token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) from_date = datetime.now().replace(microsecond=0) exam_body = { 'title': '', 'description': '', 'exercises': '[]', 'exam_duration': 300, 'shuffle_exercises': True, 'max_retries': 1, 'from_date': from_date, 'to_date': from_date + timedelta(days=10) } res = self.client.patch(f'/api/v1/exams/{exam.id}', headers={'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}, json=exam_body) self.assertEqual(res.status_code, 200, res.get_json()) data = res.get_json() self.check_fields_list(data, ['success', 'updated']) self.assertTrue(data['success']) self.assertEqual(data['updated'], exam.id) exam = Exam.get_by_id(exam.id) for key, value in exam_body.items(): self.assertEqual(value, getattr(exam, key), f'{key}: {value}')
def test_enroll_students_to_exam_student_enroll_others(self): """A student cannot enroll others students""" exams_ids = set(exam.id for exam in Exam.get_query().all()) # Select two students and determines which exams they are not enrolled # to not_enr_exams = [] students = Student.get_query().limit(2).all() for student in students: student_subscriptions = \ (StudentSubscription.get_query() .filter(StudentSubscription.student_id == student.id) .all()) enr_exams = [exam.id for exam in student_subscriptions] not_enr_exams_ids = exams_ids - set(enr_exams) not_enr_exams.append(list(not_enr_exams_ids)) for i in range(len(students)): token = generate_user_token(students[i].username, STUDENT_PERMISSIONS) exam_id = not_enr_exams[(i + 1) % 2][0] student_id = students[(i + 1) % 2].id res = self.client.post(f'/api/v1/enrolls/{exam_id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }, json=[student_id]) self.assertEqual(res.status_code, 403, res.get_json()) data = res.get_json() self.assertEqual(data['description'], 'Cannot enroll others students.', data)
def test_enroll_students_to_exam_as_student(self): """Student can enroll him self to one exam""" exams_ids = [exam.id for exam in Exam.get_query().all()] # Select 5 students students = Student.get_query().limit(5).all() students_enrolls = { student.id: (subscription.exam_id for subscription in StudentSubscription.get_query().filter( StudentSubscription.student_id == student.id).all()) for student in students } # Determine which exams the students is not enrolled in students_not_enrolled = { student_id: set(exams_ids) - set(exams_ids_) for student_id, exams_ids_ in students_enrolls.items() } sub_count_before = StudentSubscription.get_query().count() try: for student in students: # Enroll the student in all the exams he is not enrolled to token = generate_user_token(student.username, STUDENT_PERMISSIONS) for exam_id in students_not_enrolled[student.id]: res = self.client.post(f'/api/v1/enrolls/{exam_id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }, json=[]) self.assertEqual(res.status_code, 200, res.get_json()) data = res.get_json() self.check_fields_list(data, ['success', 'new_enrolls']) # Must be one because he is was not enrolled to this exam self.assertEqual(data['new_enrolls'], 1) # The student should be enrolled to all exams now sub_count = ((StudentSubscription.get_query().filter( StudentSubscription.student_id == student.id).count())) self.assertEqual(sub_count, len(exams_ids)) # All students should be enrolled to all exams sub_count_after = StudentSubscription.get_query().count() self.assertEqual(len(students) * len(exams_ids), sub_count_after) finally: # Restore the database to its initial state deletion_list = [] for student_id, exams_ids in students_not_enrolled.items(): for exam_id in exams_ids: deletion_list.append((StudentSubscription.get_query( ).filter( StudentSubscription.student_id == student_id).filter( StudentSubscription.exam_id == exam_id).first())) Exam.persist_changes({'delete': deletion_list}) sub_count_after = StudentSubscription.get_query().count() self.assertEqual(sub_count_after, sub_count_before)
def test_list_enrolled_exam_teacher(self): """Teachers cannot enroll to exams""" teachers = Teacher.get_query().all() for teacher in teachers: token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) res = self.client.get('/api/v1/enrolls', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }) self.assertEqual(res.status_code, 403)
def test_get_exams_list_student(self): """Student trying to retrieve list of exams""" # Test as student student = Student.query.first() for permissions in [STUDENT_PERMISSIONS, TEACHER_PERMISSIONS]: # Generate a header for the student token = generate_user_token(student.username, permissions) res = self.client.get('/api/v1/exams', headers={'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}) # A registered student could not access exams lists self.assertEqual(res.status_code, 403, res.get_json())
def test_list_enrolled_students_student(self): """Students cannot list who is enrolled to one exam""" students_subscriptions = StudentSubscription.get_query().limit(10) for student_subscription in students_subscriptions: student = Student.get_by_id(student_subscription.student_id) token = generate_user_token(student.username, STUDENT_PERMISSIONS) res = self.client.get( f'/api/v1/enrolls/{student_subscription.exam_id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }) self.assertEqual(res.status_code, 403, res.get_json())
def test_delete_exam_teacher_others_exams(self): """Teacher trying to archive others teachers exam""" teacher = Teacher.query.order_by(Teacher.id.desc()).first() token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) exams_ids = [exam.id for exam in Exam.get_query().all() if exam.author_id != teacher.id][:10] for exam_id in exams_ids: res = self.client.delete(f'/api/v1/exams/{exam_id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}) self.assertEqual(res.status_code, 403, res.get_json())
def test_delete_exam_teacher_inexistant(self): """Teacher archiving inexistant exam""" teacher = Teacher.query.order_by(Teacher.id.desc()).first() exam1 = Exam.query.order_by(Exam.id).first() exam2 = Exam.query.order_by(Exam.id.desc()).first() exams_ids = [exam1.id - 1, exam2.id + 1] token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) for exam_id in exams_ids: res = self.client.delete(f'/api/v1/exams/{exam_id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}) self.assertEqual(res.status_code, 404, res.get_json())
def test_create_exam_teacher(self): """Teacher creating a new exam""" # Test as teacher teacher = Teacher.query.order_by(Teacher.id.desc()).first() # Generate a header for a teacher token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) res = self.client.post('/api/v1/exams', headers={'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}) self.assertEqual(res.status_code, 200, res.get_json()) data = res.get_json() self.check_fields_list(data, ['success', 'exam']) self.assertTrue('success')
def test_edit_exam_teacher_exam_not_found(self): """Cannot modify not founds exams""" first_exam = Exam.query.order_by(Exam.id).first() last_exam = Exam.query.order_by(Exam.id.desc()).first() exams_ids = (first_exam.id - 1, last_exam.id + 1) teacher = Teacher.get_by_id(first_exam.author_id) token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) exam_body = {} # Not needed for exam_id in exams_ids: res = self.client.patch(f'/api/v1/exams/{exam_id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}, json=exam_body) self.assertEqual(res.status_code, 404, res.get_json())
def test_get_exams_list_teacher(self): """Teacher fetching their exams""" # Test as teacher teacher = Teacher.query.first() exams_count = Exam.query.filter(Exam.author_id == teacher.id).count() # Generate a header for a teacher token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) res = self.client.get('/api/v1/exams', headers={'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}) self.assertEqual(res.status_code, 200, res.get_json()) data = res.get_json() self.check_exam_list_fields(data) self.assertTrue(data['success']) self.assertEqual(data['end'] - data['start'], len(data['exams'])) self.assertEqual(data['exams_count'], exams_count)
def test_list_enrolled_students_others_exams(self): """Teacher cannot list enrolled students of another teacher's exam""" teacher1 = (Teacher.get_query().join(Exam).order_by( Teacher.id).first()) teacher2 = (Teacher.get_query().join(Exam).order_by( Teacher.id.desc()).first()) exam1 = Exam.get_query().filter(Exam.author_id == teacher1.id).first() exam2 = Exam.get_query().filter(Exam.author_id == teacher2.id).first() tests_cases = ((teacher1, exam2), (teacher2, exam1)) for teacher, exam in tests_cases: token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) res = self.client.get(f'/api/v1/enrolls/{exam.id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }) self.assertEqual(res.status_code, 403, res.get_json())
def test_list_enrolled_students_teacher(self): """Return the names of students enrolled to one exam""" teacher = Teacher.get_query().first() exams = Exam.get_query().filter(Exam.author_id == teacher.id).all() token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) for exam in exams: res = self.client.get(f'/api/v1/enrolls/{exam.id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }) self.assertEqual(res.status_code, 200, res.get_json()) data = res.get_json() self.check_fields_list(data, ['success', 'students']) self.assertTrue(data['success']) enroll_count = (StudentSubscription.get_query().filter( StudentSubscription.exam_id == exam.id).count()) self.assertEqual(len(data['students']), enroll_count)
def test_list_enrolled_exam_student(self): """List of the exams the student is enrolled to""" students = Student.get_query().all() tokens = [ generate_user_token(student.username, STUDENT_PERMISSIONS) for student in students ] total_exams_enrolls = StudentSubscription.get_query().count() for token, student in zip(tokens, students): res = self.client.get('/api/v1/enrolls', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}' }) self.assertEqual(res.status_code, 200, [student, res.get_json()]) data = res.get_json() self.check_enroll_list_fields(data) self.assertGreater(total_exams_enrolls, 0) total_exams_enrolls -= data['exams_count'] self.assertEqual(total_exams_enrolls, 0)
def test_edit_exam_teacher_important_fields(self): """Teacher trying to edit an exam without sending appropriate data""" # trying to update non updateable fields data = { 'id': 36, 'author_id': 2, 'dt_creation': datetime.now().replace(microsecond=0), 'is_archived': True, 'dt_archive': datetime.now().replace(microsecond=0), } exam = Exam.query.first() teacher = Teacher.get_by_id(exam.author_id) token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) data_list = [{}, data] + [{key: value} for key, value in data.items()] for data in data_list: res = self.client.patch(f'/api/v1/exams/{exam.id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}, json=data) self.assertEqual(res.status_code, 400, res.get_json())
def test_delete_exam_teacher(self): """Teacher archiving their exam""" exam = Exam.query.first() new_exam_dict = generate_random_exam(exam.author_id) new_exam = Exam(**new_exam_dict) new_exam.insert() try: teacher = Teacher.get_by_id(new_exam.author_id) token = generate_user_token(teacher.username, TEACHER_PERMISSIONS) res = self.client.delete(f'/api/v1/exams/{new_exam.id}', headers={ 'Content-Type': 'application/json', 'Authorization': f'bearer {token}'}) self.assertEqual(res.status_code, 200, res.get_json()) data = res.get_json() self.check_fields_list(data, ['success', 'deleted']) self.assertTrue('success') self.assertEqual(data['deleted'], new_exam.id) self.assertIsNone(Exam.get_by_id(new_exam.id)) finally: new_exam.delete()