Files
notifications-admin/tests/app/models/test_service.py
Ben Thorner 32efb9a03d Fix go-live checks ignoring nested templates
This is a very low impact bug since a user can always create such
templates after their service is live and not be subject to checks
we do before that point. Still, we may as well fix it.

The main benefit of this change is actually to contribute towards
moving methods like "get_templates" out of the Service class so
we can simplify and cache their results more effectively.

Note: I wanted to simplify the Service class further as the two
"has_" properties are only used once in the app code. Unfortunately
they are tightly coupled in one of the tests as well [^1].

[^1]: bef0382cca/tests/app/main/views/service_settings/test_service_settings.py (L1961-L1962)
2022-05-27 12:46:37 +01:00

288 lines
9.5 KiB
Python

import uuid
import pytest
from app.models.organisation import Organisation
from app.models.service import Service
from app.models.user import User
from tests import organisation_json, service_json
from tests.conftest import ORGANISATION_ID, create_folder, create_template
INV_PARENT_FOLDER_ID = '7e979e79-d970-43a5-ac69-b625a8d147b0'
INV_CHILD_1_FOLDER_ID = '92ee1ee0-e4ee-4dcc-b1a7-a5da9ebcfa2b'
VIS_PARENT_FOLDER_ID = 'bbbb222b-2b22-2b22-222b-b222b22b2222'
INV_CHILD_2_FOLDER_ID = 'fafe723f-1d39-4a10-865f-e551e03d8886'
def _get_all_folders(active_user_with_permissions):
return [
{
'name': "Invisible folder",
'id': str(uuid.uuid4()),
'parent_id': None,
'users_with_permission': []
},
{
'name': "Parent 1 - invisible",
'id': INV_PARENT_FOLDER_ID,
'parent_id': None,
'users_with_permission': []
},
{
'name': "1's Visible child",
'id': str(uuid.uuid4()),
'parent_id': INV_PARENT_FOLDER_ID,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': "1's Invisible child",
'id': INV_CHILD_1_FOLDER_ID,
'parent_id': INV_PARENT_FOLDER_ID,
'users_with_permission': []
},
{
'name': "1's Visible grandchild",
'id': str(uuid.uuid4()),
'parent_id': INV_CHILD_1_FOLDER_ID,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': "Parent 2 - visible",
'id': VIS_PARENT_FOLDER_ID,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': "2's Visible child",
'id': str(uuid.uuid4()),
'parent_id': VIS_PARENT_FOLDER_ID,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': "2's Invisible child",
'id': INV_CHILD_2_FOLDER_ID,
'parent_id': VIS_PARENT_FOLDER_ID,
'users_with_permission': []
},
{
'name': "2's Visible grandchild",
'id': str(uuid.uuid4()),
'parent_id': INV_CHILD_2_FOLDER_ID,
'users_with_permission': [active_user_with_permissions['id']],
},
]
def test_get_user_template_folders_only_returns_folders_visible_to_user(
notify_admin,
mock_get_template_folders,
service_one,
active_user_with_permissions,
mocker
):
mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions)
service = Service(service_one)
result = service.get_user_template_folders(User(active_user_with_permissions))
assert result == [
{
'name': ["Parent 1 - invisible", "1's Visible child"],
'id': mocker.ANY,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': ["Parent 1 - invisible", ["1's Invisible child", "1's Visible grandchild"]],
'id': mocker.ANY,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': "2's Visible child",
'id': mocker.ANY,
'parent_id': VIS_PARENT_FOLDER_ID,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': ["2's Invisible child", "2's Visible grandchild"],
'id': mocker.ANY,
'parent_id': VIS_PARENT_FOLDER_ID,
'users_with_permission': [active_user_with_permissions['id']],
},
{
'name': "Parent 2 - visible",
'id': VIS_PARENT_FOLDER_ID,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']],
},
]
def test_get_template_folders_shows_user_folders_when_user_id_passed_in(
notify_admin,
mock_get_template_folders,
service_one,
active_user_with_permissions,
mocker
):
mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions)
service = Service(service_one)
result = service.get_template_folders(user=User(active_user_with_permissions))
assert result == [
{
'name': ["Parent 1 - invisible", "1's Visible child"],
'id': mocker.ANY,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']]
},
{
'name': ["Parent 1 - invisible", ["1's Invisible child", "1's Visible grandchild"]],
'id': mocker.ANY,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']]
},
{
'name': "Parent 2 - visible",
'id': VIS_PARENT_FOLDER_ID,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']]
},
]
def test_get_template_folders_shows_all_folders_when_user_id_not_passed_in(
mock_get_template_folders,
service_one,
active_user_with_permissions,
mocker
):
mock_get_template_folders.return_value = _get_all_folders(active_user_with_permissions)
service = Service(service_one)
result = service.get_template_folders()
assert result == [
{
'name': "Invisible folder",
'id': mocker.ANY,
'parent_id': None,
'users_with_permission': []
},
{
'name': "Parent 1 - invisible",
'id': INV_PARENT_FOLDER_ID,
'parent_id': None,
'users_with_permission': []
},
{
'name': "Parent 2 - visible",
'id': VIS_PARENT_FOLDER_ID,
'parent_id': None,
'users_with_permission': [active_user_with_permissions['id']],
}
]
def test_organisation_type_when_services_organisation_has_no_org_type(mocker, service_one):
service = Service(service_one)
service._dict['organisation_id'] = ORGANISATION_ID
org = organisation_json(organisation_type=None)
mocker.patch('app.organisations_client.get_organisation', return_value=org)
assert not org['organisation_type']
assert service.organisation_type == 'central'
def test_organisation_type_when_service_and_its_org_both_have_an_org_type(mocker, service_one):
# service_one has an organisation_type of 'central'
service = Service(service_one)
service._dict['organisation'] = ORGANISATION_ID
org = organisation_json(organisation_type='local')
mocker.patch('app.organisations_client.get_organisation', return_value=org)
assert service.organisation_type == 'local'
def test_organisation_name_comes_from_cache(mocker, service_one):
mock_redis_get = mocker.patch(
'app.extensions.RedisClient.get',
return_value=b'"Borchester Council"',
)
mock_get_organisation = mocker.patch('app.organisations_client.get_organisation')
service = Service(service_one)
service._dict['organisation'] = ORGANISATION_ID
assert service.organisation_name == 'Borchester Council'
mock_redis_get.assert_called_once_with(f'organisation-{ORGANISATION_ID}-name')
assert mock_get_organisation.called is False
def test_organisation_name_goes_into_cache(mocker, service_one):
mocker.patch(
'app.extensions.RedisClient.get',
return_value=None,
)
mock_redis_set = mocker.patch(
'app.extensions.RedisClient.set',
)
mocker.patch(
'app.organisations_client.get_organisation',
return_value=organisation_json(),
)
service = Service(service_one)
service._dict['organisation'] = ORGANISATION_ID
assert service.organisation_name == 'Test Organisation'
mock_redis_set.assert_called_once_with(
f'organisation-{ORGANISATION_ID}-name',
'"Test Organisation"',
ex=604800,
)
def test_service_without_organisation_doesnt_need_org_api(mocker, service_one):
mock_redis_get = mocker.patch('app.extensions.RedisClient.get')
mock_get_organisation = mocker.patch('app.organisations_client.get_organisation')
service = Service(service_one)
service._dict['organisation'] = None
assert service.organisation_id is None
assert service.organisation_name is None
assert isinstance(service.organisation, Organisation)
assert mock_redis_get.called is False
assert mock_get_organisation.called is False
def test_bad_permission_raises(service_one):
with pytest.raises(KeyError) as e:
Service(service_one).has_permission('foo')
assert str(e.value) == "'foo is not a service permission'"
@pytest.mark.parametrize("purchase_order_number,expected_result", [
[None, None],
["PO1234", [None, None, None, "PO1234"]]
])
def test_service_billing_details(purchase_order_number, expected_result):
service = Service(service_json(purchase_order_number=purchase_order_number))
service._dict['purchase_order_number'] = purchase_order_number
assert service.billing_details == expected_result
def test_has_templates_of_type_includes_folders(
mocker,
service_one,
mock_get_template_folders,
):
mocker.patch(
'app.service_api_client.get_service_templates',
return_value={'data': [create_template(
folder='something', template_type='sms'
)]}
)
mocker.patch(
'app.template_folder_api_client.get_template_folders',
return_value=[create_folder(id='something')]
)
assert Service(service_one).has_templates_of_type('sms')