smoke test the rest of the apps
This commit is contained in:
+20
-15
@@ -971,26 +971,21 @@ class ExamOrCollectionGenericBase(models.Model, AuthorMixin):
|
||||
|
||||
|
||||
def clone_model(self):
|
||||
M2M_fields = (
|
||||
"exam_questions",
|
||||
"author",
|
||||
"valid_cid_users",
|
||||
"valid_user_users",
|
||||
"cid_user_groups",
|
||||
"user_user_groups",
|
||||
)
|
||||
m2m_fields = [f.name for f in self._meta.many_to_many]
|
||||
FK_fields = ("examcollection",)
|
||||
|
||||
model_dict = model_to_dict(self)
|
||||
|
||||
m2m_to_update = {}
|
||||
for field in M2M_fields:
|
||||
m2m_to_update[field] = model_dict[field]
|
||||
del model_dict[field]
|
||||
for field in m2m_fields:
|
||||
if field in model_dict:
|
||||
m2m_to_update[field] = model_dict[field]
|
||||
del model_dict[field]
|
||||
fk_to_update = {}
|
||||
for field in FK_fields:
|
||||
fk_to_update[field] = model_dict[field]
|
||||
del model_dict[field]
|
||||
if field in model_dict:
|
||||
fk_to_update[field] = model_dict[field]
|
||||
del model_dict[field]
|
||||
|
||||
cloned_model = self.__class__(**model_dict)
|
||||
cloned_model.pk = None
|
||||
@@ -2381,7 +2376,17 @@ class FindingBase(models.Model):
|
||||
return json.dumps(self.annotation_json)
|
||||
|
||||
def get_pretty_annotation_json(self):
|
||||
return get_pretty_json(json.loads(self.annotation_json))
|
||||
if not self.annotation_json:
|
||||
return ""
|
||||
try:
|
||||
return get_pretty_json(json.loads(self.annotation_json))
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
def get_pretty_viewport_json(self):
|
||||
return get_pretty_json(json.loads(self.viewport_json))
|
||||
if not self.viewport_json:
|
||||
return ""
|
||||
try:
|
||||
return get_pretty_json(json.loads(self.viewport_json))
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container my-5">
|
||||
<div class="card bg-dark text-white border-secondary">
|
||||
<div class="card-body">
|
||||
<h1 class="card-title mb-4">{{ app_name|title }} Help</h1>
|
||||
<p class="card-text">Welcome to the radiology education platform. There is no custom help document for the <strong>{{ app_name }}</strong> application yet.</p>
|
||||
<hr class="border-secondary my-4">
|
||||
<a href="javascript:history.back()" class="btn btn-secondary">Go Back</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,117 @@
|
||||
import pytest
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.models import Group, User
|
||||
from django.test import Client
|
||||
from generic.models import Examination, Supervisor, CidUserGroup, UserUserGroup, CidUser
|
||||
|
||||
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 cid_manager_client(db):
|
||||
user = User.objects.create_user(username="manager", password="password", email="manager@test.com")
|
||||
g, _ = Group.objects.get_or_create(name="cid_user_manager")
|
||||
user.groups.add(g)
|
||||
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")
|
||||
g, _ = Group.objects.get_or_create(name="cid_user_manager")
|
||||
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, create_user, create_examination):
|
||||
supervisor = Supervisor.objects.create(
|
||||
email="sup@test.com",
|
||||
name="Test Supervisor",
|
||||
user=create_user
|
||||
)
|
||||
cid_group = CidUserGroup.objects.create(name="Cid Group")
|
||||
user_group = UserUserGroup.objects.create(name="User Group")
|
||||
cid_user = CidUser.objects.create(cid=99999, name="Test Cid User", email="cid@test.com", passcode="smokepasscode")
|
||||
|
||||
return {
|
||||
"examination": create_examination,
|
||||
"supervisor": supervisor,
|
||||
"cid_group": cid_group,
|
||||
"user_group": user_group,
|
||||
"cid_user": cid_user,
|
||||
}
|
||||
|
||||
URL_SPECS = [
|
||||
("generic:examination_view", None),
|
||||
("generic:create_examination", None),
|
||||
("generic:examination_detail", lambda d: {"pk": d["examination"].pk}),
|
||||
("generic:examination_update", lambda d: {"pk": d["examination"].pk}),
|
||||
("generic:examination_delete", lambda d: {"pk": d["examination"].pk}),
|
||||
("generic:supervisor", None),
|
||||
("generic:supervisor_create", None),
|
||||
("generic:supervisor_detail", lambda d: {"pk": d["supervisor"].pk}),
|
||||
("generic:supervisor_edit", lambda d: {"pk": d["supervisor"].pk}),
|
||||
("generic:supervisor_delete", lambda d: {"pk": d["supervisor"].pk}),
|
||||
("generic:supervisor_overview", lambda d: {"pk": d["supervisor"].pk}),
|
||||
("generic:manage_cids", None),
|
||||
("generic:manage_cid_exams", None),
|
||||
("generic:cid_group_view", None),
|
||||
("generic:cid_group_create", None),
|
||||
("generic:cid_group_detail", lambda d: {"group_id": d["cid_group"].pk}),
|
||||
("generic:cid_group_update", lambda d: {"pk": d["cid_group"].pk}),
|
||||
("generic:cid_group_delete", lambda d: {"pk": d["cid_group"].pk}),
|
||||
("generic:user_group_view", None),
|
||||
("generic:user_group_create", None),
|
||||
("generic:user_group_detail", lambda d: {"group_id": d["user_group"].pk}),
|
||||
("generic:user_group_update", lambda d: {"pk": d["user_group"].pk}),
|
||||
("generic:user_group_delete", lambda d: {"pk": d["user_group"].pk}),
|
||||
]
|
||||
|
||||
@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, 403, 404}, 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, 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_manager(cid_manager_client, smoke_data, url_name, kwargs_lambda):
|
||||
kwargs = kwargs_lambda(smoke_data) if kwargs_lambda else None
|
||||
url = reverse(url_name, kwargs=kwargs)
|
||||
response = cid_manager_client.get(url, follow=False)
|
||||
assert response.status_code != 500, f"500 Server Error on {url_name} ({url}) for Manager"
|
||||
assert response.status_code in SAFE_STATUS_CODES, f"Unexpected status code {response.status_code} on {url_name} for Manager"
|
||||
|
||||
@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}, f"Unexpected status code {response.status_code} on {url_name} for Superuser"
|
||||
+11
-3
@@ -4085,7 +4085,13 @@ class GenericViewBase:
|
||||
return False
|
||||
|
||||
def help(self, request):
|
||||
return render(request, f"{self.app_name}/help.html", {"app_name": self.app_name})
|
||||
from django.template.loader import TemplateDoesNotExist, get_template
|
||||
try:
|
||||
get_template(f"{self.app_name}/help.html")
|
||||
template_name = f"{self.app_name}/help.html"
|
||||
except TemplateDoesNotExist:
|
||||
template_name = "generic/help.html"
|
||||
return render(request, template_name, {"app_name": self.app_name})
|
||||
|
||||
def question_review(self, request, pk):
|
||||
"""
|
||||
@@ -6456,6 +6462,7 @@ class UpdateQuestionMixin(RedirectMixin, RevisionMixin, UpdateView):
|
||||
raise PermissionDenied() # or Http404
|
||||
|
||||
|
||||
@login_required
|
||||
def supervisor_overview(request, pk):
|
||||
supervisor = get_object_or_404(Supervisor, pk=pk)
|
||||
|
||||
@@ -6463,7 +6470,7 @@ def supervisor_overview(request, pk):
|
||||
try:
|
||||
if not request.user.supervisor == supervisor:
|
||||
raise PermissionDenied()
|
||||
except Supervisor.RelatedObjectDoesNotExist:
|
||||
except User.supervisor.RelatedObjectDoesNotExist:
|
||||
raise PermissionDenied()
|
||||
|
||||
trainees = User.objects.filter(userprofile__supervisor=supervisor)
|
||||
@@ -6475,6 +6482,7 @@ def supervisor_overview(request, pk):
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def supervisor_trainee(request, pk, trainee_id):
|
||||
supervisor = get_object_or_404(Supervisor, pk=pk)
|
||||
|
||||
@@ -6482,7 +6490,7 @@ def supervisor_trainee(request, pk, trainee_id):
|
||||
try:
|
||||
if not request.user.supervisor == supervisor:
|
||||
raise PermissionDenied()
|
||||
except Supervisor.RelatedObjectDoesNotExist:
|
||||
except User.supervisor.RelatedObjectDoesNotExist:
|
||||
raise PermissionDenied()
|
||||
|
||||
# We do this to check that the supervisor can (should) see the trainee results
|
||||
|
||||
+14
-1
@@ -21,7 +21,20 @@ class UserSearchSelectMultipleWidget:
|
||||
|
||||
def __init__(self, name, value):
|
||||
self.name = name
|
||||
self.value = value or []
|
||||
if value is None:
|
||||
self.value = []
|
||||
elif hasattr(value, "values_list"):
|
||||
self.value = list(value.values_list("pk", flat=True))
|
||||
elif isinstance(value, (list, tuple, set)):
|
||||
self.value = [v.pk if hasattr(v, "pk") else v for v in value]
|
||||
elif hasattr(value, "pk"):
|
||||
self.value = [value.pk]
|
||||
elif isinstance(value, (int, str)):
|
||||
self.value = [value]
|
||||
elif hasattr(value, "__iter__") and not isinstance(value, (str, bytes)):
|
||||
self.value = [v.pk if hasattr(v, "pk") else v for v in value]
|
||||
else:
|
||||
self.value = [value]
|
||||
|
||||
def render(self):
|
||||
field_id = f"id_{self.name}"
|
||||
|
||||
Reference in New Issue
Block a user