mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-07-07 01:48:54 -04:00
The GDS Way™[1] recommends using Flake8 to lint Python projects.
This commit takes the Flake8 config from Digital Marketplace API[2] and
removes the bits we don’t need.
It changes the `max_complexity` setting to 14, which is the most complex
code we have in this repo currently (we shouldn’t be writing code _more_
complex than what we already have).
This commit also fixes the errors found by Flake8, which includes 6(!)
tests which were never getting run because they had the same names as
existing tests.
Here is a full list of the errors that were found and fixed:
```
./app/__init__.py:2:1: F401 're' imported but unused
./app/__init__.py:4:1: F401 'json' imported but unused
./app/__init__.py:8:1: F401 'dateutil' imported but unused
./app/__init__.py:11:1: F401 'flask.escape' imported but unused
./app/__init__.py:41:1: F401 'app.proxy_fix' imported but unused
./app/__init__.py:129:5: F821 undefined name 'proxy_fix'
./app/__init__.py:221:19: F821 undefined name 'highlight'
./app/__init__.py:221:35: F821 undefined name 'JavascriptLexer'
./app/__init__.py:221:54: F821 undefined name 'HtmlFormatter'
./app/config.py:2:1: F401 'datetime.timedelta' imported but unused
./app/event_handlers.py:2:1: F401 'flask_login.current_user' imported but unused
./app/utils.py:11:1: F401 'dateutil.parser' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.two_factor' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.notifications' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.add_service' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.forgot_password' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.inbound_number' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.styleguide' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.organisations' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.letter_jobs' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.verify' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.conversation' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.api_keys' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.send' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.dashboard' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.jobs' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.manage_users' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.sign_in' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.sign_out' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.code_not_received' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.invites' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.platform_admin' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.providers' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.service_settings' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.index' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.new_password' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.user_profile' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.feedback' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.choose_service' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.templates' imported but unused
./app/main/__init__.py:5:1: F401 'app.main.views.register' imported but unused
./app/main/forms.py:12:1: F401 'wtforms.SelectField' imported but unused
./app/main/views/api_keys.py:37:29: E241 multiple spaces after ':'
./app/main/views/feedback.py:3:1: F401 'flask.flash' imported but unused
./app/main/views/feedback.py:122:17: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/inbound_number.py:1:1: F401 'flask.url_for' imported but unused
./app/main/views/inbound_number.py:1:1: F401 'flask.session' imported but unused
./app/main/views/inbound_number.py:1:1: F401 'flask.redirect' imported but unused
./app/main/views/inbound_number.py:1:1: F401 'flask.request' imported but unused
./app/main/views/inbound_number.py:13:1: F401 'flask.jsonify' imported but unused
./app/main/views/jobs.py:31:1: F401 'app.utils.get_template' imported but unused
./app/main/views/letter_jobs.py:1:1: F401 'datetime' imported but unused
./app/main/views/letter_jobs.py:6:1: F401 'app.format_datetime_24h' imported but unused
./app/main/views/manage_users.py:111:9: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/notifications.py:121:5: F841 local variable 'status_args' is assigned to but never used
./app/main/views/organisations.py:1:1: F401 'flask.request' imported but unused
./app/main/views/service_settings.py:77:9: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/service_settings.py:82:9: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/service_settings.py:420:13: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/sign_in.py:12:1: F401 'flask_login.confirm_login' imported but unused
./app/main/views/sign_in.py:17:1: F401 'app.service_api_client' imported but unused
./app/main/views/sign_in.py:62:13: E123 closing bracket does not match indentation of opening bracket's line
./app/main/views/templates.py:4:1: F401 'flask.json' imported but unused
./app/main/views/templates.py:17:1: F401 'notifications_utils.formatters.escape_html' imported but unused
./app/main/views/templates.py:23:1: F401 'app.utils.get_help_argument' imported but unused
./app/main/views/templates.py:64:13: E123 closing bracket does not match indentation of opening bracket's line
./app/notify_client/service_api_client.py:6:1: F401 '.notification_api_client' imported but unused
./app/notify_client/user_api_client.py:1:1: F401 'uuid' imported but unused
./app/notify_client/user_api_client.py:3:1: F401 'flask.session' imported but unused
./tests/__init__.py:1:1: F401 'csv' imported but unused
./tests/app/main/test_asset_fingerprinter.py:2:1: F401 'os' imported but unused
./tests/app/main/test_asset_fingerprinter.py:4:1: F401 'unittest.mock' imported but unused
./tests/app/main/test_asset_fingerprinter.py:98:9: F841 local variable 'string_with_unicode_character' is assigned to but never used
./tests/app/main/test_errorhandlers.py:2:1: F401 'flask.url_for' imported but unused
./tests/app/main/test_permissions.py:26:13: F841 local variable 'response' is assigned to but never used
./tests/app/main/test_placeholder_form.py:3:1: F401 'wtforms.Label' imported but unused
./tests/app/main/test_placeholder_form.py:11:10: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:10:67: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:23:65: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:37:48: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:51:67: F841 local variable 'req' is assigned to but never used
./tests/app/main/test_two_factor_form.py:65:67: F841 local variable 'req' is assigned to but never used
./tests/app/main/views/test_accept_invite.py:356:5: F841 local variable 'element' is assigned to but never used
./tests/app/main/views/test_activity.py:11:1: F811 redefinition of unused 'mock_get_notifications' from line 11
./tests/app/main/views/test_activity.py:18:1: F401 'datetime.datetime' imported but unused
./tests/app/main/views/test_activity.py:102:5: F841 local variable 'content' is assigned to but never used
./tests/app/main/views/test_activity.py:104:5: F841 local variable 'notification' is assigned to but never used
./tests/app/main/views/test_activity.py:337:5: F841 local variable '_notifications_mock' is assigned to but never used
./tests/app/main/views/test_activity.py:373:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_activity.py:378:9: E121 continuation line under-indented for hanging indent
./tests/app/main/views/test_activity.py:404:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_activity.py:407:9: E121 continuation line under-indented for hanging indent
./tests/app/main/views/test_api_keys.py:354:5: F841 local variable 'response' is assigned to but never used
./tests/app/main/views/test_conversation.py:5:1: F401 'bs4.BeautifulSoup' imported but unused
./tests/app/main/views/test_conversation.py:198:5: F841 local variable 'mock_get_inbound_sms' is assigned to but never used
./tests/app/main/views/test_dashboard.py:53:5: F841 local variable 'mock_template_stats' is assigned to but never used
./tests/app/main/views/test_dashboard.py:72:5: F841 local variable 'mock_template_stats' is assigned to but never used
./tests/app/main/views/test_jobs.py:2:1: F401 'uuid' imported but unused
./tests/app/main/views/test_jobs.py:3:1: F401 'urllib.parse.urlparse' imported but unused
./tests/app/main/views/test_jobs.py:3:1: F401 'urllib.parse.quote' imported but unused
./tests/app/main/views/test_jobs.py:3:1: F401 'urllib.parse.parse_qs' imported but unused
./tests/app/main/views/test_jobs.py:9:1: F401 'app.main.views.jobs.get_status_filters' imported but unused
./tests/app/main/views/test_jobs.py:10:1: F401 'tests.notification_json' imported but unused
./tests/app/main/views/test_letters.py:6:1: F401 'tests.service_json' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.REQUESTED_STATUSES' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.DELIVERED_STATUSES' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.SENDING_STATUSES' imported but unused
./tests/app/main/views/test_notifications.py:5:1: F401 'app.utils.FAILURE_STATUSES' imported but unused
./tests/app/main/views/test_platform_admin.py:242:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_platform_admin.py:247:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_send.py:3:1: F401 'unittest.mock.Mock' imported but unused
./tests/app/main/views/test_send.py:18:1: F811 redefinition of unused 'mock_get_service' from line 18
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.multiple_letter_contact_blocks' imported but unused
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.no_sms_senders' imported but unused
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.multiple_sms_senders' imported but unused
./tests/app/main/views/test_send.py:18:1: F401 'tests.conftest.no_letter_contact_blocks' imported but unused
./tests/app/main/views/test_send.py:102:5: F841 local variable 'response' is assigned to but never used
./tests/app/main/views/test_send.py:870:5: F841 local variable 'response' is assigned to but never used
./tests/app/main/views/test_send.py:1367:5: F841 local variable 'service_id' is assigned to but never used
./tests/app/main/views/test_send.py:1451:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_send.py:1620:80: E226 missing whitespace around arithmetic operator
./tests/app/main/views/test_send.py:1909:13: E126 continuation line over-indented for hanging indent
./tests/app/main/views/test_send.py:1912:9: E121 continuation line under-indented for hanging indent
./tests/app/main/views/test_service_settings.py:13:1: F811 redefinition of unused 'no_reply_to_email_addresses' from line 13
./tests/app/main/views/test_service_settings.py:13:1: F401 'tests.conftest.single_reply_to_email_address' imported but unused
./tests/app/main/views/test_service_settings.py:28:5: E123 closing bracket does not match indentation of opening bracket's line
./tests/app/main/views/test_service_settings.py:104:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:166:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:186:5: F841 local variable 'mocked_get_fn' is assigned to but never used
./tests/app/main/views/test_service_settings.py:217:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:237:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:257:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:307:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:340:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:466:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:555:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:615:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:719:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:874:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:902:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:954:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:986:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1101:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1121:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1271:1: F811 redefinition of unused 'test_set_letter_contact_block_saves' from line 1189
./tests/app/main/views/test_service_settings.py:1433:5: F841 local variable 'page' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1495:5: F841 local variable 'mocked_get_fn' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1540:5: F841 local variable 'mocked_get_fn' is assigned to but never used
./tests/app/main/views/test_service_settings.py:1570:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1589:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1621:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1641:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1658:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1676:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1697:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1759:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_service_settings.py:1775:1: F811 redefinition of unused 'single_reply_to_email_address' from line 13
./tests/app/main/views/test_templates.py:3:1: F401 'uuid' imported but unused
./tests/app/main/views/test_templates.py:11:1: F401 'tests.conftest.mock_get_user' imported but unused
./tests/app/main/views/test_templates.py:514:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_templates.py:672:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_templates.py:795:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_templates.py:835:1: F811 redefinition of unused 'mock_get_user' from line 11
./tests/app/main/views/test_two_factor.py:67:13: E126 continuation line over-indented for hanging indent
./tests/app/notify_client/test_notification_client.py:79:5: F841 local variable 'mock_post' is assigned to but never used
```
1. https://gds-way.cloudapps.digital/manuals/programming-languages/python/linting.html#how-to-use-flake8
2. d5ab8afef4/.flake8
357 lines
12 KiB
Python
357 lines
12 KiB
Python
from flask import url_for
|
||
from bs4 import BeautifulSoup
|
||
from unittest.mock import ANY
|
||
|
||
import app
|
||
|
||
from app.notify_client.models import InvitedUser
|
||
from tests.conftest import sample_invite as create_sample_invite
|
||
from tests.conftest import mock_check_invite_token as mock_check_token_invite
|
||
|
||
|
||
def test_existing_user_accept_invite_calls_api_and_redirects_to_dashboard(
|
||
client,
|
||
service_one,
|
||
api_user_active,
|
||
sample_invite,
|
||
mock_get_service,
|
||
mock_check_invite_token,
|
||
mock_get_user_by_email,
|
||
mock_get_users_by_service,
|
||
mock_accept_invite,
|
||
mock_add_user_to_service,
|
||
):
|
||
|
||
expected_service = service_one['id']
|
||
expected_redirect_location = 'http://localhost/services/{}/dashboard'.format(expected_service)
|
||
expected_permissions = ['send_messages', 'manage_service', 'manage_api_keys']
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'))
|
||
|
||
mock_check_invite_token.assert_called_with('thisisnotarealtoken')
|
||
mock_get_user_by_email.assert_called_with('invited_user@test.gov.uk')
|
||
assert mock_accept_invite.call_count == 1
|
||
mock_add_user_to_service.assert_called_with(expected_service, api_user_active.id, expected_permissions)
|
||
|
||
assert response.status_code == 302
|
||
assert response.location == expected_redirect_location
|
||
|
||
|
||
def test_existing_user_with_no_permissions_accept_invite(
|
||
client,
|
||
mocker,
|
||
service_one,
|
||
api_user_active,
|
||
sample_invite,
|
||
mock_check_invite_token,
|
||
mock_get_user_by_email,
|
||
mock_get_users_by_service,
|
||
mock_add_user_to_service,
|
||
mock_get_service,
|
||
):
|
||
|
||
expected_service = service_one['id']
|
||
sample_invite['permissions'] = ''
|
||
expected_permissions = []
|
||
mocker.patch('app.invite_api_client.accept_invite', return_value=sample_invite)
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'))
|
||
mock_add_user_to_service.assert_called_with(expected_service, api_user_active.id, expected_permissions)
|
||
|
||
assert response.status_code == 302
|
||
|
||
|
||
def test_if_existing_user_accepts_twice_they_redirect_to_sign_in(
|
||
client,
|
||
mocker,
|
||
sample_invite,
|
||
mock_get_service,
|
||
):
|
||
|
||
sample_invite['status'] = 'accepted'
|
||
invite = InvitedUser(**sample_invite)
|
||
mocker.patch('app.invite_api_client.check_token', return_value=invite)
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True)
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert (
|
||
page.h1.string,
|
||
page.select('main p')[0].text.strip(),
|
||
) == (
|
||
'You need to sign in again',
|
||
'We signed you out because you haven’t used Notify for a while.',
|
||
)
|
||
|
||
|
||
def test_existing_user_of_service_get_redirected_to_signin(
|
||
client,
|
||
mocker,
|
||
api_user_active,
|
||
sample_invite,
|
||
mock_get_service,
|
||
mock_get_user_by_email,
|
||
mock_accept_invite,
|
||
):
|
||
sample_invite['email_address'] = api_user_active.email_address
|
||
invite = InvitedUser(**sample_invite)
|
||
mocker.patch('app.invite_api_client.check_token', return_value=invite)
|
||
mocker.patch('app.user_api_client.get_users_for_service', return_value=[api_user_active])
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True)
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert (
|
||
page.h1.string,
|
||
page.select('main p')[0].text.strip(),
|
||
) == (
|
||
'You need to sign in again',
|
||
'We signed you out because you haven’t used Notify for a while.',
|
||
)
|
||
assert mock_accept_invite.call_count == 1
|
||
|
||
|
||
def test_existing_signed_out_user_accept_invite_redirects_to_sign_in(
|
||
client,
|
||
service_one,
|
||
api_user_active,
|
||
sample_invite,
|
||
mock_check_invite_token,
|
||
mock_get_user_by_email,
|
||
mock_get_users_by_service,
|
||
mock_add_user_to_service,
|
||
mock_accept_invite,
|
||
mock_get_service,
|
||
):
|
||
|
||
expected_service = service_one['id']
|
||
expected_permissions = ['send_messages', 'manage_service', 'manage_api_keys']
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True)
|
||
|
||
mock_check_invite_token.assert_called_with('thisisnotarealtoken')
|
||
mock_get_user_by_email.assert_called_with('invited_user@test.gov.uk')
|
||
mock_add_user_to_service.assert_called_with(expected_service, api_user_active.id, expected_permissions)
|
||
assert mock_accept_invite.call_count == 1
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert (
|
||
page.h1.string,
|
||
page.select('main p')[0].text.strip(),
|
||
) == (
|
||
'You need to sign in again',
|
||
'We signed you out because you haven’t used Notify for a while.',
|
||
)
|
||
|
||
|
||
def test_new_user_accept_invite_calls_api_and_redirects_to_registration(
|
||
client,
|
||
service_one,
|
||
mock_check_invite_token,
|
||
mock_dont_get_user_by_email,
|
||
mock_add_user_to_service,
|
||
mock_get_users_by_service,
|
||
mock_get_service,
|
||
):
|
||
|
||
expected_redirect_location = 'http://localhost/register-from-invite'
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'))
|
||
|
||
mock_check_invite_token.assert_called_with('thisisnotarealtoken')
|
||
mock_dont_get_user_by_email.assert_called_with('invited_user@test.gov.uk')
|
||
|
||
assert response.status_code == 302
|
||
assert response.location == expected_redirect_location
|
||
|
||
|
||
def test_new_user_accept_invite_calls_api_and_views_registration_page(
|
||
client,
|
||
service_one,
|
||
mock_check_invite_token,
|
||
mock_dont_get_user_by_email,
|
||
mock_add_user_to_service,
|
||
mock_get_users_by_service,
|
||
mock_get_service,
|
||
):
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True)
|
||
|
||
mock_check_invite_token.assert_called_with('thisisnotarealtoken')
|
||
mock_dont_get_user_by_email.assert_called_with('invited_user@test.gov.uk')
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert page.h1.string.strip() == 'Create an account'
|
||
|
||
email_in_page = page.find('main').find('p')
|
||
assert email_in_page.text.strip() == 'Your account will be created with this email: invited_user@test.gov.uk' # noqa
|
||
|
||
form = page.find('form')
|
||
name = form.find('input', id='name')
|
||
password = form.find('input', id='password')
|
||
service = form.find('input', type='hidden', id='service')
|
||
email = form.find('input', type='hidden', id='email_address')
|
||
|
||
assert email
|
||
assert email.attrs['value'] == 'invited_user@test.gov.uk'
|
||
assert name
|
||
assert password
|
||
assert service
|
||
assert service.attrs['value'] == service_one['id']
|
||
|
||
|
||
def test_cancelled_invited_user_accepts_invited_redirect_to_cancelled_invitation(
|
||
client,
|
||
service_one,
|
||
mocker,
|
||
mock_get_user,
|
||
mock_get_service,
|
||
):
|
||
cancelled_invitation = create_sample_invite(mocker, service_one, status='cancelled')
|
||
mock_check_token_invite(mocker, cancelled_invitation)
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'))
|
||
|
||
app.invite_api_client.check_token.assert_called_with('thisisnotarealtoken')
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert page.h1.string.strip() == 'The invitation you were sent has been cancelled'
|
||
|
||
|
||
def test_new_user_accept_invite_completes_new_registration_redirects_to_verify(
|
||
client,
|
||
service_one,
|
||
sample_invite,
|
||
api_user_active,
|
||
mock_check_invite_token,
|
||
mock_dont_get_user_by_email,
|
||
mock_is_email_unique,
|
||
mock_register_user,
|
||
mock_send_verify_code,
|
||
mock_accept_invite,
|
||
mock_get_users_by_service,
|
||
mock_add_user_to_service,
|
||
mock_get_service,
|
||
):
|
||
|
||
expected_service = service_one['id']
|
||
expected_email = sample_invite['email_address']
|
||
expected_from_user = service_one['users'][0]
|
||
expected_redirect_location = 'http://localhost/register-from-invite'
|
||
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'))
|
||
with client.session_transaction() as session:
|
||
assert response.status_code == 302
|
||
assert response.location == expected_redirect_location
|
||
invited_user = session.get('invited_user')
|
||
assert invited_user
|
||
assert expected_service == invited_user['service']
|
||
assert expected_email == invited_user['email_address']
|
||
assert expected_from_user == invited_user['from_user']
|
||
|
||
data = {'service': invited_user['service'],
|
||
'email_address': invited_user['email_address'],
|
||
'from_user': invited_user['from_user'],
|
||
'password': 'longpassword',
|
||
'mobile_number': '+447890123456',
|
||
'name': 'Invited User'
|
||
}
|
||
|
||
expected_redirect_location = 'http://localhost/verify'
|
||
response = client.post(url_for('main.register_from_invite'), data=data)
|
||
assert response.status_code == 302
|
||
assert response.location == expected_redirect_location
|
||
|
||
mock_send_verify_code.assert_called_once_with(ANY, 'sms', data['mobile_number'])
|
||
|
||
mock_register_user.assert_called_with(data['name'],
|
||
data['email_address'],
|
||
data['mobile_number'],
|
||
data['password'])
|
||
|
||
assert mock_accept_invite.call_count == 1
|
||
|
||
|
||
def test_signed_in_existing_user_cannot_use_anothers_invite(
|
||
logged_in_client,
|
||
mocker,
|
||
api_user_active,
|
||
sample_invite,
|
||
mock_get_user,
|
||
mock_accept_invite,
|
||
mock_get_service,
|
||
):
|
||
invite = InvitedUser(**sample_invite)
|
||
mocker.patch('app.invite_api_client.check_token', return_value=invite)
|
||
mocker.patch('app.user_api_client.get_users_for_service', return_value=[api_user_active])
|
||
|
||
response = logged_in_client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True)
|
||
assert response.status_code == 403
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert page.h1.string.strip() == '403'
|
||
flash_banners = page.find_all('div', class_='banner-dangerous')
|
||
assert len(flash_banners) == 1
|
||
banner_contents = flash_banners[0].text.strip()
|
||
assert "You’re signed in as test@user.gov.uk." in banner_contents
|
||
assert "This invite is for another email address." in banner_contents
|
||
assert "Sign out and click the link again to accept this invite." in banner_contents
|
||
assert mock_accept_invite.call_count == 0
|
||
|
||
|
||
def test_new_invited_user_verifies_and_added_to_service(
|
||
client,
|
||
service_one,
|
||
sample_invite,
|
||
api_user_active,
|
||
mock_check_invite_token,
|
||
mock_dont_get_user_by_email,
|
||
mock_is_email_unique,
|
||
mock_register_user,
|
||
mock_send_verify_code,
|
||
mock_check_verify_code,
|
||
mock_get_user,
|
||
mock_update_user,
|
||
mock_add_user_to_service,
|
||
mock_accept_invite,
|
||
mock_get_service,
|
||
mock_get_service_templates,
|
||
mock_get_template_statistics,
|
||
mock_get_jobs,
|
||
mock_has_permissions,
|
||
mock_get_users_by_service,
|
||
mock_get_detailed_service,
|
||
mock_get_usage,
|
||
):
|
||
|
||
# visit accept token page
|
||
response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'))
|
||
data = {'service': sample_invite['service'],
|
||
'email_address': sample_invite['email_address'],
|
||
'from_user': sample_invite['from_user'],
|
||
'password': 'longpassword',
|
||
'mobile_number': '+447890123456',
|
||
'name': 'Invited User'
|
||
}
|
||
|
||
# get redirected to register from invite
|
||
response = client.post(url_for('main.register_from_invite'), data=data)
|
||
|
||
# that sends user on to verify
|
||
response = client.post(url_for('main.verify'), data={'sms_code': '12345'}, follow_redirects=True)
|
||
|
||
# when they post codes back to admin user should be added to
|
||
# service and sent on to dash board
|
||
expected_permissions = ['send_messages', 'manage_service', 'manage_api_keys']
|
||
|
||
with client.session_transaction() as session:
|
||
new_user_id = session['user_id']
|
||
mock_add_user_to_service.assert_called_with(data['service'], new_user_id, expected_permissions)
|
||
mock_accept_invite.assert_called_with(data['service'], sample_invite['id'])
|
||
mock_check_verify_code.assert_called_once_with(new_user_id, '12345', 'sms')
|
||
assert service_one['id'] == session['service_id']
|
||
|
||
raw_html = response.data.decode('utf-8')
|
||
page = BeautifulSoup(raw_html, 'html.parser')
|
||
assert page.find('h1').text == 'Dashboard'
|