def test_process_other_id_records(app, mocker): """Test create or update researcher other id.""" mocker.patch("orcid_hub.utils.send_email", send_mail_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_external_identifierv3", create_or_update_fund_mock) mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", return_value=get_profile()) org = app.data["org"] u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=TaskType.OTHER_ID) OtherIdRecord.create(task=t, type="grant_number", value="xyz", url="https://xyz.com", relationship="SELF", is_active=True, status="email sent", first_name="Test", last_name="Test", email="*****@*****.**", visibility="PUBLIC", display_index=1) UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scopes="/read-limited,/person/update", access_token="Test_token") utils.process_other_id_records() record = OtherIdRecord.get(email="*****@*****.**") assert 12399 == record.put_code assert "12344" == record.orcid
def test_sync_profile(app, mocker): """Test sync_profile.""" mocker.patch("orcid_api.MemberAPIV20Api.update_employment", return_value=Mock(status=201, headers={'Location': '12344/XYZ/54321'})) mocker.patch("orcid_api.MemberAPIV20Api.update_education", return_value=Mock(status=201, headers={'Location': '12344/XYZ/12345'})) org = Organisation.create( name="THE ORGANISATION:test_sync_profile", tuakiri_name="THE ORGANISATION:test_sync_profile", confirmed=True, orcid_client_id="APP-5ZVH4JRQ0C27RVH5", orcid_secret="Client Secret", city="CITY", country="COUNTRY", disambiguated_id="ID", disambiguation_source="SOURCE") u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) access_token = "ACCESS-TOKEN" t = Task.create(org=org, task_type=TaskType.SYNC) api = MemberAPI(org=org) mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record", lambda *args: None) api.sync_profile(task=t, user=u, access_token=access_token) OrcidToken.create(user=u, org=org, scope="/read-limited,/activities/update") mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record", lambda *args: None) api.sync_profile(task=t, user=u, access_token=access_token) assert Log.select().count() > 0 mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record", return_value=get_profile()) api.sync_profile(task=t, user=u, access_token=access_token) last_log = Log.select().order_by(Log.id.desc()).first() assert "Successfully update" in last_log.message
def test_scheduled_tasks(app, mocker): """Test scheduled tasks.""" org = app.data["org"] task = Task.create(org=org, task_type=TaskType.AFFILIATION) rq = app.extensions["rq2"] s = rq.get_scheduler() s.run(burst=True) task = Task.get(task.id) utils.process_tasks.queue() task = Task.get(task.id) assert task.expires_at is not None task.expires_at = utils.datetime(1988, 1, 1) task.save() utils.process_tasks.queue() assert Task.select().where(Task.id == task.id).count() == 0 Organisation.update(webhook_enabled=True, email_notifications_enabled=True).execute() User.update(orcid_updated_at=utils.date.today().replace(day=1) - utils.timedelta(days=1)).execute() send_email = mocker.patch("orcid_hub.utils.send_email") utils.send_orcid_update_summary.queue(org_id=org.id) send_email.assert_called()
def test_send_work_funding_peer_review_invitation(app, mocker): """Test to send user invitation.""" send_email = mocker.patch("orcid_hub.utils.send_email") org = app.data["org"] inviter = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid=None, confirmed=True, organisation=org) email = "*****@*****.**" u = User.create(email=email, name="TEST USER", roles=Role.RESEARCHER, orcid=None, confirmed=True, organisation=org) UserOrg.create(user=u, org=org) task = Task.create(org=org, task_type=1) fr = FundingRecord.create(task=task, title="xyz", type="Award") FundingInvitee.create(record=fr, email=email, first_name="Alice", last_name="Bob") server_name = app.config.get("SERVER_NAME") app.config["SERVER_NAME"] = "abc.orcidhub.org.nz" utils.send_user_invitation(inviter=inviter, org=org, email=email, name=u.name, user=u, task_id=task.id) app.config["SERVER_NAME"] = server_name send_email.assert_called_once()
def test_create_or_update_peer_review(email_patch, patch, test_db, request_ctx): """Test create or update peer review.""" org = Organisation.create(name="THE ORGANISATION", tuakiri_name="THE ORGANISATION", confirmed=True, orcid_client_id="APP-5ZVH4JRQ0C27RVH5", orcid_secret="Client Secret", city="CITY", country="COUNTRY", disambiguation_org_id="ID", disambiguation_org_source="SOURCE") u = User.create(email="*****@*****.**", name="TEST USER", username="******", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(id=12, org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=3) pr = PeerReviewRecord.create(task=t, review_group_id="issn:12131", reviewer_role="reviewer", review_url="xyz", review_type="REVIEW", subject_external_id_type="doi", subject_external_id_value="1212", subject_external_id_url="url/SELF", subject_external_id_relationship="SELF", subject_container_name="Journal title", subject_type="JOURNAL_ARTICLE", subject_name_title="name", subject_name_subtitle="subtitle", subject_name_translated_title_lang_code="en", subject_name_translated_title="sdsd", subject_url="url", convening_org_name="THE ORGANISATION", convening_org_city="auckland", convening_org_region="auckland", convening_org_country="nz", convening_org_disambiguated_identifier="123", convening_org_disambiguation_source="1212", is_active=True) PeerReviewInvitee.create(peer_review_record=pr, first_name="Test", email="*****@*****.**", orcid="12344", visibility="PUBLIC") PeerReviewExternalId.create(peer_review_record=pr, type="Test_type", value="122334_different", url="Test", relationship="SELF") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scope="/read-limited,/activities/update", access_token="Test_token") utils.process_peer_review_records() peer_review_invitees = PeerReviewInvitee.get(orcid=12344) assert 12399 == peer_review_invitees.put_code assert "12344" == peer_review_invitees.orcid
def test_create_or_update_work(email_patch, patch, test_db, request_ctx): """Test create or update work.""" org = Organisation.create(name="THE ORGANISATION", tuakiri_name="THE ORGANISATION", confirmed=True, orcid_client_id="APP-5ZVH4JRQ0C27RVH5", orcid_secret="Client Secret", city="CITY", country="COUNTRY", disambiguation_org_id="ID", disambiguation_org_source="SOURCE") u = User.create(email="*****@*****.**", name="TEST USER", username="******", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=2) wr = WorkRecord.create(task=t, title="Test titile", sub_title="Test titile", translated_title="Test title", translated_title_language_code="Test", journal_title="Test titile", short_description="Test desc", citation_type="Test", citation_value="Test", type="BOOK_CHAPTER", url="Test org", language_code="en", country="Test", org_name="Test_orgname", city="Test city", region="Test", is_active=True) WorkInvitees.create(work_record=wr, first_name="Test", email="*****@*****.**", orcid="12344", visibility="PUBLIC") WorkExternalId.create(work_record=wr, type="Test_type", value="Test_value", url="Test", relationship="SELF") WorkContributor.create(work_record=wr, contributor_sequence="1", orcid="1213", role="LEAD", name="xyz", email="*****@*****.**") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scope="/read-limited,/activities/update", access_token="Test_token") utils.process_work_records() work_invitees = WorkInvitees.get(orcid=12344) assert 12399 == work_invitees.put_code assert "12344" == work_invitees.orcid
def test_create_or_update_funding(email_patch, patch, test_db, request_ctx): """Test create or update funding.""" org = Organisation.create(name="THE ORGANISATION", tuakiri_name="THE ORGANISATION", confirmed=True, orcid_client_id="APP-5ZVH4JRQ0C27RVH5", orcid_secret="Client Secret", city="CITY", country="COUNTRY", disambiguation_org_id="ID", disambiguation_org_source="SOURCE") u = User.create(email="*****@*****.**", name="TEST USER", username="******", roles=Role.RESEARCHER, orcid="123", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=1) fr = FundingRecord.create(task=t, title="Test titile", translated_title="Test title", translated_title_language_code="Test", type="GRANT", organization_defined_type="Test org", short_description="Test desc", amount="1000", currency="USD", org_name="Test_orgname", city="Test city", region="Test", country="Test", disambiguated_org_identifier="Test_dis", disambiguation_source="Test_source", is_active=True) FundingInvitees.create(funding_record=fr, first_name="Test", email="*****@*****.**", visibility="PUBLIC", orcid="123") ExternalId.create(funding_record=fr, type="Test_type", value="Test_value", url="Test", relationship="SELF") FundingContributor.create(funding_record=fr, orcid="1213", role="LEAD", name="Contributor", email="*****@*****.**") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scope="/read-limited,/activities/update", access_token="Test_token") utils.process_funding_records() funding_invitees = FundingInvitees.get(orcid=12344) assert 12399 == funding_invitees.put_code assert "12344" == funding_invitees.orcid
def test_process_tasks(request_ctx): """Test expiration data setting and deletion of the exprired tasks.""" org = Organisation.get(name="TEST0") super_user = User.get(email="*****@*****.**") with patch("orcid_hub.utils.send_email") as send_email, request_ctx("/") as ctx: login_user(super_user) # flake8: noqa task = Task.load_from_csv( """First name Last name email address Organisation Campus/Department City Course or Job title\tStart date End date Student/Staff\tCountry FNA LBA [email protected] TEST1 Research Funding Wellington Programme Manager - ORCID 2016-09 Staff\tNew Zealand """, filename="TEST_TASK.tsv", org=org) Task.update(created_at=datetime(1999, 1, 1), updated_at=datetime(1999, 1, 1)).execute() utils.process_tasks() assert Task.select().count() == 1 assert not Task.select().where(Task.expires_at.is_null()).exists() send_email.assert_called_once() task = Task.select().first() args, kwargs = send_email.call_args assert "email/task_expiration.html" in args assert kwargs["error_count"] == 0 hostname = ctx.request.host assert kwargs["export_url"] == ( f"https://{hostname}/admin/affiliationrecord/export/csv/?task_id={task.id}") assert kwargs["recipient"] == ( super_user.name, super_user.email, ) assert kwargs["subject"] == "Batch process task is about to expire" assert kwargs["task"] == task # After the second go everything should be deleted utils.process_tasks() assert Task.select().count() == 0 # Funding processing task: task = Task.create( created_at=datetime(1999, 1, 1), org=org, filename="FUNDING.json", created_by=super_user, updated_by=super_user, task_type=TaskType.FUNDING.value) Task.update(updated_at=datetime(1999, 1, 1)).execute() assert Task.select().where(Task.expires_at.is_null()).count() == 1 utils.process_tasks() assert Task.select().count() == 1 assert Task.select().where(Task.expires_at.is_null()).count() == 0 utils.process_tasks() assert Task.select().count() == 0 args, kwargs = send_email.call_args assert "email/task_expiration.html" in args assert kwargs["error_count"] == 0 hostname = ctx.request.host assert kwargs["export_url"] == ( f"https://{hostname}/admin/fundingrecord/export/csv/?task_id={task.id}") assert kwargs["recipient"] == ( super_user.name, super_user.email, ) assert kwargs["subject"] == "Batch process task is about to expire" assert kwargs["task"] == task # Incorrect task type: task = Task.create( created_at=datetime(1999, 1, 1), org=org, filename="ERROR.err", created_by=super_user, updated_by=super_user, task_type=-12345) Task.update(updated_at=datetime(1999, 1, 1)).execute() with pytest.raises(Exception, message="Unexpeced task type: -12345 (ERROR.err)."): utils.process_tasks() task.delete().execute() # Cover case with an exterenal SP: with patch("orcid_hub.utils.EXTERNAL_SP", "SOME.EXTERNAL.SP"): Task.create( created_at=datetime(1999, 1, 1), org=org, filename="FILE.file", created_by=super_user, updated_by=super_user) Task.update(updated_at=datetime(1999, 1, 1)).execute() assert Task.select().count() == 1 utils.process_tasks() utils.process_tasks() assert Task.select().count() == 0
def test_send_user_invitation(app, mocker): """Test to send user invitation.""" send_email = mocker.patch("orcid_hub.utils.send_email") org = app.data["org"] inviter = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid=None, confirmed=True, organisation=org) email = "*****@*****.**" first_name = "TEST" last_name = "Test" affiliation_types = {"staff"} u = User.create(email=email, name="TEST USER", roles=Role.RESEARCHER, orcid=None, confirmed=True, organisation=org) UserOrg.create(user=u, org=org) task = Task.create(org=org) mock_smtp = mocker.patch("smtplib.SMTP").return_value instance = mock_smtp.return_value error = { email: (450, "Requested mail action not taken: mailbox unavailable") } instance.utils.send_user_invitation.return_value = error result = instance.utils.send_user_invitation( inviter=inviter, org=org, email=email, first_name=first_name, last_name=last_name, affiliation_types=affiliation_types, task_id=task.id) assert instance.utils.send_user_invitation.called # noqa: E712 assert (450, 'Requested mail action not taken: mailbox unavailable' ) == result[email] send_email = mocker.patch("orcid_hub.utils.send_email") result = utils.send_user_invitation(inviter=inviter.id, org=org.id, email=email, first_name=first_name, last_name=last_name, affiliation_types=affiliation_types, start_date=[1971, 1, 1], end_date=[2018, 5, 29], task_id=task.id) send_email.assert_called_once() assert result == UserInvitation.select().order_by( UserInvitation.id.desc()).first() with pytest.raises(Exception) as excinfo: send_email.reset_mock() dkim_key_path = utils.app.conig["DKIM_KEY_PATH"] app.conig["DKIM_KEY_PATH"] = "/file/not/found.key" result = utils.send_user_invitation( inviter=inviter.id, org=org.id, email=email, first_name=first_name, last_name=last_name, affiliation_types=affiliation_types, start_date=[1971, 1, 1], end_date=[2018, 5, 29], task_id=task.id) send_email.assert_not_called() utils.app.conig["DKIM_KEY_PATH"] = dkim_key_path assert "/file/not/found.key" in str(excinfo.value)
def test_create_or_update_affiliation(app, mocker): """Test create or update affiliation.""" mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.update_employmentv3", return_value=Mock(status=201, headers={'Location': '12344/XYZ/12399'})) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_employmentv3", return_value=Mock(status=201, headers={'Location': '12344/XYZ/12399'})) send_email = mocker.patch("orcid_hub.utils.send_email") capture_event = mocker.patch( "sentry_sdk.transport.HttpTransport.capture_event") org = app.data["org"] u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="123", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=TaskType.AFFILIATION) OrcidToken.create(user=u, org=org, scopes="/read-limited,/activities/update", access_token="Test_token") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") u = User.create(email="*****@*****.**", name="TEST USER 2", roles=Role.RESEARCHER, confirmed=True, organisation=org) UserOrg.create(user=u, org=org) AffiliationRecord.create(is_active=True, task=t, local_id="Test", first_name="Test", last_name="Test", email="*****@*****.**", orcid="123112311231", organisation="asdasd", affiliation_type="staff", role="Test", department="Test", city="Test", state="Test", country="NZ", disambiguated_id="Test", disambiguation_source="Test") AffiliationRecord.create(is_active=True, task=t, local_id="Test", first_name="Test", last_name="Test", email="*****@*****.**", orcid="123112311231", organisation=org.name, affiliation_type="staff", role="Test", department="Test", city="Test", state="Test", country="NZ") AffiliationRecord.create(is_active=True, task=t, local_id="Test", first_name="Test", last_name="Test", email="*****@*****.**", orcid="123112311231", organisation="ANOTHER ORG", affiliation_type="staff", role="Test", department="Test", city="Test", state="Test", country="NZ", visibility="PUBLIC") AffiliationRecord.create(is_active=True, task=t, local_id="Test#2", first_name="Test2", last_name="Test2", email="*****@*****.**", organisation=org.name, affiliation_type="staff") tasks = (Task.select( Task, AffiliationRecord, User, UserInvitation.id.alias("invitation_id"), OrcidToken).join( AffiliationRecord, on=(Task.id == AffiliationRecord.task_id).alias("record")).join( User, JOIN.LEFT_OUTER, on=((User.email == AffiliationRecord.email) | (User.orcid == AffiliationRecord.orcid))).join( Organisation, JOIN.LEFT_OUTER, on=(Organisation.id == Task.org_id)).join( UserInvitation, JOIN.LEFT_OUTER, on=((UserInvitation.email == AffiliationRecord.email) & (UserInvitation.task_id == Task.id))). join(OrcidToken, JOIN.LEFT_OUTER, on=((OrcidToken.user_id == User.id) & (OrcidToken.org_id == Organisation.id) & (OrcidToken.scopes.contains("/activities/update"))))) app.config["SERVER_NAME"] = "orcidhub" for (task_id, org_id, user), tasks_by_user in groupby( tasks, lambda t: ( t.id, t.org_id, t.record.user, )): with patch("orcid_hub.orcid_client.MemberAPIV3.get_record", return_value=get_profile() if user.orcid else None) as get_record: utils.create_or_update_affiliations(user=user, org_id=org_id, records=tasks_by_user) get_record.assert_any_call() affiliation_record = AffiliationRecord.select().order_by( AffiliationRecord.id).limit(1).first() assert 12399 == affiliation_record.put_code assert "12344" == affiliation_record.orcid assert ("Employment record was updated" in affiliation_record.status or "Employment record was created" in affiliation_record.status) capture_event.assert_called() send_email.assert_called_once()
def test_create_or_update_property_record(app, mocker): """Test create or update researcher keyword, researcher url, other name and country""" mocker.patch("orcid_hub.utils.send_email", send_mail_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_keywordv3", create_or_update_fund_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_researcher_urlv3", create_or_update_fund_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_other_namev3", create_or_update_fund_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_addressv3", create_or_update_fund_mock) mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", return_value=get_profile()) org = app.data["org"] u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) OrcidToken.create(user=u, org=org, scopes="/read-limited,/person/update", access_token="Test_token") t = Task.create(id=12, org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=TaskType.PROPERTY) PropertyRecord.create(task=t, type="KEYWORD", is_active=True, status="email sent", first_name="Test", last_name="Test", email="*****@*****.**", visibility="PUBLIC", value="dummy name", display_index=1) PropertyRecord.create(task=t, type="COUNTRY", is_active=True, status="email sent", first_name="Test", last_name="Test", email="*****@*****.**", visibility="PUBLIC", value="IN", display_index=1) PropertyRecord.create(task=t, type="URL", is_active=True, status="email sent", first_name="Test", last_name="Test", email="*****@*****.**", visibility="PUBLIC", name="url name", value="https://www.xyz.com", display_index=1) PropertyRecord.create(task=t, type="NAME", is_active=True, status="email sent", first_name="Test", last_name="Test", email="*****@*****.**", visibility="PUBLIC", value="dummy name", display_index=1) UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") utils.process_property_records() keyword_record = PropertyRecord.get(email="*****@*****.**", type="KEYWORD") assert 12399 == keyword_record.put_code assert "12344" == keyword_record.orcid address_record = PropertyRecord.get(email="*****@*****.**", type="COUNTRY") assert 12399 == address_record.put_code assert "12344" == address_record.orcid url_record = PropertyRecord.get(email="*****@*****.**", type="URL") assert 12399 == url_record.put_code assert "12344" == url_record.orcid other_name_record = PropertyRecord.get(email="*****@*****.**", type="NAME") assert 12399 == other_name_record.put_code assert "12344" == other_name_record.orcid
def test_create_or_update_peer_review(app, mocker): """Test create or update peer review.""" mocker.patch("orcid_hub.utils.send_email", send_mail_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_peer_reviewv3", create_or_update_fund_mock) org = app.data["org"] mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", return_value=get_profile(org=org)) u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(id=12, org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=TaskType.PEER_REVIEW) pr = PeerReviewRecord.create( task=t, review_group_id="issn:12131", reviewer_role="reviewer", review_url="xyz", review_type="REVIEW", subject_external_id_type="doi", subject_external_id_value="1212", subject_external_id_url="url/SELF", subject_external_id_relationship="SELF", subject_container_name="Journal title", subject_type="JOURNAL_ARTICLE", subject_name_title="name", subject_name_subtitle="subtitle", review_completion_date=PartialDate.create("2003-07-14"), subject_name_translated_title_lang_code="en", subject_name_translated_title="sdsd", subject_url="url", convening_org_name="THE ORGANISATION", convening_org_city="auckland", convening_org_region="auckland", convening_org_country="NZ", convening_org_disambiguated_identifier="123", convening_org_disambiguation_source="1212", is_active=True) PeerReviewInvitee.create(record=pr, first_name="Test", email="*****@*****.**", orcid="12344", visibility="PUBLIC") PeerReviewExternalId.create(record=pr, type="Test_type", value="122334_different", url="Test", relationship="SELF") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scopes="/read-limited,/activities/update", access_token="Test_token") utils.process_peer_review_records() peer_review_invitees = PeerReviewInvitee.get(orcid=12344) assert 12399 == peer_review_invitees.put_code assert "12344" == peer_review_invitees.orcid
def test_create_or_update_work(app, mocker): """Test create or update work.""" mocker.patch("orcid_hub.utils.send_email", send_mail_mock) mocker.patch("orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_workv3", create_or_update_fund_mock) org = app.data["org"] mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", return_value=get_profile(org=org)) u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=TaskType.WORK) wr = WorkRecord.create(task=t, title="Test titile", subtitle="Test titile", translated_title="Test title", translated_title_language_code="hi", journal_title="Test titile", short_description="Test desc", citation_type="bibtex", citation_value="Test", type="BOOK_CHAPTER", publication_date=PartialDate.create("2003-07-14"), url="Test org", language_code="en", country="NZ", org_name="Test_orgname", city="Test city", region="Test", is_active=True) WorkInvitee.create(record=wr, first_name="Test", email="*****@*****.**", orcid="12344", visibility="PUBLIC") WorkExternalId.create(record=wr, type="Test_type", value="Test_value", url="Test", relationship="SELF") WorkContributor.create(record=wr, contributor_sequence="first", orcid="1213", role="author", name="xyz", email="*****@*****.**") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scopes="/read-limited,/activities/update", access_token="Test_token") utils.process_work_records() invitee = WorkInvitee.get(orcid="12344") assert 12399 == invitee.put_code assert "12344" == invitee.orcid
def test_create_or_update_funding(app, mocker): """Test create or update funding.""" mocker.patch("orcid_hub.utils.send_email", send_mail_mock) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.create_fundingv3", create_or_update_fund_mock) org = app.data["org"] mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", return_value=get_profile(org=org)) u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="123", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=TaskType.FUNDING) fr = FundingRecord.create(task=t, title="Test titile", translated_title="Test title", translated_title_language_code="hi", type="GRANT", organization_defined_type="Test org", short_description="Test desc", amount="1000", currency="USD", org_name="Test_orgname", city="Test city", region="Test", url="url", start_date=PartialDate.create("2003-07-14"), end_date=PartialDate.create("2004-07-14"), country="NZ", disambiguated_id="Test_dis", disambiguation_source="Test_source", is_active=True) FundingInvitee.create(record=fr, first_name="Test", email="*****@*****.**", visibility="PUBLIC", orcid="123") ExternalId.create(record=fr, type="Test_type", value="Test_value", url="Test", relationship="SELF") FundingContributor.create(record=fr, orcid="1213", role="LEAD", name="Contributor", email="*****@*****.**") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scopes="/read-limited,/activities/update", access_token="Test_token") utils.process_funding_records() funding_invitees = FundingInvitee.get(orcid="12344") assert 12399 == funding_invitees.put_code assert "12344" == funding_invitees.orcid
def test_sync_profile(app, mocker): """Test sync_profile.""" mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.update_employmentv3", return_value=Mock(status=201, headers={'Location': '12344/XYZ/54321'})) mocker.patch( "orcid_api_v3.api.DevelopmentMemberAPIV30Api.update_educationv3", return_value=Mock(status=201, headers={'Location': '12344/XYZ/12345'})) def sync_profile_mock(*args, **kwargs): utils.sync_profile(*args, **kwargs) return Mock(id="test-test-test-test") mocker.patch("orcid_hub.utils.sync_profile.queue", sync_profile_mock) org = Organisation.create( name="THE ORGANISATION:test_sync_profile", tuakiri_name="THE ORGANISATION:test_sync_profile", confirmed=True, orcid_client_id="APP-5ZVH4JRQ0C27RVH5", orcid_secret="Client Secret", city="CITY", country="NZ", disambiguated_id="ID", disambiguation_source="SOURCE") u = User.create(email="*****@*****.**", name="TEST USER", roles=Role.RESEARCHER, orcid="12344", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) utils.sync_profile(task_id=999999) t = Task.create(org=org, task_type=TaskType.SYNC) mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", lambda *args: None) utils.sync_profile(task_id=t.id, delay=0) resp = get_profile() mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", lambda *args: resp) utils.sync_profile(task_id=t.id, delay=0) resp["activities-summary"]["educations"]["affiliation-group"] = [] mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", lambda *args: resp) utils.sync_profile(task_id=t.id, delay=0) mocker.patch("orcid_hub.orcid_client.MemberAPIV3.update_employmentv3", side_effect=Exception("FAILED")) utils.sync_profile(task_id=t.id, delay=0) resp["activities-summary"]["employments"]["affiliation-group"][0][ "summaries"][0]["employment-summary"]["source"] = None resp["activities-summary"]["employments"]["affiliation-group"][0][ "summaries"][0]["employment-summary"]["source"] = None mocker.patch("orcid_hub.orcid_client.MemberAPIV3.get_record", lambda *args: resp) utils.sync_profile(task_id=t.id, delay=0) org.disambiguated_id = None org.save() utils.sync_profile(task_id=t.id, delay=0) assert Log.select().count() > 0
def test_create_or_update_affiliation(patch, test_db, request_ctx): """Test create or update affiliation.""" org = Organisation.create(name="THE ORGANISATION", tuakiri_name="THE ORGANISATION", confirmed=True, orcid_client_id="APP-5ZVH4JRQ0C27RVH5", orcid_secret="Client Secret", city="CITY", country="COUNTRY", disambiguation_org_id="ID", disambiguation_org_source="SOURCE") u = User.create(email="*****@*****.**", name="TEST USER", username="******", roles=Role.RESEARCHER, orcid="123", confirmed=True, organisation=org) UserOrg.create(user=u, org=org) t = Task.create(org=org, filename="xyz.json", created_by=u, updated_by=u, task_type=0) AffiliationRecord.create(is_active=True, task=t, external_id="Test", first_name="Test", last_name="Test", email="*****@*****.**", orcid="123112311231", organisation="asdasd", affiliation_type="staff", role="Test", department="Test", city="Test", state="Test", country="Test", disambiguated_id="Test", disambiguation_source="Test") UserInvitation.create(invitee=u, inviter=u, org=org, task=t, email="*****@*****.**", token="xyztoken") OrcidToken.create(user=u, org=org, scope="/read-limited,/activities/update", access_token="Test_token") tasks = (Task.select( Task, AffiliationRecord, User, UserInvitation.id.alias("invitation_id"), OrcidToken ).where( AffiliationRecord.processed_at.is_null(), AffiliationRecord.is_active, ((User.id.is_null(False) & User.orcid.is_null(False) & OrcidToken.id.is_null(False)) | ((User.id.is_null() | User.orcid.is_null() | OrcidToken.id.is_null()) & UserInvitation.id.is_null() & (AffiliationRecord.status.is_null() | AffiliationRecord.status.contains("sent").__invert__())))).join( AffiliationRecord, on=(Task.id == AffiliationRecord.task_id)).join( User, JOIN.LEFT_OUTER, on=((User.email == AffiliationRecord.email) | (User.orcid == AffiliationRecord.orcid))).join( Organisation, JOIN.LEFT_OUTER, on=(Organisation.id == Task.org_id)). join(UserInvitation, JOIN.LEFT_OUTER, on=((UserInvitation.email == AffiliationRecord.email) & (UserInvitation.task_id == Task.id))).join( OrcidToken, JOIN.LEFT_OUTER, on=((OrcidToken.user_id == User.id) & (OrcidToken.org_id == Organisation.id) & (OrcidToken.scope.contains("/activities/update")) )).limit(20)) for (task_id, org_id, user), tasks_by_user in groupby( tasks, lambda t: ( t.id, t.org_id, t.affiliation_record.user, )): utils.create_or_update_affiliations(user=user, org_id=org_id, records=tasks_by_user) affiliation_record = AffiliationRecord.get(task=t) assert 12399 == affiliation_record.put_code assert "12344" == affiliation_record.orcid assert "Employment record was updated" in affiliation_record.status
def test_affiliation_api(client, mocker): """Test affiliation API in various formats.""" exception = mocker.patch.object(client.application.logger, "exception") capture_event = mocker.patch( "sentry_sdk.transport.HttpTransport.capture_event") resp = client.post( "/oauth/token", content_type="application/x-www-form-urlencoded", data= b"grant_type=client_credentials&client_id=TEST0-ID&client_secret=TEST0-SECRET" ) data = json.loads(resp.data) access_token = data["access_token"] resp = client.post( "/api/v1.0/affiliations/?filename=TEST42.csv", headers=dict(authorization=f"Bearer {access_token}"), content_type="text/csv", data= b"First Name,Last Name,email,Organisation,Affiliation Type,Role,Department,Start Date," b"End Date,City,State,Country,Disambiguated Id,Disambiguated Source\n" b"Researcher,Par,[email protected],Royal Org1,Staff,Programme Guide - " b"ORCID,Research Funding,2016-09,,Wellington,SATE,NZ,,\n" b"Roshan,Pawar,[email protected],Royal Org1,Staff,AAA,Research " b"Funding,2016-09,,Wellington,SATE,NZ,,\n" b"Roshan,Pawar,[email protected],Royal Org1,Student,BBB,Research " b"Funding,2016-09,,Wellington,SATE,New Zealand,,") data = json.loads(resp.data) assert data["filename"] == "TEST42.csv" assert data["task-type"] == "AFFILIATION" assert len(data["records"]) == 3 task_id = data["id"] resp = client.get("/api/v1.0/tasks", headers=dict(authorization=f"Bearer {access_token}")) tasks = json.loads(resp.data) assert tasks[0]["id"] == task_id resp = client.get("/api/v1.0/tasks?type=AFFILIATION", headers=dict(authorization=f"Bearer {access_token}")) tasks = json.loads(resp.data) assert tasks[0]["id"] == task_id resp = client.get("/api/v1.0/tasks?type=AFFILIATION&page=1&page_size=20", headers=dict(authorization=f"Bearer {access_token}")) tasks = json.loads(resp.data) assert tasks[0]["id"] == task_id task_copy = copy.deepcopy(data) del (task_copy["id"]) task_copy["filename"] = "TASK-COPY.csv" resp = client.post("/api/v1.0/affiliations/", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(task_copy)) assert Task.select().count() == 2 for r in data["records"]: del (r["id"]) r["city"] = "TEST000" resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(data)) data = json.loads(resp.data) assert len(resp.json["records"]) == 3 # should get a new set of records del (data["records"][2]) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(data)) assert len(resp.json["records"]) == 2 incorrect_data = copy.deepcopy(data) incorrect_data["records"].insert(0, { "first-name": "TEST000 FN", "last-name": "TEST000 LN", }) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(incorrect_data)) assert resp.status_code == 422 assert resp.json["error"] == "Validation error." resp = client.get(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) incorrect_data = copy.deepcopy(resp.json) incorrect_data["records"].insert( 0, { "email": "*****@*****.**", "first-name": "TEST000 FN", "last-name": "TEST000 LN", }) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(incorrect_data)) assert resp.status_code == 422 assert resp.json["error"] == "Validation error." resp = client.get(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) new_data = copy.deepcopy(resp.json) new_data["records"].insert( 0, { "email": "*****@*****.**", "first-name": "TEST000 FN", "last-name": "TEST000 LN", "affiliation-type": "staff", "city": "TEST000" }) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) data = json.loads(resp.data) assert resp.status_code == 200 assert len(data["records"]) == 3 resp = client.put(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(data)) data = json.loads(resp.data) assert resp.status_code == 200 assert len(resp.json["records"]) == 3 resp = client.get(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) new_data = copy.deepcopy(resp.json) for i, r in enumerate(new_data["records"]): new_data["records"][i] = {"id": r["id"], "is-active": True} resp = client.patch(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) assert resp.status_code == 200 assert len(resp.json["records"]) == 3 assert all(r["is-active"] for r in resp.json["records"]) assert all(r["city"] == "TEST000" for r in resp.json["records"]) resp = client.head(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert "Last-Modified" in resp.headers resp = client.head("/api/v1.0/affiliations/999999999", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 404 resp = client.get("/api/v1.0/affiliations/999999999", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 404 resp = client.patch("/api/v1.0/affiliations/999999999", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) assert resp.status_code == 404 with patch.object(Task, "get", side_effect=Exception("ERROR")): resp = client.delete( f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 400 assert resp.json == { "error": "Unhandled exception occurred.", "exception": "ERROR" } resp = client.delete(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert Task.select().count() == 1 resp = client.delete(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 404 other_user = User.get(email="*****@*****.**") other_task = Task.create(created_by=other_user, org=other_user.organisation, filename="OTHER.csv", task_type=TaskType.AFFILIATION) resp = client.head(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 403 resp = client.get(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 403 resp = client.patch(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) assert resp.status_code == 403 resp = client.delete(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 403 resp = client.patch(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=b'') assert resp.status_code == 400 resp = client.post("/api/v1.0/affiliations/?filename=TEST42.csv", headers=dict(authorization=f"Bearer {access_token}", accept="text/yaml"), content_type="text/yaml", data="""task-type: AFFILIATION filename: TEST42.yml records: - affiliation-type: student city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Roshan last-name: Pawar organisation: Royal Org1 role: BBB start-date: 2016-09 - affiliation-type: staff city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Roshan last-name: Pawar organisation: Royal Org1 role: AAA start-date: 2016-09 - affiliation-type: staff city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Researcher is-active: false last-name: Par organisation: Royal Org1 role: Programme Guide - ORCID start-date: 2016-09 """) assert resp.json["filename"] == "TEST42.yml" assert resp.json["task-type"] == "AFFILIATION" assert len(resp.json["records"]) == 3 task_id = resp.json["id"] task = Task.get(id=task_id) assert task.affiliation_records.count() == 3 resp = client.put(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}", accept="text/yaml"), content_type="text/yaml", data="""task-type: AFFILIATION filename: TEST42.yml records: - affiliation-type: student id: 9999999999 city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Roshan last-name: Pawar organisation: Royal Org1 role: BBB start-date: 2016-09 """) assert resp.status_code == 400 assert resp.json["error"] == "Unhandled exception occurred." assert "Instance matching query does not exist" in resp.json["exception"] with patch.object(AffiliationRecord, "get", side_effect=Exception("ERROR")): resp = client.put(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}", accept="text/yaml"), content_type="text/yaml", data="""task-type: AFFILIATION filename: TEST42.yml records: - affiliation-type: student id: 9999999999 city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Roshan last-name: Pawar organisation: Royal Org1 role: BBB start-date: 2016-09 """) assert resp.status_code == 400 assert resp.json == { "error": "Unhandled exception occurred.", "exception": "ERROR" } resp = client.post(f"/api/v1.0/affiliations/?filename=TEST42.csv", headers=dict(authorization=f"Bearer {access_token}", accept="text/yaml"), content_type="text/yaml", data="""task-type: INCORRECT filename: TEST42.yml records: - affiliation-type: student id: 9999999999 """) assert resp.status_code == 422 assert resp.json["error"] == "Validation error." assert "INCORRECT" in resp.json["message"] resp = client.post("/api/v1.0/affiliations/?filename=TEST_ERROR.csv", headers=dict(authorization=f"Bearer {access_token}", accept="text/yaml"), content_type="text/yaml", data="""task-type: AFFILIATION filename: TEST_ERROR.yml records: - affiliation-type: student something fishy is going here... """) assert resp.status_code == 415 assert resp.json[ "error"] == "Invalid request format. Only JSON, CSV, or TSV are acceptable." assert "something fishy is going here..." in resp.json["message"] exception.assert_called() capture_event.assert_called()
def test_affiliation_api(client): """Test affiliation API in various formats.""" resp = client.post( "/oauth/token", content_type="application/x-www-form-urlencoded", data= b"grant_type=client_credentials&client_id=TEST0-ID&client_secret=TEST0-SECRET" ) data = json.loads(resp.data) access_token = data["access_token"] resp = client.post( "/api/v1.0/affiliations/?filename=TEST42.csv", headers=dict(authorization=f"Bearer {access_token}"), content_type="text/csv", data= b"First Name,Last Name,email,Organisation,Affiliation Type,Role,Department,Start Date," b"End Date,City,State,Country,Disambiguated Id,Disambiguated Source\n" b"Researcher,Par,[email protected],Royal Org1,Staff,Programme Guide - " b"ORCID,Research Funding,2016-09,,Wellington,SATE,NZ,,\n" b"Roshan,Pawar,[email protected],Royal Org1,Staff,AAA,Research " b"Funding,2016-09,,Wellington,SATE,NZ,,\n" b"Roshan,Pawar,[email protected],Royal Org1,Student,BBB,Research " b"Funding,2016-09,,Wellington,SATE,New Zealand,,") data = json.loads(resp.data) assert data["filename"] == "TEST42.csv" assert data["task-type"] == "AFFILIATION" assert len(data["records"]) == 3 task_id = data["id"] resp = client.get("/api/v1.0/tasks", headers=dict(authorization=f"Bearer {access_token}")) tasks = json.loads(resp.data) assert tasks[0]["id"] == task_id task_copy = copy.deepcopy(data) del (task_copy["id"]) task_copy["filename"] = "TASK-COPY.csv" resp = client.post("/api/v1.0/affiliations/", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(task_copy)) assert Task.select().count() == 2 for r in data["records"]: del (r["id"]) r["city"] = "TEST000" resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(data)) data = json.loads(resp.data) assert len(data["records"]) == 3 # should get a new set of records del (data["records"][2]) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(data)) new_data = json.loads(resp.data) assert len(new_data["records"]) == 2 incorrect_data = copy.deepcopy(data) incorrect_data["records"].insert(0, { "first-name": "TEST000 FN", "last-name": "TEST000 LN", }) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(incorrect_data)) data = json.loads(resp.data) assert resp.status_code == 422 assert data["error"] == "Validation error." resp = client.get(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) data = json.loads(resp.data) incorrect_data = copy.deepcopy(data) incorrect_data["records"].insert( 0, { "email": "*****@*****.**", "first-name": "TEST000 FN", "last-name": "TEST000 LN", }) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(incorrect_data)) data = json.loads(resp.data) assert resp.status_code == 422 assert data["error"] == "Validation error." resp = client.get(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) data = json.loads(resp.data) new_data = copy.deepcopy(data) new_data["records"].insert( 0, { "email": "*****@*****.**", "first-name": "TEST000 FN", "last-name": "TEST000 LN", "affiliation-type": "staff", "city": "TEST000" }) resp = client.post(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) data = json.loads(resp.data) assert resp.status_code == 200 assert len(data["records"]) == 3 resp = client.put(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(data)) data = json.loads(resp.data) assert resp.status_code == 200 assert len(data["records"]) == 3 resp = client.get(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) data = json.loads(resp.data) new_data = copy.deepcopy(data) for i, r in enumerate(new_data["records"]): new_data["records"][i] = {"id": r["id"], "is-active": True} resp = client.patch(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) data = json.loads(resp.data) assert resp.status_code == 200 assert len(data["records"]) == 3 assert all(r["is-active"] for r in data["records"]) assert all(r["city"] == "TEST000" for r in data["records"]) resp = client.head(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert "Last-Modified" in resp.headers resp = client.head("/api/v1.0/affiliations/999999999", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 404 resp = client.get("/api/v1.0/affiliations/999999999", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 404 resp = client.patch("/api/v1.0/affiliations/999999999", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) assert resp.status_code == 404 resp = client.delete(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert Task.select().count() == 1 resp = client.delete(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 404 other_user = User.get(email="*****@*****.**") other_task = Task.create(created_by=other_user, org=other_user.organisation, filename="OTHER.csv", task_type=TaskType.AFFILIATION) resp = client.head(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 403 resp = client.get(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 403 resp = client.patch(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=json.dumps(new_data)) assert resp.status_code == 403 resp = client.delete(f"/api/v1.0/affiliations/{other_task.id}", headers=dict(authorization=f"Bearer {access_token}")) assert resp.status_code == 403 resp = client.patch(f"/api/v1.0/affiliations/{task_id}", headers=dict(authorization=f"Bearer {access_token}"), content_type="application/json", data=b'') assert resp.status_code == 400 resp = client.post("/api/v1.0/affiliations/?filename=TEST42.csv", headers=dict(authorization=f"Bearer {access_token}", accept="text/yaml"), content_type="text/yaml", data="""task-type: AFFILIATION filename: TEST42.yml records: - affiliation-type: student city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Roshan last-name: Pawar organisation: Royal Org1 role: BBB start-date: 2016-09 - affiliation-type: staff city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Roshan last-name: Pawar organisation: Royal Org1 role: AAA start-date: 2016-09 - affiliation-type: staff city: Wellington country: NZ department: Research Funding email: [email protected] first-name: Researcher is-active: false last-name: Par organisation: Royal Org1 role: Programme Guide - ORCID start-date: 2016-09 """) data = json.loads(resp.data) assert data["filename"] == "TEST42.yml" assert data["task-type"] == "AFFILIATION" assert len(data["records"]) == 3 task_id = data["id"] task = Task.get(id=task_id) assert task.affiliation_records.count() == 3