import json import datetime from django.http import HttpResponse from django.urls import reverse import pytest from atlas.models import Case, CaseCollection, Finding, Condition #from atlas.views import GenericExamViews from pytest_django.asserts import assertRedirects, assertContains, assertQuerySetEqual from django.test import TestCase #@pytest.mark.django_db def test_create_condition(db): abnormality = Condition.objects.create(name="Abnorm") assert abnormality.name == "Abnorm" def test_condition_tree_structure(db): parent = Condition.objects.create(name="parent") child1 = Condition.objects.create(name="child1") child2 = Condition.objects.create(name="child2") parent.child.set([child1, child2]) child1_1 = Condition.objects.create(name="child1_1") child1_2 = Condition.objects.create(name="child1_2") child1.child.set([child1_1, child1_2]) assert len(parent.get_children()) == 2 assert len(child1.get_children()) == 2 assert len(child1.get_parents()) == 1 assert parent in child1.get_parents() assert len(child2.get_parents()) == 1 assert parent in child2.get_parents() #@pytest.fixture #def create_basic_user(db, django_user_model): # return django_user_model.objects.create_superuser("basicuser", "ross@xkjq.uk", "password") # #@pytest.fixture #def create_exam(db): # return Exam.objects.create(name="test exam", exam_mode=True) # #def test_exam_creation(create_exam): # exams = Exam.objects.filter(name="test exam") # assert exams.exists() # # exam = exams.first() # # assert exam.time_limit == 35 * 60 # #def test_exam_list(rf, admin_user, create_exam): # request = rf.get('/rapids/exam/') # # Remember that when using RequestFactory, the request does not pass # # through middleware. If your view expects fields such as request.user to be # # set, you need to set them explicitly. # # The following line sets request.user to an admin user. # request.user = admin_user # response = GenericExamViews.exam_list(request) # #print(response) # assert response.status_code == 200 # #def test_exam_active_admin(rf, admin_user, create_exam, client): # request = rf.get(reverse('rapids:active_exams')) # request.user = admin_user # response = GenericExamViews.active_exams(request) # print(response.content) # assert response.status_code == 200 # #def test_exam_active_basic_user(create_basic_user, create_exam, client): # client.login(username="basicuser", password="password") # response = client.get(reverse('rapids:active_exams')) # print(response.content) # assert response.status_code == 200 def test_create_case(db, create_case): case = create_case assert case.title == "Sample Case" def test_create_series(db, create_series): series = create_series assert series def test_collection(db, create_case_collection, create_case, make_case, client, create_user): collection: CaseCollection = create_case_collection # create some cases case1 = create_case case2 = make_case() case3 = make_case(title="Case 3") case4 = make_case(title="Case 4") collection.cases.set([case1, case2, case3, case4]) case5 = make_case(title="Case 5") assert collection.cases.all().count() == 4 collection.add_case(case5) assert collection.cases.all().count() == 5 assert collection.get_case_by_index(0) == case1 assert collection.get_case_by_index(1) == case2 assert collection.get_case_by_index(2) == case3 assert collection.get_case_by_index(3) == case4 assert collection.get_case_by_index(4) == case5 assert collection.get_absolute_url() == reverse("atlas:collection_detail", kwargs={"pk": collection.pk}) assert collection.get_take_url() == reverse("atlas:collection_take_start", kwargs={"pk": collection.pk}) start_order = collection.get_cases() new_order = [ case5.pk, case1.pk, case2.pk, case3.pk, case4.pk ] response: HttpResponse = client.post(reverse("atlas:exam_json_edit", kwargs={"pk":collection.pk} ), json=new_order, follow=True) # Check that sorting the exam works # First attempt is not logged in from urllib.parse import quote expected_next = quote(reverse("atlas:exam_json_edit", kwargs={"pk": collection.pk})) assertRedirects(response, f"{reverse('login')}?next={expected_next}") client.force_login(create_user) # Random user cannot modify order response: HttpResponse = client.post(reverse("atlas:exam_json_edit", kwargs={"pk":collection.pk} ), json=new_order, follow=True) assert response.status_code == 403 assertQuerySetEqual(start_order , collection.get_cases()) # Once the user has been made an author, they can modify the order collection.add_author(create_user) response: HttpResponse = client.post(reverse("atlas:exam_json_edit", kwargs={"pk":collection.pk} ), data={"set_exam_order" : json.dumps(new_order)}, follow=True) assert response.status_code == 200 assert collection.get_cases().count() == 5 assert collection.get_case_by_index(0) == case5 assert collection.get_case_by_index(1) == case1 @pytest.mark.django_db def test_linked_cases_overview_can_copy_study_date_to_chain(client, create_user, make_case): user = create_user case1 = make_case(title="Case 1") case2 = make_case(title="Case 2") case2.previous_case = case1 case2.save(update_fields=["previous_case"]) case1.author.add(user) case2.author.add(user) client.force_login(user) response = client.post( reverse("atlas:linked_cases_overview", kwargs={"case_id": case1.pk}), data={ f"study_date_{case1.pk}": "2026-01-10", f"study_date_{case2.pk}": "2026-01-12", "apply_to_all_from": str(case1.pk), }, follow=True, ) assert response.status_code == 200 case1.refresh_from_db() case2.refresh_from_db() assert str(case1.study_date) == "2026-01-10" assert str(case2.study_date) == "2026-01-10" @pytest.mark.django_db def test_case_save_auto_populates_study_date_when_missing(monkeypatch, make_case): expected_date = datetime.date(2026, 2, 14) monkeypatch.setattr(Case, "_get_series_study_date", lambda self: expected_date) case = make_case(title="Autodate Case") case.study_date = None case.save(update_fields=["study_date"]) case.refresh_from_db() assert case.study_date == expected_date @pytest.mark.django_db def test_case_save_preserves_manual_study_date(monkeypatch, make_case): manual_date = datetime.date(2026, 3, 1) monkeypatch.setattr(Case, "_get_series_study_date", lambda self: datetime.date(2026, 4, 1)) case = make_case(title="Manual Date Case") case.study_date = manual_date case.save(update_fields=["study_date"]) case.refresh_from_db() assert case.study_date == manual_date @pytest.mark.django_db def test_linked_cases_editor_is_hidden_until_requested(client, create_user, make_case): user = create_user case1 = make_case(title="Case 1") case2 = make_case(title="Case 2") case2.previous_case = case1 case2.save(update_fields=["previous_case"]) case1.author.add(user) case2.author.add(user) client.force_login(user) response_default = client.get( reverse("atlas:linked_cases_overview", kwargs={"case_id": case1.pk}) ) assert response_default.status_code == 200 assertContains(response_default, "Open case series editor") assert "Case Series Editor" not in response_default.content.decode("utf-8") response_with_editor = client.get( reverse("atlas:linked_cases_overview", kwargs={"case_id": case1.pk}) + "?show_editor=1" ) assert response_with_editor.status_code == 200 assertContains(response_with_editor, "Case Series Editor") @pytest.mark.django_db def test_linked_cases_study_dates_editor_is_hidden_until_requested(client, create_user, make_case): user = create_user case1 = make_case(title="Case 1") case2 = make_case(title="Case 2") case2.previous_case = case1 case2.save(update_fields=["previous_case"]) case1.author.add(user) case2.author.add(user) client.force_login(user) response_default = client.get( reverse("atlas:linked_cases_overview", kwargs={"case_id": case1.pk}) ) assert response_default.status_code == 200 assertContains(response_default, "Open study dates editor") assert "Study Dates" not in response_default.content.decode("utf-8") response_with_editor = client.get( reverse("atlas:linked_cases_overview", kwargs={"case_id": case1.pk}) + "?show_dates=1" ) assert response_with_editor.status_code == 200 assertContains(response_with_editor, "Study Dates") @pytest.mark.django_db def test_linked_case_card_shows_scaled_relative_timeline_label(client, create_user, make_case): user = create_user case1 = make_case(title="Case 1") case2 = make_case(title="Case 2") case2.previous_case = case1 case2.study_date = datetime.date(2028, 1, 1) case2.save(update_fields=["previous_case", "study_date"]) case1.study_date = datetime.date(2026, 1, 1) case1.save(update_fields=["study_date"]) case1.author.add(user) case2.author.add(user) client.force_login(user) response = client.get( reverse("atlas:linked_cases_overview", kwargs={"case_id": case1.pk}) ) assert response.status_code == 200 assertContains(response, "Timeline +2 years")