smoke test the rest of the apps

This commit is contained in:
Ross
2026-06-10 22:05:12 +01:00
parent e670adf2d0
commit 6bb9441748
55 changed files with 1454 additions and 109 deletions
+3 -2
View File
@@ -106,7 +106,8 @@ class UserAnswerFilter(django_filters.FilterSet):
)
def __init__(self, data=None, queryset=None, prefix=None, strict=None, user=None, request=None):
if not request.user.groups.filter(name="sba_checker").exists():
queryset = queryset.filter(open_access=True) | queryset.filter(author__id=request.user.id)
if not request.user.is_superuser:
if not request.user.groups.filter(name="sba_checker").exists():
queryset = queryset.filter(exam__open_access=True) | queryset.filter(exam__author__id=request.user.id)
super(UserAnswerFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request)
pass
@@ -0,0 +1,7 @@
{% extends 'sbas/base.html' %}
{% block content %}
<form method="post">{% csrf_token %}
<p>Are you sure you want to delete "{{ object }}"?</p>
<input type="submit" value="Confirm" class="btn btn-danger">
</form>
{% endblock %}
-3
View File
@@ -1,3 +0,0 @@
from django.test import TestCase
# Create your tests here.
+1
View File
@@ -0,0 +1 @@
# Package marker for tests
+131
View File
@@ -0,0 +1,131 @@
import pytest
from django.urls import reverse
from django.contrib.auth.models import Group, User
from django.test import Client
SAFE_STATUS_CODES = {200, 301, 302, 303, 403, 404, 405}
@pytest.fixture
def candidate_client(db):
user = User.objects.create_user(username="candidate", password="password", email="candidate@test.com")
client = Client()
client.force_login(user)
return client
@pytest.fixture
def superuser_client(db):
user = User.objects.create_superuser(username="superuser", password="password", email="superuser@test.com")
for group_name in ["sba_checker", "cid_user_manager"]:
g, _ = Group.objects.get_or_create(name=group_name)
user.groups.add(g)
client = Client()
client.force_login(user)
return client
@pytest.fixture
def anonymous_client(db):
return Client()
@pytest.fixture
def smoke_data(db, settings, tmp_path):
from sbas.models import Question, Exam, UserAnswer, Category
settings.MEDIA_ROOT = str(tmp_path)
create_user = User.objects.create_user(username="smoke_user", email="smoke_user@test.com")
cat, _ = Category.objects.get_or_create(category="Test Category")
question = Question.objects.create(
stem="Test Stem",
a_answer="Ans A",
b_answer="Ans B",
c_answer="Ans C",
d_answer="Ans D",
e_answer="Ans E",
best_answer="a",
category=cat,
)
exam = Exam.objects.create(
name="Test SBA Exam",
exam_mode=True,
active=True
)
exam.author.add(create_user)
from sbas.models import ExamQuestionDetail
ExamQuestionDetail.objects.create(exam=exam, question=question, sort_order=1)
user_answer = UserAnswer.objects.create(
user=create_user,
exam=exam,
question=question,
answer="a",
)
return {
"question": question,
"exam": exam,
"user_answer": user_answer,
}
URL_SPECS = [
("sbas:question_view", None),
("sbas:question_create", None),
("sbas:question_update", lambda d: {"pk": d["question"].pk}),
("sbas:question_clone", lambda d: {"pk": d["question"].pk}),
("sbas:question_delete", lambda d: {"pk": d["question"].pk}),
("sbas:exam_markers", lambda d: {"pk": d["exam"].pk}),
("sbas:exam_groups_edit", lambda d: {"pk": d["exam"].pk}),
("sbas:exam_authors", lambda d: {"pk": d["exam"].pk}),
("sbas:exam_clone", lambda d: {"exam_id": d["exam"].pk}),
("sbas:exam_clone2", lambda d: {"exam_id": d["exam"].pk}),
("sbas:active_exams", None),
("sbas:exam_create", None),
("sbas:exam_update", lambda d: {"pk": d["exam"].pk}),
("sbas:exam_delete", lambda d: {"pk": d["exam"].pk}),
("sbas:user_answer_table_view", None),
("sbas:user_answer_view", lambda d: {"pk": d["user_answer"].pk}),
("sbas:user_answer_delete", lambda d: {"pk": d["user_answer"].pk}),
("sbas:llm_prompt_view", None),
("sbas:import_llm_questions", None),
("sbas:import_llm_confirm", None),
("sbas:exam_create_from_filters_with_name", None),
("sbas:generate_exam", None),
("sbas:question_overview", None),
("sbas:question_search_page", None),
("sbas:question_search_partial", None),
("sbas:exam_review_question_responses", lambda d: {"pk": d["exam"].pk, "q_index": 0}),
("sbas:exam_review_question_summary", lambda d: {"pk": d["exam"].pk, "q_index": 0}),
("sbas:toggle_frcr", lambda d: {"pk": d["question"].pk}),
("sbas:merge_category", None),
("sbas:index", None),
("sbas:help", None),
]
@pytest.mark.django_db
@pytest.mark.parametrize("url_name, kwargs_lambda", URL_SPECS)
def test_url_smoke_anonymous(anonymous_client, smoke_data, url_name, kwargs_lambda):
kwargs = kwargs_lambda(smoke_data) if kwargs_lambda else None
url = reverse(url_name, kwargs=kwargs)
response = anonymous_client.get(url, follow=False)
assert response.status_code != 500, f"500 Server Error on {url_name} ({url}) for Anonymous"
assert response.status_code in {200, 302, 400, 403, 404, 405}, f"Unexpected status code {response.status_code} on {url_name} for Anonymous"
@pytest.mark.django_db
@pytest.mark.parametrize("url_name, kwargs_lambda", URL_SPECS)
def test_url_smoke_candidate(candidate_client, smoke_data, url_name, kwargs_lambda):
kwargs = kwargs_lambda(smoke_data) if kwargs_lambda else None
url = reverse(url_name, kwargs=kwargs)
response = candidate_client.get(url, follow=False)
assert response.status_code != 500, f"500 Server Error on {url_name} ({url}) for Candidate"
assert response.status_code in SAFE_STATUS_CODES or response.status_code == 400, f"Unexpected status code {response.status_code} on {url_name} for Candidate"
@pytest.mark.django_db
@pytest.mark.parametrize("url_name, kwargs_lambda", URL_SPECS)
def test_url_smoke_superuser(superuser_client, smoke_data, url_name, kwargs_lambda):
kwargs = kwargs_lambda(smoke_data) if kwargs_lambda else None
url = reverse(url_name, kwargs=kwargs)
response = superuser_client.get(url, follow=False)
assert response.status_code != 500, f"500 Server Error on {url_name} ({url}) for Superuser"
assert response.status_code in {200, 301, 302, 303, 400, 403, 404, 405}, f"Unexpected status code {response.status_code} on {url_name} for Superuser"
+2
View File
@@ -207,6 +207,8 @@ def exam_review_question_summary(request, pk: int, q_index: int):
class AuthorOrCheckerRequiredMixin(object):
def get_object(self, *args, **kwargs):
obj = super().get_object(*args, **kwargs)
if self.request.user.is_superuser:
return obj
if self.request.user.groups.filter(name="sbas_checker").exists():
return obj
if self.request.user not in obj.author.all():