def test_user_upload_to_display_set_without_interface(client, settings): # Override the celery settings settings.task_eager_propagates = (True, ) settings.task_always_eager = (True, ) user = UserFactory() rs = ReaderStudyFactory(use_display_sets=False) rs.add_editor(user=user) ci = ComponentInterface.objects.filter(slug="generic-overlay").get() civ = ComponentInterfaceValueFactory(interface=ci) ds = DisplaySetFactory(reader_study=rs) ds.values.add(civ) assert ds.values.count() == 1 upload = create_upload_from_file( file_path=Path(__file__).parent / "resources" / "image10x10x10.mha", creator=user, ) with capture_on_commit_callbacks(execute=True): response = get_view_for_user( viewname="api:upload-session-list", user=user, client=client, method=client.post, content_type="application/json", data={ "uploads": [upload.api_url], "display_set": ds.pk }, HTTP_X_FORWARDED_PROTO="https", ) assert response.status_code == 400 assert ("An interface needs to be defined to upload to a display set." in response.json()["non_field_errors"])
def test_assert_modification_allowed(): rs = ReaderStudyFactory(use_display_sets=False) ci = ComponentInterfaceFactory( kind=InterfaceKind.InterfaceKindChoices.BOOL) civ = ComponentInterfaceValueFactory(interface=ci, value=True) ds = DisplaySetFactory(reader_study=rs) ds.values.add(civ) del ds.is_editable civ2 = ComponentInterfaceValueFactory(interface=ci, value=True) ds.values.remove(civ) ds.values.add(civ2) assert ds.values.count() == 1 assert ds.values.first() == civ2 q = QuestionFactory(reader_study=rs) AnswerFactory(question=q, display_set=ds) del ds.is_editable with pytest.raises(ValidationError): with transaction.atomic(): ds.values.remove(civ2) assert ds.values.count() == 1 assert ds.values.first() == civ2
def test_reader_study_add_ground_truth_ds(client, settings): settings.task_eager_propagates = (True,) settings.task_always_eager = (True,) rs = ReaderStudyFactory(use_display_sets=True) QuestionFactory( reader_study=rs, question_text="bar", answer_type=Question.AnswerType.SINGLE_LINE_TEXT, ) civ = ComponentInterfaceValueFactory(image=ImageFactory()) ds = DisplaySetFactory(reader_study=rs) ds.values.add(civ) editor = UserFactory() rs.editors_group.user_set.add(editor) gt = io.StringIO() fake_writer = csv.writer(gt) fake_writer.writerows([["images", "foo"], [str(ds.pk), "bar"]]) gt.seek(0) response = get_view_for_user( viewname="reader-studies:add-ground-truth", client=client, method=client.post, reverse_kwargs={"slug": rs.slug}, data={"ground_truth": gt}, follow=True, user=editor, ) assert response.status_code == 200
def test_display_set_order(): rs = ReaderStudyFactory(use_display_sets=False) ds = DisplaySetFactory(reader_study=rs) assert ds.order == 10 ds = DisplaySetFactory(reader_study=rs) assert ds.order == 20 ds.order = 15 ds.save() ds = DisplaySetFactory(reader_study=rs) assert ds.order == 20
def test_changing_reader_study_updates_permissions(): ds = DisplaySetFactory() im = ImageFactory() civ = ComponentInterfaceValueFactory(image=im) with capture_on_commit_callbacks(execute=True): ds.values.set([civ]) assert get_groups_with_set_perms(im) == { ds.reader_study.editors_group: {"view_image"}, ds.reader_study.readers_group: {"view_image"}, } rs = ReaderStudyFactory(use_display_sets=False) ds.reader_study = rs with capture_on_commit_callbacks(execute=True): ds.save() assert get_groups_with_set_perms(im) == { rs.editors_group: {"view_image"}, rs.readers_group: {"view_image"}, }
def test_display_set_permissions_signal(client, reverse): ds1, ds2 = DisplaySetFactory.create_batch(2) im1, im2, im3, im4 = ImageFactory.create_batch(4) civ1, civ2, civ3, civ4 = ( ComponentInterfaceValueFactory(image=im1), ComponentInterfaceValueFactory(image=im2), ComponentInterfaceValueFactory(image=im3), ComponentInterfaceValueFactory(image=im4), ) with capture_on_commit_callbacks(execute=True): if reverse: for civ in [civ1, civ2, civ3, civ4]: civ.display_sets.add(ds1, ds2) for civ in [civ3, civ4]: civ.display_sets.remove(ds1, ds2) for civ in [civ1, civ2]: civ.display_sets.remove(ds2) else: # Test that adding images works ds1.values.add(civ1, civ2, civ3, civ4) # Test that removing images works ds1.values.remove(civ3, civ4) assert get_groups_with_set_perms(im1) == { ds1.reader_study.editors_group: {"view_image"}, ds1.reader_study.readers_group: {"view_image"}, } assert get_groups_with_set_perms(im2) == { ds1.reader_study.editors_group: {"view_image"}, ds1.reader_study.readers_group: {"view_image"}, } assert get_groups_with_set_perms(im3) == {} assert get_groups_with_set_perms(im4) == {} # Test clearing with capture_on_commit_callbacks(execute=True): if reverse: civ1.display_sets.clear() civ2.display_sets.clear() else: ds1.values.clear() assert get_groups_with_set_perms(im1) == {} assert get_groups_with_set_perms(im2) == {}
def test_display_set_description(): rs = ReaderStudyFactory() reader = UserFactory() rs.add_reader(reader) images = [ImageFactory() for _ in range(6)] ci = ComponentInterface.objects.get(slug="generic-medical-image") result = {} for image in images: ds = DisplaySetFactory(reader_study=rs) result[ds.pk] = f"<p>{str(image.pk)}</p>" civ = ComponentInterfaceValueFactory(interface=ci, image=image) ds.values.add(civ) rs.case_text = {im.name: str(im.pk) for im in images} rs.case_text["no_image"] = "not an image" rs.save() for ds in rs.display_sets.all(): assert ds.description == result[ds.pk]
def test_deleting_display_set_removes_permissions(): ds1, ds2 = DisplaySetFactory.create_batch(2) im = ImageFactory() civ = ComponentInterfaceValueFactory(image=im) with capture_on_commit_callbacks(execute=True): ds1.values.set([civ]) ds2.values.set([civ]) assert get_groups_with_set_perms(im) == { ds1.reader_study.editors_group: {"view_image"}, ds1.reader_study.readers_group: {"view_image"}, ds2.reader_study.editors_group: {"view_image"}, ds2.reader_study.readers_group: {"view_image"}, } with capture_on_commit_callbacks(execute=True): ds1.delete() assert get_groups_with_set_perms(im) == { ds2.reader_study.editors_group: {"view_image"}, ds2.reader_study.readers_group: {"view_image"}, }
def test_reader_study_display_set_list(client): user = UserFactory() rs = ReaderStudyFactory(use_display_sets=True) rs.add_editor(user) civ = ComponentInterfaceValueFactory(image=ImageFactory()) ds = DisplaySetFactory(reader_study=rs) ds.values.add(civ) response = get_view_for_user( viewname="reader-studies:display_sets", reverse_kwargs={"slug": rs.slug}, client=client, user=user, ) assert response.status_code == 200 response = get_view_for_user( viewname="reader-studies:display_sets", reverse_kwargs={"slug": rs.slug}, client=client, user=user, method=client.get, follow=True, data={ "length": 10, "draw": 1, "order[0][dir]": "desc", "order[0][column]": 0, }, **{"HTTP_X_REQUESTED_WITH": "XMLHttpRequest"}, ) resp = response.json() assert str(ds.pk) in resp["data"][0][0]
def test_progress_for_user(settings, use_display_sets): # noqa: C901 settings.task_eager_propagates = (True, ) settings.task_always_eager = (True, ) rs = ReaderStudyFactory(use_display_sets=use_display_sets) im1, im2 = ImageFactory(name="im1"), ImageFactory(name="im2") q1, q2, q3 = [ QuestionFactory(reader_study=rs), QuestionFactory(reader_study=rs), QuestionFactory(reader_study=rs), ] reader = UserFactory() rs.add_reader(reader) question_perc = 100 / 6 assert rs.get_progress_for_user(reader) == { "diff": 0.0, "hangings": 0.0, "questions": 0.0, } if use_display_sets: ci = ComponentInterface.objects.get(slug="generic-medical-image") civ1 = ComponentInterfaceValueFactory(image=im1, interface=ci) civ2 = ComponentInterfaceValueFactory(image=im2, interface=ci) ds1, ds2 = DisplaySetFactory(reader_study=rs), DisplaySetFactory( reader_study=rs) ds1.values.add(civ1) ds2.values.add(civ2) else: rs.images.set([im1, im2]) rs.hanging_list = [{"main": im1.name}, {"main": im2.name}] rs.save() progress = rs.get_progress_for_user(reader) assert progress["hangings"] == 0 assert progress["questions"] == 0 a11 = AnswerFactory(question=q1, answer="foo", creator=reader) if use_display_sets: a11.display_set = ds1 a11.save() else: a11.images.add(im1) progress = rs.get_progress_for_user(reader) assert progress["hangings"] == 0 assert progress["questions"] == pytest.approx(question_perc) a21 = AnswerFactory(question=q1, answer="foo", creator=reader) if use_display_sets: a21.display_set = ds2 a21.save() else: a21.images.add(im2) progress = rs.get_progress_for_user(reader) assert progress["hangings"] == 0 assert progress["questions"] == pytest.approx(question_perc * 2) a12 = AnswerFactory(question=q2, answer="foo", creator=reader) a13 = AnswerFactory(question=q3, answer="foo", creator=reader) if use_display_sets: a12.display_set = ds1 a12.save() a13.display_set = ds1 a13.save() else: a12.images.add(im1) a13.images.add(im1) progress = rs.get_progress_for_user(reader) assert progress["hangings"] == 50 assert progress["questions"] == pytest.approx(question_perc * 4) editor = UserFactory() rs.add_reader(editor) rs.add_editor(editor) for q in [q1, q2, q3]: if use_display_sets: for ds in [ds1, ds2]: a = AnswerFactory( question=q, answer="foo", creator=editor, is_ground_truth=True, display_set=ds, ) else: for im in [im1, im2]: a = AnswerFactory( question=q, answer="foo", creator=editor, is_ground_truth=True, ) a.images.add(im) progress = rs.get_progress_for_user(editor) assert progress["hangings"] == 0 assert progress["questions"] == 0 for q in [q1, q2, q3]: if use_display_sets: for ds in [ds1, ds2]: a = AnswerFactory( question=q, answer="foo", creator=editor, is_ground_truth=False, display_set=ds, ) else: for im in [im1, im2]: a = AnswerFactory( question=q, answer="foo", creator=editor, is_ground_truth=False, ) a.images.add(im) progress = rs.get_progress_for_user(editor) assert progress["hangings"] == 100.0 assert progress["questions"] == 100.0