def test_it_does_not_return_null_values_in_response( test_client: FlaskClient, yesterday: Date, commit: Callable[[], None]) -> None: address = Address(country=countries.get('gb'), city='City', region=None) # produces null value when serialized affiliation = Affiliation( '2', address=address, organisation='Org', department=None, # produces null value when serialized starts=yesterday, restricted=False) profile = Profile('a1b2c3d4', Name('Foo Bar'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**', restricted=False) profile.add_affiliation(affiliation) db.session.add(profile) commit() headers = Headers() headers.set('X-Consumer-Groups', 'View-restricted-profiles, Something else') response = test_client.get('/profiles/a1b2c3d4', headers=headers) data = json.loads(response.data.decode('UTF-8')) assert response.status_code == 200, response.status_code assert response.headers.get( 'Content-Type') == 'application/vnd.elife.profile+json;version=1' assert validate_json(data, schema_name='profile.v1') is True assert contains_none_values(data) is False
def test_it_updates_email_addresses(): profile = Profile('12345678', Name('Name')) profile.add_email_address('*****@*****.**', True, True) orcid_record = { 'person': { 'emails': { 'email': [ { 'email': '*****@*****.**', 'primary': True, 'verified': True, 'visibility': 'PUBLIC' }, ] }, } } update_profile_from_orcid_record(profile, orcid_record) assert len(profile.email_addresses) == 1 assert profile.email_addresses[0].email == '*****@*****.**' assert profile.email_addresses[0].restricted is False assert profile.email_addresses[0].position == 0
def test_it_does_not_return_restricted_data_when_authenticated( test_client: FlaskClient, yesterday: Date, commit: Callable[[], None]) -> None: address = Address(country=countries.get('gb'), city='City', region='Region') affiliation = Affiliation('1', address=address, organisation='Org', department='Dep', starts=yesterday, restricted=True) profile = Profile('a1b2c3d4', Name('Foo Bar'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**', restricted=True) profile.add_affiliation(affiliation) db.session.add(profile) commit() response = test_client.get('/profiles/a1b2c3d4') data = json.loads(response.data.decode('UTF-8')) assert response.status_code == 200 assert response.headers.get( 'Content-Type') == 'application/vnd.elife.profile+json;version=1' assert validate_json(data, schema_name='profile.v1') is True assert not data['affiliations'] assert not data['emailAddresses']
def _update_email_addresses_from_orcid_record(profile: Profile, orcid_record: dict) -> None: orcid_email_dicts = extract_email_addresses(orcid_record) profiles = SQLAlchemyProfiles(db) for index, email_dict in enumerate(orcid_email_dicts): email = email_dict.get('email') try: email_profile = profiles.get_by_email_address(email) except ProfileNotFound: continue if email_profile.id != profile.id: message = ('Profile %s is trying to add email address %s but this ' 'email is associated with profile %s which violates ' 'unique constraint for email addresses' % (profile.id, email, email_profile.id)) LOGGER.error(message) del orcid_email_dicts[index] for email in profile.email_addresses: found = False for orcid_email in orcid_email_dicts: if orcid_email['email'] == email.email: found = True break if not found: profile.remove_email_address(email.email) for orcid_email in orcid_email_dicts: profile.add_email_address( orcid_email['email'], orcid_email['primary'], orcid_email['visibility'] != VISIBILITY_PUBLIC)
def test_it_gets_profiles_by_their_email_address(): profiles = SQLAlchemyProfiles(db) profile1 = Profile('12345678', Name('name1')) profile1.add_email_address('*****@*****.**') profile1.add_email_address('*****@*****.**') profile2 = Profile('12345679', Name('name2')) profile2.add_email_address('*****@*****.**') profiles.add(profile1) profiles.add(profile2) assert profiles.get_by_email_address('*****@*****.**') == profile1 assert profiles.get_by_email_address('*****@*****.**') == profile1 assert profiles.get_by_email_address('*****@*****.**', '*****@*****.**') == profile1 assert profiles.get_by_email_address('*****@*****.**', '*****@*****.**') == profile1 assert profiles.get_by_email_address('*****@*****.**') == profile2 with pytest.raises(ProfileNotFound): profiles.get_by_email_address() with pytest.raises(ProfileNotFound): profiles.get_by_email_address('*****@*****.**') with pytest.raises(ProfileNotFound): profiles.get_by_email_address('*****@*****.**', '*****@*****.**')
def test_it_can_get_only_non_restricted_email_addresses(): profile = Profile('12345678', Name('foo'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**', restricted=True) profile.add_email_address('*****@*****.**') profile.add_email_address('*****@*****.**') assert len(profile.get_email_addresses()) == 2
def test_it_normalizes_profile_with_single_email_address( id_, preferred, index, orcid, email): profile = Profile(id_, Name(preferred, index), orcid) profile.add_email_address(email) normalized_profile = normalize(profile) assert len(normalized_profile['emailAddresses']) == 1
def test_it_can_get_all_email_addresses_including_restricted(): profile = Profile('12345678', Name('foo'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**', restricted=True) profile.add_email_address('*****@*****.**') profile.add_email_address('*****@*****.**') assert len(profile.get_email_addresses(include_restricted=True)) == 3
def test_it_removes_email_addresses(): profile = Profile('12345678', Name('Name')) profile.add_email_address('*****@*****.**') orcid_record = {'person': {}} update_profile_from_orcid_record(profile, orcid_record) assert len(profile.email_addresses) == 0
def test_it_finds_a_profile_by_email_address_when_exchanging( test_client: FlaskClient) -> None: original_profile = Profile('a1b2c3d4', Name('Foo', 'Bar')) original_profile.add_email_address('*****@*****.**') original_profile.add_email_address('*****@*****.**') db.session.add(original_profile) db.session.commit() with requests_mock.Mocker() as mocker: mocker.post('http://www.example.com/oauth/token', json={ 'access_token': '1/fFAGRNJru1FTz70BzhT3Zg', 'expires_in': 3920, 'foo': 'bar', 'token_type': 'Bearer', 'orcid': '0000-0002-1825-0097', 'name': 'Josiah Carberry' }) mocker.get( 'http://www.example.com/api/v2.1/0000-0002-1825-0097/record', json={ 'person': { 'emails': { 'email': [ { 'email': '*****@*****.**', 'primary': True, 'verified': True, 'visibility': 'PUBLIC' }, { 'email': '*****@*****.**', 'primary': False, 'verified': True, 'visibility': 'PUBLIC' }, ] }, } }) response = test_client.post( '/oauth2/token', data={ 'client_id': 'client_id', 'client_secret': 'client_secret', 'redirect_uri': 'http://www.example.com/client/redirect', 'grant_type': 'authorization_code', 'code': '1234' }) assert Profile.query.count() == 1 assert str(original_profile.name) == 'Josiah Carberry' assert [e.email for e in original_profile.email_addresses ] == ['*****@*****.**', '*****@*****.**'] assert response.status_code == 200
def test_it_will_send_event_if_email_address_is_updated(mock_publisher: MagicMock, profile: Profile, session: scoped_session, commit: Callable[[], None]): event_publisher = send_update_events(publisher=mock_publisher) models_committed.connect(receiver=event_publisher) profile.add_email_address('*****@*****.**') session.add(profile) commit() assert mock_publisher.publish.call_count == 1 assert mock_publisher.publish.call_args[0][0] == {'id': '12345678', 'type': 'profile'}
def test_it_normalizes_profile_with_multiple_email_addresses_with_primary_address_first( ): primary_address = '*****@*****.**' profile = Profile('12345678', Name('Foo Bar', 'Bar, Foo'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**') profile.add_email_address('*****@*****.**') profile.add_email_address(primary_address, primary=True) normalized_profile = normalize(profile) assert len(normalized_profile['emailAddresses']) == 3 assert normalized_profile['emailAddresses'][0]['value'] == primary_address
def test_list_of_profiles_only_contains_snippets( test_client: FlaskClient, commit: Callable[[], None]) -> None: profile = Profile('a1b2c3d4', Name('Foo Bar'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**') db.session.add(profile) commit() response = test_client.get('/profiles') data = json.loads(response.data.decode('UTF-8')) assert validate_json(data, schema_name='profile-list.v1') is True assert 'emailAddresses' not in data['items'][0]
def test_it_avoids_email_address_conflicts(): profiles = SQLAlchemyProfiles(db) profile1 = Profile('12345678', Name('name1')) profile1.add_email_address('*****@*****.**') profile2 = Profile('12345679', Name('name2')) profile2.add_email_address('*****@*****.**') profile1 = profiles.add(profile1) profile2 = profiles.add(profile2) assert profile1 == profile2 with pytest.raises(ProfileNotFound): profiles.get('12345679')
def test_does_not_contain_restricted_email_addresses( test_client: FlaskClient, commit: Callable[[], None]) -> None: profile = Profile('a1b2c3d4', Name('Foo Bar'), '0000-0002-1825-0097') profile.add_email_address('*****@*****.**') profile.add_email_address('*****@*****.**', restricted=True) db.session.add(profile) commit() response = test_client.get('/profiles/a1b2c3d4') data = json.loads(response.data.decode('UTF-8')) assert response.status_code == 200 assert response.headers.get( 'Content-Type') == 'application/vnd.elife.profile+json;version=1' assert validate_json(data, schema_name='profile.v1') is True assert [e['value'] for e in data['emailAddresses']] == ['*****@*****.**']
def test_it_sets_a_webhook_when_a_profile_is_updated(profile: Profile, orcid_config: Dict[str, str], mock_orcid_client: MagicMock, session: scoped_session, url_safe_serializer: URLSafeSerializer, commit: Callable[[], None]): session.add(profile) commit() webhook_maintainer = maintain_orcid_webhook(orcid_config, mock_orcid_client, url_safe_serializer) models_committed.connect(receiver=webhook_maintainer) profile.add_email_address('*****@*****.**') session.add(profile) commit() assert mock_orcid_client.set_webhook.call_count == 1 assert mock_orcid_client.set_webhook.call_args[0][0] == '0000-0002-1825-0097' assert mock_orcid_client.set_webhook.call_args[0][1] == 'http://localhost/orcid-webhook/{}' \ .format(url_safe_serializer.dumps('0000-0002-1825-0097'))
def test_it_prevents_unique_constraint_error_when_inserting_existing_email_address( test_client: FlaskClient, webhook_payload: str) -> None: """ This test was added as a result of this issue: https://github.com/elifesciences/issues/issues/4633 """ profile_1 = Profile('a1b2c3d4', Name('Foo Bar')) profile_1.add_email_address('*****@*****.**', restricted=False) profile_2 = Profile('b2c3d4e5', Name('Old Name'), '0000-0002-1825-0097') db.session.add(profile_1) db.session.add(profile_2) db.session.commit() with requests_mock.Mocker() as mocker: mocker.get( 'http://www.example.com/api/v2.1/0000-0002-1825-0097/record', json={ 'person': { 'name': { 'family-name': { 'value': 'Name' }, 'given-names': { 'value': 'New' } }, 'emails': { 'email': [{ 'email': '*****@*****.**', 'primary': True, 'verified': True, 'visibility': 'PUBLIC' }] } } }) response = test_client.post( '/orcid-webhook/{}'.format(webhook_payload)) assert response.status_code == 204 response = test_client.get('/profiles/a1b2c3d4') assert response.status_code == 200 data = json.loads(response.data) assert data['id'] == 'a1b2c3d4' assert data.get('orcid') is None assert data['emailAddresses'][0]['value'] == '*****@*****.**' assert data['name']['preferred'] == 'Foo Bar' response = test_client.get('/profiles/b2c3d4e5') assert response.status_code == 200 data = json.loads(response.data) assert data['id'] == 'b2c3d4e5' assert data['orcid'] == '0000-0002-1825-0097' assert data['emailAddresses'] == [] assert data['name']['preferred'] == 'New Name'