From 300e74ec94e0c11c99b0cdb301eaa7e91224d315 Mon Sep 17 00:00:00 2001 From: Ross Date: Mon, 12 Dec 2022 16:16:53 +0000 Subject: [PATCH] Basic anatomy user integration testing --- .../templates/anatomy/exam_scores_user.html | 2 +- anatomy/tests/test_anatomy_exams.py | 301 ++++++++++++------ generic/urls.py | 3 +- generic/views.py | 11 +- physics/tests/test_physics_exams.py | 52 +-- physics/views.py | 3 + rad/test_helpers.py | 23 +- 7 files changed, 263 insertions(+), 132 deletions(-) diff --git a/anatomy/templates/anatomy/exam_scores_user.html b/anatomy/templates/anatomy/exam_scores_user.html index 7148ce56..0dbe2421 100644 --- a/anatomy/templates/anatomy/exam_scores_user.html +++ b/anatomy/templates/anatomy/exam_scores_user.html @@ -23,7 +23,7 @@
{{ans}}
{% if exam.publish_results %} - {{score}} + {{score}} {% endif %} View diff --git a/anatomy/tests/test_anatomy_exams.py b/anatomy/tests/test_anatomy_exams.py index 6d13119d..ef83ca02 100644 --- a/anatomy/tests/test_anatomy_exams.py +++ b/anatomy/tests/test_anatomy_exams.py @@ -15,36 +15,37 @@ from bs4 import BeautifulSoup from anatomy.views import GenericExamViews as AnatomyExamViews -from anatomy.models import Answer, Exam, AnatomyQuestion as Question, QuestionType, Structure +from anatomy.models import ( + Answer, + Exam, + AnatomyQuestion as Question, + QuestionType, + Structure, +) -from generic.models import CidUser, CidUserGroup +from generic.models import CidUser, CidUserGroup, UserUserGroup + +from rad.test_helpers import AssertNotFound, create_cid_user_and_groups + +from django.contrib.auth.models import User APP_NAME = "anatomy" -def create_cid_user_and_groups(db): - group1 = CidUserGroup.objects.create(name="Group1") - group2 = CidUserGroup.objects.create(name="Group2") - - cid_user_1000 = CidUser.objects.create(cid=1000, passcode="ABCD", group=group1) - cid_user_1001 = CidUser.objects.create(cid=1001, passcode="EFGH", group=group1) - cid_user_2001 = CidUser.objects.create(cid=2001, passcode="EFGH", group=group2) - - assert cid_user_1000.cid == 1000 - assert cid_user_1001.cid == 1001 - - def create_exam(db): exam: Exam = AnatomyExamViews.Exam.objects.create( name="Cid Exam", exam_mode=True, active=True ) group1: CidUserGroup = CidUserGroup.objects.get(name="Group1") + usergroup1: UserUserGroup = UserUserGroup.objects.get(name="Group1") exam.cid_user_groups.add(group1) exam.valid_cid_users.add(*group1.ciduser_set.all()) + exam.valid_user_users.add(*usergroup1.users.all()) + assert exam in group1.anatomy_cid_user_groups.all() assert exam @@ -85,7 +86,12 @@ def create_question(exam, answer=None): answer_text = "testanswer" else: answer_text = answer - answer = Answer(question=question, answer=answer_text, answer_compare=answer_text, status=Answer.MarkOptions.CORRECT) + answer = Answer( + question=question, + answer=answer_text, + answer_compare=answer_text, + status=Answer.MarkOptions.CORRECT, + ) answer.save() return question @@ -99,46 +105,62 @@ def test_exams(db, client): create_question_types(db) question1 = create_question(exam) - create_question(exam) - create_question(exam) + generated_questions = [question1, create_question(exam), create_question(exam)] active_exams = client.get(reverse(f"{APP_NAME}:active_exams")) assert active_exams.status_code == 200 assert len(json.loads(active_exams.content)["exams"]) == 0 + cid_user_1000 = CidUser.objects.get(cid=1000) cid_user_1001 = CidUser.objects.get(cid=1001) + cid_user_2001 = CidUser.objects.get(cid=2001) + user1 = User.objects.get(username="user1") + + users_tested = 1 + for cid_user in [cid_user_1001, cid_user_1000, user1]: + if isinstance(cid_user, CidUser): + testing_cid_user = True + else: + testing_cid_user = False + current_user = cid_user + client.force_login(cid_user) + + exam.active = True + exam.publish_results = False + exam.save() - for cid_user in [cid_user_1001]: # Test active exams sections works as intended - active_exams_cid = client.get( - reverse( + if testing_cid_user: + active_exams_url = reverse( f"active_exams_cid", kwargs={"cid": cid_user.cid, "passcode": cid_user.passcode}, ) - ) + else: + active_exams_url = reverse( + f"active_exams", + ) + + active_exams_cid = client.get(active_exams_url) assert active_exams_cid.status_code == 200 assert len(json.loads(active_exams_cid.content)["exams"]) == 1 - active_exams_cid = client.get( - reverse(f"active_exams_cid", kwargs={"cid": 1001, "passcode": "EFGH"}) - ) + if testing_cid_user: + no_active_exams_cid = client.get( + reverse(f"active_exams_cid", kwargs={"cid": 2001, "passcode": "EGFH"}) + ) - assert active_exams_cid.status_code == 200 - assert len(json.loads(active_exams_cid.content)["exams"]) == 1 + assert no_active_exams_cid.status_code == 401 + assert json.loads(no_active_exams_cid.content)["status"] == "invalid" - no_active_exams_cid = client.get( - reverse(f"active_exams_cid", kwargs={"cid": 2001, "passcode": "EGFH"}) - ) - - assert no_active_exams_cid.status_code == 401 - assert json.loads(no_active_exams_cid.content)["status"] == "invalid" - - invalid_passcode = client.get( - reverse(f"active_exams_cid", kwargs={"cid": 1001, "passcode": "ABCD"}) - ) - assert invalid_passcode.status_code == 401 - assert json.loads(invalid_passcode.content)["status"] == "invalid" + invalid_passcode = client.get( + reverse( + f"active_exams_cid", + kwargs={"cid": cid_user.cid, "passcode": "AAAA"}, + ) + ) + assert invalid_passcode.status_code == 401 + assert json.loads(invalid_passcode.content)["status"] == "invalid" exam_metadata = json.loads(active_exams_cid.content)["exams"][0] @@ -166,9 +188,14 @@ def test_exams(db, client): exam.active = True exam.save() + if testing_cid_user: + post_cid = cid_user.cid + else: + post_cid = f"u-{current_user.pk}" + post_json = { "eid": f"anatomy/{exam.pk}", - "cid": cid_user_1001.cid, + "cid": post_cid, "start_time": "1659618141.731", "answers": [[]], } @@ -184,7 +211,7 @@ def test_exams(db, client): post_json = { "eid": f"anatomy/{exam.pk+10}", - "cid": cid_user_1001.cid, + "cid": post_cid, "start_time": "1659618141.731", "answers": [[]], } @@ -208,20 +235,21 @@ def test_exams(db, client): for questions in exam_json["questions"]: for qid in questions: - valid_answers.append( - { - "eid": exam_json["eid"], - "cid": cid_user_1001.cid, - "passcode": cid_user_1001.passcode, - "qid": qid, - "qidn": "1", - "ans": f"answer {qid}", - } - ) + post_data = { + "eid": exam_json["eid"], + "cid": post_cid, + "qid": qid, + "qidn": "1", + "ans": f"answer {qid}", + } + if testing_cid_user: + post_data["passcode"] = cid_user.passcode + + valid_answers.append(post_data) post_json = { "eid": exam_json["eid"], - "cid": cid_user_1001.cid, + "cid": post_cid, "start_time": "1659618141.731", "answers": json.dumps(valid_answers), } @@ -236,67 +264,131 @@ def test_exams(db, client): assert json_res["question_count"] == 3 # We can then check the answers have been submitted (and can be viewed by the user) - + + if testing_cid_user: + # Get overview scores page (invalid passcode) + AssertNotFound( + client, + reverse( + f"cid_scores", kwargs={"cid": cid_user.cid, "passcode": "AAAA"} + ), + ) + + cid_scores_url = reverse( + f"cid_scores", + kwargs={"cid": cid_user.cid, "passcode": cid_user.passcode}, + ) + else: + cid_scores_url = reverse(f"user_scores") + # Get overview scores page - cid_scores_res = client.get( - reverse(f"cid_scores", kwargs={"cid": 1001, "passcode": "EFGH"}) - ) + cid_scores_res = client.get(cid_scores_url) cid_scores_soup = BeautifulSoup(cid_scores_res.content, "html.parser") - print(cid_scores_soup.find("div", {"id" : "exam-assigned"})) - search_exam = cid_scores_soup.find("div", {"id" : "exam-assigned"}).find("ul", {"class" : exam.app_name}).find_all("li", attrs={"data-exam-id": exam.pk}) + search_exam = ( + cid_scores_soup.find("div", {"id": "exam-assigned"}) + .find("ul", {"class": exam.app_name}) + .find_all("li", attrs={"data-exam-id": exam.pk}) + ) assert search_exam assert exam.name in str(search_exam) assert "Active" in str(search_exam) - #assert "Active" in assigned_exams # check it is active + # assert "Active" in assigned_exams # check it is active - invalid_exam = cid_scores_soup.find_all("li", attrs={"data-exam-id": exam.pk+5}) - assert not invalid_exam # Check we can't find an invalid exam + invalid_exam = cid_scores_soup.find_all( + "li", attrs={"data-exam-id": exam.pk + 5} + ) + assert not invalid_exam # Check we can't find an invalid exam # Check that we have a results link - results_exam = cid_scores_soup.find("div", {"id" : "exam-results"}).find("ul", {"class" : exam.app_name}).find_all("li", attrs={"data-exam-id": exam.pk}) + results_exam = ( + cid_scores_soup.find("div", {"id": "exam-results"}) + .find("ul", {"class": exam.app_name}) + .find_all("li", attrs={"data-exam-id": exam.pk}) + ) assert results_exam assert exam.name in str(results_exam) - assert exam.name+" test" not in str(results_exam) - assert "Results Published" not in str(results_exam) # It should not be published yet + assert exam.name + " test" not in str(results_exam) + assert "Results Published" not in str( + results_exam + ) # It should not be published yet + if testing_cid_user: + AssertNotFound( + client, + reverse( + f"{exam.app_name}:exam_scores_cid_user", + kwargs={"pk": exam.pk, "cid": cid_user.cid, "passcode": "AAAA"}, + ), + ) + AssertNotFound( + client, + reverse( + f"{exam.app_name}:exam_scores_cid_user", + kwargs={ + "pk": exam.pk, + "cid": cid_user_2001.cid, + "passcode": cid_user_2001.passcode, + }, + ), + ) + + exam_scores_url = reverse( + f"{exam.app_name}:exam_scores_cid_user", + kwargs={ + "pk": exam.pk, + "cid": cid_user.cid, + "passcode": cid_user.passcode, + }, + ) + else: + exam_scores_url = reverse( + f"{exam.app_name}:exam_scores_user", + kwargs={"pk": exam.pk}, + ) # Load the exam results page - cid_exam_scores_res = client.get( - reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"}) - ) + cid_exam_scores_res = client.get(exam_scores_url) + # Load the exam results page cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") # Check that we have an alert that exams are not published alert = cid_exam_scores_soup.find("div", {"class": "alert"}) assert "Results are not currently published." in str(alert) - - answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li") + answer_lis = cid_exam_scores_soup.find( + "ul", {"class": "score-answer-list"} + ).find_all("li") assert len(answer_lis) == len(valid_answers) - for n in range(len(valid_answers)): # Check no answers are visible if results not published + for n in range( + len(valid_answers) + ): # Check no answers are visible if results not published answer = valid_answers[n] li = answer_lis[n] - assert answer["ans"] in str(li) # Check that the saved answer is shown + assert answer["ans"] in str(li) # Check that the saved answer is shown - assert not li.find("span", {"class": "correct-answer"}) # and that the correct answer isn't + assert not li.find( + "span", {"class": "correct-answer"} + ) # and that the correct answer isn't - assert cid_exam_scores_soup.find("div", {"class": "score-overview"}) is None # check we hide the score overview if not published + assert ( + cid_exam_scores_soup.find("div", {"class": "score-overview"}) is None + ) # check we hide the score overview if not published # Add another question to the exam create_question(exam) # Load the exam results page (again) - cid_exam_scores_res = client.get( - reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"}) - ) + cid_exam_scores_res = client.get(exam_scores_url) cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") - answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li") + answer_lis = cid_exam_scores_soup.find( + "ul", {"class": "score-answer-list"} + ).find_all("li") assert len(answer_lis) == len(valid_answers) + 1 assert "Not answered" in str(answer_lis[-1]) @@ -305,41 +397,70 @@ def test_exams(db, client): exam.save() # Load the exam results page (again) - cid_exam_scores_res = client.get( - reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"}) - ) + cid_exam_scores_res = client.get(exam_scores_url) cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") - assert cid_exam_scores_soup.find("div", {"class": "alert"}) is None # Check our warning banner is gone + assert ( + cid_exam_scores_soup.find("div", {"class": "alert"}) is None + ) # Check our warning banner is gone - answer_lis = cid_exam_scores_soup.find("ul", {"class": "score-answer-list"}).find_all("li") + answer_lis = cid_exam_scores_soup.find( + "ul", {"class": "score-answer-list"} + ).find_all("li") assert len(answer_lis) == len(valid_answers) + 1 assert "Not answered" in str(answer_lis[-1]) # Repetition.... - for n in range(len(valid_answers)): # Check answers are visible if results published + for n in range( + len(valid_answers) + ): # Check answers are visible if results published answer = valid_answers[n] li = answer_lis[n] - assert answer["ans"] in str(li) # Check that the saved answer is shown + assert answer["ans"] in str(li) # Check that the saved answer is shown assert li.find("span", {"class": "correct-answer"}).string == "testanswer" - assert cid_exam_scores_soup.find("div", {"class": "score-overview"}).find("span", {"id": "total-score"}).string == "0 (3 unmarked)" + if users_tested == 1: + # First user the answers will not have been saved + assert ( + cid_exam_scores_soup.find("div", {"class": "score-overview"}) + .find("span", {"id": "total-score"}) + .string + == "0 (3 unmarked)" + ) + else: + # Subsequent users should already have answers marked (apart from the last question which we have deleted) + assert ( + cid_exam_scores_soup.find("div", {"class": "score-overview"}) + .find("span", {"id": "total-score"}) + .string + == "4 (1 unmarked)" + ) for question in exam.exam_questions.all(): try: - new_ans = Answer(question=question, answer=question.get_unmarked_user_answers().pop(), status=Answer.MarkOptions.CORRECT) + new_ans = Answer( + question=question, + answer=question.get_unmarked_user_answers().pop(), + status=Answer.MarkOptions.CORRECT, + ) new_ans.save() - except KeyError: # Final question does not have an answer + except KeyError: # Final question does not have an answer pass # Load the exam results page (again) - cid_exam_scores_res = client.get( - reverse(f"{exam.app_name}:exam_scores_cid_user", kwargs={"pk": exam.pk, "cid": 1001, "passcode": "EFGH"}) - ) + cid_exam_scores_res = client.get(exam_scores_url) cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") - assert cid_exam_scores_soup.find("div", {"class": "score-overview"}).find("span", {"id": "total-score"}).string == "6" \ No newline at end of file + assert ( + cid_exam_scores_soup.find("div", {"class": "score-overview"}) + .find("span", {"id": "total-score"}) + .string + == "6" + ) + + generated_questions.pop(-1).delete() + users_tested = users_tested + 1 diff --git a/generic/urls.py b/generic/urls.py index 12e91638..d126cdfc 100755 --- a/generic/urls.py +++ b/generic/urls.py @@ -2,6 +2,7 @@ from django.urls import path, include from generic.models import Examination from . import views +from generic.views import ExamViews as GenericExamViews app_name = "generic" @@ -131,7 +132,7 @@ def generic_view_urls(generic_views): return urlpatterns -def generic_exam_urls(generic_exam_view): +def generic_exam_urls(generic_exam_view: GenericExamViews): urlpatterns = [ path("", generic_exam_view.index, name="index"), path("exam//", generic_exam_view.exam_overview, name="exam_overview"), diff --git a/generic/views.py b/generic/views.py index 46c4c938..a2003b47 100644 --- a/generic/views.py +++ b/generic/views.py @@ -58,7 +58,7 @@ from .forms import ( UserUserGroupForm, ) -from .models import CidUser, CidUserGroup, Examination, QuestionNote, Supervisor, UserGrades, UserProfile, UserUserGroup, get_next_cid +from .models import CidUser, CidUserGroup, ExamBase, Examination, QuestionNote, Supervisor, UserGrades, UserProfile, UserUserGroup, get_next_cid from rapids.models import Rapid as RapidQuestion from rapids.models import Exam as RapidExam @@ -1319,9 +1319,11 @@ class ExamViews(View, LoginRequiredMixin): eid = int(answer["eid"].split("/")[1]) uid = False + passcode = None try: cid = int(answer["cid"]) + passcode = answer["passcode"] except ValueError: if answer["cid"].startswith("u-"): cid = False @@ -1352,9 +1354,9 @@ class ExamViews(View, LoginRequiredMixin): } ) - exam = get_object_or_404(self.Exam, pk=eid) + exam: ExamBase = get_object_or_404(self.Exam, pk=eid) - if not exam.check_cid_user(cid, answer["passcode"], user_id=uid): + if not exam.check_cid_user(cid, passcode, user_id=uid): return JsonResponse( {"success": False, "error": "invalid cid / passcode"} ) @@ -1597,7 +1599,8 @@ class ExamViews(View, LoginRequiredMixin): if not exam.exam_mode: raise Http404("Packet not in exam mode") - # TODO:Need some kind of test for cid + if cid is not None and not exam.check_cid_user(cid, passcode, request): + raise Http404("Error accessing exam") questions = ( exam.exam_questions.all() diff --git a/physics/tests/test_physics_exams.py b/physics/tests/test_physics_exams.py index 9b5921ab..c87d8c1e 100644 --- a/physics/tests/test_physics_exams.py +++ b/physics/tests/test_physics_exams.py @@ -19,7 +19,7 @@ from physics.views import GenericExamViews as PhysicsExamViews from physics.models import Category, CidUserAnswer, Exam, Question from generic.models import CidUser, CidUserGroup, UserUserGroup -from rad.test_helpers import AssertNotFound +from rad.test_helpers import AssertNotFound, create_cid_user_and_groups from django.contrib.auth.models import User @@ -29,23 +29,6 @@ APP_NAME = "physics" -def create_cid_user_and_groups(db): - group1 = CidUserGroup.objects.create(name="Group1") - group2 = CidUserGroup.objects.create(name="Group2") - - cid_user_1000 = CidUser.objects.create(cid=1000, passcode="ABCD", group=group1) - cid_user_1001 = CidUser.objects.create(cid=1001, passcode="EFGH", group=group1) - cid_user_2001 = CidUser.objects.create(cid=2001, passcode="EFGH", group=group2) - - assert cid_user_1000.cid == 1000 - assert cid_user_1001.cid == 1001 - - # Create UserUsers - user1 = User.objects.create_user(username="user1", email="test@email.com", password="test1234") - - usergroup1 = UserUserGroup.objects.create(name="Group1") - usergroup1.users.add(user1) - usergroup2 = UserUserGroup.objects.create(name="Group2") def create_exam(db): @@ -122,7 +105,7 @@ def test_exams(db, client): create_category(db) - questions = [create_question(exam), create_question(exam), create_question(exam)] + generated_questions = [create_question(exam), create_question(exam), create_question(exam)] active_exams = client.get(reverse(f"{APP_NAME}:active_exams")) assert active_exams.status_code == 200 @@ -150,7 +133,6 @@ def test_exams(db, client): exam.active = True exam.publish_results = False exam.save() - # Test active exams sections works as intended start_page_res = client.get( reverse(f"physics:exam_start", kwargs={"pk": exam.pk}) ) @@ -161,7 +143,7 @@ def test_exams(db, client): else: assert "Start Exam" in str(start_page_soup) - for n, question in enumerate(questions): + for n, question in enumerate(generated_questions): if testing_cid_user: take_url = reverse( f"physics:exam_take", @@ -203,7 +185,7 @@ def test_exams(db, client): # Check that relevant buttons are being displayed assert cid_take_soup.find("button", {"name": "finish"}) is not None - if n < len(questions) - 1: + if n < len(generated_questions) - 1: assert cid_take_soup.find("button", {"name": "next"}) is not None if n > 0: @@ -213,7 +195,7 @@ def test_exams(db, client): n + 1 ) # + 1 for 0 offset assert cid_take_soup.find("span", {"id": "exam-length"}).string == str( - len(questions) + len(generated_questions) ) # Check that stem text is displayed @@ -276,8 +258,8 @@ def test_exams(db, client): # Loop through questions again to test submissions # All physics questions have 5 parts (and require a csrf token) - questions_len = len(questions) - 1 - for n, question in enumerate(questions): + questions_len = len(generated_questions) - 1 + for n, question in enumerate(generated_questions): if testing_cid_user: question_url = reverse( f"physics:exam_take", @@ -388,8 +370,8 @@ def test_exams(db, client): == 0 ) - # Get overview scores page (invalid passcode) if testing_cid_user: + # Get overview scores page (invalid passcode) AssertNotFound(client, reverse(f"cid_scores", kwargs={"cid": cid_user.cid, "passcode": "AAAA"}) ) @@ -468,12 +450,12 @@ def test_exams(db, client): # Check that we are showing enough questions / answers answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"}) - assert len(answer_lis) == 5 * len(questions) + assert len(answer_lis) == 5 * len(generated_questions) submitted_answers = cid_exam_scores_soup.find_all( "span", {"class": "submitted-user-answer"} ) - assert len(submitted_answers) == 5 * len(questions) + assert len(submitted_answers) == 5 * len(generated_questions) for ans in submitted_answers: assert ans.text.strip() == "True" @@ -483,7 +465,7 @@ def test_exams(db, client): # Add another question to the exam extra_question = create_question(exam) - questions.append(extra_question) + generated_questions.append(extra_question) # Load the exam results page (again) cid_exam_scores_res = client.get( @@ -492,12 +474,12 @@ def test_exams(db, client): cid_exam_scores_soup = BeautifulSoup(cid_exam_scores_res.content, "html.parser") answer_lis = cid_exam_scores_soup.find_all("li", {"class": "question-part"}) - assert len(answer_lis) == 5 * len(questions) + assert len(answer_lis) == 5 * len(generated_questions) submitted_answers = cid_exam_scores_soup.find_all( "span", {"class": "submitted-user-answer"} ) - assert len(submitted_answers) == 5 * len(questions) + assert len(submitted_answers) == 5 * len(generated_questions) for ans in submitted_answers[:-5]: assert ans.text.strip() == "True" @@ -524,10 +506,10 @@ def test_exams(db, client): correct_answers = cid_exam_scores_soup.find_all( "span", {"class": "correct-answer"} ) - assert len(correct_answers) == 5 * len(questions) + assert len(correct_answers) == 5 * len(generated_questions) n = 0 - for question in questions: + for question in generated_questions: for ans in question.get_answers(): assert correct_answers[n].text.strip() == f"Correct answer: {ans}" n = n + 1 @@ -535,7 +517,7 @@ def test_exams(db, client): submitted_answers = cid_exam_scores_soup.find_all( "span", {"class": "submitted-user-answer"} ) - assert len(submitted_answers) == 5 * len(questions) + assert len(submitted_answers) == 5 * len(generated_questions) for ans in submitted_answers[:-5]: assert ans.text.strip() == "True" @@ -613,5 +595,5 @@ def test_exams(db, client): cid_take_soup = BeautifulSoup(cid_take_res.content, "html.parser") assert "Exam is currently inactive" in cid_take_soup.text - questions.pop(-1).delete() + generated_questions.pop(-1).delete() users_tested = users_tested + 1 \ No newline at end of file diff --git a/physics/views.py b/physics/views.py index 39aa75cc..b3942068 100644 --- a/physics/views.py +++ b/physics/views.py @@ -102,6 +102,9 @@ def active_exams(request): def exam_scores_cid_user(request, pk, cid=None, passcode=None): exam = get_object_or_404(Exam, pk=pk) + if not exam.exam_mode: + raise Http404("Packet not in exam mode") + if cid is not None and not exam.check_cid_user(cid, passcode, request): raise Http404("Error accessing exam") diff --git a/rad/test_helpers.py b/rad/test_helpers.py index 03feb0cd..2523bf8f 100644 --- a/rad/test_helpers.py +++ b/rad/test_helpers.py @@ -1,6 +1,27 @@ from http import HTTPStatus +from generic.models import CidUser, CidUserGroup, UserUserGroup +from django.contrib.auth.models import User + def AssertNotFound(client, url): """Helper to quickly test for urls that should return a 404 (NOT FOUND) error""" response = client.get(url) - assert response.status_code == HTTPStatus.NOT_FOUND, f"Response content: {response.content}" \ No newline at end of file + assert response.status_code == HTTPStatus.NOT_FOUND, f"Response content: {response.content}" + + +def create_cid_user_and_groups(db): + group1 = CidUserGroup.objects.create(name="Group1") + group2 = CidUserGroup.objects.create(name="Group2") + + cid_user_1000 = CidUser.objects.create(cid=1000, passcode="ABCD", group=group1) + cid_user_1001 = CidUser.objects.create(cid=1001, passcode="EFGH", group=group1) + cid_user_2001 = CidUser.objects.create(cid=2001, passcode="EFGH", group=group2) + + assert cid_user_1000.cid == 1000 + assert cid_user_1001.cid == 1001 + + # Create UserUsers + user1 = User.objects.create_user(username="user1", email="test@email.com", password="test1234") + usergroup1 = UserUserGroup.objects.create(name="Group1") + usergroup1.users.add(user1) + usergroup2 = UserUserGroup.objects.create(name="Group2") \ No newline at end of file