"""Tests for vend_contact logic. Whatever that means.""" from unittest import mock import pytest from permissions.logic import vend_contact from permissions.models import vend_contact as vend_contact_model @mock.patch('permissions.models.vend_contact_role.VendContactRole') @mock.patch('permissions.models.vend_contact.VendContact') @mock.patch('permissions.models.contact.Contact') def test_create_vend_contact_and_roles_existing_profile( contact_cls_mock: mock.MagicMock, vend_contact_cls_mock: mock.MagicMock, vend_contact_role_cls_mock: mock.MagicMock, ) -> None: """Test create_vend_contact_and_roles when there's an existing profile.""" session_mock = mock.Mock() params = { 'session': session_mock, 'role_ids': [1, 2], 'identity': mock.Mock( email='e@ma.il', first_name='🐻‍❄️', last_name='🐼', auth0_user_id='🐻' ), 'vendor_id': 34, 'subaccount_id': 56, 'master_contact': False, 'existing_profile': {'profile_id': 7890}, } existing_vend_contact = mock.Mock(master=vend_contact_model.YNEnum.Y) vend_contact_cls_mock.get_by_id.return_value = existing_vend_contact vc_role_mock1 = mock.Mock() vc_role_mock2 = mock.Mock() vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.return_value = [ vc_role_mock1, vc_role_mock2, ] result = vend_contact.create_vend_contact_and_roles(**params) assert result == existing_vend_contact # Assert vend contact wasn't updated with master=N assert result.master == vend_contact_model.YNEnum.Y # Assert that all methods were called with expected values vend_contact_cls_mock.get_by_id.assert_called_with(session=session_mock, vend_contact_id=7890) contact_cls_mock.create.assert_not_called() vend_contact_cls_mock.create.assert_not_called() vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.assert_called_with( tx=session_mock, vend_contact=existing_vend_contact, role_ids=params['role_ids'], ) # Assert that all instances were added to the session session_mock.add.assert_has_calls( [mock.call(existing_vend_contact), mock.call(vc_role_mock1), mock.call(vc_role_mock2)] ) @mock.patch('permissions.logic.vend_contact.g') @mock.patch('permissions.models.vend_contact_role.VendContactRole') @mock.patch('permissions.models.vend_contact.VendContact') def test_create_vend_contact_and_roles_existing_profile_update_master_contact( vend_contact_cls_mock: mock.MagicMock, vend_contact_role_cls_mock: mock.MagicMock, g_mock: mock.MagicMock, app_context, ) -> None: """Test create_vend_contact_and_roles when profile exists and master contact is updated.""" session_mock = mock.Mock() params = { 'session': session_mock, 'role_ids': [1, 2], 'identity': mock.Mock( id=1, email='e@ma.il', first_name='🐻‍❄️', last_name='🐼', auth0_user_id='🐻' ), 'vendor_id': 34, 'subaccount_id': 56, 'master_contact': True, 'existing_profile': {'profile_id': 7890}, } existing_vend_contact = mock.Mock( master=vend_contact_model.YNEnum.N, active=vend_contact_model.YNEnum.N ) vend_contact_cls_mock.get_by_id.return_value = existing_vend_contact vc_role_mock1 = mock.Mock() vc_role_mock2 = mock.Mock() vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.return_value = [ vc_role_mock1, vc_role_mock2, ] result = vend_contact.create_vend_contact_and_roles(**params) assert result == existing_vend_contact assert result.master == vend_contact_model.YNEnum.Y assert result.active == vend_contact_model.YNEnum.Y assert vend_contact_cls_mock.update_existing_master_contact.called_once_with( tx=session_mock, vendor_id=34, ) g_mock.log.info.assert_called_with( 'Master contact updated for vendor.', resources={'vendor_id': 34, 'identity_id': 1}, ) @mock.patch('permissions.logic.vend_contact.g') @mock.patch('permissions.models.vend_contact.VendContact') def test_create_vend_contact_and_roles_existing_profile_but_no_vc_found( vend_contact_cls_mock: mock.MagicMock, g_mock: mock.MagicMock, app_context, ) -> None: """Test create_vend_contact_and_roles when profile exists but no vend_contact is found.""" vend_contact_cls_mock.get_by_id.return_value = None session_mock = mock.Mock() params = { 'session': session_mock, 'role_ids': [1, 2], 'identity': mock.Mock(), 'vendor_id': 34, 'subaccount_id': 56, 'master_contact': False, 'existing_profile': {'profile_id': 7890}, } with pytest.raises(RuntimeError) as e: vend_contact.create_vend_contact_and_roles(**params) assert str(e) == 'No vend_contact found for existing label profile' g_mock.log.error.assert_called_with( 'No vend_contact found for existing label profile', resources={'label_profile_id': 7890}, ) @mock.patch('permissions.models.vend_contact_role.VendContactRole') @mock.patch('permissions.models.vend_contact.VendContact') @mock.patch('permissions.models.contact.Contact') def test_create_vend_contact_and_roles_no_existing_profile( contact_cls_mock, vend_contact_cls_mock, vend_contact_role_cls_mock, ): """Test create_vend_contact_and_roles when there's no existing profile.""" session_mock = mock.Mock() params = { 'session': session_mock, 'role_ids': [1, 2], 'identity': mock.Mock( email='e@ma.il', first_name='🐻‍❄️', last_name='🐼', auth0_user_id='🐻' ), 'vendor_id': 34, 'subaccount_id': 56, 'master_contact': False, 'existing_profile': None, } contact_mock = mock.Mock() contact_cls_mock.create.return_value = contact_mock vend_contact_id = 789 vend_contact_mock = mock.Mock(id=vend_contact_id) vend_contact_cls_mock.create.return_value = vend_contact_mock vc_role_mock1 = mock.Mock() vc_role_mock2 = mock.Mock() vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.return_value = [ vc_role_mock1, vc_role_mock2, ] result = vend_contact.create_vend_contact_and_roles(**params) # Assert that all methods were called with expected values contact_cls_mock.create.assert_called_with( first_name=params['identity'].first_name, last_name=params['identity'].last_name, email=params['identity'].email, ) # Assert that master_contact update has not been called vend_contact_cls_mock.update_existing_master_contact.assert_not_called() vend_contact_cls_mock.create.assert_called_with( contact=contact_mock, vendor_id=params['vendor_id'], subaccount_id=params['subaccount_id'], email=params['identity'].email, auth0_user_id=params['identity'].auth0_user_id, master=vend_contact_model.YNEnum.N, ) vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.assert_called_with( tx=session_mock, vend_contact=vend_contact_mock, role_ids=params['role_ids'], ) # Assert that all instances were added to the session session_mock.add.assert_has_calls( [ mock.call(contact_mock), mock.call(vend_contact_mock), mock.call(vc_role_mock1), mock.call(vc_role_mock2), ] ) # Assert that the result of the method call is expected assert result == vend_contact_mock @mock.patch('permissions.logic.vend_contact.g') @mock.patch('permissions.models.contact.Contact') @mock.patch('permissions.models.vend_contact.VendContact') @mock.patch('permissions.models.vend_contact_role.VendContactRole') def test_create_vend_contact_and_roles_with_update_master_contact_no_existing_profile( vend_contact_role_cls_mock, vend_contact_cls_mock, contact_cls_mock, g_mock, app_context, ): """Test create_vend_contact_and_roles...""" session_mock = mock.Mock() params = { 'session': session_mock, 'role_ids': [1, 2], 'identity': mock.Mock( email='e@ma.il', first_name='🐻‍❄️', last_name='🐼', auth0_user_id='🐻' ), 'vendor_id': 34, 'subaccount_id': 56, 'master_contact': True, 'existing_profile': None, } contact_mock = mock.Mock() contact_cls_mock.create.return_value = contact_mock vend_contact_id = 789 vend_contact_mock = mock.Mock(id=vend_contact_id) vend_contact_cls_mock.create.return_value = vend_contact_mock vc_role_mock1 = mock.Mock() vc_role_mock2 = mock.Mock() vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.return_value = [ vc_role_mock1, vc_role_mock2, ] vend_contact.create_vend_contact_and_roles(**params) # Assert that master_contact update has been called vend_contact_cls_mock.update_existing_master_contact.assert_called_once_with( tx=session_mock, vendor_id=params['vendor_id'] ) @mock.patch('permissions.logic.vend_contact.owsusers') @mock.patch('permissions.logic.vend_contact.g') @mock.patch('permissions.models.vend_contact.VendContact.get_next_active_for_identity_or_none') def test_set_new_auth0_vend_contact_id_found_one(get_next_mock, g_mock, owsusers_mock, app_context): """Test set_new_auth0_vend_contact_id behavior when a next vend_contact is found.""" vend_contact_id = 1000001 vendor_id = 212435 subaccount_id = 1334 get_next_mock.return_value = mock.Mock( id=vend_contact_id, vendor_id=vendor_id, subaccount_id=subaccount_id, ) session_mock = mock.Mock() identity_id = '⛎-⛎-🆔' auth0_user_id = 'hexvalue' identity_mock = mock.Mock(id=identity_id, auth0_user_id=auth0_user_id) admin_id = 'another-uuid' admin_profile_id = 23523 vend_contact.set_new_auth0_vend_contact_id( session=session_mock, identity=identity_mock, admin_id=admin_id, admin_profile_id=admin_profile_id, ) g_mock.log.info.assert_called_with( 'Setting new auth0 vend_contact for user', resources={ 'identity_id': identity_id, 'vend_contact_id': vend_contact_id, 'vendor_id': vendor_id, 'subaccount_id': subaccount_id, 'admin_identity_id': admin_id, }, ) owsusers_mock.set_auth0_vend_contact_id.assert_called_with( vend_contact_id=vend_contact_id, identity_id=identity_id, auth0_user_id=auth0_user_id, admin_id=admin_id, admin_profile_id=admin_profile_id, ) @mock.patch('permissions.logic.vend_contact.owsusers') @mock.patch('permissions.logic.vend_contact.g') @mock.patch('permissions.models.vend_contact.VendContact.get_next_active_for_identity_or_none') def test_set_new_auth0_vend_contact_id_none_available( get_next_mock, g_mock, owsusers_mock, app_context ): """Test set_new_auth0_vend_contact_id behavior when a next vend_contact is not found.""" get_next_mock.return_value = None identity_id = '⛎-⛎-🆔' identity_mock = mock.Mock(id=identity_id) admin_id = 'test-admin-id' vend_contact.set_new_auth0_vend_contact_id( session=mock.Mock(), identity=identity_mock, admin_id=admin_id, admin_profile_id=mock.Mock() ) g_mock.log.info.assert_called_with( 'Identity has no active vend_contacts; user will not have workstation access', resources={ 'identity_id': identity_id, 'admin_identity_id': admin_id, }, ) owsusers_mock.set_auth0_vend_contact_id.assert_not_called() @pytest.mark.parametrize( 'identity_first_name,identity_last_name,identity_name,expected_first_name,expected_last_name', [ ('FirstName', None, 'John Doe', 'FirstName', 'Doe'), (None, None, None, '', ''), ], ) @mock.patch('permissions.models.vend_contact_role.VendContactRole') @mock.patch('permissions.models.vend_contact.VendContact') @mock.patch('permissions.models.contact.Contact') def test_create_vend_contact_and_roles_parse_name( contact_cls_mock: mock.MagicMock, vend_contact_cls_mock: mock.MagicMock, vend_contact_role_cls_mock: mock.MagicMock, identity_first_name: str | None, identity_last_name: str | None, identity_name: str | None, expected_first_name: str, expected_last_name: str, ) -> None: """Test create_vend_contact_and_roles parses name field when first_name or last_name is null.""" session_mock = mock.Mock() # Configure the mock to properly handle the name attribute identity_mock = mock.Mock(spec=['email', 'first_name', 'last_name', 'name', 'auth0_user_id']) identity_mock.email = 'e@ma.il' identity_mock.first_name = identity_first_name identity_mock.last_name = identity_last_name identity_mock.name = identity_name identity_mock.auth0_user_id = '🐻' params = { 'session': session_mock, 'role_ids': [1, 2], 'identity': identity_mock, 'vendor_id': 34, 'subaccount_id': 56, 'master_contact': False, 'existing_profile': None, } contact_mock = mock.Mock() contact_cls_mock.create.return_value = contact_mock vend_contact_id = 789 vend_contact_mock = mock.Mock(id=vend_contact_id) vend_contact_cls_mock.create.return_value = vend_contact_mock vend_contact_role_cls_mock.create_by_role_ids_if_not_exist.return_value = [] result = vend_contact.create_vend_contact_and_roles(**params) contact_cls_mock.create.assert_called_with( first_name=expected_first_name, last_name=expected_last_name, email=params['identity'].email, ) assert result == vend_contact_mock