diff --git a/tests/app/main/views/test_organisations.py b/tests/app/main/views/organisations/test_organisation_invites.py similarity index 90% rename from tests/app/main/views/test_organisations.py rename to tests/app/main/views/organisations/test_organisation_invites.py index dc025a4c0..c391bfff2 100644 --- a/tests/app/main/views/test_organisations.py +++ b/tests/app/main/views/organisations/test_organisation_invites.py @@ -5,7 +5,7 @@ import pytest from bs4 import BeautifulSoup from flask import url_for from notifications_python_client.errors import HTTPError -from tests.conftest import normalize_spaces +from tests.conftest import normalize_spaces, ORGANISATION_ID from app.notify_client.models import InvitedOrgUser @@ -42,11 +42,10 @@ def test_organisation_page_shows_all_organisations( def test_view_organisation_shows_the_correct_organisation( - logged_in_platform_admin_client, - fake_uuid, + logged_in_client, mocker ): - org = {'id': fake_uuid, 'name': 'Test 1', 'active': True} + org = {'id': ORGANISATION_ID, 'name': 'Test 1', 'active': True} mocker.patch( 'app.organisations_client.get_organisation', return_value=org ) @@ -54,8 +53,8 @@ def test_view_organisation_shows_the_correct_organisation( 'app.organisations_client.get_organisation_services', return_value=[] ) - response = logged_in_platform_admin_client.get( - url_for('.organisation_dashboard', org_id=fake_uuid) + response = logged_in_client.get( + url_for('.organisation_dashboard', org_id=ORGANISATION_ID) ) assert response.status_code == 200 @@ -85,14 +84,14 @@ def test_create_new_organisation( def test_organisation_services_show( - logged_in_platform_admin_client, + logged_in_client, mock_get_organisation, mock_get_organisation_services, mocker, fake_uuid, ): - response = logged_in_platform_admin_client.get( - url_for('.organisation_dashboard', org_id=mock_get_organisation['id']), + response = logged_in_client.get( + url_for('.organisation_dashboard', org_id=ORGANISATION_ID), ) assert response.status_code == 200 @@ -111,15 +110,15 @@ def test_organisation_services_show( def test_view_team_members( - logged_in_platform_admin_client, + logged_in_client, mocker, mock_get_organisation, mock_get_users_for_organisation, mock_get_invited_users_for_organisation, fake_uuid ): - response = logged_in_platform_admin_client.get( - url_for('.manage_org_users', org_id=fake_uuid), + response = logged_in_client.get( + url_for('.manage_org_users', org_id=ORGANISATION_ID), ) assert response.status_code == 200 @@ -136,11 +135,10 @@ def test_view_team_members( def test_invite_org_user( - logged_in_platform_admin_client, + logged_in_client, mocker, mock_get_organisation, sample_org_invite, - fake_uuid ): mock_invite_org_user = mocker.patch( @@ -148,27 +146,26 @@ def test_invite_org_user( return_value=InvitedOrgUser(**sample_org_invite) ) - logged_in_platform_admin_client.post( - url_for('.invite_org_user', org_id=mock_get_organisation['id']), + logged_in_client.post( + url_for('.invite_org_user', org_id=ORGANISATION_ID), data={'email_address': 'test@example.gov.uk'} ) mock_invite_org_user.assert_called_once_with( sample_org_invite['invited_by'], - '{}'.format(mock_get_organisation['id']), + '{}'.format(ORGANISATION_ID), 'test@example.gov.uk', ) def test_invite_org_user_errors_when_same_email_as_inviter( - logged_in_platform_admin_client, + client_request, mocker, mock_get_organisation, sample_org_invite, - fake_uuid ): new_org_user_data = { - 'email_address': 'platform@admin.gov.uk', + 'email_address': 'test@user.gov.uk', } mock_invite_org_user = mocker.patch( @@ -176,14 +173,13 @@ def test_invite_org_user_errors_when_same_email_as_inviter( return_value=InvitedOrgUser(**sample_org_invite) ) - response = logged_in_platform_admin_client.post( - url_for('.invite_org_user', org_id=mock_get_organisation['id']), - data=new_org_user_data + page = client_request.post( + '.invite_org_user', + org_id=ORGANISATION_ID, + _data=new_org_user_data, + _follow_redirects=True ) - assert response.status_code == 200 - page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') - assert mock_invite_org_user.called is False assert normalize_spaces(page.select_one('.error-message').text) == 'You can’t send an invitation to yourself' @@ -226,7 +222,7 @@ def test_cancelled_invite_opened_by_user( ) == 'If you need access to Org 1, you’ll have to ask them to invite you again.' mock_get_user.assert_called_once_with(fake_uuid) - mock_get_organisation.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af') + mock_get_organisation.assert_called_once_with(ORGANISATION_ID) def test_user_invite_already_accepted( @@ -238,7 +234,7 @@ def test_user_invite_already_accepted( assert response.status_code == 302 assert response.location == url_for( 'main.organisation_dashboard', - org_id='596364a0-858e-42c8-9062-a8fe822260af', + org_id=ORGANISATION_ID, _external=True ) @@ -250,20 +246,19 @@ def test_existing_user_invite_already_is_member_of_organisation( mock_get_users_for_organisation, mock_accept_org_invite, mock_add_user_to_organisation, - fake_uuid ): response = client.get(url_for('main.accept_org_invite', token='thisisnotarealtoken')) assert response.status_code == 302 assert response.location == url_for( 'main.organisation_dashboard', - org_id='596364a0-858e-42c8-9062-a8fe822260af', + org_id=ORGANISATION_ID, _external=True ) - mock_accept_org_invite.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af', ANY) + mock_accept_org_invite.assert_called_once_with(ORGANISATION_ID, ANY) mock_get_user_by_email.assert_called_once_with('invited_user@test.gov.uk') - mock_get_users_for_organisation.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af') + mock_get_users_for_organisation.assert_called_once_with(ORGANISATION_ID) def test_existing_user_invite_not_a_member_of_organisation( @@ -273,22 +268,21 @@ def test_existing_user_invite_not_a_member_of_organisation( mock_get_users_for_organisation, mock_accept_org_invite, mock_add_user_to_organisation, - fake_uuid ): response = client.get(url_for('main.accept_org_invite', token='thisisnotarealtoken')) assert response.status_code == 302 assert response.location == url_for( 'main.organisation_dashboard', - org_id='596364a0-858e-42c8-9062-a8fe822260af', + org_id=ORGANISATION_ID, _external=True ) - mock_accept_org_invite.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af', ANY) + mock_accept_org_invite.assert_called_once_with(ORGANISATION_ID, ANY) mock_get_user_by_email.assert_called_once_with('invited_user@test.gov.uk') - mock_get_users_for_organisation.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af') + mock_get_users_for_organisation.assert_called_once_with(ORGANISATION_ID) mock_add_user_to_organisation.assert_called_once_with( - '596364a0-858e-42c8-9062-a8fe822260af', + ORGANISATION_ID, '6ce466d0-fd6a-11e5-82f5-e0accb9d11a6' ) @@ -306,7 +300,7 @@ def test_user_accepts_invite( mock_check_org_invite_token.assert_called_once_with('thisisnotarealtoken') mock_dont_get_user_by_email.assert_called_once_with('invited_user@test.gov.uk') - mock_get_users_for_organisation.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af') + mock_get_users_for_organisation.assert_called_once_with(ORGANISATION_ID) def test_registration_from_org_invite_404s_if_user_not_in_session( diff --git a/tests/app/main/views/organisations/test_organisations.py b/tests/app/main/views/organisations/test_organisations.py new file mode 100644 index 000000000..da541f008 --- /dev/null +++ b/tests/app/main/views/organisations/test_organisations.py @@ -0,0 +1,179 @@ +import pytest +from bs4 import BeautifulSoup +from flask import url_for +from tests.conftest import normalize_spaces, ORGANISATION_ID + + +@pytest.mark.parametrize('endpoint', ['.organisations', '.add_organisation']) +def test_global_organisation_pages_are_platform_admin_only(client_request, endpoint): + client_request.get( + endpoint, + _expected_status=403, + _test_page_title=False + ) + + +def test_organisation_page_shows_all_organisations( + logged_in_platform_admin_client, + mocker +): + orgs = [ + {'id': '1', 'name': 'Test 1', 'active': True}, + {'id': '2', 'name': 'Test 2', 'active': True}, + {'id': '3', 'name': 'Test 3', 'active': False}, + ] + + mocker.patch( + 'app.organisations_client.get_organisations', return_value=orgs + ) + response = logged_in_platform_admin_client.get( + url_for('.organisations') + ) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + + assert normalize_spaces( + page.select_one('h1').text + ) == "Organisations" + + for index, org in enumerate(orgs): + assert page.select('a.browse-list-link')[index].text == org['name'] + if not org['active']: + assert page.select_one('.table-field-status-default,heading-medium').text == '- archived' + assert normalize_spaces((page.select('a.browse-list-link')[-1]).text) == 'Create an organisation' + + +def test_create_new_organisation( + logged_in_platform_admin_client, + mocker +): + mock_create_organisation = mocker.patch( + 'app.organisations_client.create_organisation' + ) + + org = {'name': 'new name'} + + logged_in_platform_admin_client.post( + url_for('.add_organisation'), + content_type='multipart/form-data', + data=org + ) + + mock_create_organisation.assert_called_once_with(name=org['name']) + + +def test_view_organisation_shows_the_correct_organisation( + logged_in_client, + mocker +): + org = {'id': ORGANISATION_ID, 'name': 'Test 1', 'active': True} + mocker.patch( + 'app.organisations_client.get_organisation', return_value=org + ) + mocker.patch( + 'app.organisations_client.get_organisation_services', return_value=[] + ) + + response = logged_in_client.get( + url_for('.organisation_dashboard', org_id=ORGANISATION_ID) + ) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + + assert normalize_spaces(page.select_one('.heading-large').text) == org['name'] + + +def test_edit_organisation_shows_the_correct_organisation( + logged_in_client, + mocker +): + org = {'id': ORGANISATION_ID, 'name': 'Test 1', 'active': True} + mocker.patch( + 'app.organisations_client.get_organisation', return_value=org + ) + + response = logged_in_client.get( + url_for('.update_organisation', org_id=ORGANISATION_ID) + ) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + + assert page.select_one('#name').attrs.get('value') == org['name'] + + +def test_update_organisation( + logged_in_client, + mocker, +): + org = {'name': 'new name'} + + mocker.patch( + 'app.organisations_client.get_organisation', return_value=org + ) + mock_update_organisation = mocker.patch( + 'app.organisations_client.update_organisation' + ) + + logged_in_client.post( + url_for('.update_organisation', org_id=ORGANISATION_ID), + content_type='multipart/form-data', + data=org + ) + + assert mock_update_organisation.called + mock_update_organisation.assert_called_once_with( + org_id=ORGANISATION_ID, + name=org['name'] + ) + + +def test_organisation_dashboard_shows_services( + logged_in_client, + mock_get_organisation, + mock_get_organisation_services, + mocker, +): + response = logged_in_client.get( + url_for('.organisation_dashboard', org_id=ORGANISATION_ID), + ) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + + assert len(page.select('.browse-list-item')) == 3 + + for i in range(0, 3): + service_name = mock_get_organisation_services(ORGANISATION_ID)[i]['name'] + service_id = mock_get_organisation_services(ORGANISATION_ID)[i]['id'] + + assert normalize_spaces(page.select('.browse-list-item')[i].text) == service_name + assert normalize_spaces( + page.select('.browse-list-item a')[i]['href'] + ) == '/services/{}'.format(service_id) + + +def test_view_team_members( + logged_in_client, + mocker, + mock_get_organisation, + mock_get_users_for_organisation, + mock_get_invited_users_for_organisation, +): + response = logged_in_client.get( + url_for('.manage_org_users', org_id=ORGANISATION_ID), + ) + + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + + for i in range(0, 2): + assert normalize_spaces( + page.select('.user-list-item .heading-small')[i].text + ) == 'Test User {}'.format(i + 1) + + assert normalize_spaces( + page.select('.tick-cross-list-edit-link')[1].text + ) == 'Cancel invitation' diff --git a/tests/conftest.py b/tests/conftest.py index dfd434e5c..ca7627b96 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -704,6 +704,7 @@ def mock_update_service_raise_httperror_duplicate_name(mocker): SERVICE_ONE_ID = "596364a0-858e-42c8-9062-a8fe822260eb" SERVICE_TWO_ID = "147ad62a-2951-4fa1-9ca0-093cd1a52c52" +ORGANISATION_ID = "c011fa40-4cbe-4524-b415-dde2f421bd9c" @pytest.fixture(scope='function') @@ -1165,7 +1166,7 @@ def active_user_with_permissions(fake_uuid): 'view_activity']}, 'platform_admin': False, 'auth_type': 'sms_auth', - 'organisations': [] + 'organisations': [ORGANISATION_ID] } user = User(user_data) return user @@ -2692,7 +2693,7 @@ def mock_update_service_callback_api(mocker): @pytest.fixture(scope='function') def organisation_one(api_user_active): - return organisation_json('596364a0-858e-42c8-9062-a8fe822260af', 'organisation one', [api_user_active.id]) + return organisation_json(ORGANISATION_ID, 'organisation one', [api_user_active.id]) @pytest.fixture(scope='function')