def test_strange_solution_with_no_files( exercise: Exercise, student_user: User, staff_user: User, ): solution = conftest.create_solution( exercise, student_user, files=[], hash_='koko', ) staff_client = conftest.get_logged_user(staff_user.username) view_response = staff_client.get(f'{routes.SOLUTIONS}/{solution.id}') assert view_response.status_code == 200 solution = Solution.get_by_id(solution.id) assert solution.state == Solution.STATES.DONE.name to_show_in_view = { 'solution': solution, 'file_id': None, 'shared_url': '', 'is_manager': False, 'solution_files': (), 'viewer_is_solver': True, } with pytest.raises(ResourceNotFound): assert get_view_parameters(**to_show_in_view) user_client = conftest.get_logged_user(student_user.username) assert len(list(notifications.get(student_user))) == 1 view_response = user_client.get(f'{routes.SOLUTIONS}/{solution.id}') assert view_response.status_code == 404
def test_download_solution( self, exercise: Exercise, student_user: User, ): storage = self.create_zipfile_storage() hash_ = hashing.by_file(storage) solution = conftest.create_solution( exercise=exercise, student_user=student_user, files=list(TestDownloadSolution.get_zip_files()), hash_=hash_, ) client = conftest.get_logged_user(student_user.username) download_response = client.get(f'{routes.DOWNLOADS}/{solution.id}') downloaded_bytes_file = BytesIO(download_response.data) downloaded_zipfile = ZipFile(downloaded_bytes_file, 'r') exist_zipfile = ZipFile(self.zipfile_file, 'r') for exist_filename, downloaded_filename in zip( exist_zipfile.namelist(), downloaded_zipfile.namelist(), ): assert exist_filename == downloaded_filename with exist_zipfile.open(exist_filename, 'r') as exist_file: with downloaded_zipfile.open( downloaded_filename, 'r', ) as downloaded_file: assert exist_file.read() == downloaded_file.read()
def test_zip(self, course: Course, student_user: User): conftest.create_exercise(course, 1) conftest.create_exercise(course, 2) conftest.create_exercise(course, 3) conftest.create_exercise(course, 4, is_archived=True) conftest.create_usercourse(student_user, course) client = conftest.get_logged_user(username=student_user.username) # Uploading a multiple zip solutions file upload_response = client.post(f'/upload/{course.id}', data={ 'file': self.zipfiles_extractors_bytes_io[1], }) json_response_upload = json.loads( upload_response.get_data(as_text=True), ) assert len(json_response_upload['exercise_misses']) == 1 assert len(json_response_upload['exercise_matches']) == 2 assert upload_response.status_code == 200 # Uploading a zip file with a same solution exists in the previous zip second_upload_response = client.post( f'/upload/{course.id}', data={ 'file': self.zipfiles_extractors_bytes_io[0], }) assert second_upload_response.status_code == 400
def test_solutions_of_user( staff_user: User, student_user: User, course: Course, solution: Solution, _assessments, ): conftest.create_usercourse(student_user, course) client = conftest.get_logged_user(staff_user.username) client.post( f'/assessment/{solution.id}', data=json.dumps({'assessment': 2}), content_type='application/json', ) solution = Solution.get_by_id(solution.id) assert solution.assessment.name == 'Nice' client.post( f'/assessment/{solution.id}', data=json.dumps({'assessment': None}), content_type='application/json', ) exercise2 = conftest.create_exercise(course, 2) solution2 = conftest.create_solution(exercise2, student_user) client.post( f'/assessment/{solution2.id}', data=json.dumps({'assessment': 3}), content_type='application/json', ) solution2 = Solution.get_by_id(solution2.id) exercises = solution.of_user(student_user.id, from_all_courses=True) assert exercises[0].get('assessment') is None assert exercises[1].get('assessment') == 'Try again'
def test_share_solution_by_another_user( exercise: Exercise, student_user: User, ): student_user2 = conftest.create_student_user(index=1) solution = conftest.create_solution(exercise, student_user2) client = conftest.get_logged_user(student_user.username) not_exist_share_response = client.post('/share', data=json.dumps({ 'solutionId': solution.id + 1, 'act': 'get', }), content_type='application/json') assert not_exist_share_response.status_code == 404 not_user_solution_share_response = client.post( '/share', data=json.dumps({ 'solutionId': solution.id, 'act': 'get', }), content_type='application/json', ) assert not_user_solution_share_response.status_code == 403
def test_manager_can_see_solutions( solution: Solution, staff_user: User, ): staff_client = conftest.get_logged_user(staff_user.username) view_response = staff_client.get(f'{routes.SOLUTIONS}/{solution.id}') assert view_response.status_code == 200
def test_courses_exercises( course: Course, student_user: User, captured_templates, ): course2 = conftest.create_course(index=1) conftest.create_usercourse(student_user, course) conftest.create_exercise(course2, 1) conftest.create_exercise(course2, 2) assert len( list(Exercise.get_objects(student_user.id, from_all_courses=True), )) == 0 client = conftest.get_logged_user(username=student_user.username) client.get(f'course/{course.id}') template, _ = captured_templates[-1] assert template.name == 'exercises.html' conftest.create_exercise(course, 1, index=1) assert len(list(Exercise.get_objects(student_user.id))) == 1 unregistered_response = client.get(f'course/{course2.id}') assert unregistered_response.status_code == 403 fail_response = client.get('course/123456') assert fail_response.status_code == 404 conftest.create_usercourse(student_user, course2) client.get(f'course/{course2.id}') template, _ = captured_templates[-1] assert template.name == 'exercises.html' assert len(list(Exercise.get_objects(student_user.id))) == 2
def test_done_checking( solution: Solution, staff_user: User, ): client = conftest.get_logged_user(staff_user.username) response = client.post( f'/checked/{solution.exercise.id}/{solution.id}', ) assert response.status_code == 200
def test_limiter_shared_link(student_user: User, solution: Solution): client = conftest.get_logged_user(student_user.username) shared_solution = conftest.create_shared_solution(solution) for _ in range(webapp.config['LIMITS_PER_MINUTE']): response = client.get(f'{routes.SHARED}/{shared_solution}') assert response.status_code == 200 response = client.get(f'{routes.SHARED}/{shared_solution}') assert response.status_code == 429
def test_comment_text_escaping(student_user: User, solution: Solution): client = conftest.get_logged_user(student_user.username) comment_response = client.post('/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'create', 'kind': 'text', 'comment': USER_COMMENT_BEFORE_ESCAPING, 'line': 1, }), content_type='application/json') assert comment_response.status_code == 200 assert solution.comments[0].comment.text == USER_COMMENT_AFTER_ESCAPING
def test_invalid_file_solution( solution: Solution, student_user: User, ): client = conftest.get_logged_user(student_user.username) successful_response = client.get(f'/view/{solution.id}') assert successful_response.status_code == 200 fail_response = client.get(f'/view/{solution.id}/12345') assert fail_response.status_code == 404
def test_zip_bomb(self, student_user: User): conftest.create_exercise() client = conftest.get_logged_user(username=student_user.username) # Trying to upload a zipbomb file upload_response = client.post('/upload', data={ 'file': self.zipbomb_bytes_io, }) assert upload_response.status_code == 413
def test_shared_url_with_disabled_shared_solutions( solution: Solution, student_user: User, ): client = conftest.get_logged_user(student_user.username) shared_solution = conftest.create_shared_solution(solution) conftest.disable_shareable_solutions() not_shared_solution_response = client.get( f'{routes.SHARED}/{shared_solution}', ) assert not_shared_solution_response.status_code == 404
def test_view_user_page( student_user: User, staff_user: User, ): student_user2 = conftest.create_student_user(index=1) client = conftest.get_logged_user(student_user.username) user_response = client.get(f'/user/{student_user.id}') assert user_response.status_code == 200 another_user_response = client.get(f'/user/{student_user2.id}') assert another_user_response.status_code == 403 conftest.logout_user(client) client2 = conftest.get_logged_user(staff_user.username) not_exist_user_response = client2.get('/user/99') assert not_exist_user_response.status_code == 404 another_user_response = client2.get(f'/user/{student_user2.id}') assert another_user_response.status_code == 200
def test_limiter_login_success(student_user: User): client = webapp.test_client() client.post('/login', data={ 'username': student_user.username, 'password': '******', }, follow_redirects=True) fail_login_response = client.get('/exercises') assert fail_login_response.status_code == 302 client = conftest.get_logged_user(student_user.username) success_login_response = client.get('/exercises') assert success_login_response.status_code == 200
def test_share_with_disabled_shareable_solutions( solution: Solution, student_user: User, ): client = conftest.get_logged_user(student_user.username) conftest.disable_shareable_solutions() shared_response = client.post('/share', data=json.dumps({ 'solutionId': solution.id, 'act': 'get', }), content_type='application/json') assert shared_response.status_code == 403
def test_upload_invalid_exercise( self, course: Course, student_user: User, ): conftest.create_usercourse(student_user, course) client = conftest.get_logged_user(username=student_user.username) fail_upload_response = client.post(f'/upload/{course.id}', data={ 'file': self.image_bytes_io, }) assert fail_upload_response.status_code == 400
def test_valid_change_password(captured_templates): student_user = conftest.create_student_user(index=1) client = conftest.get_logged_user(student_user.username) conftest.change_client_password( client, 'fake pass', 'some_password', 'some_password', ) template, _ = captured_templates[-1] assert template.name == "login.html" check_logout_response = client.get('/exercises') assert check_logout_response.status_code == 302
def test_create_note( student_user: User, staff_user: User, exercise: Exercise, ): client = conftest.get_logged_user(staff_user.username) # Trying to create note with no text new_note_response = client.post( f'/notes/{student_user.id}', data=json.dumps({'act': 'create'}), query_string={'note': ''}, content_type='application/json', ) assert new_note_response.status_code == 422 # Creating a staff note staff_note_response = client.post( f'/notes/{student_user.id}', data=json.dumps({'act': 'create'}), query_string={ 'note': 'staff note', 'privacy': '1' }, content_type='application/json', ) assert staff_note_response.status_code == 200 # Creating a private note private_note = {'note': 'private note', 'exercise': exercise.subject} private_note_response = client.post( f'/notes/{student_user.id}', data=json.dumps({'act': 'create'}), query_string=private_note, content_type='application/json', ) assert private_note_response.status_code == 200 # Fetching notes user_page_notes = client.get( f'notes/{student_user.id}', query_string={'act': 'fetch'}, content_type='application/json', ) json_user_page_notes = json.loads( user_page_notes.get_data(as_text=True), ) staff_note, private_note = json_user_page_notes assert staff_note.get('privacy') == 30 assert private_note.get('privacy') == 40 assert private_note.get('subject') == exercise.subject assert staff_note.get('fullname') == staff_user.fullname
def test_upload_correct_course( self, course: Course, student_user: User, ): conftest.create_exercise(course, 1) conftest.create_usercourse(student_user, course) client = conftest.get_logged_user(username=student_user.username) success_upload_response = client.post(f'/upload/{course.id}', data={ 'file': self.pyfile_different_course, }) assert success_upload_response.status_code == 200
def test_upload_another_course( self, course: Course, student_user: User, ): course2 = conftest.create_course(index=1) conftest.create_exercise(course2, 1) conftest.create_usercourse(student_user, course) client = conftest.get_logged_user(username=student_user.username) fail_upload_response = client.post(f'/upload/{course2.id}', data={ 'file': self.pyfile_different_course, }) assert fail_upload_response.status_code == 400
def test_user_notes(student_user: User): client = conftest.get_logged_user(student_user.username) # User trying to create a note, doesn't matter what new_note_response = client.post( f'/notes/{student_user.id}', data=json.dumps({'act': 'create'}), content_type='application/json', ) assert new_note_response.status_code == 403 # Trying to reach not exist user not_exist_user_note_response = client.get( '/notes/99', data=json.dumps({'act': 'fetch'}), content_type='application/json', ) assert not_exist_user_note_response.status_code == 404
def test_view_page( exercise: Exercise, student_user: User, ): student_user2 = conftest.create_student_user(index=1) solution = conftest.create_solution(exercise, student_user) solution2 = conftest.create_solution(exercise, student_user2) client = conftest.get_logged_user(student_user.username) view_response = client.get(f'/view/{solution.id}') assert view_response.status_code == 200 another_user_solution_response = client.get(f'/view/{solution2.id}') assert another_user_solution_response.status_code == 403 not_exist_solution_response = client.get('/view/0') assert not_exist_solution_response.status_code == 404
def test_last_view_status( solution: Solution, student_user: User, staff_user: User, ): client = conftest.get_logged_user(student_user.username) assert solution.last_status_view == SolutionStatusView.UPLOADED.name client.get(f'/view/{solution.id}') solution = Solution.get_by_id(solution.id) assert solution.last_status_view == SolutionStatusView.NOT_CHECKED.name solutions.mark_as_checked(solution.id, staff_user.id) solution = Solution.get_by_id(solution.id) assert solution.last_status_view == SolutionStatusView.NOT_CHECKED.name client.get(f'/view/{solution.id}') solution = Solution.get_by_id(solution.id) assert solution.last_status_view == SolutionStatusView.CHECKED.name
def test_register_public_course( student_user: User, course: Course, captured_templates, ): client = conftest.get_logged_user(username=student_user.username) not_public_course_response = client.get(f'/course/join/{course.id}') assert not_public_course_response.status_code == 403 unknown_course_response = client.get('/course/join/123456') assert unknown_course_response.status_code == 404 course.is_public = True course.save() course = Course.get_by_id(course.id) client.get(f'/course/join/{course.id}') template, _ = captured_templates[-1] assert template.name == 'exercises.html' already_registered_response = client.get(f'/course/join/{course.id}') assert already_registered_response.status_code == 409
def test_send_page( student_user: User, course: Course, exercise: Exercise, ): course2 = conftest.create_course(2) exercise2 = conftest.create_exercise(course2, 1) conftest.create_usercourse(student_user, course) client = conftest.get_logged_user(student_user.username) success_send_response = client.get(f'send/{course.id}') assert success_send_response.status_code == 200 success_send_response2 = client.get(f'send/{course.id}/{exercise.id}') assert success_send_response2.status_code == 200 fail_send_response = client.get(f'send/{course2.id}') assert fail_send_response.status_code == 403 fail_send_response = client.get(f'send/{course2.id}/{exercise2.id}') assert fail_send_response.status_code == 403
def test_invalid_change_password(captured_templates): student_user = conftest.create_student_user(index=1) client = conftest.get_logged_user(student_user.username) for _ in range(MAX_INVALID_PASSWORD_TRIES): conftest.change_client_password( client, 'wrong pass', 'some_password', 'some_password', ) template, _ = captured_templates[-1] assert template.name == "change-password.html" conftest.change_client_password( client, 'fake pass', 'some_password', 'some_password', ) template, _ = captured_templates[-1] assert template.name == "change-password.html"
def test_user_comments( exercise: Exercise, student_user: User, ): solution = conftest.create_solution(exercise, student_user) client = conftest.get_logged_user(student_user.username) # Creating a comment comment_response = client.post('/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'create', 'kind': 'text', 'comment': 'hey', 'line': 1, }), content_type='application/json') assert comment_response.status_code == 200 # Creating another comment another_comment_response = client.post( '/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'create', 'kind': 'text', 'comment': 'noice', 'line': 2, }), content_type='application/json', ) assert another_comment_response.status_code == 200 # Removing the second comment json_response_another_comment = json.loads( another_comment_response.get_data(as_text=True), ) delete_response = client.get('/comments', query_string={ 'fileId': solution.files[0].id, 'act': 'delete', 'commentId': json_response_another_comment['id'], }, content_type='application/json') assert delete_response.status_code == 200 # Disabling users comments option conftest.disable_users_comments() # Trying to remove a comment json_response_comment = json.loads( comment_response.get_data(as_text=True), ) delete_response = client.get('/comments', query_string={ 'fileId': solution.files[0].id, 'act': 'delete', 'commentId': json_response_comment['id'], }, content_type='application/json') assert delete_response.status_code == 403 # Trying to create a comment disable_comment_response = client.post( '/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'create', 'kind': 'text', 'comment': 'well well well', 'line': 2, }), content_type='application/json', ) assert disable_comment_response.status_code == 403
def test_staff_and_user_comments( exercise: Exercise, student_user: User, staff_user: User, ): solution = conftest.create_solution(exercise, student_user) client = conftest.get_logged_user(staff_user.username) # Enabling user comments option conftest.enable_users_comments() # Creating a comment comment_response = client.post('/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'create', 'kind': 'text', 'comment': 'try again', 'line': 1, }), content_type='application/json') assert comment_response.status_code == 200 # Creating another comment another_comment_response = client.post( '/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'create', 'kind': 'text', 'comment': 'hey', 'line': 1, }), content_type='application/json', ) assert another_comment_response.status_code == 200 # Unknown act comment unknown_comment_response = client.post( '/comments', data=json.dumps({ 'fileId': solution.files[0].id, 'act': 'unknown', 'kind': 'text', 'comment': 'hey', 'line': 1, }), content_type='application/json', ) assert unknown_comment_response.status_code == 400 # Not existing fileId comment file_id_comment_response = client.post( '/comments', data=json.dumps({ 'fileId': 99, 'act': 'create', 'kind': 'text', 'comment': 'hey', 'line': 1, }), content_type='application/json', ) assert file_id_comment_response.status_code == 404 # Removing the second comment json_response_another_comment = json.loads( another_comment_response.get_data(as_text=True), ) delete_response = client.get('/comments', query_string={ 'fileId': solution.files[0].id, 'act': 'delete', 'commentId': json_response_another_comment['id'], }, content_type='application/json') assert delete_response.status_code == 200 conftest.logout_user(client) client2 = conftest.get_logged_user(student_user.username) # Trying to remove a comment json_response_comment = json.loads( comment_response.get_data(as_text=True), ) delete_response = client2.get('/comments', query_string={ 'fileId': solution.files[0].id, 'act': 'delete', 'commentId': json_response_comment['id'], }, content_type='application/json') assert delete_response.status_code == 403
def test_share_solution_function( exercise: Exercise, student_user: User, ): student_user2 = conftest.create_student_user(index=1) solution = conftest.create_solution(exercise, student_user2) client2 = conftest.get_logged_user(student_user2.username) # Sharing his own solution shared_response = client2.post('/share', data=json.dumps({ 'solutionId': solution.id, 'act': 'get', }), content_type='application/json') assert shared_response.status_code == 200 # Unknown act of share unknown_shared_response = client2.post('/share', data=json.dumps({ 'solutionId': solution.id, 'act': 'unknown', }), content_type='application/json') assert unknown_shared_response.status_code == 400 # Entering another student solution shared_url = SharedSolution.get_or_none( SharedSolution.solution == solution, ) assert len(shared_url.entries) == 0 conftest.logout_user(client2) client = conftest.get_logged_user(student_user.username) shared_response = client.get(f'{routes.SHARED}/{shared_url}') assert shared_response.status_code == 200 assert len(shared_url.entries) == 1 # Downloading another student solution by solution.id solution_id_download_response = client.get( f'{routes.DOWNLOADS}/{solution.id}', ) assert solution_id_download_response.status_code == 403 # Downloading another student solution download_response = client.get(f'{routes.DOWNLOADS}/{shared_url}', ) assert download_response.status_code == 200 # Deleting another user's solution delete_not_user_solution_response = client.post( '/share', data=json.dumps({ 'solutionId': solution.id, 'act': 'delete', }), content_type='application/json', ) assert delete_not_user_solution_response.status_code == 403 # Deleting his own solution conftest.logout_user(client) client2 = conftest.get_logged_user(student_user2.username) delete_share_response = client2.post('/share', data=json.dumps({ 'solutionId': solution.id, 'act': 'delete', }), content_type='application/json') assert delete_share_response.status_code == 200 # Entering not shared solution after deletion conftest.logout_user(client2) client = conftest.get_logged_user(student_user.username) not_shared_solution_response = client.get( f'{routes.SHARED}/{shared_url}', ) assert not_shared_solution_response.status_code == 404