"""Tests for profile handlers.""" import json from unittest.mock import call, patch from owsresponse import response import pytest from users import ( constants, # noqa ) from users.logic import profiles @pytest.mark.parametrize( ('profile_json', 'create_profile_response', 'expected_status_code', 'expected_result_data'), ( # 201 created ( { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, response.Response( status=201, message={ 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, ), 201, { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, ), # 201 created, no profile id ( { 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, response.Response( status=201, message={ 'profile_id': 888888889, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, ), 201, { 'profile_id': 888888889, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, ), # 201 Podcast profile created. ( { 'profile_name': 'Test Podcast Profile', 'profile_type': 'PodcastProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Podcast Profile', 'profile_type': 'PodcastProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Podcast Profile', 'profile_type': 'PodcastProfile', 'roles': ['admin'], }, ), # 201 Insights profile created. ( { 'profile_name': 'Test Insights Profile', 'profile_type': 'InsightsProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Insights Profile', 'profile_type': 'InsightsProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Insights Profile', 'profile_type': 'InsightsProfile', 'roles': ['admin'], }, ), # 201 OrchAdminProfile profile created. ( { 'profile_name': 'Test OrchAdmin Profile', 'profile_type': 'OrchAdminProfile', 'roles': ['administrator'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test OrchAdmin Profile', 'profile_type': 'OrchAdminProfile', 'roles': ['administrator'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test OrchAdmin Profile', 'profile_type': 'OrchAdminProfile', 'roles': ['administrator'], }, ), # 201 Abacus profile created. ( { 'profile_name': 'Test Abacus Profile', 'profile_type': 'AbacusProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Abacus Profile', 'profile_type': 'AbacusProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Abacus Profile', 'profile_type': 'AbacusProfile', 'roles': ['admin'], }, ), # 201 Content profile created. ( { 'profile_name': 'Test Content Profile', 'profile_type': 'ContentProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Content Profile', 'profile_type': 'ContentProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Content Profile', 'profile_type': 'ContentProfile', 'roles': ['admin'], }, ), # 201 Distribution profile created. ( { 'profile_name': 'Test DistributionProfile', 'profile_type': 'DistributionProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test DistributionProfile', 'profile_type': 'DistributionProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test DistributionProfile', 'profile_type': 'DistributionProfile', 'roles': ['admin'], }, ), # 201 Publishing profile created. ( { 'profile_name': 'Test Publishing Profile', 'profile_type': 'PublishingProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Publishing Profile', 'profile_type': 'PublishingProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Publishing Profile', 'profile_type': 'PublishingProfile', 'roles': ['admin'], }, ), # 201 Moneyhub profile created. ( { 'profile_name': 'Test Moneyhub Profile', 'profile_type': 'MoneyhubProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Moneyhub Profile', 'profile_type': 'MoneyhubProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Moneyhub Profile', 'profile_type': 'MoneyhubProfile', 'roles': ['admin'], }, ), # 201 Collaborator profile created. ( { 'profile_name': 'Test Collaborator Profile', 'profile_type': 'CollaboratorsProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Collaborators Profile', 'profile_type': 'CollaboratorsProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Collaborators Profile', 'profile_type': 'CollaboratorsProfile', 'roles': ['admin'], }, ), # 201 Documents profile created. ( { 'profile_name': 'Test Documents Profile', 'profile_type': 'DocumentsProfile', 'roles': ['payee_management'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Documents Profile', 'profile_type': 'DocumentsProfile', 'roles': ['payee_management'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Documents Profile', 'profile_type': 'DocumentsProfile', 'roles': ['payee_management'], }, ), # 201 Audience profile created. ( { 'profile_name': 'Test Audience Profile', 'profile_type': 'AudienceProfile', 'roles': ['admin'], }, response.Response( status=201, message={ 'profile_id': 888888899, 'profile_name': 'Test Audience Profile', 'profile_type': 'AudienceProfile', 'roles': ['admin'], }, ), 201, { 'profile_id': 888888899, 'profile_name': 'Test Audience Profile', 'profile_type': 'AudienceProfile', 'roles': ['admin'], }, ), # 404 identity does not exist ( { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, response.create_not_found_response(message=constants.ERROR_MESSAGE_IDENTITY_NOT_FOUND), 404, {'code': 'not_found_error', 'message': constants.ERROR_MESSAGE_IDENTITY_NOT_FOUND}, ), # 400 invalid profile type ( { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'banana', 'roles': ['catalog', 'analytics'], }, response.create_error_response( code=constants.ERROR_CODE_PROFILE_VALIDATION_ERROR, message={'profile_type': ['Invalid enum member banana']}, ), 400, { 'code': constants.ERROR_CODE_PROFILE_VALIDATION_ERROR, 'message': {'profile_type': ['Invalid enum member banana']}, }, ), # 400 missing required fields ( {'profile_id': 555, 'roles': ['catalog', 'analytics']}, response.create_error_response( code=constants.ERROR_CODE_PROFILE_VALIDATION_ERROR, message={'profile_type': ['Invalid enum member banana']}, ), 400, { 'code': constants.ERROR_CODE_PROFILE_VALIDATION_ERROR, 'message': { 'profile_name': ['Missing data for required field.'], 'profile_type': ['Missing data for required field.'], }, }, ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_create_profile_handler( neo4j_exit, neo4j_enter, mocker, fixture_client, profile_json, create_profile_response, expected_status_code, expected_result_data, ): """Test 'POST /profile/identity/' handler.""" orchard_identity_id = '5c00e1ea4e00d94722205b05' create_profile_mock = mocker.patch('users.logic.profiles.create_profile') create_profile_mock.return_value = create_profile_response handler_response = fixture_client.post( '/profile/identity/{IDENTITY_ID}'.format(IDENTITY_ID=orchard_identity_id), json=profile_json ) result_data = json.loads(handler_response.data.decode()) if result_data.get('code') != (constants.ERROR_CODE_PROFILE_VALIDATION_ERROR): assert create_profile_mock.called create_profile_mock.assert_called_with(orchard_identity_id, profile_json) assert handler_response.status_code == expected_status_code assert result_data == expected_result_data @pytest.mark.parametrize( ('get_profile_response', 'expected_status_code', 'expected_result_data'), ( # 204 deleted ( response.Response( message={ 'profile_id': 555, 'profile_name': 'Updated Profile Name', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], } ), 200, { 'profile_id': 555, 'profile_name': 'Updated Profile Name', 'profile_type': 'ArtistProfile', 'roles': ['catalog', 'analytics'], }, ), # 404 profile not found ( response.create_not_found_response(message=constants.ERROR_MESSAGE_PROFILE_NOT_FOUND), 404, {'code': 'not_found_error', 'message': constants.ERROR_MESSAGE_PROFILE_NOT_FOUND}, ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_get_profile_handler( neo4j_exit, neo4j_enter, mocker, fixture_client, get_profile_response, expected_status_code, expected_result_data, ): """Test 'GET /profile/profile_id//profile_type/' handler.""" # noqa profile_id = 8888 profile_type = 'ArtistProfile' get_profile_mock = mocker.patch('users.logic.profiles.get_profile') get_profile_mock.return_value = get_profile_response handler_response = fixture_client.get( ('/profile/profile_id/{PROFILE_ID}/profile_type/{PROFILE_TYPE}').format( PROFILE_ID=profile_id, PROFILE_TYPE=profile_type ) ) result_data = None if handler_response.data.decode() != '': result_data = json.loads(handler_response.data.decode()) if handler_response.status_code != 404: assert get_profile_mock.called get_profile_mock.assert_called_with(profile_id, profile_type) assert handler_response.status_code == expected_status_code assert result_data == expected_result_data @pytest.mark.parametrize( ('request_url', 'expected_status_code', 'expected_result_data'), ( ( '/profile/profile_id/78159/profile_type/LabelProfile', 200, {'get_profile': 'called'}, ), ( '/profile/profile_id/b67ff9f2-dfa7-49f1-8f57-f7d0e73c2319/profile_type/LabelProfile', 200, {'get_profile_by_uuid': 'called'}, ), ( '/profile/profile_uuid/b67ff9f2-dfa7-49f1-8f57-f7d0e73c2319', 200, {'get_profile_by_uuid': 'called'}, ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_get_profile_handler_variations( neo4j_exit, neo4j_enter, mocker, fixture_client, request_url, expected_status_code, expected_result_data, ): """Test various 'GET /profile' calls.""" # noqa get_profile_response = response.Response({'get_profile': 'called'}) get_profile_uuid_response = response.Response({'get_profile_by_uuid': 'called'}) mocker.patch('users.logic.profiles.get_profile', return_value=get_profile_response) mocker.patch('users.logic.profiles.get_profile_by_uuid', return_value=get_profile_uuid_response) handler_response = fixture_client.get(request_url) assert handler_response.status_code == expected_status_code result_data = json.loads(handler_response.data.decode()) assert result_data == expected_result_data @pytest.mark.parametrize( ('delete_profile_response', 'expected_status_code', 'expected_result_data'), ( # 204 deleted (response.Response(status=204), 204, None), # 404 profile not found ( response.create_not_found_response(message=constants.ERROR_MESSAGE_PROFILE_NOT_FOUND), 404, {'code': 'not_found_error', 'message': constants.ERROR_MESSAGE_PROFILE_NOT_FOUND}, ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_delete_profile_handler( neo4j_exit, neo4j_enter, mocker, fixture_client, delete_profile_response, expected_status_code, expected_result_data, ): """Test 'DELETE /profile/profile_id//profile_type/' handler.""" # noqa profile_id = 8888 profile_type = 'ArtistProfile' delete_profile_mock = mocker.patch('users.logic.profiles.delete_profile') delete_profile_mock.return_value = delete_profile_response handler_response = fixture_client.delete( ('/profile/profile_id/{PROFILE_ID}/profile_type/{PROFILE_TYPE}').format( PROFILE_ID=profile_id, PROFILE_TYPE=profile_type ) ) result_data = None if handler_response.data.decode() != '': result_data = json.loads(handler_response.data.decode()) if handler_response.status_code != 404: assert delete_profile_mock.called delete_profile_mock.assert_called_with(profile_id, profile_type) assert handler_response.status_code == expected_status_code assert result_data == expected_result_data @pytest.mark.parametrize( ('request_url', 'expected_status_code', 'uuid_called', 'call_args'), ( ( '/profile/profile_id/78159/profile_type/LabelProfile', 204, False, (78159, 'LabelProfile'), ), ( '/profile/profile_id/b67ff9f2-dfa7-49f1-8f57/profile_type/LabelProfile', 204, True, ('b67ff9f2-dfa7-49f1-8f57',), ), ('/profile/profile_uuid/b67ff9f2-dfa7-49f1-8f57', 204, True, ('b67ff9f2-dfa7-49f1-8f57',)), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_delete_profile_variety( neo4j_exit, neo4j_enter, mocker, fixture_client, request_url, expected_status_code, uuid_called, call_args, ): """Test various 'DELETE /profile' calls.""" delete_profile = response.Response({'delete_profile': 'called'}, status=204) delete_profile_by_uuid = response.Response({'delete_profile_by_uuid': 'called'}, status=204) mocker.patch('users.logic.profiles.delete_profile', return_value=delete_profile) mocker.patch('users.logic.profiles.delete_profile_by_uuid', return_value=delete_profile_by_uuid) handler_response = fixture_client.delete(request_url) assert handler_response.status_code == expected_status_code if uuid_called: profiles.delete_profile_by_uuid.assert_called_once_with(*call_args) else: profiles.delete_profile.assert_called_once_with(*call_args) @pytest.mark.parametrize( ( 'profile_id', 'profile_type', 'payload', 'update_profile_response', 'expected_status_code', 'expected_result_data', ), ( # 200 ok, patched ( 555, 'ArtistProfile', {'profile_name': 'Test Profile', 'roles': ['analytics', 'catalog']}, response.Response( message={ 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['analytics', 'catalog'], } ), 200, { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['analytics', 'catalog'], }, ), # 200 ok, name only ( 555, 'ArtistProfile', {'profile_name': 'Test Profile'}, response.Response( message={ 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['analytics', 'catalog'], } ), 200, { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['analytics', 'catalog'], }, ), # 200 ok, name for PodcastProfile ( 555, 'PodcastProfile', {'profile_name': 'Updated Profile Name'}, response.Response( message={ 'profile_id': 666, 'profile_name': 'Updated Profile Name', 'profile_type': 'PodcastProfile', 'roles': ['administrator'], } ), 200, { 'profile_id': 666, 'profile_name': 'Updated Profile Name', 'profile_type': 'PodcastProfile', 'roles': ['administrator'], }, ), # 200 ok, name for InsightsProfile ( 555, 'InsightsProfile', {'profile_name': 'Updated Profile Name'}, response.Response( message={ 'profile_id': 666, 'profile_name': 'Updated Profile Name', 'profile_type': 'InsightsProfile', 'roles': ['administrator'], } ), 200, { 'profile_id': 666, 'profile_name': 'Updated Profile Name', 'profile_type': 'InsightsProfile', 'roles': ['administrator'], }, ), # 200 ok, name for OrchAdminProfile ( 555, 'OrchAdminProfile', {'profile_name': 'Updated Profile Name'}, response.Response( message={ 'profile_id': 666, 'profile_name': 'Updated Profile Name', 'profile_type': 'OrchAdminProfile', 'roles': ['administrator'], } ), 200, { 'profile_id': 666, 'profile_name': 'Updated Profile Name', 'profile_type': 'OrchAdminProfile', 'roles': ['administrator'], }, ), # 200 ok, only updates name and roles ( 555, 'ArtistProfile', { 'profile_id': 777, 'profile_type': 'LabelProfile', 'profile_name': 'Test Profile', 'roles': ['analytics', 'catalog'], }, response.Response( message={ 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['analytics', 'catalog'], } ), 200, { 'profile_id': 555, 'profile_name': 'Test Profile', 'profile_type': 'ArtistProfile', 'roles': ['analytics', 'catalog'], }, ), # 400 error validating partial field types ( 555, 'ArtistProfile', { 'profile_name': 999, 'roles': 'banana', }, None, 400, { 'code': constants.ERROR_CODE_VALIDATION_ERROR, 'message': { 'profile_name': ['Not a valid string.'], 'roles': ['Not a valid list.'], }, }, ), # 404 profile does not exist ( 999999, 'ArtistProfile', {'profile_name': 'Test Profile', 'roles': ['analytics', 'catalog']}, response.create_not_found_response(message=constants.ERROR_MESSAGE_PROFILE_NOT_FOUND), 404, {'code': 'not_found_error', 'message': constants.ERROR_MESSAGE_PROFILE_NOT_FOUND}, ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_update_profile_handler( neo4j_exit, neo4j_enter, mocker, fixture_client, profile_id, profile_type, payload, update_profile_response, expected_status_code, expected_result_data, ): """Test 'PATCH /profile/profile_id//profile_type/' handler.""" # noqa update_profile_mock = mocker.patch('users.logic.profiles.update_profile') update_profile_mock.return_value = update_profile_response handler_response = fixture_client.patch( ('/profile/profile_id/{PROFILE_ID}/profile_type/{PROFILE_TYPE}').format( PROFILE_ID=profile_id, PROFILE_TYPE=profile_type ), json=payload, ) result_data = json.loads(handler_response.data.decode()) if result_data.get('code') != (constants.ERROR_CODE_PROFILE_VALIDATION_ERROR): assert update_profile_mock.called update_profile_mock.assert_called_with(profile_id, profile_type, payload) assert handler_response.status_code == expected_status_code assert result_data == expected_result_data @pytest.mark.parametrize( ( 'identity_id', 'profile_id', 'profile_type', 'add_profile_to_identity_response', 'expected_status_code', 'expected_result_data', ), ( # 200 ok ('123456789abcdefghijklm', 12345, 'InsightsProfile', response.Response(), 200, 'null'), # 400 validation error ( '12345abc', 12345, 'InsightsProfile', None, 400, """{"code": "validation_error", "message": {"identity_id": ["Length must be between 22 and 36."]}}""", # noqa ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_add_profile_to_identity( neo4j_exit, neo4j_enter, mocker, fixture_client, identity_id, profile_id, profile_type, add_profile_to_identity_response, expected_status_code, expected_result_data, ): """Test 'POST /users/identity//profile//' handler.""" # noqa add_profile_to_identity_mock = mocker.patch('users.logic.profiles.add_profile_to_identity') add_profile_to_identity_mock.return_value = add_profile_to_identity_response handler_response = fixture_client.post( ('/users/identity/{IDENTITY_ID}/profile/{PROFILE_TYPE}/{PROFILE_ID}').format( IDENTITY_ID=identity_id, PROFILE_TYPE=profile_type, PROFILE_ID=profile_id ) ) result_data = None if handler_response: result_data = json.dumps(handler_response.json) if add_profile_to_identity_response is not None: add_profile_to_identity_mock.assert_called_with(identity_id, profile_id, profile_type) assert handler_response.status_code == expected_status_code assert result_data == expected_result_data @pytest.mark.parametrize( ( 'identity_id', 'profile_id', 'profile_type', 'delete_profile_to_identity_response', 'expected_status_code', 'expected_result_data', ), ( # 200 ok ('123456789abcdefghijklm', 12345, 'InsightsProfile', response.Response(), 200, None), # 400 validation error ( '12345abc', 12345, 'InsightsProfile', None, 400, """{"code": "validation_error", "message": {"identity_id": ["Length must be between 22 and 36."]}}""", # noqa ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_delete_profile_to_identity_handler( neo4j_exit, neo4j_enter, mocker, fixture_client, identity_id, profile_id, profile_type, delete_profile_to_identity_response, expected_status_code, expected_result_data, ): """Test 'DELETE /users/identity//profile//' handler.""" # noqa delete_profile_to_identity_mock = mocker.patch( 'users.logic.profiles.delete_profile_to_identity' ) delete_profile_to_identity_mock.return_value = delete_profile_to_identity_response handler_response = fixture_client.delete( ('/users/identity/{IDENTITY_ID}/profile/{PROFILE_TYPE}/{PROFILE_ID}').format( IDENTITY_ID=identity_id, PROFILE_TYPE=profile_type, PROFILE_ID=profile_id ) ) result_data = None if handler_response.json: result_data = json.dumps(handler_response.json) if delete_profile_to_identity_response is not None: delete_profile_to_identity_mock.assert_called_with(identity_id, profile_id, profile_type) assert handler_response.status_code == expected_status_code assert result_data == expected_result_data @pytest.mark.parametrize( 'url_prefix', ['/profile', '/auth0/users/profile'], ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_get_identity_for_profile(neo4j_exit, neo4j_enter, mocker, fixture_client, url_prefix): """Test test_get_identity_for_profile.""" profile_id = 12345 profile_type = 'Account360Profile' expected_response = response.Response( {'name': 'New User', 'email': 'test@theorchard.com', 'id': '5dd7d78c4ec49c0e2c4e4d1f'} ) get_mock = mocker.patch('users.logic.profiles.get_identity_for_profile') get_mock.return_value = expected_response handler_response = fixture_client.get( f'{url_prefix}/profile_id/{profile_id}/profile_type/{profile_type}/identity' ) # noqa assert get_mock.called get_mock.assert_called_with(profile_id, profile_type) assert handler_response.status_code == 200 @pytest.mark.parametrize( ('request_url', 'expected_status_code', 'expected_result_data'), ( ( '/profile/profile_id/78159/profile_type/LabelProfile/identity', 200, {'get_identity_for_profile': 'called'}, ), ( '/profile/profile_id/b67ff9f2-dfa7-49f1-8f57/profile_type/LabelProfile/identity', 200, {'get_identity_for_profile_uuid': 'called'}, ), ( '/profile/profile_uuid/b67ff9f2-dfa7-49f1-8f57/identity', 200, {'get_identity_for_profile_uuid': 'called'}, ), ( '/auth0/users/profile/profile_id/78159/profile_type/LabelProfile/identity', 200, {'get_identity_for_profile': 'called'}, ), ( '/auth0/users/profile/profile_id/b67ff9f2-dfa7-49f1-8f57/profile_type/LabelProfile/identity', # noqa: E501 200, {'get_identity_for_profile_uuid': 'called'}, ), ( '/auth0/users/profile/profile_uuid/b67ff9f2-dfa7-49f1-8f57/identity', 200, {'get_identity_for_profile_uuid': 'called'}, ), ), ) @patch('users.handlers.profile.Neo4jSession.__enter__') @patch('users.handlers.profile.Neo4jSession.__exit__') def test_get_identity_for_profile_variety( neo4j_exit, neo4j_enter, mocker, fixture_client, request_url, expected_status_code, expected_result_data, ): """Test test_get_identity_for_profile for diff urls.""" get_profile_response = response.Response({'get_identity_for_profile': 'called'}) get_profile_uuid_response = response.Response({'get_identity_for_profile_uuid': 'called'}) mocker.patch('users.logic.profiles.get_identity_for_profile', return_value=get_profile_response) mocker.patch( 'users.logic.profiles.get_identity_for_profile_uuid', return_value=get_profile_uuid_response ) handler_response = fixture_client.get(request_url) assert handler_response.status_code == expected_status_code result_data = json.loads(handler_response.data.decode()) assert result_data == expected_result_data @pytest.mark.parametrize( ( 'headers', 'args', 'identity_response', 'applications_response', 'expected_code', 'expected_message', 'expected_get_applications_call', 'expected_get_identity_call', ), ( # Success cases pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, {}, response.Response({'identity': {'default_brand': constants.ORCHARD_BRAND}}, status=200), response.Response({'applications': 'data'}, status=200), 200, {'applications': 'data'}, call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08', None, constants.ORCHARD_BRAND, None, None), call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08'), id='success', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'resource_type': 'Vendor', 'resource_uuid': '39844906-b611-44f4-acf7-07dcb33af6cb', }, response.Response({'identity': {'default_brand': constants.ORCHARD_BRAND}}, status=200), response.Response({'applications': 'data'}, status=200), 200, {'applications': 'data'}, call( '46b961bb-ecaa-4fa7-a7b5-93ec651ddd08', None, constants.ORCHARD_BRAND, 'Vendor', '39844906-b611-44f4-acf7-07dcb33af6cb', ), call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08'), id='success with filter by resource', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'brand': constants.AWAL_BRAND, }, response.Response({'identity': {'default_brand': constants.ORCHARD_BRAND}}, status=200), response.Response({'applications': 'data'}, status=200), 200, {'applications': 'data'}, call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08', None, constants.AWAL_BRAND, None, None), call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08'), id='success with brand override', ), # Identity not found pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, {}, response.Response(errors={'identity': 'not_found'}, status=404), None, 404, {'identity': 'not_found'}, None, call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08'), id='identity not found', ), # Applications not found pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, {}, response.Response({'identity': {'default_brand': constants.ORCHARD_BRAND}}, status=200), response.Response(errors={'applications': 'not_found'}, status=404), 404, {'applications': 'not_found'}, call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08', None, constants.ORCHARD_BRAND, None, None), call('46b961bb-ecaa-4fa7-a7b5-93ec651ddd08'), id='applications not found', ), # Validation error cases pytest.param( {}, {}, None, None, 400, { 'code': 'bad_request', 'message': 'invalid combination of profile_type, profile_id, and identity_id', }, None, None, id='validation error: invalid combination of profile_type, profile_id, and identity_id', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'brand': 'INVALID', }, None, None, 400, { 'code': 'validation_error', 'message': { 'brand': [ 'Must be one of: theorchard, sme, overdrive, awal, knr, orchard, ' 'helpcenter, ab, msk, altafonte.' ] }, }, None, None, id='validation error: invalid brand', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'resource_type': 'INVALID', 'resource_uuid': '46b961bb-ecaa-4fa7-a7b5-93ec651ddd08', }, None, None, 400, { 'code': 'validation_error', 'message': { 'resource_type': [ 'Must be one of: Vendor, SubAccount, LabelParticipant, Collaborator.' ] }, }, None, None, id='validation error: invalid resource_type', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'resource_type': 'Vendor', 'resource_uuid': 'INVALID', }, None, None, 400, {'code': 'validation_error', 'message': {'resource_uuid': ['Not a valid UUID.']}}, None, None, id='validation error: invalid resource_uuid', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'resource_type': 'Vendor', }, None, None, 400, { 'code': 'validation_error', 'message': { '_schema': ['resource_type and resource_uuid must be provided together.'] }, }, None, None, id='validation error: missing resource_uuid', ), pytest.param( {'Orchard-Profile-Type': 'SettingsProfile', 'Orchard-Profile-Id': '363462'}, { 'resource_uuid': '46b961bb-ecaa-4fa7-a7b5-93ec651ddd08', }, None, None, 400, { 'code': 'validation_error', 'message': { '_schema': ['resource_type and resource_uuid must be provided together.'] }, }, None, None, id='validation error: missing resource_type', ), ), ) def test_get_applications( headers, args, identity_response, applications_response, expected_code, expected_message, expected_get_applications_call, expected_get_identity_call, mocker, fixture_client, ): """Test get_applications handler.""" mocker.patch('users.handlers.profile.Neo4jSession.__enter__') mocker.patch('users.handlers.profile.Neo4jSession.__exit__') mocker.patch.object(profiles, 'get_identity_from_graph_tx', return_value=identity_response) mocker.patch.object( profiles, 'get_applications_for_identity_tx', return_value=applications_response ) identity_id = '46b961bb-ecaa-4fa7-a7b5-93ec651ddd08' url = f'/users/identity/{identity_id}/applications' if args: url += '?' + '&'.join([f'{key}={value}' for key, value in args.items()]) handler_response = fixture_client.get(url, headers=headers) assert handler_response.status_code == expected_code result = json.loads(handler_response.data.decode()) assert result == expected_message if expected_get_identity_call: profiles.get_identity_from_graph_tx.assert_called_once_with( *expected_get_identity_call.args, **expected_get_identity_call.kwargs ) else: profiles.get_identity_from_graph_tx.assert_not_called() if expected_get_applications_call: profiles.get_applications_for_identity_tx.assert_called_once_with( *expected_get_applications_call.args, **expected_get_applications_call.kwargs ) else: profiles.get_applications_for_identity_tx.assert_not_called()