def test_page_delete(client, TwoChallengeSets): # Two pages with the same title, make sure the right one is deleted c1p1 = PageFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, title="page1" ) c2p1 = PageFactory( challenge=TwoChallengeSets.ChallengeSet2.challenge, title="page1" ) assert Page.objects.filter(pk=c1p1.pk).exists() assert Page.objects.filter(pk=c2p1.pk).exists() response = get_view_for_user( viewname="pages:delete", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": "page1"}, ) assert response.status_code == 302 assert not Page.objects.filter(pk=c1p1.pk).exists() assert Page.objects.filter(pk=c2p1.pk).exists() response = get_view_for_user( url=response.url, client=client, user=TwoChallengeSets.admin12 ) assert response.status_code == 200
def test_workstation_create_detail(client): user = UserFactory(is_staff=True) title = "my Workstation" description = "my AWESOME workstation" response = get_view_for_user( client=client, viewname="workstations:create", user=user ) assert response.status_code == 200 response = get_view_for_user( client=client, method=client.post, viewname="workstations:create", user=user, data={ "title": title, "description": description, "logo": get_temporary_image(), }, ) assert response.status_code == 302 assert response.url == reverse( "workstations:detail", kwargs={"slug": slugify(title)} ) w = Workstation.objects.get(title=title) assert w.title == title assert w.description == description response = get_view_for_user(url=response.url, client=client, user=user) assert title in response.rendered_content assert description in response.rendered_content
def test_setting_submission_page_html(client, ChallengeSet): custom_html = "<p>My custom html</p>" response = get_view_for_user( client=client, user=ChallengeSet.participant, viewname="evaluation:submission-create", challenge=ChallengeSet.challenge, ) assert response.status_code == 200 assert custom_html not in response.rendered_content ChallengeSet.challenge.evaluation_config.submission_page_html = custom_html ChallengeSet.challenge.evaluation_config.save() response = get_view_for_user( client=client, user=ChallengeSet.participant, viewname="evaluation:submission-create", challenge=ChallengeSet.challenge, ) assert response.status_code == 200 assert custom_html in response.rendered_content
def test_duplicate_registration_denied(client, TwoChallengeSets): user = UserFactory() assert not RegistrationRequest.objects.filter( user=user, challenge=TwoChallengeSets.ChallengeSet1.challenge ).exists() rr = RegistrationRequestFactory( user=user, challenge=TwoChallengeSets.ChallengeSet1.challenge ) assert RegistrationRequest.objects.filter( user=user, challenge=TwoChallengeSets.ChallengeSet1.challenge ).exists() response = get_view_for_user( viewname="participants:registration-create", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=user, ) assert response.status_code == 200 assert rr.status_to_string() in response.rendered_content # Creating a request in another challenge should work assert not RegistrationRequest.objects.filter( user=user, challenge=TwoChallengeSets.ChallengeSet2.challenge ).exists() response = get_view_for_user( viewname="participants:registration-create", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet2.challenge, user=user, ) assert response.status_code == 302 assert RegistrationRequest.objects.filter( user=user, challenge=TwoChallengeSets.ChallengeSet2.challenge ).exists()
def test_external_challenge_buttons(client): create_url = reverse("challenges:external-create") list_url = reverse("challenges:external-list") response = get_view_for_user(client=client, viewname="challenges:list") assert create_url not in response.rendered_content assert list_url not in response.rendered_content user = UserFactory() response = get_view_for_user( client=client, viewname="challenges:list", user=user ) assert create_url not in response.rendered_content assert list_url not in response.rendered_content staff_user = UserFactory(is_staff=True) response = get_view_for_user( client=client, viewname="challenges:list", user=staff_user ) assert create_url in response.rendered_content assert list_url in response.rendered_content
def test_workstation_proxy(client): u1, u2 = UserFactory(), UserFactory() session = SessionFactory(creator=u1) url = reverse( "workstations:session-proxy", kwargs={ "slug": session.workstation_image.workstation.slug, "pk": session.pk, "path": "foo/bar/../baz/test", }, ) response = get_view_for_user(client=client, url=url, user=u1) assert response.status_code == 200 assert response.has_header("X-Accel-Redirect") redirect_url = response.get("X-Accel-Redirect") assert redirect_url.endswith("foo/baz/test") assert redirect_url.startswith("/workstation-proxy/") assert session.hostname in redirect_url # try as another user response = get_view_for_user(client=client, url=url, user=u2) assert not response.has_header("X-Accel-Redirect") assert response.status_code == 403
def test_page_create(client, TwoChallengeSets): page_html = "<h1>HELLO WORLD</h1>" page_title = "testpage1" response = get_view_for_user( viewname="pages:create", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.ChallengeSet1.admin, data={ "title": page_title, "html": page_html, "permission_lvl": Page.ALL, }, ) assert response.status_code == 302 response = get_view_for_user(url=response.url, client=client) assert response.status_code == 200 assert page_html in str(response.content) # Check that it was created in the correct challenge response = get_view_for_user( viewname="pages:detail", client=client, challenge=TwoChallengeSets.ChallengeSet1.challenge, reverse_kwargs={"page_title": page_title}, ) assert response.status_code == 200 response = get_view_for_user( viewname="pages:detail", client=client, challenge=TwoChallengeSets.ChallengeSet2.challenge, reverse_kwargs={"page_title": page_title}, ) assert response.status_code == 404
def test_page_list_filter(client, TwoChallengeSets): """ Check that only pages related to this challenge are listed """ p1 = PageFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, title="challenge1page1", ) p2 = PageFactory( challenge=TwoChallengeSets.ChallengeSet2.challenge, title="challenge2page1", ) response = get_view_for_user( viewname="pages:list", client=client, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, ) assert p1.title in response.rendered_content assert p2.title not in response.rendered_content response = get_view_for_user( viewname="pages:list", client=client, challenge=TwoChallengeSets.ChallengeSet2.challenge, user=TwoChallengeSets.admin12, ) assert p1.title not in response.rendered_content assert p2.title in response.rendered_content
def test_image_response(client): image_file = ImageFileFactory() response = get_view_for_user( url=image_file.file.url, client=client, user=None ) # Forbidden view assert response.status_code == 404 assert not response.has_header("x-accel-redirect") staff_user = UserFactory(is_staff=True) response = get_view_for_user( url=image_file.file.url, client=client, user=staff_user ) assert response.status_code == 200 assert response.has_header("x-accel-redirect") redirect = response.get("x-accel-redirect") assert redirect.startswith( f"/{settings.PROTECTED_S3_STORAGE_KWARGS['bucket_name']}/" ) assert "AWSAccessKeyId" in redirect assert "Signature" in redirect assert "Expires" in redirect
def test_page_update(client, TwoChallengeSets): p1 = PageFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, title="page1updatetest", html="oldhtml", ) # page with the same name in another challenge to check selection PageFactory( challenge=TwoChallengeSets.ChallengeSet2.challenge, title="page1updatetest", html="oldhtml", ) response = get_view_for_user( viewname="pages:update", client=client, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": p1.title}, ) assert response.status_code == 200 assert 'value="page1updatetest"' in response.rendered_content response = get_view_for_user( viewname="pages:update", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": p1.title}, data={ "title": "editedtitle", "permission_lvl": Page.ALL, "html": "newhtml", }, ) assert response.status_code == 302 response = get_view_for_user( viewname="pages:detail", client=client, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": "editedtitle"}, ) assert response.status_code == 200 assert "newhtml" in str(response.content) # check that the other page is unaffected response = get_view_for_user( viewname="pages:detail", client=client, challenge=TwoChallengeSets.ChallengeSet2.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": "page1updatetest"}, ) assert response.status_code == 200 assert "oldhtml" in str(response.content)
def test_submission_download(client, TwoChallengeSets): """ Only the challenge admin should be able to download submissions """ submission = SubmissionFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, creator=TwoChallengeSets.ChallengeSet1.participant, ) tests = [ # ( # image response + annotation response not test ground truth, # user # ) (404, None), (404, TwoChallengeSets.ChallengeSet1.non_participant), (404, TwoChallengeSets.ChallengeSet1.participant), (404, TwoChallengeSets.ChallengeSet1.participant1), (200, TwoChallengeSets.ChallengeSet1.creator), (200, TwoChallengeSets.ChallengeSet1.admin), (404, TwoChallengeSets.ChallengeSet2.non_participant), (404, TwoChallengeSets.ChallengeSet2.participant), (404, TwoChallengeSets.ChallengeSet2.participant1), (404, TwoChallengeSets.ChallengeSet2.creator), (404, TwoChallengeSets.ChallengeSet2.admin), (200, TwoChallengeSets.admin12), (404, TwoChallengeSets.participant12), (200, TwoChallengeSets.admin1participant2), ] for test in tests: response = get_view_for_user( url=submission.file.url, client=client, user=test[1] ) assert response.status_code == test[0]
def test_new_registration_email(participant_review, client, ChallengeSet): user = UserFactory() ChallengeSet.challenge.require_participant_review = participant_review ChallengeSet.challenge.save() assert not RegistrationRequest.objects.filter( user=user, challenge=ChallengeSet.challenge ).exists() response = get_view_for_user( viewname="participants:registration-create", client=client, method=client.post, user=user, challenge=ChallengeSet.challenge, ) assert response.status_code == 302 assert RegistrationRequest.objects.filter( user=user, challenge=ChallengeSet.challenge ).exists() if participant_review: email = mail.outbox[-1] approval_link = reverse( "participants:registration-list", kwargs={"challenge_short_name": ChallengeSet.challenge.short_name}, ) assert ChallengeSet.admin.email in email.to assert "new participation request" in email.subject.lower() assert ChallengeSet.challenge.short_name in email.subject assert approval_link in email.alternatives[0][0] else: with pytest.raises(IndexError): # No emails if no review # noinspection PyStatementEffect mail.outbox[-1]
def test_workstationimage_update(client): user = UserFactory(is_staff=True) wsi = WorkstationImageFactory() assert wsi.initial_path != "" assert wsi.websocket_port != 1337 assert wsi.http_port != 1234 response = get_view_for_user( client=client, method=client.post, viewname="workstations:image-update", reverse_kwargs={"slug": wsi.workstation.slug, "pk": wsi.pk}, user=user, data={"initial_path": "", "websocket_port": 1337, "http_port": 1234}, ) assert response.status_code == 302 assert response.url == wsi.get_absolute_url() wsi.refresh_from_db() assert wsi.initial_path == "" assert wsi.websocket_port == 1337 assert wsi.http_port == 1234
def test_participants_list_is_filtered(client, TwoChallengeSets): response = get_view_for_user( viewname="participants:list", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.admin12, ) tests = [ (False, TwoChallengeSets.ChallengeSet1.non_participant), (True, TwoChallengeSets.ChallengeSet1.participant), (True, TwoChallengeSets.ChallengeSet1.participant1), (False, TwoChallengeSets.ChallengeSet1.creator), (False, TwoChallengeSets.ChallengeSet1.admin), (False, TwoChallengeSets.ChallengeSet2.non_participant), (False, TwoChallengeSets.ChallengeSet2.participant), (False, TwoChallengeSets.ChallengeSet2.participant1), (False, TwoChallengeSets.ChallengeSet2.creator), (False, TwoChallengeSets.ChallengeSet2.admin), # admin12 is in the response as they're loading the page (True, TwoChallengeSets.admin12), (True, TwoChallengeSets.participant12), (False, TwoChallengeSets.admin1participant2), ] for test in tests: assert (test[1].username in response.rendered_content) == test[0] assert "Participants for " in response.rendered_content
def test_challenge_list_is_filtered(client, TwoChallengeSets): c1 = TwoChallengeSets.ChallengeSet1.challenge.short_name c2 = TwoChallengeSets.ChallengeSet2.challenge.short_name tests = [ ([], [c1, c2], TwoChallengeSets.ChallengeSet1.non_participant), ([c1], [c2], TwoChallengeSets.ChallengeSet1.participant), ([c1], [c2], TwoChallengeSets.ChallengeSet1.participant1), ([c1], [c2], TwoChallengeSets.ChallengeSet1.creator), ([c1], [c2], TwoChallengeSets.ChallengeSet1.admin), ([], [c1, c2], TwoChallengeSets.ChallengeSet2.non_participant), ([c2], [c1], TwoChallengeSets.ChallengeSet2.participant), ([c2], [c1], TwoChallengeSets.ChallengeSet2.participant1), ([c2], [c1], TwoChallengeSets.ChallengeSet2.creator), ([c2], [c1], TwoChallengeSets.ChallengeSet2.admin), ([c1, c2], [], TwoChallengeSets.admin12), ([c1, c2], [], TwoChallengeSets.participant12), ([c1, c2], [], TwoChallengeSets.admin1participant2), ] for test in tests: response = get_view_for_user( url=reverse("challenges:users-list"), client=client, user=test[2] ) for short_name in test[0]: assert short_name in response.rendered_content for short_name in test[1]: assert short_name not in response.rendered_content
def get_submission_view(): return get_view_for_user( viewname="evaluation:submission-create", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.ChallengeSet1.participant, )
def test_admins_remove(client, TwoChallengeSets): assert TwoChallengeSets.ChallengeSet1.challenge.is_admin( user=TwoChallengeSets.admin12 ) assert TwoChallengeSets.ChallengeSet2.challenge.is_admin( user=TwoChallengeSets.admin12 ) response = get_view_for_user( viewname="admins:update", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, data={ "user": TwoChallengeSets.admin12.pk, "action": AdminsForm.REMOVE, }, user=TwoChallengeSets.ChallengeSet1.admin, ) assert response.status_code == 302 assert not TwoChallengeSets.ChallengeSet1.challenge.is_admin( user=TwoChallengeSets.admin12 ) assert TwoChallengeSets.ChallengeSet2.challenge.is_admin( user=TwoChallengeSets.admin12 )
def test_session_create(client): user = UserFactory(is_staff=True) ws = WorkstationFactory() # Create some workstations and pretend that they're ready wsi_old = WorkstationImageFactory(workstation=ws, ready=True) wsi_new = WorkstationImageFactory(workstation=ws, ready=True) wsi_not_ready = WorkstationImageFactory(workstation=ws) wsi_other_ws = WorkstationImageFactory(ready=True) assert Session.objects.count() == 0 response = get_view_for_user( client=client, method=client.post, viewname="workstations:session-create", reverse_kwargs={"slug": ws.slug}, user=user, ) assert response.status_code == 302 sessions = Session.objects.all() assert len(sessions) == 1 # Should select the most recent workstation assert sessions[0].workstation_image == wsi_new assert sessions[0].creator == user
def test_page_move(page_to_move, move_op, expected, client, TwoChallengeSets): pages = [] c2_pages = [] for i in range(4): pages.append( PageFactory(challenge=TwoChallengeSets.ChallengeSet1.challenge) ) # Same page name in challenge 2, make sure that these are unaffected c2_pages.append( PageFactory( challenge=TwoChallengeSets.ChallengeSet2.challenge, title=pages[i].title, ) ) assert_page_order(pages, [1, 2, 3, 4]) assert_page_order(c2_pages, [1, 2, 3, 4]) response = get_view_for_user( viewname="pages:update", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": pages[page_to_move].title}, data={ "title": pages[page_to_move].title, "permission_lvl": pages[page_to_move].permission_lvl, "html": pages[page_to_move].html, "move": move_op, }, ) assert response.status_code == 302 assert_page_order(pages, expected) assert_page_order(c2_pages, [1, 2, 3, 4])
def test_session_redirect(client): user = UserFactory(is_staff=True) WorkstationImageFactory( workstation__title=settings.DEFAULT_WORKSTATION_SLUG, ready=True ) response = get_view_for_user( client=client, viewname="workstations:default-session-redirect", user=user, ) assert response.status_code == 302 response = get_view_for_user(client=client, user=user, url=response.url) assert response.status_code == 200
def test_challenge_list(client): c = ChallengeFactory(hidden=False) hidden = ChallengeFactory(hidden=True) response = get_view_for_user(client=client, viewname="challenges:list") assert c.short_name in response.rendered_content assert hidden.short_name not in response.rendered_content
def test_team_creation(client, TwoChallengeSets, team_name): response = get_view_for_user( viewname="teams:create", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, method=client.post, user=TwoChallengeSets.ChallengeSet1.participant, data={"name": team_name}, ) assert response.status_code == 302 response = get_view_for_user( url=response.url, client=client, user=TwoChallengeSets.ChallengeSet1.participant, ) assert response.status_code == 200 assert team_name in response.rendered_content
def test_job_list(client, TwoChallengeSets): validate_admin_or_participant_view( viewname="evaluation:job-list", two_challenge_set=TwoChallengeSets, client=client, ) *_, j_p_s1, j_p_s2, j_p1_s1, j_p12_s1_c1, j_p12_s1_c2 = submissions_and_jobs( TwoChallengeSets ) # Participants should only be able to see their own jobs response = get_view_for_user( viewname="evaluation:job-list", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.ChallengeSet1.participant, ) assert str(j_p_s1.pk) in response.rendered_content assert str(j_p_s2.pk) in response.rendered_content assert str(j_p1_s1.pk) not in response.rendered_content assert str(j_p12_s1_c1.pk) not in response.rendered_content assert str(j_p12_s1_c2.pk) not in response.rendered_content # Admins should be able to see all jobs response = get_view_for_user( viewname="evaluation:job-list", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.ChallengeSet1.admin, ) assert str(j_p_s1.pk) in response.rendered_content assert str(j_p_s2.pk) in response.rendered_content assert str(j_p1_s1.pk) in response.rendered_content assert str(j_p12_s1_c1.pk) in response.rendered_content assert str(j_p12_s1_c2.pk) not in response.rendered_content # Only jobs relevant to this challenge should be listed response = get_view_for_user( viewname="evaluation:job-list", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.participant12, ) assert str(j_p12_s1_c1.pk) in response.rendered_content assert str(j_p12_s1_c2.pk) not in response.rendered_content assert str(j_p_s1.pk) not in response.rendered_content assert str(j_p_s2.pk) not in response.rendered_content assert str(j_p1_s1.pk) not in response.rendered_content
def test_create_page_with_same_title(client, TwoChallengeSets): PageFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, title="page1" ) # Creating a page with the same title should be denied response = get_view_for_user( viewname="pages:create", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.ChallengeSet1.admin, data={"title": "page1", "html": "hello", "permission_lvl": Page.ALL}, ) assert response.status_code == 200 assert "A page with that title already exists" in response.rendered_content # Creating one in another challenge should work response = get_view_for_user( viewname="pages:create", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet2.challenge, user=TwoChallengeSets.ChallengeSet2.admin, data={"title": "page1", "html": "hello", "permission_lvl": Page.ALL}, ) assert response.status_code == 302 # Check the updating PageFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, title="page2" ) response = get_view_for_user( viewname="pages:update", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, user=TwoChallengeSets.admin12, reverse_kwargs={"page_title": "page2"}, data={ "title": "page1", "html": " ", "permission_lvl": Page.ALL, "move": BLANK_CHOICE_DASH[0], }, ) assert response.status_code == 200 assert "A page with that title already exists" in response.rendered_content
def test_workstation_list_view(client): w1, w2 = WorkstationFactory(), WorkstationFactory() user = UserFactory(is_staff=True) response = get_view_for_user( viewname="workstations:list", client=client, user=user ) assert w1.get_absolute_url() in response.rendered_content assert w2.get_absolute_url() in response.rendered_content w1.delete() response = get_view_for_user( viewname="workstations:list", client=client, user=user ) assert w1.get_absolute_url() not in response.rendered_content assert w2.get_absolute_url() in response.rendered_content
def test_upload_list_is_filtered(client, TwoChallengeSets): u1 = UploadFactory(challenge=TwoChallengeSets.ChallengeSet1.challenge) u2 = UploadFactory(challenge=TwoChallengeSets.ChallengeSet2.challenge) response = get_view_for_user( viewname="uploads:list", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.admin12, ) assert u1.file.name in response.rendered_content assert u2.file.name not in response.rendered_content
def test_session_api_permissions(client): tests = [(UserFactory(), 403), (UserFactory(is_staff=True), 200)] session = SessionFactory() for test in tests: response = get_view_for_user( client=client, viewname="api:session-list", user=test[0], content_type="application/json", ) assert response.status_code == test[1] response = get_view_for_user( client=client, viewname="api:session-detail", reverse_kwargs={"pk": session.pk}, user=test[0], content_type="application/json", ) assert response.status_code == test[1]
def test_join_page_links(client, ChallengeSet): tests = [ (ChallengeSet.non_participant, "Click here to join"), (ChallengeSet.participant, "You are already participating"), ] for test in tests: response = get_view_for_user( viewname="participants:registration-create", client=client, user=test[0], challenge=ChallengeSet.challenge, ) assert test[1] in response.rendered_content rr = RegistrationRequestFactory( user=test[0], challenge=ChallengeSet.challenge ) response = get_view_for_user( viewname="participants:registration-create", client=client, user=test[0], challenge=ChallengeSet.challenge, ) assert rr.status_to_string() in response.rendered_content
def test_registration_list_is_filtered(client, TwoChallengeSets): r1 = RegistrationRequestFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge ) r2 = RegistrationRequestFactory( challenge=TwoChallengeSets.ChallengeSet2.challenge ) response = get_view_for_user( viewname="participants:registration-list", challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, user=TwoChallengeSets.admin12, ) assert r1.user.username in response.rendered_content assert r2.user.username not in response.rendered_content
def test_session_list_api(client): user = UserFactory(is_staff=True) response = get_view_for_user( client=client, viewname="api:session-list", user=user, content_type="application/json", ) assert response.status_code == 200 assert response.json()["count"] == 0 s, _ = SessionFactory(), SessionFactory() response = get_view_for_user( client=client, viewname="api:session-list", user=user, content_type="application/json", ) assert response.status_code == 200 assert response.json()["count"] == 2
def test_api_rs_answer_list_permissions(client): rs_set = TwoReaderStudies() q1, q2 = ( QuestionFactory(reader_study=rs_set.rs1), QuestionFactory(reader_study=rs_set.rs2), ) reader11 = UserFactory() rs_set.rs1.add_reader(reader11) a1, a11, a2 = ( AnswerFactory(question=q1, creator=rs_set.reader1, answer=""), AnswerFactory(question=q1, creator=reader11, answer=""), AnswerFactory(question=q2, creator=rs_set.reader2, answer=""), ) tests = ( (None, 200, []), (rs_set.creator, 200, []), (rs_set.editor1, 200, [a1.pk, a11.pk]), (rs_set.reader1, 200, [a1.pk]), (reader11, 200, [a11.pk]), (rs_set.editor2, 200, [a2.pk]), (rs_set.reader2, 200, [a2.pk]), (rs_set.u, 200, []), ) for test in tests: response = get_view_for_user( viewname="api:reader-studies-answer-list", client=client, user=test[0], content_type="application/json", ) assert response.status_code == test[1] # We provided auth details and get a response assert response.json()["count"] == len(test[2]) pks = [obj["pk"] for obj in response.json()["results"]] for pk in test[2]: assert str(pk) in pks
def test_workstation_redirect_permissions(client, two_workstation_sets, viewname): two_workstation_sets.ws1.workstation.slug = ( settings.DEFAULT_WORKSTATION_SLUG) two_workstation_sets.ws1.workstation.save() two_workstation_sets.ws1.image.ready = True two_workstation_sets.ws1.image.save() tests = ( (two_workstation_sets.ws1.editor, 302), (two_workstation_sets.ws1.user, 302), (two_workstation_sets.ws2.editor, 403), (two_workstation_sets.ws2.user, 403), (UserFactory(), 403), (UserFactory(is_staff=True), 403), (None, 302), ) kwargs = {} if viewname in [ "workstations:workstation-session-create", "workstations:workstation-image-session-create", ]: kwargs.update({"slug": two_workstation_sets.ws1.workstation.slug}) if viewname == "workstations:workstation-image-session-create": kwargs.update({"pk": two_workstation_sets.ws1.image.pk}) for test in tests: response = get_view_for_user( viewname=viewname, client=client, user=test[0], reverse_kwargs=kwargs, method=client.post, data={"region": "eu-central-1"}, ) assert response.status_code == test[1] if test[1] == 302 and test[0] is not None: session = Session.objects.get(creator=test[0]) assert response.url == session.get_absolute_url()
def test_assign_answer_image(client, settings, answer_type): settings.task_eager_propagates = (True, ) settings.task_always_eager = (True, ) rs = ReaderStudyFactory() im = ImageFactory() editor, reader = UserFactory(), UserFactory() rs.images.add(im) rs.add_editor(editor) rs.add_reader(reader) question = QuestionFactory(reader_study=rs, answer_type=answer_type) us = RawImageUploadSessionFactory(creator=reader) answer = AnswerFactory( creator=reader, question=question, answer={"upload_session_pk": str(us.pk)}, ) f = StagedFileFactory(file__from_path=Path(__file__).parent.parent / "cases_tests" / "resources" / "image10x10x10.mha") RawImageFileFactory(upload_session=us, staged_file_id=f.file_id) with capture_on_commit_callbacks(execute=True): response = get_view_for_user( viewname="api:upload-session-process-images", reverse_kwargs={"pk": us.pk}, user=reader, client=client, method=client.patch, data={"answer": str(answer.pk)}, content_type="application/json", ) assert response.status_code == 200 answer.refresh_from_db() image = us.image_set.first() assert answer.answer_image == image assert reader.has_perm("view_image", image) assert editor.has_perm("view_image", image)
def test_new_registration_email(participant_review, client, challenge_set): user = UserFactory() challenge_set.challenge.require_participant_review = participant_review challenge_set.challenge.save() assert not RegistrationRequest.objects.filter( user=user, challenge=challenge_set.challenge ).exists() response = get_view_for_user( viewname="participants:registration-create", client=client, method=client.post, user=user, challenge=challenge_set.challenge, ) assert response.status_code == 302 assert RegistrationRequest.objects.filter( user=user, challenge=challenge_set.challenge ).exists() if participant_review: approval_link = reverse( "participants:registration-list", kwargs={ "challenge_short_name": challenge_set.challenge.short_name }, ) admin_emails = [ e for e in mail.outbox if challenge_set.admin.email in e.to ] assert len(admin_emails) == 1 email = admin_emails[0] assert challenge_set.admin.email in email.to assert "new participation request" in email.subject.lower() assert challenge_set.challenge.short_name in email.subject assert approval_link in email.alternatives[0][0] else: # No emails if no review assert len(mail.outbox) == 0
def test_registration_updated_email(new_state, client, challenge_set): rr = RegistrationRequestFactory(challenge=challenge_set.challenge) response = get_view_for_user( viewname="participants:registration-update", client=client, method=client.post, user=challenge_set.admin, challenge=challenge_set.challenge, reverse_kwargs={"pk": rr.pk}, data={"status": new_state}, ) assert response.status_code == 302 email = mail.outbox[-1] assert rr.user.email in email.to if new_state == RegistrationRequest.ACCEPTED: assert "request accepted" in email.subject.lower() else: assert "request rejected" in email.subject.lower() assert challenge_set.challenge.short_name in email.body
def test_follows_deleted_when_base_obj_deleted(client): base_object = AlgorithmFactory( access_request_handling=AccessRequestHandlingOptions.MANUAL_REVIEW) editor = UserFactory() base_object.add_editor(editor) permission_create_url = reverse( "algorithms:permission-request-create", kwargs={"slug": base_object.slug}, ) user = UserFactory() _ = get_view_for_user(client=client, user=user, url=permission_create_url, method=client.post) pr = AlgorithmPermissionRequest.objects.get() assert is_following(user, pr) base_object.delete() assert not Follow.objects.filter(object_id=base_object.pk)
def test_team_member_addition(client, TwoChallengeSets): team = TeamFactory( challenge=TwoChallengeSets.ChallengeSet1.challenge, owner=TwoChallengeSets.ChallengeSet1.participant, ) assert TwoChallengeSets.ChallengeSet1.participant in team.get_members() assert TwoChallengeSets.ChallengeSet1.participant1 not in team.get_members( ) # Participant1 requests to join team response = get_view_for_user( viewname='teams:member-create', challenge=TwoChallengeSets.ChallengeSet1.challenge, client=client, method=client.post, user=TwoChallengeSets.ChallengeSet1.participant1, reverse_kwargs={'pk': team.pk}, ) assert TwoChallengeSets.ChallengeSet1.participant1 in team.get_members() assert response.status_code == 302
def test_registration_updated_email(new_state, client, ChallengeSet): rr = RegistrationRequestFactory(challenge=ChallengeSet.challenge) response = get_view_for_user( viewname='participants:registration-update', client=client, method=client.post, user=ChallengeSet.admin, challenge=ChallengeSet.challenge, reverse_kwargs={'pk': rr.pk}, data={'status': new_state}, ) assert response.status_code == 302 email = mail.outbox[-1] assert rr.user.email in email.to if new_state == RegistrationRequest.ACCEPTED: assert 'request accepted' in email.subject else: assert 'request rejected' in email.subject assert ChallengeSet.challenge.short_name in email.body
def test_case_text_is_scrubbed(client): u = UserFactory() im, im1 = ImageFactory(), ImageFactory() rs = ReaderStudyFactory( case_text={ im.name: "<b>My Help Text</b><script>naughty</script>", "not an image name": "Shouldn't appear in result", im1.name: "Doesn't belong to this study so ignore", }) rs.images.add(im) rs.add_reader(u) response = get_view_for_user(client=client, url=rs.api_url, user=u) assert response.status_code == 200 # Case should be indexed with the api url assert response.json()["case_text"] == { im.api_url: "<p><b>My Help Text</b>naughty</p>" }
def test_output_download(client): """Only viewers of the job should be allowed to download result files.""" user1, user2 = UserFactory(), UserFactory() job = AlgorithmJobFactory(creator=user1) detection_interface = ComponentInterface( store_in_database=False, relative_path="detection_results.json", slug="detection-json-file", title="Detection JSON File", kind=ComponentInterface.Kind.JSON, ) detection_interface.save() job.algorithm_image.algorithm.outputs.add(detection_interface) output_civ = ComponentInterfaceValue.objects.create( interface=detection_interface) detection = { "detected points": [{ "type": "Point", "start": [0, 1, 2], "end": [3, 4, 5] }] } output_civ.file.save( "detection_results.json", ContentFile( bytes(json.dumps(detection, ensure_ascii=True, indent=2), "utf-8")), ) job.outputs.add(output_civ) tests = [ (403, None), (302, user1), (403, user2), ] for test in tests: response = get_view_for_user(url=job.outputs.first().file.url, client=client, user=test[1]) assert response.status_code == test[0]
def test_login_redirect(self, client): e = EvaluationFactory() for view_name, kwargs in [ ("phase-create", {}), ("phase-update", { "slug": e.submission.phase.slug }), ("method-create", {}), ("method-list", {}), ("method-detail", { "pk": e.method.pk }), ("submission-create", { "slug": e.submission.phase.slug }), ("submission-create-legacy", { "slug": e.submission.phase.slug }), ("submission-list", {}), ("submission-detail", { "pk": e.submission.pk }), ("list", {}), ("update", { "pk": e.pk }), ]: response = get_view_for_user( client=client, viewname=f"evaluation:{view_name}", reverse_kwargs={ "challenge_short_name": e.submission.phase.challenge.short_name, **kwargs, }, user=None, ) assert response.status_code == 302 assert response.url.startswith( f"https://testserver/accounts/login/?next=http%3A//" f"{e.submission.phase.challenge.short_name}.testserver/")
def test_user_upload_to_archive_item_with_new_interface(client, settings): # Override the celery settings settings.task_eager_propagates = (True, ) settings.task_always_eager = (True, ) user = UserFactory() archive = ArchiveFactory() archive.add_editor(user=user) ci = ComponentInterfaceFactory(kind=ComponentInterface.Kind.STRING, title="Test") civ = ComponentInterfaceValueFactory(interface=ci) item = ArchiveItemFactory(archive=archive) item.values.add(civ) assert item.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], "archive_item": item.pk, "interface": "generic-overlay", }, HTTP_X_FORWARDED_PROTO="https", ) assert response.status_code == 201 upload_session = response.json() assert upload_session["uploads"] == [upload.api_url] item.refresh_from_db() assert item.values.count() == 2 assert "generic-overlay" in [ item.interface.slug for item in item.values.all() ]
def test_page_move( page_to_move, move_op, expected, client, two_challenge_sets ): pages = [*two_challenge_sets.challenge_set_1.challenge.page_set.all()] c2_pages = [*two_challenge_sets.challenge_set_2.challenge.page_set.all()] for i in range(3): pages.append( PageFactory(challenge=two_challenge_sets.challenge_set_1.challenge) ) # Same page name in challenge 2, make sure that these are unaffected c2_pages.append( PageFactory( challenge=two_challenge_sets.challenge_set_2.challenge, display_title=pages[i + 1].display_title, ) ) assert [p.order for p in pages] == [1, 2, 3, 4] assert [p.order for p in c2_pages] == [1, 2, 3, 4] response = get_view_for_user( viewname="pages:update", client=client, method=client.post, challenge=two_challenge_sets.challenge_set_1.challenge, user=two_challenge_sets.admin12, reverse_kwargs={"slug": pages[page_to_move].slug}, data={ "display_title": pages[page_to_move].display_title, "permission_level": pages[page_to_move].permission_level, "html": pages[page_to_move].html, "move": move_op, }, ) for p in chain(pages, c2_pages): p.refresh_from_db() assert response.status_code == 302 assert [p.order for p in pages] == expected assert [p.order for p in c2_pages] == [1, 2, 3, 4]
def test_registration_review_workflow(choice, expected, client, challenge_set): user = UserFactory() challenge_set.challenge.require_participant_review = True challenge_set.challenge.save() rr = RegistrationRequestFactory(challenge=challenge_set.challenge, user=user) assert not challenge_set.challenge.is_participant(user) assert rr.status == RegistrationRequest.PENDING response = get_view_for_user( client=client, method=client.post, viewname="participants:registration-update", challenge=challenge_set.challenge, user=challenge_set.admin, reverse_kwargs={"pk": rr.pk}, data={"status": choice}, ) assert response.status_code == 302 assert challenge_set.challenge.is_participant(user) == expected assert RegistrationRequest.objects.get(pk=rr.pk).status == choice
def test_user_autocomplete_permissions(client): alg_set = TwoAlgorithms() tests = ( (None, 302), (alg_set.creator, 403), (alg_set.editor1, 200), (alg_set.user1, 403), (alg_set.editor2, 200), (alg_set.user2, 403), (alg_set.u, 403), ) for test in tests: response = get_view_for_user( viewname="algorithms:users-autocomplete", client=client, user=test[0], ) assert response.status_code == test[1]
def test_create_multipart_upload(client): # https://uppy.io/docs/aws-s3-multipart/#createMultipartUpload-file u = UserFactory() response = get_view_for_user( client=client, viewname="api:upload-list", method=client.post, data={"filename": "foo.bat"}, content_type="application/json", user=u, ) assert response.status_code == 201 upload_file = response.json() assert upload_file["status"] == "Initialized" assert upload_file["s3_upload_id"] != "" assert upload_file["key"] == f"uploads/{u.pk}/{upload_file['pk']}" assert upload_file["filename"] == "foo.bat"
def test_user_autocomplete_permissions(client): rs_set = TwoReaderStudies() tests = ( (None, 302), (rs_set.creator, 403), (rs_set.editor1, 200), (rs_set.reader1, 403), (rs_set.editor2, 200), (rs_set.reader2, 403), (rs_set.u, 403), ) for test in tests: response = get_view_for_user( viewname="reader-studies:users-autocomplete", client=client, user=test[0], ) assert response.status_code == test[1]
def test_session_update_extends_timeout(client): user = UserFactory() s = SessionFactory(creator=user) assert s.maximum_duration == timedelta(minutes=10) response = get_view_for_user( client=client, method=client.patch, viewname="api:session-keep-alive", reverse_kwargs={"pk": s.pk}, user=user, content_type="application/json", ) assert response.status_code == 200 s.refresh_from_db() # Just check that it changed from the default assert s.maximum_duration != timedelta(minutes=10)
def test_question_create(client): rs_set = TwoReaderStudies() tests = ( (None, 0, 302), (rs_set.editor1, 1, 302), (rs_set.reader1, 0, 403), (rs_set.editor2, 0, 403), (rs_set.reader2, 0, 403), (rs_set.u, 0, 403), ) for test in tests: response = get_view_for_user( viewname="reader-studies:add-question", client=client, method=client.post, data={ "question_text": "What?", "answer_type": "STXT", "order": 1, "image_port": "", "direction": "H", "options-TOTAL_FORMS": 2, "options-INITIAL_FORMS": 1, "options-MIN_NUM_FORMS": 0, "options-MAX_NUM_FORMS": 1000, }, reverse_kwargs={"slug": rs_set.rs1.slug}, user=test[0], ) assert response.status_code == test[2] qs = Question.objects.all() assert len(qs) == test[1] if test[1] > 0: question = qs[0] assert question.reader_study == rs_set.rs1 assert question.question_text == "What?" question.delete()
def test_admins_add(client, TwoChallengeSets): user = UserFactory() assert not TwoChallengeSets.ChallengeSet1.challenge.is_admin(user=user) assert not TwoChallengeSets.ChallengeSet2.challenge.is_admin(user=user) response = get_view_for_user( viewname="admins:update", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, data={ "user": user.pk, "action": AdminsForm.ADD }, user=TwoChallengeSets.ChallengeSet1.admin, ) assert response.status_code == 302 email = mail.outbox[-1] assert TwoChallengeSets.ChallengeSet1.challenge.short_name in email.subject assert user.email in email.to assert TwoChallengeSets.ChallengeSet1.challenge.is_admin(user=user) assert not TwoChallengeSets.ChallengeSet2.challenge.is_admin(user=user)
def test_admins_remove(client, TwoChallengeSets): assert TwoChallengeSets.ChallengeSet1.challenge.is_admin( user=TwoChallengeSets.admin12) assert TwoChallengeSets.ChallengeSet2.challenge.is_admin( user=TwoChallengeSets.admin12) response = get_view_for_user( viewname="admins:update", client=client, method=client.post, challenge=TwoChallengeSets.ChallengeSet1.challenge, data={ "user": TwoChallengeSets.admin12.pk, "action": AdminsForm.REMOVE }, user=TwoChallengeSets.ChallengeSet1.admin, ) assert response.status_code == 302 assert not TwoChallengeSets.ChallengeSet1.challenge.is_admin( user=TwoChallengeSets.admin12) assert TwoChallengeSets.ChallengeSet2.challenge.is_admin( user=TwoChallengeSets.admin12)
def test_autocomplete_for_verified_email(self, client): archive = ArchiveFactory() admin = UserFactory() archive.add_editor(admin) call_command("check_permissions") user = UserenaSignup.objects.create_user("userena", "*****@*****.**", "testpassword", active=True) VerificationFactory(user=user, is_verified=True) response = get_view_for_user( client=client, viewname="users-autocomplete", user=admin, data={"q": user.verification.email}, ) assert response.status_code == 200 assert str(user.pk) in response.json()["results"][0]["id"]
def test_workstationimage_detail(client): user = UserFactory(is_staff=True) ws = WorkstationFactory() wsi1, wsi2 = ( WorkstationImageFactory(workstation=ws), WorkstationImageFactory(workstation=ws), ) response = get_view_for_user( viewname="workstations:image-detail", reverse_kwargs={ "slug": ws.slug, "pk": wsi1.pk }, client=client, user=user, ) assert response.status_code == 200 assert str(wsi1.pk) in response.rendered_content assert str(wsi2.pk) not in response.rendered_content
def test_admins_remove(client, two_challenge_sets): assert two_challenge_sets.challenge_set_1.challenge.is_admin( user=two_challenge_sets.admin12) assert two_challenge_sets.challenge_set_2.challenge.is_admin( user=two_challenge_sets.admin12) response = get_view_for_user( viewname="admins:update", client=client, method=client.post, challenge=two_challenge_sets.challenge_set_1.challenge, data={ "user": two_challenge_sets.admin12.pk, "action": AdminsForm.REMOVE, }, user=two_challenge_sets.challenge_set_1.admin, ) assert response.status_code == 302 assert not two_challenge_sets.challenge_set_1.challenge.is_admin( user=two_challenge_sets.admin12) assert two_challenge_sets.challenge_set_2.challenge.is_admin( user=two_challenge_sets.admin12)
def test_registration_admin_changed_mind(client, challenge_set): user = UserFactory() challenge_set.challenge.require_participant_review = False challenge_set.challenge.save() rr = RegistrationRequestFactory(challenge=challenge_set.challenge, user=user) assert challenge_set.challenge.is_participant(user) assert rr.status == RegistrationRequest.ACCEPTED response = get_view_for_user( client=client, method=client.post, viewname="participants:registration-update", challenge=challenge_set.challenge, user=challenge_set.admin, reverse_kwargs={"pk": rr.pk}, data={"status": RegistrationRequest.REJECTED}, ) assert response.status_code == 302 assert not challenge_set.challenge.is_participant(user) assert (RegistrationRequest.objects.get( pk=rr.pk).status == RegistrationRequest.REJECTED)
def test_answer_is_correct_type(client, answer_type, answer, expected): im = ImageFactory() rs = ReaderStudyFactory() rs.images.add(im) rs.save() reader = UserFactory() rs.add_reader(reader) q = QuestionFactory(reader_study=rs, answer_type=answer_type) response = get_view_for_user( viewname="api:reader-studies-answer-list", user=reader, client=client, method=client.post, data={"answer": answer, "images": [im.api_url], "question": q.api_url}, content_type="application/json", ) assert response.status_code == expected
def test_abort_multipart_upload(client): # https://uppy.io/docs/aws-s3-multipart/#abortMultipartUpload-file-uploadId-key u = UserFactory() upload = UserUpload.objects.create(creator=u) response = get_view_for_user( client=client, viewname="api:upload-abort-multipart-upload", reverse_kwargs={"pk": upload.pk, "s3_upload_id": upload.s3_upload_id}, method=client.patch, data={}, content_type="application/json", user=u, ) assert response.status_code == 200 assert response.json()["pk"] == str(upload.pk) assert response.json()["s3_upload_id"] == "" assert response.json()["key"] == upload.key assert response.json()["status"] == "Aborted"
def test_upload_session_owned_by_answer_creator(client, settings, answer_type): settings.task_eager_propagates = (True, ) settings.task_always_eager = (True, ) rs = ReaderStudyFactory() im = ImageFactory() editor, reader = UserFactory(), UserFactory() rs.images.add(im) rs.add_editor(editor) rs.add_reader(reader) question = QuestionFactory(reader_study=rs, answer_type=answer_type) us1 = RawImageUploadSessionFactory(creator=reader) us2 = RawImageUploadSessionFactory(creator=editor) answer1 = AnswerFactory( creator=reader, question=question, answer={"upload_session_pk": str(us1.pk)}, ) f = StagedFileFactory(file__from_path=Path(__file__).parent.parent / "cases_tests" / "resources" / "image10x10x10.mha") RawImageFileFactory(upload_session=us1, staged_file_id=f.file_id) response = get_view_for_user( viewname="api:upload-session-process-images", reverse_kwargs={"pk": us2.pk}, user=editor, client=client, method=client.patch, data={"answer": str(answer1.pk)}, content_type="application/json", ) assert response.status_code == 400 assert (b"User does not have permission to add an image to this answer" in response.rendered_content)
def test_workstationimage_create(client): u2 = UserFactory() w1 = WorkstationFactory() w2 = WorkstationFactory() w2.add_editor(user=u2) staged_file = StagedFileFactory(file__filename="example.tar.gz") assert w1.workstationimage_set.count() == 0 assert w2.workstationimage_set.count() == 0 response = get_view_for_user( client=client, method=client.post, viewname="workstations:image-create", reverse_kwargs={"slug": w2.slug}, user=u2, data={ "chunked_upload": staged_file.file_id, "initial_path": "a", "websocket_port": 1337, "http_port": 1234, }, ) assert response.status_code == 302 w1.refresh_from_db() w2.refresh_from_db() assert w1.workstationimage_set.count() == 0 w2_images = w2.workstationimage_set.all() assert len(w2_images) == 1 assert w2_images[0].creator == u2 assert w2_images[0].websocket_port == 1337 assert w2_images[0].http_port == 1234 assert w2_images[0].staged_image_uuid == staged_file.file_id assert w2_images[0].initial_path == "a"
def test_job_update_permissions(client, view_name): alg_set = TwoAlgorithms() j1, j2 = ( AlgorithmJobFactory(algorithm_image__algorithm=alg_set.alg1), AlgorithmJobFactory(algorithm_image__algorithm=alg_set.alg2), ) tests = ( (None, j1, 302), (None, j2, 302), (alg_set.creator, j1, 403), (alg_set.creator, j2, 403), (alg_set.editor1, j1, 403), (alg_set.editor1, j2, 403), (alg_set.user1, j1, 403), (alg_set.user1, j2, 403), (alg_set.editor2, j1, 403), (alg_set.editor2, j2, 403), (alg_set.user2, j1, 403), (alg_set.user2, j2, 403), (alg_set.u, j1, 403), (alg_set.u, j2, 403), (j1.creator, j1, 200), (j1.creator, j2, 403), (j2.creator, j1, 403), (j2.creator, j2, 200), ) for test in tests: response = get_view_for_user( viewname=f"algorithms:{view_name}", client=client, user=test[0], reverse_kwargs={ "slug": test[1].algorithm_image.algorithm.slug, "pk": test[1].pk, }, ) assert response.status_code == test[2]