Files
notifications-admin/tests/app/main/views/test_organisations.py
Chris Hill-Scott f3a0c505bd Enforce order and style of imports
Done using isort[1], with the following command:
```
isort -rc ./app ./tests
```

Adds linting to the `run_tests.sh` script to stop badly-sorted imports
getting re-introduced.

Chosen style is ‘Vertical Hanging Indent’ with trailing commas, because
I think it gives the cleanest diffs, eg:
```
from third_party import (
    lib1,
    lib2,
    lib3,
    lib4,
)
```

1. https://pypi.python.org/pypi/isort
2018-02-27 16:35:13 +00:00

518 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from datetime import datetime, timedelta
from unittest.mock import ANY
import pytest
from bs4 import BeautifulSoup
from flask import url_for
from tests.conftest import normalize_spaces
from app.notify_client.models import InvitedOrgUser
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_view_organisation_shows_the_correct_organisation(
logged_in_platform_admin_client,
fake_uuid,
mocker
):
org = {'id': fake_uuid, '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_platform_admin_client.get(
url_for('.organisation_dashboard', org_id=fake_uuid)
)
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_platform_admin_client,
fake_uuid,
mocker
):
org = {'id': fake_uuid, 'name': 'Test 1', 'active': True}
mocker.patch(
'app.organisations_client.get_organisation', return_value=org
)
response = logged_in_platform_admin_client.get(
url_for('.update_organisation', org_id=fake_uuid)
)
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_create_new_organisation(
logged_in_platform_admin_client,
mocker,
fake_uuid
):
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_update_organisation(
logged_in_platform_admin_client,
mocker,
fake_uuid,
):
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_platform_admin_client.post(
url_for('.update_organisation', org_id=fake_uuid),
content_type='multipart/form-data',
data=org
)
assert mock_update_organisation.called
mock_update_organisation.assert_called_once_with(
org_id=fake_uuid,
name=org['name']
)
def test_organisation_services_show(
logged_in_platform_admin_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']),
)
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(mock_get_organisation['id'])[i]['name']
service_id = mock_get_organisation_services(mock_get_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_platform_admin_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),
)
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'
def test_invite_org_user(
logged_in_platform_admin_client,
mocker,
mock_get_organisation,
sample_org_invite,
fake_uuid
):
mock_invite_org_user = mocker.patch(
'app.org_invite_api_client.create_invite',
return_value=InvitedOrgUser(**sample_org_invite)
)
logged_in_platform_admin_client.post(
url_for('.invite_org_user', org_id=mock_get_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']),
'test@example.gov.uk',
)
def test_invite_org_user_errors_when_same_email_as_inviter(
logged_in_platform_admin_client,
mocker,
mock_get_organisation,
sample_org_invite,
fake_uuid
):
new_org_user_data = {
'email_address': 'platform@admin.gov.uk',
}
mock_invite_org_user = mocker.patch(
'app.org_invite_api_client.create_invite',
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
)
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 cant send an invitation to yourself'
# Broken
def test_accepted_invite_when_user_already_logged_in(
logged_in_client,
mock_check_org_invite_token
):
response = logged_in_client.get(
url_for('main.accept_org_invite', token='thisisnotarealtoken'),
follow_redirects=True
)
assert response.status_code == 403
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
assert 'This invite is for another email address.' in normalize_spaces(page.select_one('.banner-dangerous').text)
def test_cancelled_invite_opened_by_user(
client,
mock_check_org_cancelled_invite_token,
mock_get_organisation,
mock_get_user,
fake_uuid
):
response = client.get(url_for('main.accept_org_invite', token='thisisnotarealtoken'), follow_redirects=True)
assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
assert normalize_spaces(
page.select_one('h1').text
) == 'The invitation you were sent has been cancelled'
assert normalize_spaces(
page.select('main p')[0].text
) == 'Test User decided to cancel this invitation.'
assert normalize_spaces(
page.select('main p')[1].text
) == 'If you need access to Org 1, youll 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')
def test_user_invite_already_accepted(
client,
mock_check_org_accepted_invite_token
):
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',
_external=True
)
def test_existing_user_invite_already_is_member_of_organisation(
client,
mock_check_org_invite_token,
mock_get_user_by_email,
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',
_external=True
)
mock_accept_org_invite.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af', 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')
def test_existing_user_invite_not_a_member_of_organisation(
client,
mock_check_org_invite_token,
mock_get_user_by_email,
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',
_external=True
)
mock_accept_org_invite.assert_called_once_with('596364a0-858e-42c8-9062-a8fe822260af', 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_add_user_to_organisation.assert_called_once_with(
'596364a0-858e-42c8-9062-a8fe822260af',
'6ce466d0-fd6a-11e5-82f5-e0accb9d11a6'
)
def test_user_accepts_invite(
client,
mock_check_org_invite_token,
mock_dont_get_user_by_email,
mock_get_users_for_organisation,
):
response = client.get(url_for('main.accept_org_invite', token='thisisnotarealtoken'))
assert response.status_code == 302
assert response.location == url_for('main.register_from_org_invite', _external=True)
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')
def test_registration_from_org_invite_404s_if_user_not_in_session(
client,
):
response = client.get(url_for('main.register_from_org_invite'))
assert response.status_code == 404
@pytest.mark.parametrize('data, error', [
[{
'name': 'Bad Mobile',
'mobile_number': 'not good',
'password': 'validPassword!'
}, 'Must not contain letters or symbols'],
[{
'name': 'Bad Password',
'mobile_number': '+44123412345',
'password': 'password'
}, 'Choose a password thats harder to guess'],
])
def test_registration_from_org_invite_has_bad_data(
client,
sample_org_invite,
data,
error
):
invited_org_user = InvitedOrgUser(**sample_org_invite)
with client.session_transaction() as session:
session['invited_org_user'] = invited_org_user.serialize()
response = client.post(url_for('main.register_from_org_invite'), data=data)
assert response.status_code == 200
assert error in response.get_data(as_text=True)
@pytest.mark.parametrize('diff_data', [
['email_address'],
['organisation'],
['email_address', 'organisation']
])
def test_registration_from_org_invite_has_different_email_or_organisation(
client,
sample_org_invite,
diff_data
):
invited_org_user = InvitedOrgUser(**sample_org_invite)
with client.session_transaction() as session:
session['invited_org_user'] = invited_org_user.serialize()
for data in diff_data:
session['invited_org_user'][data] = 'different'
response = client.post(url_for('main.register_from_org_invite'), data={
'name': 'Test User',
'mobile_number': '+4407700900460',
'password': 'validPassword!',
'email_address': session['invited_org_user']['email_address'],
'organisation': session['invited_org_user']['organisation']
})
assert response.status_code == 400
def test_org_user_registers_with_email_already_in_use(
client,
sample_org_invite,
mock_email_is_already_in_use,
mock_get_user_by_email,
mock_accept_org_invite,
mock_add_user_to_organisation,
mock_send_already_registered_email,
mock_register_user
):
invited_org_user = InvitedOrgUser(**sample_org_invite)
with client.session_transaction() as session:
session['invited_org_user'] = invited_org_user.serialize()
response = client.post(url_for('main.register_from_org_invite'), data={
'name': 'Test User',
'mobile_number': '+4407700900460',
'password': 'validPassword!',
'email_address': session['invited_org_user']['email_address'],
'organisation': session['invited_org_user']['organisation']
})
assert response.status_code == 302
assert response.location == url_for('main.verify', _external=True)
mock_get_user_by_email.assert_called_once_with(
session['invited_org_user']['email_address']
)
assert mock_register_user.called is False
assert mock_send_already_registered_email.called is False
def test_org_user_registration(
client,
sample_org_invite,
mock_email_is_not_already_in_use,
mock_register_user,
mock_send_verify_code,
mock_get_user_by_email,
mock_send_verify_email,
mock_accept_org_invite,
mock_add_user_to_organisation,
):
invited_org_user = InvitedOrgUser(**sample_org_invite)
with client.session_transaction() as session:
session['invited_org_user'] = invited_org_user.serialize()
response = client.post(url_for('main.register_from_org_invite'), data={
'name': 'Test User',
'email_address': session['invited_org_user']['email_address'],
'mobile_number': '+4407700900460',
'password': 'validPassword!',
'organisation': session['invited_org_user']['organisation']
})
assert response.status_code == 302
assert response.location == url_for('main.verify', _external=True)
mock_get_user_by_email.called is False
mock_register_user.assert_called_once_with(
'Test User',
session['invited_org_user']['email_address'],
'+4407700900460',
'validPassword!',
'sms_auth'
)
mock_send_verify_code.assert_called_once_with(
'6ce466d0-fd6a-11e5-82f5-e0accb9d11a6',
'sms',
'+4407700900460',
)
def test_verified_org_user_redirects_to_dashboard(
client,
sample_org_invite,
mock_check_verify_code,
mock_get_user,
mock_activate_user,
mock_login,
):
invited_org_user = InvitedOrgUser(**sample_org_invite).serialize()
with client.session_transaction() as session:
session['expiry_date'] = str(datetime.utcnow() + timedelta(hours=1))
session['user_details'] = {"email": invited_org_user['email_address'], "id": invited_org_user['id']}
session['organisation_id'] = invited_org_user['organisation']
response = client.post(url_for('main.verify'), data={'sms_code': '12345'})
assert response.status_code == 302
assert response.location == url_for(
'main.organisation_dashboard',
org_id=invited_org_user['organisation'],
_external=True
)