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
@@ -67,7 +67,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="long_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="long_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
-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
+163
View File
@@ -0,0 +1,163 @@
import pytest
import tempfile
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 ["longs_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 longs.models import Long, LongSeries, LongSeriesImage, Exam, UserAnswer, Examination
settings.MEDIA_ROOT = str(tmp_path)
create_user = User.objects.create_user(username="smoke_user", email="smoke_user@test.com")
exm_name, _ = Examination.objects.get_or_create(examination="Test Examination")
question = Long.objects.create(
description="Test description",
history="Test History",
model_observations="Test Observations",
model_interpretation="Test Interpretation",
model_principle_diagnosis="Test Diagnosis",
model_differential_diagnosis="Test Differentials",
model_management="Test Management",
)
series = LongSeries.objects.create(
description="Test Series",
examination=exm_name,
)
question.series.add(series)
# Mocking series image
image = tempfile.NamedTemporaryFile(
dir=settings.MEDIA_ROOT, suffix=".jpg", delete=False
)
image.flush()
image._committed = True
image.write(b"12345ABCD")
image.seek(0)
series_image = LongSeriesImage(image=image.name, series=series)
series_image.save()
exam = Exam.objects.create(
name="Test Longs Exam",
exam_mode=True,
active=True
)
exam.author.add(create_user)
from longs.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_observations="testanswer",
answer_interpretation="testanswer",
answer_principle_diagnosis="testanswer",
answer_differential_diagnosis="testanswer",
answer_management="testanswer",
)
return {
"question": question,
"series": series,
"exam": exam,
"user_answer": user_answer,
}
URL_SPECS = [
("longs:author_list", None),
("longs:question_view", None),
("longs:series_view", None),
("longs:series_detail", lambda d: {"pk": d["series"].pk}),
("longs:long_series_order_dicom", lambda d: {"pk": d["series"].pk}),
("longs:long_series_download", lambda d: {"pk": d["series"].pk}),
("longs:long_series_order_dicom_instance", lambda d: {"pk": d["series"].pk}),
("longs:long_series_order_dicom_SeriesInstanceUID", lambda d: {"pk": d["series"].pk}),
("longs:long_series_order_upload_filename", lambda d: {"pk": d["series"].pk}),
("longs:long_series_delete", lambda d: {"pk": d["series"].pk}),
("longs:question_detail", lambda d: {"pk": d["question"].pk}),
("longs:question_json", lambda d: {"pk": d["question"].pk}),
("longs:question_json_unbased", lambda d: {"pk": d["question"].pk}),
("longs:question_json_recreate", lambda d: {"pk": d["question"].pk}),
("longs:long_split", lambda d: {"pk": d["question"].pk}),
("longs:long_clone", lambda d: {"pk": d["question"].pk}),
("longs:long_scrap", lambda d: {"pk": d["question"].pk}),
("longs:long_delete", lambda d: {"pk": d["question"].pk}),
("longs:mark_answer", lambda d: {"exam_id": d["exam"].pk, "question_number": 0, "answer_id": d["user_answer"].pk}),
("longs:mark_answer_override", lambda d: {"exam_id": d["exam"].pk, "question_number": 0, "answer_id": d["user_answer"].pk}),
("longs:mark", lambda d: {"exam_id": d["exam"].pk, "sk": 0}),
("longs:exam_markers", lambda d: {"pk": d["exam"].pk}),
("longs:exam_groups_edit", lambda d: {"pk": d["exam"].pk}),
("longs:exam_authors", lambda d: {"pk": d["exam"].pk}),
("longs:refresh_exam_question_json", lambda d: {"pk": d["exam"].pk}),
("longs:exam_create", None),
("longs:exam_clone", lambda d: {"exam_id": d["exam"].pk}),
("longs:exam_update", lambda d: {"pk": d["exam"].pk}),
("longs:exam_delete", lambda d: {"pk": d["exam"].pk}),
("longs:question_create", None),
("longs:series_create", None),
("longs:long_series_id_create", lambda d: {"pk": d["question"].pk}),
("longs:create_examination", None),
("longs:long_update", lambda d: {"pk": d["question"].pk}),
("longs:long_series_update", lambda d: {"pk": d["series"].pk}),
("longs:user_answer_table_view", None),
("longs:user_answer_view", lambda d: {"pk": d["user_answer"].pk}),
("longs:user_answer_delete", lambda d: {"pk": d["user_answer"].pk}),
("longs:user_answer_delete_multiple", None),
("longs:index", None),
("longs: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"
+9 -41
View File
@@ -99,7 +99,7 @@ from zipview.views import BaseZipView
import os
logger = logging.getLogger(__name__)
def normaliseScore(score):
@@ -176,46 +176,14 @@ def series_detail(request, pk):
@login_required
@user_is_author_or_long_checker
def long_split(request, pk):
long = get_object_or_404(Long, pk=pk)
images = long.images.all()
old_abnormality = long.abnormality.all()
old_region = long.region.all()
old_examination = long.examination.all()
old_site = long.site.all()
old_author = long.author.all()
if not images:
raise Http404
for n in range(len(images) - 1):
long.pk = None
long.save()
long.abnormality.set(old_abnormality)
long.region.set(old_region)
long.examination.set(old_examination)
long.site.set(old_site)
long.author.set(old_author)
images[n].long = long
images[n].save()
# images[-1].long
# if request.user not in long.author.all():
# raise PermissionDenied
# logging.debug(long.subspecialty.first().name.all())
return render(request, "longs/question_detail.html", {"question": long})
raise Http404("Long cases do not support direct image splitting.")
@login_required
@user_is_author_or_long_checker
def author_detail(request, pk):
# logging.debug(Author.objects.all())
# author = get_object_or_404(Author, pk=pk)
if not (request.user.pk == pk or request.user.groups.filter(name='long_checker').exists() or request.user.is_superuser):
raise PermissionDenied
author = User.objects.get(pk=pk)
longs = Long.objects.filter(author=pk)
@@ -225,7 +193,7 @@ def author_detail(request, pk):
)
@user_is_author_or_long_checker
@user_is_long_checker
def author_list(request):
authors = User.objects.all()
@@ -649,8 +617,8 @@ class LongSeriesView(LoginRequiredMixin, SingleTableMixin, FilterView):
# @user_is_long_marker
def mark_answer_override(request, exam_id, question_number, cid):
return mark_answer(request, exam_id, question_number, cid, override=True)
def mark_answer_override(request, exam_id, question_number, answer_id):
return mark_answer(request, exam_id, question_number, answer_id, override=True)
# @user_is_long_marker
@@ -1075,14 +1043,14 @@ class UserAnswerDelete(SuperuserRequiredMixin, DeleteView):
@user_passes_test(lambda u: u.is_superuser)
def user_answer_delete_multiple(request):
if request.accepts("application/json")():
if request.accepts("application/json") and request.method == "POST" and "answer_ids" in request.POST:
answer_ids = json.loads(request.POST["answer_ids"])
# We could probably delete them all at once....
for id in answer_ids:
UserAnswer.objects.get(pk=id).delete()
return JsonResponse({"status": "success"})
return JsonResponse({"status": "error"})
return JsonResponse({"status": "error"}, status=400)
@user_passes_test(lambda u: u.is_superuser)