"""Unit tests for the user_notify logic module.""" from unittest import mock import pytest from permissions.logic import user_notify from permissions.types import IdentityInput @mock.patch('permissions.logic.user_notify.auth0_invite') def test_notify_user_new_identity_with_send_invite(auth0_invite_mock): """Test notify_user_of_changes sends invite for new identity when send_invite=True.""" admin = mock.Mock() assignee = IdentityInput(first_name='A', last_name='B', email='a@b.c') tenant_roles_input = mock.Mock() brand = 'theorchard' user_notify.notify_user_of_changes( admin=admin, assignee=assignee, new_user=True, tenant_roles_input=tenant_roles_input, brand=brand, send_invite=True, ) auth0_invite_mock.send_auth0_invite.assert_called_once_with( admin_identity=admin, assignee_identity=assignee, user_auth0_id=None, tenant_roles_input=tenant_roles_input, brand=brand, vend_contact=None, ) @mock.patch('permissions.logic.user_notify.auth0_invite') def test_notify_user_new_identity_without_send_invite(auth0_invite_mock): """Test notify_user_of_changes does nothing for new identity when send_invite=False.""" user_notify.notify_user_of_changes( admin=mock.Mock(), assignee=IdentityInput(first_name='A', last_name='B', email='a@b.c'), new_user=True, tenant_roles_input=mock.Mock(), brand='theorchard', send_invite=False, ) auth0_invite_mock.send_auth0_invite.assert_not_called() @mock.patch('permissions.logic.user_notify.auth0_invite') def test_notify_user_pending_identity(auth0_invite_mock): """Test notify_user_of_changes sends invite for pending existing identity.""" admin = mock.Mock() assignee = mock.Mock() assignee.is_pending.return_value = True assignee.auth0_user_id = 'auth0|pending' tenant_roles_input = mock.Mock() vend_contact = mock.Mock() user_notify.notify_user_of_changes( admin=admin, assignee=assignee, new_user=False, tenant_roles_input=tenant_roles_input, brand='theorchard', send_invite=True, vend_contact=vend_contact, ) auth0_invite_mock.send_auth0_invite.assert_called_once_with( admin_identity=admin, assignee_identity=assignee, user_auth0_id='auth0|pending', tenant_roles_input=tenant_roles_input, brand='theorchard', vend_contact=vend_contact, ) @mock.patch('permissions.logic.user_notify.auth0_invite') def test_notify_user_pending_identity_without_send_invite(auth0_invite_mock): """Test notify_user_of_changes skips invite for pending identity when send_invite=False.""" assignee = mock.Mock() assignee.is_pending.return_value = True assignee.auth0_user_id = 'auth0|pending' user_notify.notify_user_of_changes( admin=mock.Mock(), assignee=assignee, new_user=False, tenant_roles_input=mock.Mock(), brand='theorchard', send_invite=False, vend_contact=mock.Mock(), ) auth0_invite_mock.send_auth0_invite.assert_not_called() @pytest.mark.parametrize('brand_in_orgs', [True, False]) @pytest.mark.parametrize('has_vend_contact', [True, False]) @mock.patch('permissions.logic.user_notify._should_send_permissions_notification') @mock.patch('permissions.logic.user_notify.notifications') @mock.patch('permissions.logic.user_notify.vend_contact_logic') @mock.patch('permissions.logic.user_notify.mysql') @mock.patch('permissions.logic.user_notify.users') def test_notify_user_active_identity_without_send_invite( users_mock, mysql_mock, vend_contact_logic_mock, notifications_mock, should_send_mock, brand_in_orgs, has_vend_contact, ): """Test notify_user_of_changes for active identity when send_invite=False. Email is suppressed, but the non-email side effects (Auth0 org membership and vend_contact update) still run. """ should_send_mock.return_value = True admin = mock.Mock(id='admin-id', settings_profile=mock.Mock(profile_id=123)) orgs = ['theorchard'] if brand_in_orgs else [] assignee = mock.Mock( id='identity-id', auth0_context=mock.Mock(organizations=orgs, auth0_user_id='auth0|active'), ) assignee.is_pending.return_value = False vend_contact = mock.Mock() if has_vend_contact else None session_mock = mock.Mock() mysql_mock.db_session.return_value.__enter__.return_value = session_mock user_notify.notify_user_of_changes( admin=admin, assignee=assignee, new_user=False, tenant_roles_input=mock.Mock(), brand='theorchard', send_invite=False, vend_contact=vend_contact, ) if brand_in_orgs: users_mock.create_auth0_org_member.assert_not_called() else: users_mock.create_auth0_org_member.assert_called_once_with( brand='theorchard', auth0_user_id='auth0|active', admin=admin, ) if has_vend_contact: vend_contact_logic_mock.set_new_auth0_vend_contact_id.assert_called_once() else: vend_contact_logic_mock.set_new_auth0_vend_contact_id.assert_not_called() notifications_mock.send_user_permissions_updated.assert_not_called() @pytest.mark.parametrize('brand_in_orgs', [True, False]) @pytest.mark.parametrize('has_vend_contact', [True, False]) @mock.patch('permissions.logic.user_notify._should_send_permissions_notification') @mock.patch('permissions.logic.user_notify.notifications') @mock.patch('permissions.logic.user_notify.vend_contact_logic') @mock.patch('permissions.logic.user_notify.mysql') @mock.patch('permissions.logic.user_notify.users') def test_notify_user_active_identity( users_mock, mysql_mock, vend_contact_logic_mock, notifications_mock, should_send_mock, brand_in_orgs, has_vend_contact, ): """Test notify_user_of_changes for active existing identity.""" should_send_mock.return_value = True admin = mock.Mock(id='admin-id', settings_profile=mock.Mock(profile_id=123)) orgs = ['theorchard'] if brand_in_orgs else [] assignee = mock.Mock( id='identity-id', auth0_context=mock.Mock(organizations=orgs, auth0_user_id='auth0|active'), ) assignee.is_pending.return_value = False tenant_roles_input = mock.Mock() vend_contact = mock.Mock() if has_vend_contact else None session_mock = mock.Mock() mysql_mock.db_session.return_value.__enter__.return_value = session_mock user_notify.notify_user_of_changes( admin=admin, assignee=assignee, new_user=False, tenant_roles_input=tenant_roles_input, brand='theorchard', send_invite=True, vend_contact=vend_contact, ) if brand_in_orgs: users_mock.create_auth0_org_member.assert_not_called() else: users_mock.create_auth0_org_member.assert_called_once_with( brand='theorchard', auth0_user_id='auth0|active', admin=admin, ) if has_vend_contact: vend_contact_logic_mock.set_new_auth0_vend_contact_id.assert_called_once() else: vend_contact_logic_mock.set_new_auth0_vend_contact_id.assert_not_called() notifications_mock.send_user_permissions_updated.assert_called_once() @mock.patch('permissions.logic.user_notify._should_send_permissions_notification') @mock.patch('permissions.logic.user_notify.notifications') @mock.patch('permissions.logic.user_notify.users') def test_notify_user_active_no_email_when_ff_off( users_mock, notifications_mock, should_send_mock, ): """Test notify_user_of_changes skips email when feature flag is off.""" should_send_mock.return_value = False assignee = mock.Mock( id='identity-id', auth0_context=mock.Mock(organizations=['theorchard'], auth0_user_id='auth0|active'), ) assignee.is_pending.return_value = False user_notify.notify_user_of_changes( admin=mock.Mock(), assignee=assignee, new_user=False, tenant_roles_input=mock.Mock(), brand='theorchard', send_invite=True, ) notifications_mock.send_user_permissions_updated.assert_not_called() @mock.patch('permissions.logic.user_notify.auth0_invite') def test_notify_employee_created(auth0_invite_mock): """Test notify_employee_created sends invite.""" admin = mock.Mock() assignee = mock.Mock(auth0_user_id='some-uuid') tenant_roles_input = mock.Mock() user_notify.notify_employee_created( admin=admin, assignee=assignee, tenant_roles_input=tenant_roles_input, brand='theorchard', ) auth0_invite_mock.send_auth0_invite.assert_called_once_with( admin_identity=admin, assignee_identity=assignee, user_auth0_id='some-uuid', tenant_roles_input=tenant_roles_input, brand='theorchard', vend_contact=None, ) @mock.patch('permissions.logic.user_notify._should_send_permissions_notification') @mock.patch('permissions.logic.user_notify.notifications') def test_notify_employee_updated( notifications_mock, should_send_mock, ): """Test notify_employee_updated sends permissions email.""" should_send_mock.return_value = True admin = mock.Mock() assignee = mock.Mock( id='identity-id', auth0_context=mock.Mock(organizations=[], auth0_user_id='identity-id'), ) tenant_roles_input = mock.Mock() user_notify.notify_employee_updated( admin=admin, assignee=assignee, tenant_roles_input=tenant_roles_input, brand='theorchard', ) notifications_mock.send_user_permissions_updated.assert_called_once() @mock.patch('permissions.logic.user_notify._should_send_permissions_notification') @mock.patch('permissions.logic.user_notify.notifications') def test_notify_employee_updated_no_email_when_ff_off( notifications_mock, should_send_mock, ): """Test notify_employee_updated skips email when feature flag is off.""" should_send_mock.return_value = False assignee = mock.Mock( id='identity-id', auth0_context=mock.Mock(organizations=['theorchard'], auth0_user_id='auth0|active'), ) user_notify.notify_employee_updated( admin=mock.Mock(), assignee=assignee, tenant_roles_input=mock.Mock(), brand='theorchard', ) notifications_mock.send_user_permissions_updated.assert_not_called()