mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-06-21 21:53:42 -04:00
Live services shouldn't be able to request to go live again. Once a service is live we remove the option to go live from the Settings page, but we still link to the page to request to go live from other places e.g. the 'Get started' page. As a result, we've seen some services make another request to go live when their service has already been live for months - this change will stop that from happening.
5220 lines
158 KiB
Python
5220 lines
158 KiB
Python
from datetime import datetime
|
||
from functools import partial
|
||
from unittest.mock import ANY, Mock, PropertyMock, call
|
||
from urllib.parse import parse_qs, urlparse
|
||
from uuid import UUID, uuid4
|
||
|
||
import pytest
|
||
from bs4 import BeautifulSoup
|
||
from flask import url_for
|
||
from freezegun import freeze_time
|
||
from notifications_python_client.errors import HTTPError
|
||
from notifications_utils.clients.zendesk.zendesk_client import ZendeskClient
|
||
|
||
import app
|
||
from app.utils import email_safe
|
||
from tests import (
|
||
find_element_by_tag_and_partial_text,
|
||
invite_json,
|
||
organisation_json,
|
||
sample_uuid,
|
||
service_json,
|
||
validate_route_permission,
|
||
)
|
||
from tests.conftest import (
|
||
ORGANISATION_ID,
|
||
SERVICE_ONE_ID,
|
||
TEMPLATE_ONE_ID,
|
||
create_active_user_no_api_key_permission,
|
||
create_active_user_no_settings_permission,
|
||
create_active_user_with_permissions,
|
||
create_letter_contact_block,
|
||
create_multiple_email_reply_to_addresses,
|
||
create_multiple_letter_contact_blocks,
|
||
create_multiple_sms_senders,
|
||
create_platform_admin_user,
|
||
create_reply_to_email_address,
|
||
create_sms_sender,
|
||
normalize_spaces,
|
||
)
|
||
|
||
FAKE_TEMPLATE_ID = uuid4()
|
||
|
||
|
||
@pytest.fixture
|
||
def mock_get_service_settings_page_common(
|
||
mock_get_all_letter_branding,
|
||
mock_get_inbound_number_for_service,
|
||
mock_get_free_sms_fragment_limit,
|
||
mock_get_service_data_retention,
|
||
):
|
||
return
|
||
|
||
|
||
@pytest.mark.parametrize('user, expected_rows', [
|
||
(create_active_user_with_permissions(), [
|
||
|
||
'Label Value Action',
|
||
'Service name Test Service Change service name',
|
||
'Sign-in method Text message code Change sign-in method',
|
||
|
||
'Label Value Action',
|
||
'Send emails On Change your settings for sending emails',
|
||
'Reply-to email addresses Not set Manage reply-to email addresses',
|
||
'Email branding GOV.UK Change email branding',
|
||
'Send files by email contact_us@gov.uk Manage sending files by email',
|
||
|
||
'Label Value Action',
|
||
'Send text messages On Change your settings for sending text messages',
|
||
'Text message senders GOVUK Manage text message senders',
|
||
'Start text messages with service name On Change your settings for starting text messages with service name',
|
||
'Send international text messages Off Change your settings for sending international text messages',
|
||
'Receive text messages Off Change your settings for receiving text messages',
|
||
|
||
'Label Value Action',
|
||
'Send letters Off Change your settings for sending letters',
|
||
|
||
]),
|
||
(create_platform_admin_user(), [
|
||
|
||
'Label Value Action',
|
||
'Service name Test Service Change service name',
|
||
'Sign-in method Text message code Change sign-in method',
|
||
|
||
'Label Value Action',
|
||
'Send emails On Change your settings for sending emails',
|
||
'Reply-to email addresses Not set Manage reply-to email addresses',
|
||
'Email branding GOV.UK Change email branding',
|
||
'Send files by email contact_us@gov.uk Manage sending files by email',
|
||
|
||
'Label Value Action',
|
||
'Send text messages On Change your settings for sending text messages',
|
||
'Text message senders GOVUK Manage text message senders',
|
||
'Start text messages with service name On Change your settings for starting text messages with service name',
|
||
'Send international text messages Off Change your settings for sending international text messages',
|
||
'Receive text messages Off Change your settings for receiving text messages',
|
||
|
||
'Label Value Action',
|
||
'Send letters Off Change your settings for sending letters',
|
||
|
||
'Label Value Action',
|
||
'Live Off Change service status',
|
||
'Count in list of live services Yes Change if service is counted in list of live services',
|
||
'Organisation Test organisation Central government Change organisation for service',
|
||
'Rate limit 3,000 per minute Change rate limit',
|
||
'Message limit 1,000 per day Change daily message limit',
|
||
'Free text message allowance 250,000 per year Change free text message allowance',
|
||
'Email branding GOV.UK Change email branding (admin view)',
|
||
'Letter branding Not set Change letter branding (admin view)',
|
||
'Custom data retention Email – 7 days Change data retention',
|
||
'Receive inbound SMS Off Change your settings for Receive inbound SMS',
|
||
'Email authentication Off Change your settings for Email authentication',
|
||
'Send cell broadcasts Off Change your settings for Send cell broadcasts',
|
||
]),
|
||
])
|
||
def test_should_show_overview(
|
||
client,
|
||
mocker,
|
||
api_user_active,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
user,
|
||
expected_rows,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one = service_json(
|
||
SERVICE_ONE_ID,
|
||
users=[api_user_active['id']],
|
||
permissions=['sms', 'email'],
|
||
organisation_id=ORGANISATION_ID,
|
||
contact_link='contact_us@gov.uk',
|
||
)
|
||
mocker.patch('app.service_api_client.get_service', return_value={'data': service_one})
|
||
|
||
client.login(user, mocker, service_one)
|
||
response = client.get(url_for(
|
||
'main.service_settings', service_id=SERVICE_ONE_ID
|
||
))
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert page.find('h1').text == 'Settings'
|
||
rows = page.select('tr')
|
||
assert len(rows) == len(expected_rows)
|
||
for index, row in enumerate(expected_rows):
|
||
assert row == " ".join(rows[index].text.split())
|
||
app.service_api_client.get_service.assert_called_with(SERVICE_ONE_ID)
|
||
|
||
|
||
def test_no_go_live_link_for_service_without_organisation(
|
||
client_request,
|
||
mocker,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
platform_admin_user,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
mocker.patch('app.organisations_client.get_organisation', return_value=None)
|
||
client_request.login(platform_admin_user)
|
||
page = client_request.get('main.service_settings', service_id=SERVICE_ONE_ID)
|
||
|
||
assert page.find('h1').text == 'Settings'
|
||
|
||
is_live = find_element_by_tag_and_partial_text(page, tag='td', string='Live')
|
||
assert normalize_spaces(is_live.find_next_sibling().text) == 'No (organisation must be set first)'
|
||
|
||
organisation = find_element_by_tag_and_partial_text(page, tag='td', string='Organisation')
|
||
assert normalize_spaces(organisation.find_next_siblings()[0].text) == 'Not set Central government'
|
||
assert normalize_spaces(organisation.find_next_siblings()[1].text) == 'Change organisation for service'
|
||
|
||
|
||
def test_organisation_name_links_to_org_dashboard(
|
||
client_request,
|
||
platform_admin_user,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
mocker,
|
||
mock_get_organisation,
|
||
):
|
||
service_one = service_json(SERVICE_ONE_ID,
|
||
permissions=['sms', 'email'],
|
||
organisation_id=ORGANISATION_ID)
|
||
mocker.patch('app.service_api_client.get_service', return_value={'data': service_one})
|
||
|
||
client_request.login(platform_admin_user, service_one)
|
||
response = client_request.get(
|
||
'main.service_settings', service_id=SERVICE_ONE_ID
|
||
)
|
||
|
||
org_row = find_element_by_tag_and_partial_text(response, tag='tr', string='Organisation')
|
||
assert org_row.find('a')['href'] == url_for('main.organisation_dashboard', org_id=ORGANISATION_ID)
|
||
assert normalize_spaces(org_row.find('a').text) == 'Test organisation'
|
||
|
||
|
||
@pytest.mark.parametrize('service_contact_link,expected_text', [
|
||
('contact.me@gov.uk', 'Send files by email contact.me@gov.uk Manage sending files by email'),
|
||
(None, 'Send files by email Not set up Manage sending files by email'),
|
||
])
|
||
def test_send_files_by_email_row_on_settings_page(
|
||
client_request,
|
||
platform_admin_user,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
mocker,
|
||
mock_get_organisation,
|
||
service_contact_link,
|
||
expected_text
|
||
):
|
||
service_one = service_json(
|
||
SERVICE_ONE_ID,
|
||
permissions=['sms', 'email'],
|
||
organisation_id=ORGANISATION_ID,
|
||
contact_link=service_contact_link
|
||
)
|
||
|
||
mocker.patch('app.service_api_client.get_service', return_value={'data': service_one})
|
||
|
||
client_request.login(platform_admin_user, service_one)
|
||
response = client_request.get(
|
||
'main.service_settings', service_id=SERVICE_ONE_ID
|
||
)
|
||
|
||
org_row = find_element_by_tag_and_partial_text(response, tag='tr', string='Send files by email')
|
||
assert normalize_spaces(org_row.get_text()) == expected_text
|
||
|
||
|
||
@pytest.mark.parametrize('permissions, expected_rows', [
|
||
(['email', 'sms', 'inbound_sms', 'international_sms'], [
|
||
|
||
'Service name service one Change service name',
|
||
'Sign-in method Text message code Change sign-in method',
|
||
|
||
'Label Value Action',
|
||
'Send emails On Change your settings for sending emails',
|
||
'Reply-to email addresses test@example.com Manage reply-to email addresses',
|
||
'Email branding Organisation name Change email branding',
|
||
'Send files by email Not set up Manage sending files by email',
|
||
|
||
'Label Value Action',
|
||
'Send text messages On Change your settings for sending text messages',
|
||
'Text message senders GOVUK Manage text message senders',
|
||
'Start text messages with service name On Change your settings for starting text messages with service name',
|
||
'Send international text messages On Change your settings for sending international text messages',
|
||
'Receive text messages On Change your settings for receiving text messages',
|
||
|
||
'Label Value Action',
|
||
'Send letters Off Change your settings for sending letters',
|
||
|
||
]),
|
||
(['email', 'sms', 'email_auth'], [
|
||
|
||
'Service name service one Change service name',
|
||
'Sign-in method Email link or text message code Change sign-in method',
|
||
|
||
'Label Value Action',
|
||
'Send emails On Change your settings for sending emails',
|
||
'Reply-to email addresses test@example.com Manage reply-to email addresses',
|
||
'Email branding Organisation name Change email branding',
|
||
'Send files by email Not set up Manage sending files by email',
|
||
|
||
'Label Value Action',
|
||
'Send text messages On Change your settings for sending text messages',
|
||
'Text message senders GOVUK Manage text message senders',
|
||
'Start text messages with service name On Change your settings for starting text messages with service name',
|
||
'Send international text messages Off Change your settings for sending international text messages',
|
||
'Receive text messages Off Change your settings for receiving text messages',
|
||
|
||
'Label Value Action',
|
||
'Send letters Off Change your settings for sending letters',
|
||
|
||
]),
|
||
(['letter'], [
|
||
|
||
'Service name service one Change service name',
|
||
'Sign-in method Text message code Change sign-in method',
|
||
|
||
'Label Value Action',
|
||
'Send emails Off Change your settings for sending emails',
|
||
|
||
'Label Value Action',
|
||
'Send text messages Off Change your settings for sending text messages',
|
||
|
||
'Label Value Action',
|
||
'Send letters On Change your settings for sending letters',
|
||
'Send international letters Off Change',
|
||
'Sender addresses 1 Example Street Manage sender addresses',
|
||
'Letter branding Not set Change letter branding',
|
||
|
||
]),
|
||
(['broadcast'], [
|
||
|
||
'Service name service one Change service name',
|
||
'Sign-in method Text message code Change sign-in method',
|
||
|
||
]),
|
||
])
|
||
def test_should_show_overview_for_service_with_more_things_set(
|
||
client,
|
||
active_user_with_permissions,
|
||
mocker,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
single_sms_sender,
|
||
mock_get_organisation,
|
||
mock_get_email_branding,
|
||
mock_get_service_settings_page_common,
|
||
permissions,
|
||
expected_rows
|
||
):
|
||
client.login(active_user_with_permissions, mocker, service_one)
|
||
service_one['permissions'] = permissions
|
||
service_one['email_branding'] = uuid4()
|
||
response = client.get(url_for(
|
||
'main.service_settings', service_id=service_one['id']
|
||
))
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
for index, row in enumerate(expected_rows):
|
||
assert row == " ".join(page.find_all('tr')[index + 1].text.split())
|
||
|
||
|
||
def test_if_cant_send_letters_then_cant_see_letter_contact_block(
|
||
client_request,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
no_letter_contact_blocks,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
response = client_request.get('main.service_settings', service_id=service_one['id'])
|
||
assert 'Letter contact block' not in response
|
||
|
||
|
||
def test_letter_contact_block_shows_none_if_not_set(
|
||
client_request,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
no_letter_contact_blocks,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['permissions'] = ['letter']
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
div = page.find_all('tr')[10].find_all('td')[1].div
|
||
assert div.text.strip() == 'Not set'
|
||
assert 'default' in div.attrs['class'][0]
|
||
|
||
|
||
def test_escapes_letter_contact_block(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
single_reply_to_email_address,
|
||
single_sms_sender,
|
||
mock_get_organisation,
|
||
injected_letter_contact_block,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['permissions'] = ['letter']
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
div = str(page.find_all('tr')[10].find_all('td')[1].div)
|
||
assert 'foo<br/>bar' in div
|
||
assert '<script>' not in div
|
||
|
||
|
||
def test_should_show_service_name(
|
||
client_request,
|
||
):
|
||
page = client_request.get('main.service_name_change', service_id=SERVICE_ONE_ID)
|
||
assert page.find('h1').text == 'Change your service name'
|
||
assert page.find('input', attrs={"type": "text"})['value'] == 'service one'
|
||
assert page.select_one('main p').text == 'Users will see your service name:'
|
||
assert normalize_spaces(page.select_one('main ul').text) == (
|
||
'at the start of every text message '
|
||
'as your email sender name'
|
||
)
|
||
app.service_api_client.get_service.assert_called_with(SERVICE_ONE_ID)
|
||
|
||
|
||
def test_should_show_different_change_service_name_page_for_local_services(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
):
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation_by_domain',
|
||
return_value=organisation_json(organisation_type='local'),
|
||
)
|
||
service_one['organisation_type'] = 'local'
|
||
page = client_request.get('main.service_name_change', service_id=SERVICE_ONE_ID)
|
||
assert page.find('h1').text == 'Change your service name'
|
||
assert page.find('input', attrs={"type": "text"})['value'] == 'service one'
|
||
assert page.select_one('main .govuk-body').text.strip() == (
|
||
'Your service name should tell users what the message is about as well as who it’s from. For example:'
|
||
)
|
||
# when no organisation on the service object, default org for the user is used for hint
|
||
assert "School admissions - Test Org" in page.find_all("ul", class_="govuk-list govuk-list--bullet")[0].text
|
||
|
||
app.service_api_client.get_service.assert_called_with(SERVICE_ONE_ID)
|
||
|
||
|
||
def test_should_show_service_org_in_hint_on_change_service_name_page_for_local_services_if_service_has_org(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
):
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation_by_domain',
|
||
return_value=organisation_json(organisation_type='local'),
|
||
)
|
||
mocker.patch('app.organisations_client.get_organisation', return_value=organisation_json(
|
||
organisation_type='local', name="Local Authority")
|
||
)
|
||
service_one['organisation_type'] = 'local'
|
||
service_one['organisation'] = '1234'
|
||
page = client_request.get('main.service_name_change', service_id=SERVICE_ONE_ID)
|
||
# when there is organisation on the service object, it is used for hint text instead of user default org
|
||
assert "School admissions - Local Authority" in page.find_all("ul", class_="govuk-list govuk-list--bullet")[0].text
|
||
|
||
|
||
def test_should_show_service_name_with_no_prefixing(
|
||
client_request,
|
||
service_one,
|
||
):
|
||
service_one['prefix_sms'] = False
|
||
page = client_request.get('main.service_name_change', service_id=SERVICE_ONE_ID)
|
||
assert page.find('h1').text == 'Change your service name'
|
||
assert page.select_one('main p').text == 'Users will see your service name as your email sender name.'
|
||
|
||
|
||
def test_should_redirect_after_change_service_name(
|
||
client_request,
|
||
mock_update_service,
|
||
mock_service_name_is_unique,
|
||
):
|
||
client_request.post(
|
||
'main.service_name_change',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'name': "new name"},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_name_change_confirm',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
|
||
assert mock_service_name_is_unique.called is True
|
||
|
||
|
||
def test_should_not_hit_api_if_service_name_hasnt_changed(
|
||
client_request,
|
||
mock_update_service,
|
||
mock_service_name_is_unique,
|
||
):
|
||
client_request.post(
|
||
'main.service_name_change',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'name': 'service one'},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
),
|
||
)
|
||
assert not mock_service_name_is_unique.called
|
||
assert not mock_update_service.called
|
||
|
||
|
||
def test_service_name_change_fails_if_new_name_has_less_than_2_alphanumeric_characters(
|
||
client_request,
|
||
mock_update_service,
|
||
mock_service_name_is_unique,
|
||
):
|
||
page = client_request.post(
|
||
'main.service_name_change',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'name': "."},
|
||
_expected_status=200,
|
||
)
|
||
assert not mock_service_name_is_unique.called
|
||
assert not mock_update_service.called
|
||
assert page.find("span", {"class": "govuk-error-message"})
|
||
|
||
|
||
@pytest.mark.parametrize('user, expected_text, expected_link', [
|
||
(
|
||
create_active_user_with_permissions(),
|
||
'To remove these restrictions, you can send us a request to go live.',
|
||
True,
|
||
),
|
||
(
|
||
create_active_user_no_settings_permission(),
|
||
'Your service manager can ask to have these restrictions removed.',
|
||
False,
|
||
),
|
||
])
|
||
def test_show_restricted_service(
|
||
client_request,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
user,
|
||
expected_text,
|
||
expected_link,
|
||
):
|
||
client_request.login(user)
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
assert page.find('h1').text == 'Settings'
|
||
assert page.select('main h2')[0].text == 'Your service is in trial mode'
|
||
|
||
request_to_live = page.select('main p')[1]
|
||
request_to_live_link = request_to_live.select_one('a')
|
||
assert normalize_spaces(request_to_live.text) == expected_text
|
||
|
||
if expected_link:
|
||
assert request_to_live_link.text.strip() == 'request to go live'
|
||
assert request_to_live_link['href'] == url_for('main.request_to_go_live', service_id=SERVICE_ONE_ID)
|
||
else:
|
||
assert not request_to_live_link
|
||
|
||
|
||
def test_show_restricted_broadcast_service(
|
||
client_request,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['permissions'] = 'broadcast'
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
assert page.select('main h2')[0].text == 'Your service is in trial mode'
|
||
|
||
request_to_live = page.select_one('main p')
|
||
request_to_live_link = request_to_live.select_one('a')
|
||
assert normalize_spaces(page.select_one('main p').text) == (
|
||
'To remove these restrictions, you can send us a request to go live.'
|
||
)
|
||
assert request_to_live_link['href'] == url_for('main.request_to_go_live', service_id=SERVICE_ONE_ID)
|
||
assert not page.select_one('main ul')
|
||
|
||
|
||
@freeze_time("2017-04-01 11:09:00.061258")
|
||
def test_switch_service_to_live(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_update_service,
|
||
mock_get_inbound_number_for_service
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
'main.service_switch_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'enabled': 'True'},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_update_service.assert_called_with(
|
||
SERVICE_ONE_ID,
|
||
message_limit=250000,
|
||
restricted=False,
|
||
go_live_at="2017-04-01 11:09:00.061258"
|
||
)
|
||
|
||
|
||
def test_show_live_service(
|
||
client_request,
|
||
mock_get_live_service,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
assert page.find('h1').text.strip() == 'Settings'
|
||
assert 'Your service is in trial mode' not in page.text
|
||
|
||
|
||
def test_switch_service_to_restricted(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_get_live_service,
|
||
mock_update_service,
|
||
mock_get_inbound_number_for_service,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
'main.service_switch_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'enabled': 'False'},
|
||
_expected_status=302,
|
||
_expected_response=url_for(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_update_service.assert_called_with(
|
||
SERVICE_ONE_ID,
|
||
message_limit=50,
|
||
restricted=True,
|
||
go_live_at=None
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('count_as_live, selected, labelled', (
|
||
(True, 'True', 'Yes'),
|
||
(False, 'False', 'No'),
|
||
))
|
||
def test_show_switch_service_to_count_as_live_page(
|
||
mocker,
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_update_service,
|
||
count_as_live,
|
||
selected,
|
||
labelled,
|
||
):
|
||
mocker.patch(
|
||
'app.models.service.Service.count_as_live',
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=count_as_live,
|
||
)
|
||
client_request.login(platform_admin_user)
|
||
page = client_request.get(
|
||
'main.service_switch_count_as_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
assert page.select_one('[checked]')['value'] == selected
|
||
assert page.select_one('label[for={}]'.format(
|
||
page.select_one('[checked]')['id']
|
||
)).text.strip() == labelled
|
||
|
||
|
||
@pytest.mark.parametrize('post_data, expected_persisted_value', (
|
||
('True', True),
|
||
('False', False),
|
||
))
|
||
def test_switch_service_to_count_as_live(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_update_service,
|
||
post_data,
|
||
expected_persisted_value,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
'main.service_switch_count_as_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'enabled': post_data},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_update_service.assert_called_with(
|
||
SERVICE_ONE_ID,
|
||
count_as_live=expected_persisted_value,
|
||
)
|
||
|
||
|
||
def test_should_not_allow_duplicate_names(
|
||
client_request,
|
||
mock_service_name_is_not_unique,
|
||
service_one,
|
||
):
|
||
page = client_request.post(
|
||
'main.service_name_change',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'name': "SErvICE TWO"},
|
||
_expected_status=200,
|
||
)
|
||
|
||
assert 'This service name is already in use' in page.text
|
||
app.service_api_client.is_service_name_unique.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
'SErvICE TWO',
|
||
'service.two',
|
||
)
|
||
|
||
|
||
def test_should_show_service_name_confirmation(
|
||
client_request,
|
||
):
|
||
service_new_name = 'New Name'
|
||
with client_request.session_transaction() as session:
|
||
session['service_name_change'] = service_new_name
|
||
page = client_request.get(
|
||
'main.service_name_change_confirm',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
assert 'Change your service name' in page.text
|
||
app.service_api_client.get_service.assert_called_with(SERVICE_ONE_ID)
|
||
|
||
|
||
def test_should_redirect_after_service_name_confirmation(
|
||
client_request,
|
||
mock_update_service,
|
||
mock_verify_password,
|
||
mock_get_inbound_number_for_service,
|
||
):
|
||
service_new_name = 'New Name'
|
||
with client_request.session_transaction() as session:
|
||
session['service_name_change'] = service_new_name
|
||
client_request.post(
|
||
'main.service_name_change_confirm',
|
||
service_id=SERVICE_ONE_ID,
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
),
|
||
)
|
||
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
name=service_new_name,
|
||
email_from=email_safe(service_new_name)
|
||
)
|
||
assert mock_verify_password.called is True
|
||
|
||
|
||
def test_should_raise_duplicate_name_handled(
|
||
client_request,
|
||
mock_update_service_raise_httperror_duplicate_name,
|
||
mock_verify_password,
|
||
):
|
||
with client_request.session_transaction() as session:
|
||
session['service_name_change'] = 'New Name'
|
||
|
||
client_request.post(
|
||
'main.service_name_change_confirm',
|
||
service_id=SERVICE_ONE_ID,
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_name_change',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
),
|
||
)
|
||
|
||
assert mock_update_service_raise_httperror_duplicate_name.called
|
||
assert mock_verify_password.called
|
||
|
||
|
||
def test_service_name_change_confirm_handles_expired_session(
|
||
client_request, mock_verify_password, mock_update_service
|
||
):
|
||
page = client_request.post(
|
||
'main.service_name_change_confirm',
|
||
service_id=SERVICE_ONE_ID,
|
||
_follow_redirects=True
|
||
)
|
||
assert mock_verify_password.called is False
|
||
assert mock_update_service.called is False
|
||
|
||
assert page.find('div', 'banner-dangerous').text.strip() == "The change you made was not saved. Please try again."
|
||
|
||
|
||
@pytest.mark.parametrize('volumes, consent_to_research, expected_estimated_volumes_item', [
|
||
((0, 0, 0), None, 'Tell us how many messages you expect to send Not completed'),
|
||
((1, 0, 0), None, 'Tell us how many messages you expect to send Not completed'),
|
||
((1, 0, 0), False, 'Tell us how many messages you expect to send Completed'),
|
||
((1, 0, 0), True, 'Tell us how many messages you expect to send Completed'),
|
||
((9, 99, 999), True, 'Tell us how many messages you expect to send Completed'),
|
||
])
|
||
def test_should_check_if_estimated_volumes_provided(
|
||
client_request,
|
||
mocker,
|
||
single_sms_sender,
|
||
single_reply_to_email_address,
|
||
mock_get_service_templates,
|
||
mock_get_users_by_service,
|
||
mock_get_organisation,
|
||
mock_get_invites_for_service,
|
||
volumes,
|
||
consent_to_research,
|
||
expected_estimated_volumes_item,
|
||
):
|
||
|
||
for volume, channel in zip(volumes, ('sms', 'email', 'letter')):
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=volume,
|
||
)
|
||
|
||
mocker.patch(
|
||
'app.models.service.Service.consent_to_research',
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=consent_to_research,
|
||
)
|
||
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Before you request to go live'
|
||
|
||
assert normalize_spaces(
|
||
page.select_one('.task-list .task-list-item').text
|
||
) == (
|
||
expected_estimated_volumes_item
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize((
|
||
'count_of_users_with_manage_service,'
|
||
'count_of_invites_with_manage_service,'
|
||
'expected_user_checklist_item'
|
||
), [
|
||
(1, 0, 'Add a team member who can manage settings, team and usage Not completed'),
|
||
(2, 0, 'Add a team member who can manage settings, team and usage Completed'),
|
||
(1, 1, 'Add a team member who can manage settings, team and usage Completed'),
|
||
])
|
||
@pytest.mark.parametrize('count_of_templates, expected_templates_checklist_item', [
|
||
(0, 'Add templates with examples of the content you plan to send Not completed'),
|
||
(1, 'Add templates with examples of the content you plan to send Completed'),
|
||
(2, 'Add templates with examples of the content you plan to send Completed'),
|
||
])
|
||
@pytest.mark.parametrize((
|
||
'volume_email,'
|
||
'count_of_email_templates,'
|
||
'reply_to_email_addresses,'
|
||
'expected_reply_to_checklist_item'
|
||
), [
|
||
pytest.param(None, 0, [], '', marks=pytest.mark.xfail(raises=IndexError)),
|
||
pytest.param(0, 0, [], '', marks=pytest.mark.xfail(raises=IndexError)),
|
||
(None, 1, [], 'Add a reply-to email address Not completed'),
|
||
(None, 1, [{}], 'Add a reply-to email address Completed'),
|
||
(1, 1, [], 'Add a reply-to email address Not completed'),
|
||
(1, 1, [{}], 'Add a reply-to email address Completed'),
|
||
(1, 0, [], 'Add a reply-to email address Not completed'),
|
||
(1, 0, [{}], 'Add a reply-to email address Completed'),
|
||
])
|
||
def test_should_check_for_sending_things_right(
|
||
client_request,
|
||
mocker,
|
||
service_one,
|
||
fake_uuid,
|
||
single_sms_sender,
|
||
count_of_users_with_manage_service,
|
||
count_of_invites_with_manage_service,
|
||
expected_user_checklist_item,
|
||
count_of_templates,
|
||
expected_templates_checklist_item,
|
||
volume_email,
|
||
count_of_email_templates,
|
||
reply_to_email_addresses,
|
||
expected_reply_to_checklist_item,
|
||
active_user_with_permissions,
|
||
active_user_no_settings_permission,
|
||
):
|
||
def _templates_by_type(template_type):
|
||
return {
|
||
'email': list(range(0, count_of_email_templates)),
|
||
'sms': [],
|
||
}.get(template_type)
|
||
active_user_with_permissions,
|
||
mock_get_users = mocker.patch(
|
||
'app.models.user.Users.client_method',
|
||
return_value=(
|
||
[active_user_with_permissions] * count_of_users_with_manage_service +
|
||
[active_user_no_settings_permission]
|
||
)
|
||
)
|
||
invite_one = invite_json(id_=uuid4(),
|
||
from_user=service_one['users'][0],
|
||
service_id=service_one['id'],
|
||
email_address='invited_user@test.gov.uk',
|
||
permissions='view_activity,send_messages,manage_service,manage_api_keys',
|
||
created_at=datetime.utcnow(),
|
||
status='pending',
|
||
auth_type='sms_auth',
|
||
folder_permissions=[])
|
||
|
||
invite_two = invite_one.copy()
|
||
invite_two['permissions'] = 'view_activity'
|
||
|
||
mock_get_invites = mocker.patch(
|
||
'app.models.user.InvitedUsers.client_method',
|
||
return_value=(
|
||
([invite_one] * count_of_invites_with_manage_service) +
|
||
[invite_two]
|
||
)
|
||
)
|
||
|
||
mock_templates = mocker.patch(
|
||
'app.models.service.Service.all_templates',
|
||
new_callable=PropertyMock,
|
||
return_value=list(range(0, count_of_templates)),
|
||
)
|
||
|
||
mocker.patch(
|
||
'app.models.service.Service.get_templates',
|
||
side_effect=_templates_by_type,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.organisation_id',
|
||
new_callable=PropertyMock,
|
||
return_value=None,
|
||
)
|
||
|
||
mock_get_reply_to_email_addresses = mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses',
|
||
return_value=reply_to_email_addresses
|
||
)
|
||
|
||
for channel, volume in (('email', volume_email), ('sms', 0), ('letter', 1)):
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=volume,
|
||
)
|
||
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Before you request to go live'
|
||
|
||
checklist_items = page.select('.task-list .task-list-item')
|
||
assert normalize_spaces(checklist_items[1].text) == expected_user_checklist_item
|
||
assert normalize_spaces(checklist_items[2].text) == expected_templates_checklist_item
|
||
assert normalize_spaces(checklist_items[3].text) == expected_reply_to_checklist_item
|
||
|
||
mock_get_users.assert_called_once_with(SERVICE_ONE_ID)
|
||
mock_get_invites.assert_called_once_with(SERVICE_ONE_ID)
|
||
assert mock_templates.called is True
|
||
|
||
if count_of_email_templates:
|
||
mock_get_reply_to_email_addresses.assert_called_once_with(SERVICE_ONE_ID)
|
||
|
||
|
||
@pytest.mark.parametrize('checklist_completed, agreement_signed, expected_button', (
|
||
(True, True, True),
|
||
(True, None, True),
|
||
(True, False, False),
|
||
(False, True, False),
|
||
(False, None, False),
|
||
))
|
||
def test_should_not_show_go_live_button_if_checklist_not_complete(
|
||
client_request,
|
||
mocker,
|
||
mock_get_service_templates,
|
||
mock_get_users_by_service,
|
||
mock_get_service_organisation,
|
||
mock_get_invites_for_service,
|
||
single_sms_sender,
|
||
checklist_completed,
|
||
agreement_signed,
|
||
expected_button,
|
||
):
|
||
mocker.patch(
|
||
'app.models.service.Service.go_live_checklist_completed',
|
||
new_callable=PropertyMock,
|
||
return_value=checklist_completed,
|
||
)
|
||
mocker.patch(
|
||
'app.models.organisation.Organisation.agreement_signed',
|
||
new_callable=PropertyMock,
|
||
return_value=agreement_signed,
|
||
create=True,
|
||
)
|
||
|
||
for channel in ('email', 'sms', 'letter'):
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=0,
|
||
)
|
||
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Before you request to go live'
|
||
|
||
if expected_button:
|
||
assert page.select_one('form')['method'] == 'post'
|
||
assert 'action' not in page.select_one('form')
|
||
assert normalize_spaces(page.select('main p')[0].text) == (
|
||
'When we receive your request we’ll get back to you within one working day.'
|
||
)
|
||
assert normalize_spaces(page.select('main p')[1].text) == (
|
||
'By requesting to go live you’re agreeing to our terms of use.'
|
||
)
|
||
page.select_one('[type=submit]').text.strip() == ('Request to go live')
|
||
else:
|
||
assert not page.select('form')
|
||
assert not page.select('main [type=submit]')
|
||
assert len(page.select('main p')) == 1
|
||
assert normalize_spaces(page.select_one('main p').text) == (
|
||
'You must complete these steps before you can request to go live.'
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('go_live_at, message', [
|
||
(None, '‘service one’ is already live.'),
|
||
('2020-10-09 13:55:20', '‘service one’ went live on 9 October 2020.'),
|
||
])
|
||
def test_request_to_go_live_redirects_if_service_already_live(
|
||
client_request,
|
||
service_one,
|
||
go_live_at,
|
||
message,
|
||
):
|
||
service_one['restricted'] = False
|
||
service_one['go_live_at'] = go_live_at
|
||
|
||
page = client_request.get(
|
||
'main.request_to_go_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
assert page.h1.text == 'Your service is already live'
|
||
assert normalize_spaces(page.select_one('main p').text) == message
|
||
|
||
|
||
@pytest.mark.parametrize((
|
||
'estimated_sms_volume,'
|
||
'organisation_type,'
|
||
'count_of_sms_templates,'
|
||
'sms_senders,'
|
||
'expected_sms_sender_checklist_item'
|
||
), [
|
||
pytest.param(
|
||
0,
|
||
'local',
|
||
0,
|
||
[],
|
||
'',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
pytest.param(
|
||
None,
|
||
'local',
|
||
0,
|
||
[{'is_default': True, 'sms_sender': 'GOVUK'}],
|
||
'',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
pytest.param(
|
||
1,
|
||
'central',
|
||
99,
|
||
[{'is_default': True, 'sms_sender': 'GOVUK'}],
|
||
'',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
pytest.param(
|
||
None,
|
||
'central',
|
||
99,
|
||
[{'is_default': True, 'sms_sender': 'GOVUK'}],
|
||
'',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
pytest.param(
|
||
1,
|
||
'central',
|
||
99,
|
||
[{'is_default': True, 'sms_sender': 'GOVUK'}],
|
||
'',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
(
|
||
None,
|
||
'local',
|
||
1,
|
||
[],
|
||
'Change your text message sender name Not completed',
|
||
),
|
||
(
|
||
1,
|
||
'nhs_local',
|
||
0,
|
||
[],
|
||
'Change your text message sender name Not completed',
|
||
),
|
||
(
|
||
None,
|
||
'school_or_college',
|
||
1,
|
||
[{'is_default': True, 'sms_sender': 'GOVUK'}],
|
||
'Change your text message sender name Not completed',
|
||
),
|
||
(
|
||
None,
|
||
'local',
|
||
1,
|
||
[
|
||
{'is_default': False, 'sms_sender': 'GOVUK'},
|
||
{'is_default': True, 'sms_sender': 'KUVOG'},
|
||
],
|
||
'Change your text message sender name Completed',
|
||
),
|
||
(
|
||
None,
|
||
'nhs_local',
|
||
1,
|
||
[{'is_default': True, 'sms_sender': 'KUVOG'}],
|
||
'Change your text message sender name Completed',
|
||
),
|
||
])
|
||
def test_should_check_for_sms_sender_on_go_live(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
mock_get_organisation,
|
||
mock_get_invites_for_service,
|
||
organisation_type,
|
||
count_of_sms_templates,
|
||
sms_senders,
|
||
expected_sms_sender_checklist_item,
|
||
estimated_sms_volume,
|
||
):
|
||
service_one['organisation_type'] = organisation_type
|
||
|
||
def _templates_by_type(template_type):
|
||
return list(range(0, {
|
||
'email': 0,
|
||
'sms': count_of_sms_templates,
|
||
}.get(template_type, count_of_sms_templates)))
|
||
|
||
mocker.patch(
|
||
'app.models.service.Service.has_team_members',
|
||
return_value=True,
|
||
)
|
||
mock_templates = mocker.patch(
|
||
'app.models.service.Service.all_templates',
|
||
new_callable=PropertyMock,
|
||
side_effect=partial(_templates_by_type, 'all'),
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.get_templates',
|
||
side_effect=_templates_by_type,
|
||
)
|
||
|
||
mock_get_sms_senders = mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_sms_senders',
|
||
return_value=sms_senders,
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses',
|
||
return_value=[],
|
||
)
|
||
|
||
for channel, volume in (('email', 0), ('sms', estimated_sms_volume)):
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=volume,
|
||
)
|
||
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Before you request to go live'
|
||
|
||
checklist_items = page.select('.task-list .task-list-item')
|
||
assert normalize_spaces(checklist_items[3].text) == expected_sms_sender_checklist_item
|
||
|
||
assert mock_templates.called is True
|
||
|
||
mock_get_sms_senders.assert_called_once_with(SERVICE_ONE_ID)
|
||
|
||
|
||
@pytest.mark.parametrize('agreement_signed, expected_item', (
|
||
pytest.param(
|
||
None,
|
||
'',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
(
|
||
True,
|
||
'Accept our data sharing and financial agreement Completed',
|
||
),
|
||
(
|
||
False,
|
||
'Accept our data sharing and financial agreement Not completed',
|
||
),
|
||
))
|
||
def test_should_check_for_mou_on_request_to_go_live(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
agreement_signed,
|
||
mock_get_invites_for_service,
|
||
mock_get_service_organisation,
|
||
expected_item,
|
||
):
|
||
mocker.patch(
|
||
'app.models.service.Service.has_team_members',
|
||
return_value=False,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.all_templates',
|
||
new_callable=PropertyMock,
|
||
return_value=[],
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_sms_senders',
|
||
return_value=[],
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses',
|
||
return_value=[],
|
||
)
|
||
for channel in {'email', 'sms', 'letter'}:
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=None,
|
||
)
|
||
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(agreement_signed=agreement_signed)
|
||
)
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Before you request to go live'
|
||
|
||
checklist_items = page.select('.task-list .task-list-item')
|
||
assert normalize_spaces(checklist_items[3].text) == expected_item
|
||
|
||
|
||
@pytest.mark.parametrize('organisation_type', (
|
||
'nhs_gp',
|
||
pytest.param(
|
||
'central',
|
||
marks=pytest.mark.xfail(raises=IndexError)
|
||
),
|
||
))
|
||
def test_gp_without_organisation_is_shown_agreement_step(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
organisation_type,
|
||
):
|
||
mocker.patch(
|
||
'app.models.service.Service.has_team_members',
|
||
return_value=False,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.all_templates',
|
||
new_callable=PropertyMock,
|
||
return_value=[],
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_sms_senders',
|
||
return_value=[],
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses',
|
||
return_value=[],
|
||
)
|
||
for channel in {'email', 'sms', 'letter'}:
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=None,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.organisation_id',
|
||
new_callable=PropertyMock,
|
||
return_value=None,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.organisation_type',
|
||
new_callable=PropertyMock,
|
||
return_value=organisation_type,
|
||
)
|
||
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Before you request to go live'
|
||
assert normalize_spaces(
|
||
page.select('.task-list .task-list-item')[3].text
|
||
) == (
|
||
'Accept our data sharing and financial agreement Not completed'
|
||
)
|
||
|
||
|
||
def test_non_gov_user_is_told_they_cant_go_live(
|
||
client_request,
|
||
api_nongov_user_active,
|
||
mock_get_invites_for_service,
|
||
mocker,
|
||
mock_get_organisations,
|
||
mock_get_organisation,
|
||
):
|
||
mocker.patch(
|
||
'app.models.service.Service.has_team_members',
|
||
return_value=False,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.all_templates',
|
||
new_callable=PropertyMock,
|
||
return_value=[],
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_sms_senders',
|
||
return_value=[],
|
||
)
|
||
mocker.patch(
|
||
'app.main.views.service_settings.service_api_client.get_reply_to_email_addresses',
|
||
return_value=[],
|
||
)
|
||
client_request.login(api_nongov_user_active)
|
||
page = client_request.get(
|
||
'main.request_to_go_live', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert normalize_spaces(page.select_one('main p').text) == (
|
||
'Only team members with a government email address can request to go live.'
|
||
)
|
||
assert len(page.select('main form')) == 0
|
||
assert len(page.select('main button')) == 0
|
||
|
||
|
||
@pytest.mark.parametrize('consent_to_research, displayed_consent', (
|
||
(None, None),
|
||
(True, 'yes'),
|
||
(False, 'no'),
|
||
))
|
||
@pytest.mark.parametrize('volumes, displayed_volumes', (
|
||
(
|
||
(('email', None), ('sms', None), ('letter', None)),
|
||
(None, None, None),
|
||
),
|
||
(
|
||
(('email', 1234), ('sms', 0), ('letter', 999)),
|
||
('1,234', '0', '999'),
|
||
),
|
||
))
|
||
def test_should_show_estimate_volumes(
|
||
mocker,
|
||
client_request,
|
||
volumes,
|
||
displayed_volumes,
|
||
consent_to_research,
|
||
displayed_consent,
|
||
):
|
||
for channel, volume in volumes:
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=volume,
|
||
)
|
||
mocker.patch(
|
||
'app.models.service.Service.consent_to_research',
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=consent_to_research,
|
||
)
|
||
page = client_request.get(
|
||
'main.estimate_usage', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.h1.text == 'Tell us how many messages you expect to send'
|
||
for channel, label, hint, value in (
|
||
(
|
||
'email',
|
||
'How many emails do you expect to send in the next year?',
|
||
'For example, 50,000',
|
||
displayed_volumes[0],
|
||
),
|
||
(
|
||
'sms',
|
||
'How many text messages do you expect to send in the next year?',
|
||
'For example, 50,000',
|
||
displayed_volumes[1],
|
||
),
|
||
(
|
||
'letter',
|
||
'How many letters do you expect to send in the next year?',
|
||
'For example, 50,000',
|
||
displayed_volumes[2],
|
||
),
|
||
):
|
||
assert normalize_spaces(
|
||
page.select_one('label[for=volume_{}]'.format(channel)).text
|
||
) == label
|
||
assert normalize_spaces(
|
||
page.select_one('#volume_{}-hint'.format(channel)).text
|
||
) == hint
|
||
assert page.select_one('#volume_{}'.format(channel)).get('value') == value
|
||
|
||
assert len(page.select('input[type=radio]')) == 2
|
||
|
||
if displayed_consent is None:
|
||
assert len(page.select('input[checked]')) == 0
|
||
else:
|
||
assert len(page.select('input[checked]')) == 1
|
||
assert page.select_one('input[checked]')['value'] == displayed_consent
|
||
|
||
|
||
@pytest.mark.parametrize('consent_to_research, expected_persisted_consent_to_research', (
|
||
('yes', True),
|
||
('no', False),
|
||
))
|
||
def test_should_show_persist_estimated_volumes(
|
||
client_request,
|
||
mock_update_service,
|
||
consent_to_research,
|
||
expected_persisted_consent_to_research,
|
||
):
|
||
client_request.post(
|
||
'main.estimate_usage',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'volume_email': '1,234,567',
|
||
'volume_sms': '',
|
||
'volume_letter': '098',
|
||
'consent_to_research': consent_to_research,
|
||
},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.request_to_go_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
volume_email=1234567,
|
||
volume_sms=0,
|
||
volume_letter=98,
|
||
consent_to_research=expected_persisted_consent_to_research,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('data, error_selector, expected_error_message', (
|
||
(
|
||
{
|
||
'volume_email': '1234',
|
||
'volume_sms': '2000000001',
|
||
'volume_letter': '9876',
|
||
'consent_to_research': 'yes',
|
||
},
|
||
'#volume_sms-error',
|
||
'Number of text messages must be 2,000,000,000 or less'
|
||
),
|
||
(
|
||
{
|
||
'volume_email': '1 234',
|
||
'volume_sms': '0',
|
||
'volume_letter': '9876',
|
||
'consent_to_research': '',
|
||
},
|
||
'[data-error-label="consent_to_research"]',
|
||
'Select yes or no'
|
||
),
|
||
))
|
||
def test_should_error_if_bad_estimations_given(
|
||
client_request,
|
||
mock_update_service,
|
||
data,
|
||
error_selector,
|
||
expected_error_message,
|
||
):
|
||
page = client_request.post(
|
||
'main.estimate_usage',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data=data,
|
||
_expected_status=200,
|
||
)
|
||
assert expected_error_message in page.select_one(error_selector).text
|
||
assert mock_update_service.called is False
|
||
|
||
|
||
def test_should_error_if_all_volumes_zero(
|
||
client_request,
|
||
mock_update_service,
|
||
):
|
||
page = client_request.post(
|
||
'main.estimate_usage',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'volume_email': '',
|
||
'volume_sms': '0',
|
||
'volume_letter': '0,00 0',
|
||
'consent_to_research': 'yes',
|
||
},
|
||
_expected_status=200,
|
||
)
|
||
assert page.select('input[type=text]')[0].get('value') is None
|
||
assert page.select('input[type=text]')[1]['value'] == '0'
|
||
assert page.select('input[type=text]')[2]['value'] == '0,00 0'
|
||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||
'Enter the number of messages you expect to send in the next year'
|
||
)
|
||
assert mock_update_service.called is False
|
||
|
||
|
||
def test_should_not_default_to_zero_if_some_fields_dont_validate(
|
||
client_request,
|
||
mock_update_service,
|
||
):
|
||
page = client_request.post(
|
||
'main.estimate_usage',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'volume_email': '1234',
|
||
'volume_sms': '',
|
||
'volume_letter': 'aaaaaaaaaaaaa',
|
||
'consent_to_research': 'yes',
|
||
},
|
||
_expected_status=200,
|
||
)
|
||
assert page.select('input[type=text]')[0]['value'] == '1234'
|
||
assert page.select('input[type=text]')[1].get('value') is None
|
||
assert page.select('input[type=text]')[2]['value'] == 'aaaaaaaaaaaaa'
|
||
assert normalize_spaces(
|
||
page.select_one('#volume_letter-error').text
|
||
) == 'Error: Enter the number of letters you expect to send'
|
||
assert mock_update_service.called is False
|
||
|
||
|
||
def test_non_gov_users_cant_request_to_go_live(
|
||
client_request,
|
||
api_nongov_user_active,
|
||
mock_get_organisations,
|
||
):
|
||
client_request.login(api_nongov_user_active)
|
||
client_request.post(
|
||
'main.request_to_go_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_expected_status=403,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('volumes, displayed_volumes, formatted_displayed_volumes, extra_tags', (
|
||
(
|
||
(('email', None), ('sms', None), ('letter', None)),
|
||
', , ',
|
||
(
|
||
'Emails in next year: \n'
|
||
'Text messages in next year: \n'
|
||
'Letters in next year: \n'
|
||
),
|
||
['notify_go_live_incomplete_volumes']
|
||
),
|
||
(
|
||
(('email', 1234), ('sms', 0), ('letter', 999)),
|
||
'0, 1234, 999', # This is a different order to match the spreadsheet
|
||
(
|
||
'Emails in next year: 1,234\n'
|
||
'Text messages in next year: 0\n'
|
||
'Letters in next year: 999\n'
|
||
),
|
||
[],
|
||
),
|
||
))
|
||
@freeze_time("2012-12-21 13:12:12.12354")
|
||
def test_should_redirect_after_request_to_go_live(
|
||
client_request,
|
||
mocker,
|
||
active_user_with_permissions,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisations_and_services_for_user,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_service_templates,
|
||
mock_get_users_by_service,
|
||
mock_update_service,
|
||
mock_get_invites_without_manage_permission,
|
||
volumes,
|
||
displayed_volumes,
|
||
formatted_displayed_volumes,
|
||
extra_tags,
|
||
):
|
||
for channel, volume in volumes:
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=volume,
|
||
)
|
||
mock_post = mocker.patch('app.main.views.service_settings.zendesk_client.create_ticket', autospec=True)
|
||
page = client_request.post(
|
||
'main.request_to_go_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_follow_redirects=True
|
||
)
|
||
mock_post.assert_called_with(
|
||
subject='Request to go live - service one',
|
||
message=ANY,
|
||
ticket_type=ZendeskClient.TYPE_QUESTION,
|
||
user_name=active_user_with_permissions['name'],
|
||
user_email=active_user_with_permissions['email_address'],
|
||
tags=[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
] + extra_tags + [
|
||
'notify_go_live_incomplete_checklist',
|
||
'notify_go_live_incomplete_mou',
|
||
'notify_go_live_incomplete_team_member',
|
||
],
|
||
)
|
||
assert mock_post.call_args[1]['message'] == (
|
||
'Service: service one\n'
|
||
'http://localhost/services/{service_id}\n'
|
||
'\n'
|
||
'---\n'
|
||
'Organisation type: Central\n'
|
||
'Agreement signed: Can’t tell (domain is user.gov.uk).\n'
|
||
'{formatted_displayed_volumes}'
|
||
'Consent to research: Yes\n'
|
||
'Other live services: No\n'
|
||
'\n'
|
||
'---\n'
|
||
'Request sent by test@user.gov.uk\n'
|
||
).format(
|
||
service_id=SERVICE_ONE_ID,
|
||
displayed_volumes=displayed_volumes,
|
||
formatted_displayed_volumes=formatted_displayed_volumes,
|
||
)
|
||
|
||
assert normalize_spaces(page.select_one('.banner-default').text) == (
|
||
'Thanks for your request to go live. We’ll get back to you within one working day.'
|
||
)
|
||
assert normalize_spaces(page.select_one('h1').text) == (
|
||
'Settings'
|
||
)
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
go_live_user=active_user_with_permissions['id']
|
||
)
|
||
|
||
|
||
def test_request_to_go_live_displays_go_live_notes_in_zendesk_ticket(
|
||
client_request,
|
||
mocker,
|
||
active_user_with_permissions,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisations_and_services_for_user,
|
||
single_sms_sender,
|
||
mock_get_service_organisation,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_service_templates,
|
||
mock_get_users_by_service,
|
||
mock_update_service,
|
||
mock_get_invites_without_manage_permission,
|
||
):
|
||
go_live_note = 'This service is not allowed to go live'
|
||
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
side_effect=lambda org_id: organisation_json(
|
||
ORGANISATION_ID,
|
||
'Org 1',
|
||
request_to_go_live_notes=go_live_note,
|
||
)
|
||
)
|
||
mock_post = mocker.patch('app.main.views.service_settings.zendesk_client.create_ticket', autospec=True)
|
||
client_request.post(
|
||
'main.request_to_go_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_follow_redirects=True
|
||
)
|
||
|
||
assert mock_post.call_args[1]['message'] == (
|
||
'Service: service one\n'
|
||
'http://localhost/services/{service_id}\n'
|
||
'\n'
|
||
'---\n'
|
||
'Organisation type: Central\n'
|
||
'Agreement signed: No (organisation is Org 1, a crown body). {go_live_note}\n'
|
||
'Emails in next year: 111,111\n'
|
||
'Text messages in next year: 222,222\n'
|
||
'Letters in next year: 333,333\n'
|
||
'Consent to research: Yes\n'
|
||
'Other live services: No\n'
|
||
'\n'
|
||
'---\n'
|
||
'Request sent by test@user.gov.uk\n'
|
||
).format(
|
||
service_id=SERVICE_ONE_ID,
|
||
go_live_note=go_live_note
|
||
)
|
||
|
||
|
||
def test_should_be_able_to_request_to_go_live_with_no_organisation(
|
||
client_request,
|
||
mocker,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisations_and_services_for_user,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_service_templates,
|
||
mock_get_users_by_service,
|
||
mock_update_service,
|
||
mock_get_invites_without_manage_permission,
|
||
):
|
||
for channel in {'email', 'sms', 'letter'}:
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=1,
|
||
)
|
||
mock_post = mocker.patch('app.main.views.service_settings.zendesk_client.create_ticket', autospec=True)
|
||
|
||
client_request.post(
|
||
'main.request_to_go_live',
|
||
service_id=SERVICE_ONE_ID,
|
||
_follow_redirects=True
|
||
)
|
||
|
||
assert mock_post.called is True
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
(
|
||
'has_team_members,'
|
||
'has_templates,'
|
||
'has_email_templates,'
|
||
'has_sms_templates,'
|
||
'has_email_reply_to_address,'
|
||
'shouldnt_use_govuk_as_sms_sender,'
|
||
'sms_sender_is_govuk,'
|
||
'volume_email,'
|
||
'volume_sms,'
|
||
'volume_letter,'
|
||
'expected_readyness,'
|
||
'agreement_signed,'
|
||
'expected_tags,'
|
||
),
|
||
(
|
||
( # Just sending email
|
||
True,
|
||
True,
|
||
True,
|
||
False,
|
||
True,
|
||
True,
|
||
True,
|
||
1, 0, 0,
|
||
'Yes',
|
||
True,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_complete',
|
||
],
|
||
),
|
||
( # Needs to set reply to address
|
||
True,
|
||
True,
|
||
True,
|
||
False,
|
||
False,
|
||
True,
|
||
True,
|
||
1, 0, 1,
|
||
'No',
|
||
True,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_incomplete_checklist',
|
||
'notify_go_live_incomplete_email_reply_to',
|
||
],
|
||
),
|
||
( # Just sending SMS
|
||
True,
|
||
True,
|
||
False,
|
||
True,
|
||
True,
|
||
True,
|
||
False,
|
||
0, 1, 0,
|
||
'Yes',
|
||
True,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_complete',
|
||
],
|
||
),
|
||
( # Needs to change SMS sender
|
||
True,
|
||
True,
|
||
False,
|
||
True,
|
||
True,
|
||
True,
|
||
True,
|
||
0, 1, 0,
|
||
'No',
|
||
True,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_incomplete_checklist',
|
||
'notify_go_live_incomplete_sms_sender',
|
||
],
|
||
),
|
||
( # Needs team members
|
||
False,
|
||
True,
|
||
False,
|
||
True,
|
||
True,
|
||
True,
|
||
False,
|
||
1, 0, 0,
|
||
'No',
|
||
True,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_incomplete_checklist',
|
||
'notify_go_live_incomplete_team_member',
|
||
],
|
||
),
|
||
( # Needs templates
|
||
True,
|
||
False,
|
||
False,
|
||
True,
|
||
True,
|
||
True,
|
||
False,
|
||
0, 1, 0,
|
||
'No',
|
||
True,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_incomplete_checklist',
|
||
'notify_go_live_incomplete_template_content',
|
||
],
|
||
),
|
||
( # Not done anything yet
|
||
False,
|
||
False,
|
||
False,
|
||
False,
|
||
False,
|
||
False,
|
||
True,
|
||
None, None, None,
|
||
'No',
|
||
False,
|
||
[
|
||
'notify_action',
|
||
'notify_go_live',
|
||
'notify_go_live_incomplete_volumes',
|
||
'notify_go_live_incomplete_checklist',
|
||
'notify_go_live_incomplete_mou',
|
||
'notify_go_live_incomplete_team_member',
|
||
'notify_go_live_incomplete_template_content',
|
||
],
|
||
),
|
||
),
|
||
)
|
||
def test_ready_to_go_live(
|
||
client_request,
|
||
mocker,
|
||
mock_get_service_organisation,
|
||
has_team_members,
|
||
has_templates,
|
||
has_email_templates,
|
||
has_sms_templates,
|
||
has_email_reply_to_address,
|
||
shouldnt_use_govuk_as_sms_sender,
|
||
sms_sender_is_govuk,
|
||
volume_email,
|
||
volume_sms,
|
||
volume_letter,
|
||
expected_readyness,
|
||
agreement_signed,
|
||
expected_tags,
|
||
):
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(agreement_signed=agreement_signed)
|
||
)
|
||
|
||
for prop in {
|
||
'has_team_members',
|
||
'has_templates',
|
||
'has_email_templates',
|
||
'has_sms_templates',
|
||
'has_email_reply_to_address',
|
||
'shouldnt_use_govuk_as_sms_sender',
|
||
'sms_sender_is_govuk',
|
||
}:
|
||
mocker.patch(
|
||
'app.models.service.Service.{}'.format(prop),
|
||
new_callable=PropertyMock
|
||
).return_value = locals()[prop]
|
||
|
||
for channel, volume in (
|
||
('sms', volume_sms),
|
||
('email', volume_email),
|
||
('letter', volume_letter),
|
||
):
|
||
mocker.patch(
|
||
'app.models.service.Service.volume_{}'.format(channel),
|
||
create=True,
|
||
new_callable=PropertyMock,
|
||
return_value=volume,
|
||
)
|
||
|
||
assert app.models.service.Service({
|
||
'id': SERVICE_ONE_ID
|
||
}).go_live_checklist_completed_as_yes_no == expected_readyness
|
||
|
||
assert app.models.service.Service(
|
||
{'id': SERVICE_ONE_ID}
|
||
).request_to_go_live_tags == expected_tags
|
||
|
||
|
||
@pytest.mark.parametrize('route', [
|
||
'main.service_settings',
|
||
'main.service_name_change',
|
||
'main.service_name_change_confirm',
|
||
'main.request_to_go_live',
|
||
'main.submit_request_to_go_live',
|
||
'main.archive_service'
|
||
])
|
||
def test_route_permissions(
|
||
mocker,
|
||
app_,
|
||
client,
|
||
api_user_active,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
mock_get_invites_for_service,
|
||
single_sms_sender,
|
||
route,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_service_templates,
|
||
):
|
||
validate_route_permission(
|
||
mocker,
|
||
app_,
|
||
"GET",
|
||
200,
|
||
url_for(route, service_id=service_one['id']),
|
||
['manage_service'],
|
||
api_user_active,
|
||
service_one,
|
||
session={'service_name_change': "New Service Name"}
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('route', [
|
||
'main.service_settings',
|
||
'main.service_name_change',
|
||
'main.service_name_change_confirm',
|
||
'main.request_to_go_live',
|
||
'main.submit_request_to_go_live',
|
||
'main.service_switch_live',
|
||
'main.archive_service',
|
||
])
|
||
def test_route_invalid_permissions(
|
||
mocker,
|
||
app_,
|
||
client,
|
||
api_user_active,
|
||
service_one,
|
||
route,
|
||
mock_get_service_templates,
|
||
mock_get_invites_for_service,
|
||
):
|
||
validate_route_permission(
|
||
mocker,
|
||
app_,
|
||
"GET",
|
||
403,
|
||
url_for(route, service_id=service_one['id']),
|
||
['blah'],
|
||
api_user_active,
|
||
service_one)
|
||
|
||
|
||
@pytest.mark.parametrize('route', [
|
||
'main.service_settings',
|
||
'main.service_name_change',
|
||
'main.service_name_change_confirm',
|
||
'main.request_to_go_live',
|
||
'main.submit_request_to_go_live',
|
||
])
|
||
def test_route_for_platform_admin(
|
||
mocker,
|
||
app_,
|
||
client,
|
||
platform_admin_user,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
route,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_service_templates,
|
||
mock_get_invites_for_service,
|
||
):
|
||
validate_route_permission(
|
||
mocker,
|
||
app_,
|
||
"GET",
|
||
200,
|
||
url_for(route, service_id=service_one['id']),
|
||
[],
|
||
platform_admin_user,
|
||
service_one,
|
||
session={'service_name_change': "New Service Name"}
|
||
)
|
||
|
||
|
||
def test_and_more_hint_appears_on_settings_with_more_than_just_a_single_sender(
|
||
client_request,
|
||
service_one,
|
||
multiple_reply_to_email_addresses,
|
||
multiple_letter_contact_blocks,
|
||
mock_get_organisation,
|
||
multiple_sms_senders,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['permissions'] = ['email', 'sms', 'letter']
|
||
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=service_one['id']
|
||
)
|
||
|
||
def get_row(page, label):
|
||
return normalize_spaces(
|
||
find_element_by_tag_and_partial_text(page, tag='tr', string=label).text
|
||
)
|
||
|
||
assert get_row(page, 'Reply-to email addresses') == \
|
||
"Reply-to email addresses test@example.com …and 2 more Manage reply-to email addresses"
|
||
assert get_row(page, 'Text message senders') == \
|
||
"Text message senders Example …and 2 more Manage text message senders"
|
||
assert get_row(page, 'Sender addresses') == "Sender addresses 1 Example Street …and 2 more Manage sender addresses"
|
||
|
||
|
||
@pytest.mark.parametrize('sender_list_page, index, expected_output', [
|
||
('main.service_email_reply_to', 0, 'test@example.com (default) Change'),
|
||
('main.service_letter_contact_details', 1, '1 Example Street (default) Change'),
|
||
('main.service_sms_senders', 0, 'GOVUK (default) Change')
|
||
])
|
||
def test_api_ids_dont_show_on_option_pages_with_a_single_sender(
|
||
client_request,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
sender_list_page,
|
||
index,
|
||
expected_output,
|
||
):
|
||
rows = client_request.get(
|
||
sender_list_page,
|
||
service_id=SERVICE_ONE_ID
|
||
).select(
|
||
'.user-list-item'
|
||
)
|
||
|
||
assert normalize_spaces(rows[index].text) == expected_output
|
||
assert len(rows) == index + 1
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
(
|
||
'sender_list_page,'
|
||
'endpoint_to_mock,'
|
||
'sample_data,'
|
||
'expected_items,'
|
||
),
|
||
[(
|
||
'main.service_email_reply_to',
|
||
'app.service_api_client.get_reply_to_email_addresses',
|
||
create_multiple_email_reply_to_addresses(),
|
||
[
|
||
'test@example.com (default) Change ID: 1234',
|
||
'test2@example.com Change ID: 5678',
|
||
'test3@example.com Change ID: 9457',
|
||
],
|
||
), (
|
||
'main.service_letter_contact_details',
|
||
'app.service_api_client.get_letter_contacts',
|
||
create_multiple_letter_contact_blocks(),
|
||
[
|
||
'Blank Make default',
|
||
'1 Example Street (default) Change ID: 1234',
|
||
'2 Example Street Change ID: 5678',
|
||
'foo<bar>baz Change ID: 9457',
|
||
],
|
||
), (
|
||
'main.service_sms_senders',
|
||
'app.service_api_client.get_sms_senders',
|
||
create_multiple_sms_senders(),
|
||
[
|
||
'Example (default and receives replies) Change ID: 1234',
|
||
'Example 2 Change ID: 5678',
|
||
'Example 3 Change ID: 9457',
|
||
],
|
||
),
|
||
]
|
||
)
|
||
def test_default_option_shows_for_default_sender(
|
||
client_request,
|
||
mocker,
|
||
sender_list_page,
|
||
endpoint_to_mock,
|
||
sample_data,
|
||
expected_items,
|
||
):
|
||
mocker.patch(endpoint_to_mock, return_value=sample_data)
|
||
|
||
rows = client_request.get(
|
||
sender_list_page,
|
||
service_id=SERVICE_ONE_ID
|
||
).select(
|
||
'.user-list-item'
|
||
)
|
||
|
||
assert [normalize_spaces(row.text) for row in rows] == expected_items
|
||
|
||
|
||
def test_remove_default_from_default_letter_contact_block(
|
||
client_request,
|
||
mocker,
|
||
multiple_letter_contact_blocks,
|
||
mock_update_letter_contact,
|
||
):
|
||
letter_contact_details_page = url_for(
|
||
'main.service_letter_contact_details',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
|
||
link = client_request.get_url(letter_contact_details_page).select_one('.user-list-item a')
|
||
assert link.text == 'Make default'
|
||
assert link['href'] == url_for(
|
||
'.service_make_blank_default_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
client_request.get_url(
|
||
link['href'],
|
||
_expected_status=302,
|
||
_expected_redirect=letter_contact_details_page,
|
||
)
|
||
|
||
mock_update_letter_contact.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
letter_contact_id='1234',
|
||
contact_block='1 Example Street',
|
||
is_default=False,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('sender_list_page, endpoint_to_mock, expected_output', [
|
||
(
|
||
'main.service_email_reply_to',
|
||
'app.service_api_client.get_reply_to_email_addresses',
|
||
'You have not added any reply-to email addresses yet'
|
||
),
|
||
(
|
||
'main.service_letter_contact_details',
|
||
'app.service_api_client.get_letter_contacts',
|
||
'Blank (default)'
|
||
),
|
||
(
|
||
'main.service_sms_senders',
|
||
'app.service_api_client.get_sms_senders',
|
||
'You have not added any text message senders yet'
|
||
),
|
||
])
|
||
def test_no_senders_message_shows(
|
||
client_request,
|
||
sender_list_page,
|
||
endpoint_to_mock,
|
||
expected_output,
|
||
mocker
|
||
):
|
||
mocker.patch(endpoint_to_mock, return_value=[])
|
||
|
||
rows = client_request.get(
|
||
sender_list_page,
|
||
service_id=SERVICE_ONE_ID
|
||
).select(
|
||
'.user-list-item'
|
||
)
|
||
|
||
assert normalize_spaces(rows[0].text) == expected_output
|
||
assert len(rows) == 1
|
||
|
||
|
||
@pytest.mark.parametrize('reply_to_input, expected_error', [
|
||
('', 'Cannot be empty'),
|
||
('testtest', 'Enter a valid email address'),
|
||
])
|
||
def test_incorrect_reply_to_email_address_input(
|
||
reply_to_input,
|
||
expected_error,
|
||
client_request,
|
||
no_reply_to_email_addresses
|
||
):
|
||
page = client_request.post(
|
||
'main.service_add_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'email_address': reply_to_input},
|
||
_expected_status=200
|
||
)
|
||
|
||
assert expected_error in normalize_spaces(page.select_one('.govuk-error-message').text)
|
||
|
||
|
||
@pytest.mark.parametrize('contact_block_input, expected_error', [
|
||
('', 'Cannot be empty'),
|
||
('1 \n 2 \n 3 \n 4 \n 5 \n 6 \n 7 \n 8 \n 9 \n 0 \n a', 'Contains 11 lines, maximum is 10')
|
||
])
|
||
def test_incorrect_letter_contact_block_input(
|
||
contact_block_input,
|
||
expected_error,
|
||
client_request,
|
||
no_letter_contact_blocks
|
||
):
|
||
page = client_request.post(
|
||
'main.service_add_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'letter_contact_block': contact_block_input},
|
||
_expected_status=200
|
||
)
|
||
|
||
assert normalize_spaces(page.select_one('.error-message').text) == expected_error
|
||
|
||
|
||
@pytest.mark.parametrize('sms_sender_input, expected_error', [
|
||
('elevenchars', None),
|
||
('11 chars', None),
|
||
('', 'Cannot be empty'),
|
||
('abcdefghijkhgkg', 'Enter 11 characters or fewer'),
|
||
(r' ¯\_(ツ)_/¯ ', 'Use letters and numbers only'),
|
||
('blood.co.uk', None),
|
||
('00123', "Cannot start with 00")
|
||
])
|
||
def test_incorrect_sms_sender_input(
|
||
sms_sender_input,
|
||
expected_error,
|
||
client_request,
|
||
no_sms_senders,
|
||
mock_add_sms_sender,
|
||
):
|
||
page = client_request.post(
|
||
'main.service_add_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={'sms_sender': sms_sender_input},
|
||
_expected_status=(200 if expected_error else 302)
|
||
)
|
||
|
||
error_message = page.select_one('.govuk-error-message')
|
||
count_of_api_calls = len(mock_add_sms_sender.call_args_list)
|
||
|
||
if not expected_error:
|
||
assert not error_message
|
||
assert count_of_api_calls == 1
|
||
else:
|
||
assert expected_error in error_message.text
|
||
assert count_of_api_calls == 0
|
||
|
||
|
||
@pytest.mark.parametrize('reply_to_addresses, data, api_default_args', [
|
||
([], {}, True),
|
||
(create_multiple_email_reply_to_addresses(), {}, False),
|
||
(create_multiple_email_reply_to_addresses(), {"is_default": "y"}, True)
|
||
])
|
||
def test_add_reply_to_email_address_sends_test_notification(
|
||
mocker, client_request, reply_to_addresses, data, api_default_args
|
||
):
|
||
mocker.patch('app.service_api_client.get_reply_to_email_addresses', return_value=reply_to_addresses)
|
||
data['email_address'] = "test@example.com"
|
||
mock_verify = mocker.patch(
|
||
'app.service_api_client.verify_reply_to_email_address', return_value={"data": {"id": "123"}}
|
||
)
|
||
client_request.post(
|
||
'main.service_add_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data=data,
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
'main.service_verify_reply_to_address',
|
||
service_id=SERVICE_ONE_ID,
|
||
notification_id="123",
|
||
_external=True,
|
||
) + "?is_default={}".format(api_default_args)
|
||
)
|
||
mock_verify.assert_called_once_with(SERVICE_ONE_ID, "test@example.com")
|
||
|
||
|
||
@pytest.mark.parametrize("is_default,replace,expected_header", [(True, "&replace=123", "Change"), (False, "", "Add")])
|
||
@pytest.mark.parametrize("status,expected_failure,expected_success", [
|
||
("delivered", 0, 1),
|
||
("sending", 0, 0),
|
||
("permanent-failure", 1, 0),
|
||
])
|
||
@freeze_time("2018-06-01 11:11:00.061258")
|
||
def test_service_verify_reply_to_address(
|
||
mocker,
|
||
client_request,
|
||
fake_uuid,
|
||
get_non_default_reply_to_email_address,
|
||
status,
|
||
expected_failure,
|
||
expected_success,
|
||
is_default,
|
||
replace,
|
||
expected_header
|
||
):
|
||
notification = {
|
||
"id": fake_uuid,
|
||
"status": status,
|
||
"to": "email@example.gov.uk",
|
||
"service_id": SERVICE_ONE_ID,
|
||
"template_id": TEMPLATE_ONE_ID,
|
||
"notification_type": "email",
|
||
"created_at": '2018-06-01T11:10:52.499230+00:00'
|
||
}
|
||
mocker.patch('app.notification_api_client.get_notification', return_value=notification)
|
||
mock_add_reply_to_email_address = mocker.patch('app.service_api_client.add_reply_to_email_address')
|
||
mock_update_reply_to_email_address = mocker.patch('app.service_api_client.update_reply_to_email_address')
|
||
mocker.patch(
|
||
'app.service_api_client.get_reply_to_email_addresses', return_value=[]
|
||
)
|
||
page = client_request.get(
|
||
'main.service_verify_reply_to_address',
|
||
service_id=SERVICE_ONE_ID,
|
||
notification_id=notification["id"],
|
||
_optional_args="?is_default={}{}".format(is_default, replace)
|
||
)
|
||
assert page.find('h1').text == '{} email reply-to address'.format(expected_header)
|
||
if replace:
|
||
assert "/email-reply-to/123/edit" in page.find('a', text="Back").attrs["href"]
|
||
else:
|
||
assert "/email-reply-to/add" in page.find('a', text="Back").attrs["href"]
|
||
|
||
assert len(page.find_all('div', class_='banner-dangerous')) == expected_failure
|
||
assert len(page.find_all('div', class_='banner-default-with-tick')) == expected_success
|
||
|
||
if status == "delivered":
|
||
if replace:
|
||
mock_update_reply_to_email_address.assert_called_once_with(
|
||
SERVICE_ONE_ID, "123", email_address=notification["to"], is_default=is_default
|
||
)
|
||
assert mock_add_reply_to_email_address.called is False
|
||
else:
|
||
mock_add_reply_to_email_address.assert_called_once_with(
|
||
SERVICE_ONE_ID, email_address=notification["to"], is_default=is_default
|
||
)
|
||
assert mock_update_reply_to_email_address.called is False
|
||
else:
|
||
assert mock_add_reply_to_email_address.called is False
|
||
if status == "permanent-failure":
|
||
assert page.find('input', type='email').attrs["value"] == notification["to"]
|
||
|
||
|
||
@freeze_time("2018-06-01 11:11:00.061258")
|
||
def test_add_reply_to_email_address_fails_if_notification_not_delivered_in_45_sec(mocker, client_request, fake_uuid):
|
||
notification = {
|
||
"id": fake_uuid,
|
||
"status": "sending",
|
||
"to": "email@example.gov.uk",
|
||
"service_id": SERVICE_ONE_ID,
|
||
"template_id": TEMPLATE_ONE_ID,
|
||
"notification_type": "email",
|
||
"created_at": '2018-06-01T11:10:12.499230+00:00'
|
||
}
|
||
mocker.patch(
|
||
'app.service_api_client.get_reply_to_email_addresses', return_value=[]
|
||
)
|
||
mocker.patch('app.notification_api_client.get_notification', return_value=notification)
|
||
mock_add_reply_to_email_address = mocker.patch('app.service_api_client.add_reply_to_email_address')
|
||
page = client_request.get(
|
||
'main.service_verify_reply_to_address',
|
||
service_id=SERVICE_ONE_ID,
|
||
notification_id=notification["id"],
|
||
_optional_args="?is_default={}".format(False)
|
||
)
|
||
expected_banner = page.find_all('div', class_='banner-dangerous')[0]
|
||
assert 'There’s a problem with your reply-to address' in expected_banner.text.strip()
|
||
assert mock_add_reply_to_email_address.called is False
|
||
|
||
|
||
@pytest.mark.parametrize('letter_contact_blocks, data, api_default_args', [
|
||
([], {}, True), # no existing letter contact blocks
|
||
(create_multiple_letter_contact_blocks(), {}, False),
|
||
(create_multiple_letter_contact_blocks(), {"is_default": "y"}, True)
|
||
])
|
||
def test_add_letter_contact(
|
||
letter_contact_blocks,
|
||
data,
|
||
api_default_args,
|
||
mocker,
|
||
client_request,
|
||
mock_add_letter_contact
|
||
):
|
||
mocker.patch('app.service_api_client.get_letter_contacts', return_value=letter_contact_blocks)
|
||
|
||
data['letter_contact_block'] = "1 Example Street"
|
||
client_request.post(
|
||
'main.service_add_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data=data
|
||
)
|
||
|
||
mock_add_letter_contact.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
contact_block="1 Example Street",
|
||
is_default=api_default_args
|
||
)
|
||
|
||
|
||
def test_add_letter_contact_when_coming_from_template(
|
||
no_letter_contact_blocks,
|
||
client_request,
|
||
mock_add_letter_contact,
|
||
fake_uuid,
|
||
mock_get_service_letter_template,
|
||
mock_update_service_template_sender,
|
||
):
|
||
page = client_request.get(
|
||
'main.service_add_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
from_template=fake_uuid,
|
||
)
|
||
|
||
assert page.select_one('.govuk-back-link')['href'] == url_for(
|
||
'main.view_template',
|
||
service_id=SERVICE_ONE_ID,
|
||
template_id=fake_uuid,
|
||
)
|
||
|
||
client_request.post(
|
||
'main.service_add_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'letter_contact_block': '1 Example Street',
|
||
},
|
||
from_template=fake_uuid,
|
||
_expected_redirect=url_for(
|
||
'main.view_template',
|
||
service_id=SERVICE_ONE_ID,
|
||
template_id=fake_uuid,
|
||
_external=True,
|
||
),
|
||
)
|
||
|
||
mock_add_letter_contact.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
contact_block="1 Example Street",
|
||
is_default=True,
|
||
)
|
||
mock_update_service_template_sender.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
fake_uuid,
|
||
'1234',
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('sms_senders, data, api_default_args', [
|
||
([], {}, True),
|
||
(create_multiple_sms_senders(), {}, False),
|
||
(create_multiple_sms_senders(), {"is_default": "y"}, True)
|
||
])
|
||
def test_add_sms_sender(
|
||
sms_senders,
|
||
data,
|
||
api_default_args,
|
||
mocker,
|
||
client_request,
|
||
mock_add_sms_sender
|
||
):
|
||
mocker.patch('app.service_api_client.get_sms_senders', return_value=sms_senders)
|
||
data['sms_sender'] = "Example"
|
||
client_request.post(
|
||
'main.service_add_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
_data=data
|
||
)
|
||
|
||
mock_add_sms_sender.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
sms_sender="Example",
|
||
is_default=api_default_args
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('reply_to_addresses, checkbox_present', [
|
||
([], False),
|
||
(create_multiple_email_reply_to_addresses(), True),
|
||
])
|
||
def test_default_box_doesnt_show_on_first_email_sender(
|
||
reply_to_addresses,
|
||
mocker,
|
||
checkbox_present,
|
||
client_request
|
||
):
|
||
mocker.patch('app.service_api_client.get_reply_to_email_addresses', return_value=reply_to_addresses)
|
||
|
||
page = client_request.get(
|
||
'main.service_add_email_reply_to',
|
||
service_id=SERVICE_ONE_ID
|
||
)
|
||
|
||
assert bool(page.select_one('[name=is_default]')) == checkbox_present
|
||
|
||
|
||
@pytest.mark.parametrize('contact_blocks, checkbox_present', [
|
||
([], False),
|
||
(create_multiple_letter_contact_blocks(), True)
|
||
])
|
||
def test_default_box_doesnt_show_on_first_letter_sender(
|
||
contact_blocks,
|
||
mocker,
|
||
checkbox_present,
|
||
client_request
|
||
):
|
||
mocker.patch('app.service_api_client.get_letter_contacts', return_value=contact_blocks)
|
||
|
||
page = client_request.get(
|
||
'main.service_add_letter_contact',
|
||
service_id=SERVICE_ONE_ID
|
||
)
|
||
|
||
assert bool(page.select_one('[name=is_default]')) == checkbox_present
|
||
|
||
|
||
@pytest.mark.parametrize('reply_to_address, data, api_default_args', [
|
||
(create_reply_to_email_address(is_default=True), {"is_default": "y"}, True),
|
||
(create_reply_to_email_address(is_default=True), {}, True),
|
||
(create_reply_to_email_address(is_default=False), {}, False),
|
||
(create_reply_to_email_address(is_default=False), {"is_default": "y"}, True)
|
||
])
|
||
def test_edit_reply_to_email_address_sends_verification_notification_if_address_is_changed(
|
||
reply_to_address,
|
||
data,
|
||
api_default_args,
|
||
mocker,
|
||
fake_uuid,
|
||
client_request,
|
||
):
|
||
mock_verify = mocker.patch(
|
||
'app.service_api_client.verify_reply_to_email_address', return_value={"data": {"id": "123"}}
|
||
)
|
||
mocker.patch('app.service_api_client.get_reply_to_email_address', return_value=reply_to_address)
|
||
data['email_address'] = "test@example.gov.uk"
|
||
client_request.post(
|
||
'main.service_edit_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
reply_to_email_id=fake_uuid,
|
||
_data=data
|
||
)
|
||
mock_verify.assert_called_once_with(SERVICE_ONE_ID, "test@example.gov.uk")
|
||
|
||
|
||
@pytest.mark.parametrize('reply_to_address, data, api_default_args', [
|
||
(create_reply_to_email_address(), {"is_default": "y"}, True),
|
||
(create_reply_to_email_address(), {}, True),
|
||
(create_reply_to_email_address(is_default=False), {}, False),
|
||
(create_reply_to_email_address(is_default=False), {"is_default": "y"}, True)
|
||
])
|
||
def test_edit_reply_to_email_address_goes_straight_to_update_if_address_not_changed(
|
||
reply_to_address,
|
||
data,
|
||
api_default_args,
|
||
mocker,
|
||
fake_uuid,
|
||
client_request,
|
||
mock_update_reply_to_email_address
|
||
):
|
||
mocker.patch('app.service_api_client.get_reply_to_email_address', return_value=reply_to_address)
|
||
mock_verify = mocker.patch('app.service_api_client.verify_reply_to_email_address')
|
||
data['email_address'] = "test@example.com"
|
||
client_request.post(
|
||
'main.service_edit_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
reply_to_email_id=fake_uuid,
|
||
_data=data
|
||
)
|
||
|
||
mock_update_reply_to_email_address.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
reply_to_email_id=fake_uuid,
|
||
email_address="test@example.com",
|
||
is_default=api_default_args
|
||
)
|
||
assert mock_verify.called is False
|
||
|
||
|
||
@pytest.mark.parametrize('url', [
|
||
'main.service_edit_email_reply_to',
|
||
'main.service_add_email_reply_to',
|
||
])
|
||
def test_add_edit_reply_to_email_address_goes_straight_to_update_if_address_not_changed(
|
||
mocker,
|
||
fake_uuid,
|
||
client_request,
|
||
mock_update_reply_to_email_address,
|
||
url
|
||
):
|
||
reply_to_email_address = create_reply_to_email_address()
|
||
mocker.patch('app.service_api_client.get_reply_to_email_addresses', return_value=[reply_to_email_address])
|
||
mocker.patch('app.service_api_client.get_reply_to_email_address', return_value=reply_to_email_address)
|
||
error_message = 'Your service already uses ‘reply_to@example.com’ as an email reply-to address.'
|
||
mocker.patch(
|
||
'app.service_api_client.verify_reply_to_email_address', side_effect=[HTTPError(
|
||
response=Mock(
|
||
status_code=409,
|
||
json={
|
||
'result': 'error',
|
||
'message': error_message
|
||
}
|
||
),
|
||
message=error_message
|
||
)]
|
||
)
|
||
data = {"is_default": "y", 'email_address': "reply_to@example.com"}
|
||
page = client_request.post(
|
||
url,
|
||
service_id=SERVICE_ONE_ID,
|
||
reply_to_email_id=fake_uuid,
|
||
_data=data,
|
||
_follow_redirects=True
|
||
)
|
||
|
||
assert page.find('h1').text == "Reply-to email addresses"
|
||
assert error_message in page.find('div', class_='banner-dangerous').text
|
||
|
||
assert mock_update_reply_to_email_address.called is False
|
||
|
||
|
||
@pytest.mark.parametrize('reply_to_address, expected_link_text, partial_href', [
|
||
(
|
||
create_reply_to_email_address(is_default=False),
|
||
'Delete',
|
||
partial(url_for, 'main.service_confirm_delete_email_reply_to', reply_to_email_id=sample_uuid()),
|
||
),
|
||
(
|
||
create_reply_to_email_address(is_default=True),
|
||
None,
|
||
None,
|
||
),
|
||
])
|
||
def test_shows_delete_link_for_email_reply_to_address(
|
||
mocker,
|
||
reply_to_address,
|
||
expected_link_text,
|
||
partial_href,
|
||
fake_uuid,
|
||
client_request,
|
||
):
|
||
mocker.patch('app.service_api_client.get_reply_to_email_address', return_value=reply_to_address)
|
||
|
||
page = client_request.get(
|
||
'main.service_edit_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
reply_to_email_id=sample_uuid(),
|
||
)
|
||
|
||
assert page.select_one('.govuk-back-link').text.strip() == 'Back'
|
||
assert page.select_one('.govuk-back-link')['href'] == url_for(
|
||
'.service_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
if expected_link_text:
|
||
link = page.select_one('.page-footer a')
|
||
assert normalize_spaces(link.text) == expected_link_text
|
||
assert link['href'] == partial_href(service_id=SERVICE_ONE_ID)
|
||
else:
|
||
assert not page.select('.page-footer a')
|
||
|
||
|
||
def test_confirm_delete_reply_to_email_address(
|
||
fake_uuid,
|
||
client_request,
|
||
get_non_default_reply_to_email_address
|
||
):
|
||
|
||
page = client_request.get(
|
||
'main.service_confirm_delete_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
reply_to_email_id=fake_uuid,
|
||
_test_page_title=False,
|
||
)
|
||
|
||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||
'Are you sure you want to delete this reply-to email address? '
|
||
'Yes, delete'
|
||
)
|
||
assert 'action' not in page.select_one('.banner-dangerous form')
|
||
assert page.select_one('.banner-dangerous form')['method'] == 'post'
|
||
|
||
|
||
def test_delete_reply_to_email_address(
|
||
client_request,
|
||
service_one,
|
||
fake_uuid,
|
||
get_non_default_reply_to_email_address,
|
||
mocker,
|
||
):
|
||
mock_delete = mocker.patch('app.service_api_client.delete_reply_to_email_address')
|
||
client_request.post(
|
||
'.service_delete_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
reply_to_email_id=fake_uuid,
|
||
_expected_redirect=url_for(
|
||
'main.service_email_reply_to',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_delete.assert_called_once_with(service_id=SERVICE_ONE_ID, reply_to_email_id=fake_uuid)
|
||
|
||
|
||
@pytest.mark.parametrize('letter_contact_block, data, api_default_args', [
|
||
(create_letter_contact_block(), {"is_default": "y"}, True),
|
||
(create_letter_contact_block(), {}, True),
|
||
(create_letter_contact_block(is_default=False), {}, False),
|
||
(create_letter_contact_block(is_default=False), {"is_default": "y"}, True)
|
||
])
|
||
def test_edit_letter_contact_block(
|
||
letter_contact_block,
|
||
data,
|
||
api_default_args,
|
||
mocker,
|
||
fake_uuid,
|
||
client_request,
|
||
mock_update_letter_contact
|
||
):
|
||
mocker.patch('app.service_api_client.get_letter_contact', return_value=letter_contact_block)
|
||
data['letter_contact_block'] = "1 Example Street"
|
||
client_request.post(
|
||
'main.service_edit_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
letter_contact_id=fake_uuid,
|
||
_data=data
|
||
)
|
||
|
||
mock_update_letter_contact.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
letter_contact_id=fake_uuid,
|
||
contact_block="1 Example Street",
|
||
is_default=api_default_args
|
||
)
|
||
|
||
|
||
def test_confirm_delete_letter_contact_block(
|
||
fake_uuid,
|
||
client_request,
|
||
get_default_letter_contact_block,
|
||
):
|
||
|
||
page = client_request.get(
|
||
'main.service_confirm_delete_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
letter_contact_id=fake_uuid,
|
||
_test_page_title=False,
|
||
)
|
||
|
||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||
'Are you sure you want to delete this contact block? '
|
||
'Yes, delete'
|
||
)
|
||
assert 'action' not in page.select_one('.banner-dangerous form')
|
||
assert page.select_one('.banner-dangerous form')['method'] == 'post'
|
||
|
||
|
||
def test_delete_letter_contact_block(
|
||
client_request,
|
||
service_one,
|
||
fake_uuid,
|
||
get_default_letter_contact_block,
|
||
mocker,
|
||
):
|
||
mock_delete = mocker.patch('app.service_api_client.delete_letter_contact')
|
||
client_request.post(
|
||
'.service_delete_letter_contact',
|
||
service_id=SERVICE_ONE_ID,
|
||
letter_contact_id=fake_uuid,
|
||
_expected_redirect=url_for(
|
||
'main.service_letter_contact_details',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_delete.assert_called_once_with(
|
||
service_id=SERVICE_ONE_ID,
|
||
letter_contact_id=fake_uuid,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('sms_sender, data, api_default_args', [
|
||
(create_sms_sender(), {"is_default": "y", "sms_sender": "test"}, True),
|
||
(create_sms_sender(), {"sms_sender": "test"}, True),
|
||
(create_sms_sender(is_default=False), {"sms_sender": "test"}, False),
|
||
(create_sms_sender(is_default=False), {"is_default": "y", "sms_sender": "test"}, True)
|
||
])
|
||
def test_edit_sms_sender(
|
||
sms_sender,
|
||
data,
|
||
api_default_args,
|
||
mocker,
|
||
fake_uuid,
|
||
client_request,
|
||
mock_update_sms_sender
|
||
):
|
||
mocker.patch('app.service_api_client.get_sms_sender', return_value=sms_sender)
|
||
|
||
client_request.post(
|
||
'main.service_edit_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
sms_sender_id=fake_uuid,
|
||
_data=data
|
||
)
|
||
|
||
mock_update_sms_sender.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
sms_sender_id=fake_uuid,
|
||
sms_sender="test",
|
||
is_default=api_default_args
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('sender_page, endpoint_to_mock, sender_details, default_message, params, checkbox_present', [
|
||
(
|
||
'main.service_edit_email_reply_to',
|
||
'app.service_api_client.get_reply_to_email_address',
|
||
create_reply_to_email_address(is_default=True),
|
||
'This is the default reply-to address for service one emails',
|
||
'reply_to_email_id',
|
||
False
|
||
),
|
||
(
|
||
'main.service_edit_email_reply_to',
|
||
'app.service_api_client.get_reply_to_email_address',
|
||
create_reply_to_email_address(is_default=False),
|
||
'This is the default reply-to address for service one emails',
|
||
'reply_to_email_id',
|
||
True
|
||
),
|
||
(
|
||
'main.service_edit_letter_contact',
|
||
'app.service_api_client.get_letter_contact',
|
||
create_letter_contact_block(is_default=True),
|
||
'This is currently your default address for service one.',
|
||
'letter_contact_id',
|
||
False
|
||
),
|
||
(
|
||
'main.service_edit_letter_contact',
|
||
'app.service_api_client.get_letter_contact',
|
||
create_letter_contact_block(is_default=False),
|
||
'THIS TEXT WONT BE TESTED',
|
||
'letter_contact_id',
|
||
True
|
||
),
|
||
(
|
||
'main.service_edit_sms_sender',
|
||
'app.service_api_client.get_sms_sender',
|
||
create_sms_sender(is_default=True),
|
||
'This is the default text message sender.',
|
||
'sms_sender_id',
|
||
False
|
||
),
|
||
(
|
||
'main.service_edit_sms_sender',
|
||
'app.service_api_client.get_sms_sender',
|
||
create_sms_sender(is_default=False),
|
||
'This is the default text message sender.',
|
||
'sms_sender_id',
|
||
True
|
||
)
|
||
])
|
||
def test_default_box_shows_on_non_default_sender_details_while_editing(
|
||
fake_uuid,
|
||
mocker,
|
||
sender_page,
|
||
endpoint_to_mock,
|
||
sender_details,
|
||
client_request,
|
||
default_message,
|
||
checkbox_present,
|
||
params
|
||
):
|
||
page_arguments = {
|
||
'service_id': SERVICE_ONE_ID
|
||
}
|
||
page_arguments[params] = fake_uuid
|
||
|
||
mocker.patch(endpoint_to_mock, return_value=sender_details)
|
||
|
||
page = client_request.get(
|
||
sender_page,
|
||
**page_arguments
|
||
)
|
||
|
||
if checkbox_present:
|
||
assert page.select_one('[name=is_default]')
|
||
else:
|
||
assert normalize_spaces(page.select_one('form p').text) == (
|
||
default_message
|
||
)
|
||
|
||
|
||
def test_sender_details_are_escaped(client_request, mocker, fake_uuid):
|
||
letter_contact_block = create_letter_contact_block(contact_block='foo\n\n<br>\n\nbar')
|
||
mocker.patch('app.service_api_client.get_letter_contacts', return_value=[letter_contact_block])
|
||
|
||
page = client_request.get(
|
||
'main.service_letter_contact_details',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
# get the second row (first is the default Blank sender)
|
||
assert 'foo<br>bar' in normalize_spaces(page.select('.user-list-item')[1].text)
|
||
|
||
|
||
@pytest.mark.parametrize('sms_sender, expected_link_text, partial_href', [
|
||
(
|
||
create_sms_sender(is_default=False),
|
||
'Delete',
|
||
partial(url_for, 'main.service_confirm_delete_sms_sender', sms_sender_id=sample_uuid()),
|
||
),
|
||
(
|
||
create_sms_sender(is_default=True),
|
||
None,
|
||
None,
|
||
),
|
||
])
|
||
def test_shows_delete_link_for_sms_sender(
|
||
mocker,
|
||
sms_sender,
|
||
expected_link_text,
|
||
partial_href,
|
||
fake_uuid,
|
||
client_request,
|
||
):
|
||
|
||
mocker.patch('app.service_api_client.get_sms_sender', return_value=sms_sender)
|
||
|
||
page = client_request.get(
|
||
'main.service_edit_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
sms_sender_id=sample_uuid(),
|
||
)
|
||
|
||
link = page.select_one('.page-footer a')
|
||
back_link = page.select_one('.govuk-back-link')
|
||
|
||
assert back_link.text.strip() == 'Back'
|
||
assert back_link['href'] == url_for(
|
||
'.service_sms_senders',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
if expected_link_text:
|
||
assert normalize_spaces(link.text) == expected_link_text
|
||
assert link['href'] == partial_href(service_id=SERVICE_ONE_ID)
|
||
else:
|
||
assert not link
|
||
|
||
|
||
def test_confirm_delete_sms_sender(
|
||
fake_uuid,
|
||
client_request,
|
||
get_non_default_sms_sender,
|
||
):
|
||
|
||
page = client_request.get(
|
||
'main.service_confirm_delete_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
sms_sender_id=fake_uuid,
|
||
_test_page_title=False,
|
||
)
|
||
|
||
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
||
'Are you sure you want to delete this text message sender? '
|
||
'Yes, delete'
|
||
)
|
||
assert 'action' not in page.select_one('.banner-dangerous form')
|
||
assert page.select_one('.banner-dangerous form')['method'] == 'post'
|
||
|
||
|
||
@pytest.mark.parametrize('sms_sender, expected_link_text', [
|
||
(create_sms_sender(is_default=False, inbound_number_id='1234'), None),
|
||
(create_sms_sender(is_default=True), None),
|
||
(create_sms_sender(is_default=False), 'Delete'),
|
||
])
|
||
def test_inbound_sms_sender_is_not_deleteable(
|
||
client_request,
|
||
service_one,
|
||
fake_uuid,
|
||
sms_sender,
|
||
expected_link_text,
|
||
mocker
|
||
):
|
||
mocker.patch('app.service_api_client.get_sms_sender', return_value=sms_sender)
|
||
|
||
page = client_request.get(
|
||
'.service_edit_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
sms_sender_id=fake_uuid,
|
||
)
|
||
|
||
back_link = page.select_one('.govuk-back-link')
|
||
footer_link = page.select_one('.page-footer a')
|
||
assert normalize_spaces(back_link.text) == 'Back'
|
||
|
||
if expected_link_text:
|
||
assert normalize_spaces(footer_link.text) == expected_link_text
|
||
else:
|
||
assert not footer_link
|
||
|
||
|
||
def test_delete_sms_sender(
|
||
client_request,
|
||
service_one,
|
||
fake_uuid,
|
||
get_non_default_sms_sender,
|
||
mocker,
|
||
):
|
||
mock_delete = mocker.patch('app.service_api_client.delete_sms_sender')
|
||
client_request.post(
|
||
'.service_delete_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
sms_sender_id=fake_uuid,
|
||
_expected_redirect=url_for(
|
||
'main.service_sms_senders',
|
||
service_id=SERVICE_ONE_ID,
|
||
_external=True,
|
||
)
|
||
)
|
||
mock_delete.assert_called_once_with(service_id=SERVICE_ONE_ID, sms_sender_id=fake_uuid)
|
||
|
||
|
||
@pytest.mark.parametrize('sms_sender, hide_textbox', [
|
||
(create_sms_sender(is_default=False, inbound_number_id='1234'), True),
|
||
(create_sms_sender(is_default=True), False),
|
||
])
|
||
def test_inbound_sms_sender_is_not_editable(
|
||
client_request,
|
||
service_one,
|
||
fake_uuid,
|
||
sms_sender,
|
||
hide_textbox,
|
||
mocker
|
||
):
|
||
mocker.patch('app.service_api_client.get_sms_sender', return_value=sms_sender)
|
||
|
||
page = client_request.get(
|
||
'.service_edit_sms_sender',
|
||
service_id=SERVICE_ONE_ID,
|
||
sms_sender_id=fake_uuid,
|
||
)
|
||
|
||
assert bool(page.find('input', attrs={'name': "sms_sender"})) != hide_textbox
|
||
if hide_textbox:
|
||
assert normalize_spaces(
|
||
page.select_one('form[method="post"] p').text
|
||
) == "GOVUK This phone number receives replies and cannot be changed"
|
||
|
||
|
||
def test_shows_research_mode_indicator(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['research_mode'] = True
|
||
mocker.patch('app.service_api_client.update_service', return_value=service_one)
|
||
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
element = page.find('span', {"id": "research-mode"})
|
||
assert element.text == 'research mode'
|
||
|
||
|
||
def test_does_not_show_research_mode_indicator(
|
||
client_request,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
element = page.find('span', {"id": "research-mode"})
|
||
assert not element
|
||
|
||
|
||
def test_service_set_letter_branding_platform_admin_only(
|
||
client_request,
|
||
):
|
||
client_request.get(
|
||
'main.service_set_letter_branding',
|
||
service_id=SERVICE_ONE_ID,
|
||
_expected_status=403,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('letter_branding, expected_selected, expected_items', [
|
||
# expected order: currently selected, then default, then rest alphabetically
|
||
(None, '__NONE__', (
|
||
('__NONE__', 'None'),
|
||
(str(UUID(int=2)), 'Animal and Plant Health Agency'),
|
||
(str(UUID(int=0)), 'HM Government'),
|
||
(str(UUID(int=1)), 'Land Registry'),
|
||
)),
|
||
(str(UUID(int=1)), str(UUID(int=1)), (
|
||
(str(UUID(int=1)), 'Land Registry'),
|
||
('__NONE__', 'None'),
|
||
(str(UUID(int=2)), 'Animal and Plant Health Agency'),
|
||
(str(UUID(int=0)), 'HM Government'),
|
||
)),
|
||
(str(UUID(int=2)), str(UUID(int=2)), (
|
||
(str(UUID(int=2)), 'Animal and Plant Health Agency'),
|
||
('__NONE__', 'None'),
|
||
(str(UUID(int=0)), 'HM Government'),
|
||
(str(UUID(int=1)), 'Land Registry'),
|
||
)),
|
||
])
|
||
@pytest.mark.parametrize('endpoint, extra_args', (
|
||
(
|
||
'main.service_set_letter_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
),
|
||
(
|
||
'main.edit_organisation_letter_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
),
|
||
))
|
||
def test_service_set_letter_branding_prepopulates(
|
||
mocker,
|
||
client_request,
|
||
platform_admin_user,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mock_get_all_letter_branding,
|
||
letter_branding,
|
||
expected_selected,
|
||
expected_items,
|
||
endpoint,
|
||
extra_args,
|
||
):
|
||
service_one['letter_branding'] = letter_branding
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
side_effect=lambda org_id: organisation_json(
|
||
org_id,
|
||
'Org 1',
|
||
letter_branding_id=letter_branding,
|
||
)
|
||
)
|
||
|
||
client_request.login(platform_admin_user)
|
||
page = client_request.get(
|
||
endpoint,
|
||
**extra_args,
|
||
)
|
||
|
||
assert len(page.select('input[checked]')) == 1
|
||
assert page.select('input[checked]')[0]['value'] == expected_selected
|
||
|
||
for element in {'label[for^=branding_style]', 'input[type=radio]'}:
|
||
assert len(page.select(element)) == len(expected_items)
|
||
|
||
for index, expected_item in enumerate(expected_items):
|
||
expected_value, expected_label = expected_item
|
||
assert normalize_spaces(page.select('label[for^=branding_style]')[index].text) == expected_label
|
||
assert page.select('input[type=radio]')[index]['value'] == expected_value
|
||
|
||
|
||
@pytest.mark.parametrize('selected_letter_branding, expected_post_data', [
|
||
(str(UUID(int=1)), str(UUID(int=1))),
|
||
('__NONE__', None),
|
||
])
|
||
@pytest.mark.parametrize('endpoint, extra_args, expected_redirect', (
|
||
(
|
||
'main.service_set_letter_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
'main.service_preview_letter_branding',
|
||
),
|
||
(
|
||
'main.edit_organisation_letter_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
'main.organisation_preview_letter_branding',
|
||
),
|
||
))
|
||
def test_service_set_letter_branding_redirects_to_preview_page_when_form_submitted(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_get_organisation,
|
||
mock_get_all_letter_branding,
|
||
selected_letter_branding,
|
||
expected_post_data,
|
||
endpoint,
|
||
extra_args,
|
||
expected_redirect,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
endpoint,
|
||
_data={'branding_style': selected_letter_branding},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
expected_redirect,
|
||
branding_style=expected_post_data,
|
||
_external=True,
|
||
**extra_args
|
||
),
|
||
**extra_args
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('endpoint, extra_args', (
|
||
(
|
||
'main.service_preview_letter_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
),
|
||
(
|
||
'main.organisation_preview_letter_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
),
|
||
))
|
||
def test_service_preview_letter_branding_shows_preview_letter(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_get_organisation,
|
||
mock_get_all_letter_branding,
|
||
endpoint,
|
||
extra_args,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
|
||
page = client_request.get(
|
||
endpoint,
|
||
branding_style='hm-government',
|
||
**extra_args
|
||
)
|
||
|
||
assert page.find('iframe')['src'] == url_for('main.letter_template', branding_style='hm-government')
|
||
|
||
|
||
@pytest.mark.parametrize('selected_letter_branding, expected_post_data', [
|
||
(str(UUID(int=1)), str(UUID(int=1))),
|
||
('__NONE__', None),
|
||
])
|
||
@pytest.mark.parametrize('endpoint, extra_args, expected_redirect', (
|
||
(
|
||
'main.service_preview_letter_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
'main.service_settings',
|
||
),
|
||
(
|
||
'main.organisation_preview_letter_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
'main.organisation_settings',
|
||
),
|
||
))
|
||
def test_service_preview_letter_branding_saves(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_get_organisation,
|
||
mock_get_organisation_services,
|
||
mock_update_service,
|
||
mock_update_organisation,
|
||
mock_get_all_letter_branding,
|
||
selected_letter_branding,
|
||
expected_post_data,
|
||
endpoint,
|
||
extra_args,
|
||
expected_redirect,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
endpoint,
|
||
_data={'branding_style': selected_letter_branding},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
expected_redirect,
|
||
_external=True,
|
||
**extra_args
|
||
),
|
||
**extra_args
|
||
)
|
||
|
||
if endpoint == 'main.service_preview_letter_branding':
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
letter_branding=expected_post_data,
|
||
)
|
||
assert mock_update_organisation.called is False
|
||
|
||
elif endpoint == 'main.organisation_preview_letter_branding':
|
||
mock_update_organisation.assert_called_once_with(
|
||
ORGANISATION_ID,
|
||
letter_branding_id=expected_post_data,
|
||
cached_service_ids=[
|
||
'12345',
|
||
'67890',
|
||
'596364a0-858e-42c8-9062-a8fe822260eb',
|
||
],
|
||
)
|
||
assert mock_update_service.called is False
|
||
|
||
else:
|
||
raise Exception
|
||
|
||
|
||
@pytest.mark.parametrize('current_branding, expected_values, expected_labels', [
|
||
(None, [
|
||
'__NONE__', '1', '2', '3', '4', '5',
|
||
], [
|
||
'GOV.UK', 'org 1', 'org 2', 'org 3', 'org 4', 'org 5'
|
||
]),
|
||
('5', [
|
||
'5', '__NONE__', '1', '2', '3', '4',
|
||
], [
|
||
'org 5', 'GOV.UK', 'org 1', 'org 2', 'org 3', 'org 4',
|
||
]),
|
||
])
|
||
@pytest.mark.parametrize('endpoint, extra_args', (
|
||
(
|
||
'main.service_set_email_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
),
|
||
(
|
||
'main.edit_organisation_email_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
),
|
||
))
|
||
def test_should_show_branding_styles(
|
||
mocker,
|
||
client_request,
|
||
platform_admin_user,
|
||
service_one,
|
||
mock_get_all_email_branding,
|
||
current_branding,
|
||
expected_values,
|
||
expected_labels,
|
||
endpoint,
|
||
extra_args,
|
||
):
|
||
service_one['email_branding'] = current_branding
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
side_effect=lambda org_id: organisation_json(
|
||
org_id,
|
||
'Org 1',
|
||
email_branding_id=current_branding,
|
||
)
|
||
)
|
||
|
||
client_request.login(platform_admin_user)
|
||
page = client_request.get(endpoint, **extra_args)
|
||
|
||
branding_style_choices = page.find_all('input', attrs={"name": "branding_style"})
|
||
|
||
radio_labels = [
|
||
page.find('label', attrs={"for": branding_style_choices[idx]['id']}).get_text().strip()
|
||
for idx, element in enumerate(branding_style_choices)]
|
||
|
||
assert len(branding_style_choices) == 6
|
||
|
||
for index, expected_value in enumerate(expected_values):
|
||
assert branding_style_choices[index]['value'] == expected_value
|
||
|
||
# radios should be in alphabetical order, based on their labels
|
||
assert radio_labels == expected_labels
|
||
|
||
assert 'checked' in branding_style_choices[0].attrs
|
||
assert 'checked' not in branding_style_choices[1].attrs
|
||
assert 'checked' not in branding_style_choices[2].attrs
|
||
assert 'checked' not in branding_style_choices[3].attrs
|
||
assert 'checked' not in branding_style_choices[4].attrs
|
||
assert 'checked' not in branding_style_choices[5].attrs
|
||
|
||
app.email_branding_client.get_all_email_branding.assert_called_once_with()
|
||
app.service_api_client.get_service.assert_called_once_with(service_one['id'])
|
||
|
||
|
||
@pytest.mark.parametrize('endpoint, extra_args, expected_redirect', (
|
||
(
|
||
'main.service_set_email_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
'main.service_preview_email_branding',
|
||
),
|
||
(
|
||
'main.edit_organisation_email_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
'main.organisation_preview_email_branding',
|
||
),
|
||
))
|
||
def test_should_send_branding_and_organisations_to_preview(
|
||
client_request,
|
||
platform_admin_user,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mock_get_all_email_branding,
|
||
mock_update_service,
|
||
endpoint,
|
||
extra_args,
|
||
expected_redirect,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
endpoint,
|
||
data={
|
||
'branding_type': 'org',
|
||
'branding_style': '1'
|
||
},
|
||
_expected_status=302,
|
||
_expected_location=url_for(
|
||
expected_redirect,
|
||
branding_style='1',
|
||
_external=True,
|
||
**extra_args
|
||
),
|
||
**extra_args
|
||
)
|
||
|
||
mock_get_all_email_branding.assert_called_once_with()
|
||
|
||
|
||
@pytest.mark.parametrize('endpoint, extra_args', (
|
||
(
|
||
'main.service_preview_email_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
),
|
||
(
|
||
'main.organisation_preview_email_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
),
|
||
))
|
||
def test_should_preview_email_branding(
|
||
client_request,
|
||
platform_admin_user,
|
||
mock_get_organisation,
|
||
endpoint,
|
||
extra_args,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
page = client_request.get(
|
||
endpoint,
|
||
branding_type='org',
|
||
branding_style='1',
|
||
**extra_args
|
||
)
|
||
|
||
iframe = page.find('iframe', attrs={"class": "branding-preview"})
|
||
iframeURLComponents = urlparse(iframe['src'])
|
||
iframeQString = parse_qs(iframeURLComponents.query)
|
||
|
||
assert page.find('input', attrs={"id": "branding_style"})['value'] == '1'
|
||
assert iframeURLComponents.path == '/_email'
|
||
assert iframeQString['branding_style'] == ['1']
|
||
|
||
|
||
@pytest.mark.parametrize('posted_value, submitted_value', (
|
||
('1', '1'),
|
||
('__NONE__', None),
|
||
pytest.param('None', None, marks=pytest.mark.xfail(raises=AssertionError)),
|
||
))
|
||
@pytest.mark.parametrize('endpoint, extra_args, expected_redirect', (
|
||
(
|
||
'main.service_preview_email_branding',
|
||
{'service_id': SERVICE_ONE_ID},
|
||
'main.service_settings',
|
||
),
|
||
(
|
||
'main.organisation_preview_email_branding',
|
||
{'org_id': ORGANISATION_ID},
|
||
'main.organisation_settings',
|
||
),
|
||
))
|
||
def test_should_set_branding_and_organisations(
|
||
client_request,
|
||
platform_admin_user,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mock_get_organisation_services,
|
||
mock_update_service,
|
||
mock_update_organisation,
|
||
posted_value,
|
||
submitted_value,
|
||
endpoint,
|
||
extra_args,
|
||
expected_redirect,
|
||
):
|
||
client_request.login(platform_admin_user)
|
||
client_request.post(
|
||
endpoint,
|
||
_data={
|
||
'branding_style': posted_value
|
||
},
|
||
_expected_status=302,
|
||
_expected_redirect=url_for(
|
||
expected_redirect,
|
||
_external=True,
|
||
**extra_args
|
||
),
|
||
**extra_args
|
||
)
|
||
|
||
if endpoint == 'main.service_preview_email_branding':
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
email_branding=submitted_value,
|
||
)
|
||
assert mock_update_organisation.called is False
|
||
elif endpoint == 'main.organisation_preview_email_branding':
|
||
mock_update_organisation.assert_called_once_with(
|
||
ORGANISATION_ID,
|
||
email_branding_id=submitted_value,
|
||
cached_service_ids=[
|
||
'12345',
|
||
'67890',
|
||
'596364a0-858e-42c8-9062-a8fe822260eb',
|
||
],
|
||
)
|
||
assert mock_update_service.called is False
|
||
else:
|
||
raise Exception
|
||
|
||
|
||
@pytest.mark.parametrize('method', ['get', 'post'])
|
||
@pytest.mark.parametrize('endpoint', [
|
||
'main.set_free_sms_allowance',
|
||
'main.set_message_limit',
|
||
'main.set_rate_limit',
|
||
])
|
||
def test_organisation_type_pages_are_platform_admin_only(
|
||
client_request,
|
||
method,
|
||
endpoint,
|
||
):
|
||
getattr(client_request, method)(
|
||
endpoint,
|
||
service_id=SERVICE_ONE_ID,
|
||
_expected_status=403,
|
||
_test_page_title=False,
|
||
)
|
||
|
||
|
||
def test_should_show_page_to_set_sms_allowance(
|
||
platform_admin_client,
|
||
mock_get_free_sms_fragment_limit
|
||
):
|
||
response = platform_admin_client.get(url_for(
|
||
'main.set_free_sms_allowance',
|
||
service_id=SERVICE_ONE_ID
|
||
))
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
|
||
assert normalize_spaces(page.select_one('label').text) == 'Numbers of text message fragments per year'
|
||
mock_get_free_sms_fragment_limit.assert_called_once_with(SERVICE_ONE_ID)
|
||
|
||
|
||
@freeze_time("2017-04-01 11:09:00.061258")
|
||
@pytest.mark.parametrize('given_allowance, expected_api_argument', [
|
||
('1', 1),
|
||
('250000', 250000),
|
||
pytest.param('foo', 'foo', marks=pytest.mark.xfail),
|
||
])
|
||
def test_should_set_sms_allowance(
|
||
platform_admin_client,
|
||
given_allowance,
|
||
expected_api_argument,
|
||
mock_get_free_sms_fragment_limit,
|
||
mock_create_or_update_free_sms_fragment_limit,
|
||
):
|
||
|
||
response = platform_admin_client.post(
|
||
url_for(
|
||
'main.set_free_sms_allowance',
|
||
service_id=SERVICE_ONE_ID,
|
||
),
|
||
data={
|
||
'free_sms_allowance': given_allowance,
|
||
},
|
||
)
|
||
assert response.status_code == 302
|
||
assert response.location == url_for('main.service_settings', service_id=SERVICE_ONE_ID, _external=True)
|
||
|
||
mock_create_or_update_free_sms_fragment_limit.assert_called_with(
|
||
SERVICE_ONE_ID,
|
||
expected_api_argument
|
||
)
|
||
|
||
|
||
def test_should_show_page_to_set_message_limit(
|
||
platform_admin_client,
|
||
):
|
||
response = platform_admin_client.get(url_for(
|
||
'main.set_message_limit',
|
||
service_id=SERVICE_ONE_ID
|
||
))
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
|
||
assert normalize_spaces(page.select_one('label').text) == (
|
||
'Number of messages the service is allowed to send each day'
|
||
)
|
||
assert normalize_spaces(page.select_one('input[type=text]')['value']) == (
|
||
'1000'
|
||
)
|
||
|
||
|
||
def test_should_show_page_to_set_rate_limit(
|
||
platform_admin_client,
|
||
):
|
||
response = platform_admin_client.get(url_for(
|
||
'main.set_rate_limit',
|
||
service_id=SERVICE_ONE_ID
|
||
))
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
|
||
assert normalize_spaces(page.select_one('label').text) == (
|
||
'Number of messages the service can send in a rolling 60 second window'
|
||
)
|
||
assert normalize_spaces(page.select_one('input[type=text]')['value']) == (
|
||
'3000'
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('endpoint, field_name', (
|
||
('main.set_message_limit', 'message_limit'),
|
||
('main.set_rate_limit', 'rate_limit'),
|
||
))
|
||
@pytest.mark.parametrize('new_limit, expected_api_argument', [
|
||
('1', 1),
|
||
('250000', 250000),
|
||
pytest.param('foo', 'foo', marks=pytest.mark.xfail),
|
||
])
|
||
def test_should_set_message_limit(
|
||
platform_admin_client,
|
||
new_limit,
|
||
expected_api_argument,
|
||
mock_update_service,
|
||
endpoint,
|
||
field_name,
|
||
):
|
||
|
||
response = platform_admin_client.post(
|
||
url_for(
|
||
endpoint,
|
||
service_id=SERVICE_ONE_ID,
|
||
),
|
||
data={
|
||
field_name: new_limit,
|
||
},
|
||
)
|
||
assert response.status_code == 302
|
||
assert response.location == url_for('main.service_settings', service_id=SERVICE_ONE_ID, _external=True)
|
||
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
**{field_name: expected_api_argument},
|
||
)
|
||
|
||
|
||
def test_old_set_letters_page_redirects(
|
||
client_request,
|
||
):
|
||
client_request.get(
|
||
'main.service_set_letters',
|
||
service_id=SERVICE_ONE_ID,
|
||
_expected_status=301,
|
||
_expected_redirect=url_for(
|
||
'main.service_set_channel',
|
||
service_id=SERVICE_ONE_ID,
|
||
channel='letter',
|
||
_external=True,
|
||
)
|
||
)
|
||
|
||
|
||
def test_unknown_channel_404s(
|
||
client_request,
|
||
):
|
||
client_request.get(
|
||
'main.service_set_channel',
|
||
service_id=SERVICE_ONE_ID,
|
||
channel='message-in-a-bottle',
|
||
_expected_status=404,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize((
|
||
'channel,'
|
||
'expected_first_para,'
|
||
'expected_legend,'
|
||
'initial_permissions,'
|
||
'expected_initial_value,'
|
||
'posted_value,'
|
||
'expected_updated_permissions'
|
||
), [
|
||
(
|
||
'letter',
|
||
'It costs between 35p and £1.16 to send a letter using Notify.',
|
||
'Send letters',
|
||
['email', 'sms'],
|
||
'False',
|
||
'True',
|
||
['email', 'sms', 'letter'],
|
||
),
|
||
(
|
||
'letter',
|
||
'It costs between 35p and £1.16 to send a letter using Notify.',
|
||
'Send letters',
|
||
['email', 'sms', 'letter'],
|
||
'True',
|
||
'False',
|
||
['email', 'sms'],
|
||
),
|
||
(
|
||
'sms',
|
||
'You have a free allowance of 250,000 text messages each financial year.',
|
||
'Send text messages',
|
||
[],
|
||
'False',
|
||
'True',
|
||
['sms'],
|
||
),
|
||
(
|
||
'email',
|
||
'It’s free to send emails through GOV.UK Notify.',
|
||
'Send emails',
|
||
[],
|
||
'False',
|
||
'True',
|
||
['email'],
|
||
),
|
||
(
|
||
'email',
|
||
'It’s free to send emails through GOV.UK Notify.',
|
||
'Send emails',
|
||
['email', 'sms', 'letter'],
|
||
'True',
|
||
'True',
|
||
['email', 'sms', 'letter'],
|
||
),
|
||
])
|
||
def test_switch_service_channels_on_and_off(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
mock_get_free_sms_fragment_limit,
|
||
channel,
|
||
expected_first_para,
|
||
expected_legend,
|
||
initial_permissions,
|
||
expected_initial_value,
|
||
posted_value,
|
||
expected_updated_permissions,
|
||
):
|
||
mocked_fn = mocker.patch('app.service_api_client.update_service', return_value=service_one)
|
||
service_one['permissions'] = initial_permissions
|
||
|
||
page = client_request.get(
|
||
'main.service_set_channel',
|
||
service_id=service_one['id'],
|
||
channel=channel,
|
||
)
|
||
|
||
assert normalize_spaces(page.select_one('main p').text) == expected_first_para
|
||
assert normalize_spaces(page.select_one('legend').text) == expected_legend
|
||
|
||
assert page.select_one('input[checked]')['value'] == expected_initial_value
|
||
assert len(page.select('input[checked]')) == 1
|
||
|
||
client_request.post(
|
||
'main.service_set_channel',
|
||
service_id=service_one['id'],
|
||
channel=channel,
|
||
_data={'enabled': posted_value},
|
||
_expected_redirect=url_for(
|
||
'main.service_settings',
|
||
service_id=service_one['id'],
|
||
_external=True
|
||
)
|
||
)
|
||
assert set(mocked_fn.call_args[1]['permissions']) == set(expected_updated_permissions)
|
||
assert mocked_fn.call_args[0][0] == service_one['id']
|
||
|
||
|
||
@pytest.mark.parametrize('channel', (
|
||
'email', 'sms', 'letter',
|
||
))
|
||
def test_broadcast_service_cant_post_to_set_other_channels_endpoint(
|
||
client_request,
|
||
service_one,
|
||
channel,
|
||
):
|
||
service_one['permissions'] = ['broadcast']
|
||
|
||
client_request.get(
|
||
'main.service_set_channel',
|
||
service_id=SERVICE_ONE_ID,
|
||
channel=channel,
|
||
_expected_status=403,
|
||
)
|
||
|
||
client_request.post(
|
||
'main.service_set_channel',
|
||
service_id=SERVICE_ONE_ID,
|
||
channel=channel,
|
||
_data={'enabled': 'True'},
|
||
_expected_status=403,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('permission, permissions, expected_checked', [
|
||
('international_sms', ['international_sms'], 'True'),
|
||
('international_letters', ['international_letters'], 'True'),
|
||
('international_sms', [''], 'False'),
|
||
('international_letters', [''], 'False'),
|
||
])
|
||
def test_show_international_sms_and_letters_as_radio_button(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
permission,
|
||
permissions,
|
||
expected_checked,
|
||
):
|
||
service_one['permissions'] = permissions
|
||
|
||
checked_radios = client_request.get(
|
||
f'main.service_set_{permission}',
|
||
service_id=service_one['id'],
|
||
).select(
|
||
'.multiple-choice input[checked]'
|
||
)
|
||
|
||
assert len(checked_radios) == 1
|
||
assert checked_radios[0]['value'] == expected_checked
|
||
|
||
|
||
@pytest.mark.parametrize('permission', (
|
||
'international_sms',
|
||
'international_letters',
|
||
))
|
||
@pytest.mark.parametrize('post_value, permission_expected_in_api_call', [
|
||
('True', True),
|
||
('False', False),
|
||
])
|
||
def test_switch_service_enable_international_sms_and_letters(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
permission,
|
||
post_value,
|
||
permission_expected_in_api_call,
|
||
):
|
||
mocked_fn = mocker.patch('app.service_api_client.update_service', return_value=service_one)
|
||
client_request.post(
|
||
f'main.service_set_{permission}',
|
||
service_id=service_one['id'],
|
||
_data={
|
||
'enabled': post_value
|
||
},
|
||
_expected_redirect=url_for('main.service_settings', service_id=service_one['id'], _external=True)
|
||
)
|
||
|
||
if permission_expected_in_api_call:
|
||
assert permission in mocked_fn.call_args[1]['permissions']
|
||
else:
|
||
assert permission not in mocked_fn.call_args[1]['permissions']
|
||
|
||
assert mocked_fn.call_args[0][0] == service_one['id']
|
||
|
||
|
||
@pytest.mark.parametrize('user', (
|
||
create_platform_admin_user(),
|
||
create_active_user_with_permissions(),
|
||
pytest.param(create_active_user_no_settings_permission(), marks=pytest.mark.xfail),
|
||
))
|
||
def test_archive_service_after_confirm(
|
||
client_request,
|
||
mocker,
|
||
mock_get_organisations,
|
||
mock_get_service_and_organisation_counts,
|
||
mock_get_organisations_and_services_for_user,
|
||
mock_get_users_by_service,
|
||
user,
|
||
):
|
||
mocked_fn = mocker.patch('app.service_api_client.post')
|
||
redis_delete_mock = mocker.patch('app.notify_client.service_api_client.redis_client.delete')
|
||
client_request.login(user)
|
||
page = client_request.post(
|
||
'main.archive_service',
|
||
service_id=SERVICE_ONE_ID,
|
||
_follow_redirects=True,
|
||
)
|
||
|
||
mocked_fn.assert_called_once_with('/service/{}/archive'.format(SERVICE_ONE_ID), data=None)
|
||
assert normalize_spaces(page.select_one('h1').text) == 'Choose service'
|
||
assert normalize_spaces(page.select_one('.banner-default-with-tick').text) == (
|
||
'‘service one’ was deleted'
|
||
)
|
||
# The one user which is part of this service has the sample_uuid as it's user ID
|
||
assert call(f"user-{sample_uuid()}") in redis_delete_mock.call_args_list
|
||
|
||
|
||
@pytest.mark.parametrize('user', (
|
||
create_platform_admin_user(),
|
||
create_active_user_with_permissions(),
|
||
pytest.param(create_active_user_no_settings_permission(), marks=pytest.mark.xfail),
|
||
))
|
||
def test_archive_service_prompts_user(
|
||
client_request,
|
||
mocker,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
user,
|
||
):
|
||
mocked_fn = mocker.patch('app.service_api_client.post')
|
||
client_request.login(user)
|
||
|
||
settings_page = client_request.get(
|
||
'main.archive_service',
|
||
service_id=SERVICE_ONE_ID
|
||
)
|
||
delete_link = settings_page.select('.page-footer-delete-link a')[0]
|
||
assert normalize_spaces(delete_link.text) == 'Delete this service'
|
||
assert delete_link['href'] == url_for(
|
||
'main.archive_service',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
delete_page = client_request.get(
|
||
'main.archive_service',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
assert normalize_spaces(delete_page.select_one('.banner-dangerous').text) == (
|
||
'Are you sure you want to delete ‘service one’? '
|
||
'There’s no way to undo this. '
|
||
'Yes, delete'
|
||
)
|
||
assert mocked_fn.called is False
|
||
|
||
|
||
def test_cant_archive_inactive_service(
|
||
platform_admin_client,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common
|
||
):
|
||
service_one['active'] = False
|
||
|
||
response = platform_admin_client.get(url_for('main.service_settings', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert 'Delete service' not in {a.text for a in page.find_all('a', class_='button')}
|
||
|
||
|
||
def test_suspend_service_after_confirm(
|
||
platform_admin_client,
|
||
service_one,
|
||
mocker,
|
||
mock_get_inbound_number_for_service,
|
||
):
|
||
mocked_fn = mocker.patch('app.service_api_client.post', return_value=service_one)
|
||
|
||
response = platform_admin_client.post(url_for('main.suspend_service', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 302
|
||
assert response.location == url_for('main.service_settings', service_id=service_one['id'], _external=True)
|
||
assert mocked_fn.call_args == call('/service/{}/suspend'.format(service_one['id']), data=None)
|
||
|
||
|
||
def test_suspend_service_prompts_user(
|
||
platform_admin_client,
|
||
service_one,
|
||
mocker,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
mocked_fn = mocker.patch('app.service_api_client.post')
|
||
|
||
response = platform_admin_client.get(url_for('main.suspend_service', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert 'This will suspend the service and revoke all api keys. Are you sure you want to suspend this service?' in \
|
||
page.find('div', class_='banner-dangerous').text
|
||
assert mocked_fn.called is False
|
||
|
||
|
||
def test_cant_suspend_inactive_service(
|
||
platform_admin_client,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['active'] = False
|
||
|
||
response = platform_admin_client.get(url_for('main.service_settings', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert 'Suspend service' not in {a.text for a in page.find_all('a', class_='button')}
|
||
|
||
|
||
def test_resume_service_after_confirm(
|
||
platform_admin_client,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
mocker,
|
||
mock_get_inbound_number_for_service,
|
||
):
|
||
service_one['active'] = False
|
||
mocked_fn = mocker.patch('app.service_api_client.post', return_value=service_one)
|
||
|
||
response = platform_admin_client.post(url_for('main.resume_service', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 302
|
||
assert response.location == url_for('main.service_settings', service_id=service_one['id'], _external=True)
|
||
assert mocked_fn.call_args == call('/service/{}/resume'.format(service_one['id']), data=None)
|
||
|
||
|
||
def test_resume_service_prompts_user(
|
||
platform_admin_client,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mocker,
|
||
mock_get_service_settings_page_common,
|
||
):
|
||
service_one['active'] = False
|
||
mocked_fn = mocker.patch('app.service_api_client.post')
|
||
|
||
response = platform_admin_client.get(url_for('main.resume_service', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert 'This will resume the service. New api key are required for this service to use the API.' in \
|
||
page.find('div', class_='banner-dangerous').text
|
||
assert mocked_fn.called is False
|
||
|
||
|
||
def test_cant_resume_active_service(
|
||
platform_admin_client,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common
|
||
):
|
||
response = platform_admin_client.get(url_for('main.service_settings', service_id=service_one['id']))
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert 'Resume service' not in {a.text for a in page.find_all('a', class_='button')}
|
||
|
||
|
||
@pytest.mark.parametrize('contact_details_type, contact_details_value', [
|
||
('url', 'http://example.com/'),
|
||
('email_address', 'me@example.com'),
|
||
('phone_number', '0207 123 4567'),
|
||
])
|
||
def test_send_files_by_email_contact_details_prefills_the_form_with_the_existing_contact_details(
|
||
client_request,
|
||
service_one,
|
||
contact_details_type,
|
||
contact_details_value,
|
||
):
|
||
service_one['contact_link'] = contact_details_value
|
||
|
||
page = client_request.get(
|
||
'main.send_files_by_email_contact_details', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert page.find('input', attrs={'name': 'contact_details_type', 'value': contact_details_type}).has_attr('checked')
|
||
assert page.find('input', {'id': contact_details_type}).get('value') == contact_details_value
|
||
|
||
|
||
@pytest.mark.parametrize('contact_details_type, old_value, new_value', [
|
||
('url', 'http://example.com/', 'http://new-link.com/'),
|
||
('email_address', 'old@example.com', 'new@example.com'),
|
||
('phone_number', '0207 12345', '0207 56789'),
|
||
])
|
||
def test_send_files_by_email_contact_details_updates_contact_details_and_redirects_to_settings_page(
|
||
client_request,
|
||
service_one,
|
||
mock_update_service,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_organisation,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
contact_details_type,
|
||
old_value,
|
||
new_value,
|
||
):
|
||
service_one['contact_link'] = old_value
|
||
|
||
page = client_request.post(
|
||
'main.send_files_by_email_contact_details', service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'contact_details_type': contact_details_type,
|
||
contact_details_type: new_value,
|
||
},
|
||
_follow_redirects=True
|
||
)
|
||
|
||
assert page.h1.text == 'Settings'
|
||
mock_update_service.assert_called_once_with(SERVICE_ONE_ID, contact_link=new_value)
|
||
|
||
|
||
def test_send_files_by_email_contact_details_uses_the_selected_field_when_multiple_textboxes_contain_data(
|
||
client_request,
|
||
service_one,
|
||
mock_update_service,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_organisation,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
):
|
||
service_one['contact_link'] = 'http://www.old-url.com'
|
||
|
||
page = client_request.post(
|
||
'main.send_files_by_email_contact_details', service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'contact_details_type': 'url',
|
||
'url': 'http://www.new-url.com',
|
||
'email_address': 'me@example.com',
|
||
'phone_number': '0207 123 4567'
|
||
},
|
||
_follow_redirects=True
|
||
)
|
||
|
||
assert page.h1.text == 'Settings'
|
||
mock_update_service.assert_called_once_with(SERVICE_ONE_ID, contact_link='http://www.new-url.com')
|
||
|
||
|
||
@pytest.mark.parametrize(
|
||
'contact_link, subheader, button_selected',
|
||
[
|
||
('contact.me@gov.uk', 'Change contact details for the file download page', True),
|
||
(None, 'Add contact details to the file download page', False),
|
||
]
|
||
)
|
||
def test_send_files_by_email_contact_details_page(
|
||
client_request, service_one, active_user_with_permissions, contact_link, subheader, button_selected
|
||
):
|
||
service_one["contact_link"] = contact_link
|
||
page = client_request.get(
|
||
'main.send_files_by_email_contact_details', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert normalize_spaces(page.find_all('h2')[1].text) == subheader
|
||
if button_selected:
|
||
assert 'checked' in page.find('input', {'name': 'contact_details_type', 'value': 'email_address'}).attrs
|
||
else:
|
||
assert 'checked' not in page.find('input', {'name': 'contact_details_type', 'value': 'email_address'}).attrs
|
||
|
||
|
||
def test_send_files_by_email_contact_details_displays_error_message_when_no_radio_button_selected(
|
||
client_request,
|
||
service_one
|
||
):
|
||
page = client_request.post(
|
||
'main.send_files_by_email_contact_details', service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'contact_details_type': None,
|
||
'url': '',
|
||
'email_address': '',
|
||
'phone_number': '',
|
||
},
|
||
_follow_redirects=True
|
||
)
|
||
assert normalize_spaces(page.find('span', class_='error-message').text) == 'Select an option'
|
||
assert normalize_spaces(page.h1.text) == "Send files by email"
|
||
|
||
|
||
@pytest.mark.parametrize('contact_details_type, invalid_value, error', [
|
||
('url', 'invalid.com/', 'Must be a valid URL'),
|
||
('email_address', 'me@co', 'Enter a valid email address'),
|
||
('phone_number', 'abcde', 'Must be a valid phone number'),
|
||
])
|
||
def test_send_files_by_email_contact_details_does_not_update_invalid_contact_details(
|
||
mocker,
|
||
client_request,
|
||
service_one,
|
||
contact_details_type,
|
||
invalid_value,
|
||
error,
|
||
):
|
||
service_one['contact_link'] = 'http://example.com/'
|
||
service_one['permissions'].append('upload_document')
|
||
|
||
page = client_request.post(
|
||
'main.send_files_by_email_contact_details', service_id=SERVICE_ONE_ID,
|
||
_data={
|
||
'contact_details_type': contact_details_type,
|
||
contact_details_type: invalid_value,
|
||
},
|
||
_follow_redirects=True
|
||
)
|
||
|
||
assert error in page.find('span', class_='govuk-error-message').text
|
||
assert normalize_spaces(page.h1.text) == "Send files by email"
|
||
|
||
|
||
def test_contact_link_is_not_displayed_without_the_upload_document_permission(
|
||
client_request,
|
||
service_one,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_organisation,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
):
|
||
page = client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
assert 'Contact details' not in page.text
|
||
|
||
|
||
@pytest.mark.parametrize('endpoint, permissions, expected_p', [
|
||
(
|
||
'main.service_set_inbound_sms',
|
||
['sms'],
|
||
(
|
||
'Contact us if you want to be able to receive text messages from your users.'
|
||
)
|
||
),
|
||
(
|
||
'main.service_set_inbound_sms',
|
||
['sms', 'inbound_sms'],
|
||
(
|
||
'Your service can receive text messages sent to 0781239871.'
|
||
)
|
||
),
|
||
(
|
||
'main.service_set_auth_type',
|
||
[],
|
||
(
|
||
'Text message code'
|
||
)
|
||
),
|
||
(
|
||
'main.service_set_auth_type',
|
||
['email_auth'],
|
||
(
|
||
'Email link or text message code'
|
||
)
|
||
),
|
||
])
|
||
def test_invitation_pages(
|
||
client_request,
|
||
service_one,
|
||
mock_get_inbound_number_for_service,
|
||
single_sms_sender,
|
||
endpoint,
|
||
permissions,
|
||
expected_p,
|
||
):
|
||
service_one['permissions'] = permissions
|
||
page = client_request.get(
|
||
endpoint,
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
assert normalize_spaces(page.select('main p')[0].text) == expected_p
|
||
|
||
|
||
def test_service_settings_when_inbound_number_is_not_set(
|
||
client_request,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
mock_get_organisation,
|
||
single_sms_sender,
|
||
mocker,
|
||
mock_get_all_letter_branding,
|
||
mock_get_free_sms_fragment_limit,
|
||
mock_get_service_data_retention,
|
||
):
|
||
mocker.patch('app.inbound_number_client.get_inbound_sms_number_for_service',
|
||
return_value={'data': {}})
|
||
client_request.get(
|
||
'main.service_settings',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
|
||
def test_set_inbound_sms_when_inbound_number_is_not_set(
|
||
client_request,
|
||
service_one,
|
||
single_reply_to_email_address,
|
||
single_letter_contact_block,
|
||
single_sms_sender,
|
||
mocker,
|
||
mock_get_all_letter_branding,
|
||
):
|
||
mocker.patch('app.inbound_number_client.get_inbound_sms_number_for_service',
|
||
return_value={'data': {}})
|
||
client_request.get(
|
||
'main.service_set_inbound_sms',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('user, expected_paragraphs', [
|
||
(create_active_user_with_permissions(), [
|
||
'Your service can receive text messages sent to 07700900123.',
|
||
'You can still send text messages from a sender name if you '
|
||
'need to, but users will not be able to reply to those messages.',
|
||
'Contact us if you want to switch this feature off.',
|
||
'You can set up callbacks for received text messages on the API integration page.',
|
||
]),
|
||
(create_active_user_no_api_key_permission(), [
|
||
'Your service can receive text messages sent to 07700900123.',
|
||
'You can still send text messages from a sender name if you '
|
||
'need to, but users will not be able to reply to those messages.',
|
||
'Contact us if you want to switch this feature off.',
|
||
]),
|
||
])
|
||
def test_set_inbound_sms_when_inbound_number_is_set(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
user,
|
||
expected_paragraphs,
|
||
):
|
||
service_one['permissions'] = ['inbound_sms']
|
||
mocker.patch('app.inbound_number_client.get_inbound_sms_number_for_service', return_value={
|
||
'data': {'number': '07700900123'}
|
||
})
|
||
client_request.login(user)
|
||
page = client_request.get(
|
||
'main.service_set_inbound_sms',
|
||
service_id=SERVICE_ONE_ID,
|
||
)
|
||
paragraphs = page.select('main p')
|
||
|
||
assert len(paragraphs) == len(expected_paragraphs)
|
||
|
||
for index, p in enumerate(expected_paragraphs):
|
||
assert normalize_spaces(paragraphs[index].text) == p
|
||
|
||
|
||
def test_show_sms_prefixing_setting_page(
|
||
client_request,
|
||
mock_update_service,
|
||
):
|
||
page = client_request.get(
|
||
'main.service_set_sms_prefix', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert normalize_spaces(page.select_one('legend').text) == (
|
||
'Start all text messages with ‘service one:’'
|
||
)
|
||
radios = page.select('input[type=radio]')
|
||
assert len(radios) == 2
|
||
assert radios[0]['value'] == 'on'
|
||
assert radios[0]['checked'] == ''
|
||
assert radios[1]['value'] == 'off'
|
||
with pytest.raises(KeyError):
|
||
assert radios[1]['checked']
|
||
|
||
|
||
@pytest.mark.parametrize('post_value, expected_api_argument', [
|
||
('on', True),
|
||
('off', False),
|
||
])
|
||
def test_updates_sms_prefixing(
|
||
client_request,
|
||
mock_update_service,
|
||
post_value,
|
||
expected_api_argument,
|
||
):
|
||
client_request.post(
|
||
'main.service_set_sms_prefix', service_id=SERVICE_ONE_ID,
|
||
_data={'enabled': post_value},
|
||
_expected_redirect=url_for(
|
||
'main.service_settings', service_id=SERVICE_ONE_ID,
|
||
_external=True
|
||
)
|
||
)
|
||
mock_update_service.assert_called_once_with(
|
||
SERVICE_ONE_ID,
|
||
prefix_sms=expected_api_argument,
|
||
)
|
||
|
||
|
||
def test_select_organisation(
|
||
platform_admin_client,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mock_get_organisations
|
||
):
|
||
response = platform_admin_client.get(
|
||
url_for('.link_service_to_organisation', service_id=service_one['id']),
|
||
)
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
|
||
assert len(page.select('.multiple-choice')) == 3
|
||
for i in range(0, 3):
|
||
assert normalize_spaces(
|
||
page.select('.multiple-choice label')[i].text
|
||
) == 'Org {}'.format(i + 1)
|
||
|
||
|
||
def test_select_organisation_shows_message_if_no_orgs(
|
||
platform_admin_client,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mocker
|
||
):
|
||
mocker.patch('app.organisations_client.get_organisations', return_value=[])
|
||
|
||
response = platform_admin_client.get(
|
||
url_for('.link_service_to_organisation', service_id=service_one['id']),
|
||
)
|
||
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
|
||
assert normalize_spaces(page.select_one('main p').text) == "No organisations"
|
||
assert not page.select_one('main button')
|
||
|
||
|
||
def test_update_service_organisation(
|
||
platform_admin_client,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mock_get_organisations,
|
||
mock_update_service_organisation,
|
||
):
|
||
response = platform_admin_client.post(
|
||
url_for('.link_service_to_organisation', service_id=service_one['id']),
|
||
data={'organisations': '7aa5d4e9-4385-4488-a489-07812ba13384'},
|
||
)
|
||
|
||
assert response.status_code == 302
|
||
mock_update_service_organisation.assert_called_once_with(
|
||
service_one['id'],
|
||
'7aa5d4e9-4385-4488-a489-07812ba13384'
|
||
)
|
||
|
||
|
||
def test_update_service_organisation_does_not_update_if_same_value(
|
||
platform_admin_client,
|
||
service_one,
|
||
mock_get_organisation,
|
||
mock_get_organisations,
|
||
mock_update_service_organisation,
|
||
):
|
||
response = platform_admin_client.post(
|
||
url_for('.link_service_to_organisation', service_id=service_one['id']),
|
||
data={'organisations': '7aa5d4e9-4385-4488-a489-07812ba13383'},
|
||
)
|
||
|
||
assert response.status_code == 302
|
||
mock_update_service_organisation.called is False
|
||
|
||
|
||
@pytest.mark.parametrize('branding_type', ['email', 'letter'])
|
||
@pytest.mark.parametrize('organisation_type, expected_options', (
|
||
('central', None),
|
||
('local', None),
|
||
('nhs_central', [
|
||
('nhs', 'NHS'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('nhs_local', [
|
||
('nhs', 'NHS'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('nhs_gp', [
|
||
('nhs', 'NHS'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('emergency_service', None),
|
||
('other', None),
|
||
))
|
||
def test_show_branding_request_page_when_no_branding_is_set(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_email_branding,
|
||
mock_get_letter_branding_by_id,
|
||
organisation_type,
|
||
expected_options,
|
||
branding_type
|
||
):
|
||
service_one['{}_branding'.format(branding_type)] = None
|
||
service_one['organisation_type'] = organisation_type
|
||
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type=branding_type
|
||
)
|
||
|
||
assert mock_get_email_branding.called is False
|
||
assert mock_get_letter_branding_by_id.called is False
|
||
|
||
if expected_options:
|
||
assert [
|
||
(
|
||
radio['value'],
|
||
page.select_one('label[for={}]'.format(radio['id'])).text.strip()
|
||
)
|
||
for radio in page.select('input[type=radio]')
|
||
] == expected_options
|
||
assert page.select_one(
|
||
'.conditional-radios-panel#panel-something-else textarea'
|
||
)['name'] == (
|
||
'something_else'
|
||
)
|
||
else:
|
||
assert page.select_one(
|
||
'textarea'
|
||
)['name'] == (
|
||
'something_else'
|
||
)
|
||
assert not page.select('.conditional-radios-panel')
|
||
|
||
|
||
@pytest.mark.parametrize('branding_type', ['email', 'letter'])
|
||
@pytest.mark.parametrize('organisation_type, expected_options', (
|
||
('local', [
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('nhs_central', [
|
||
('nhs', 'NHS'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('nhs_local', [
|
||
('nhs', 'NHS'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('nhs_gp', [
|
||
('nhs', 'NHS'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('emergency_service', [
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
('other', [
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
]),
|
||
))
|
||
def test_show_branding_request_page_when_no_branding_is_set_but_organisation_exists(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_email_branding,
|
||
mock_get_letter_branding_by_id,
|
||
mock_get_service_organisation,
|
||
organisation_type,
|
||
expected_options,
|
||
branding_type
|
||
):
|
||
service_one['{}_branding'.format(branding_type)] = None
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(organisation_type=organisation_type),
|
||
)
|
||
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type=branding_type
|
||
)
|
||
|
||
assert mock_get_email_branding.called is False
|
||
assert mock_get_letter_branding_by_id.called is False
|
||
|
||
assert [
|
||
(
|
||
radio['value'],
|
||
page.select_one('label[for={}]'.format(radio['id'])).text.strip()
|
||
)
|
||
for radio in page.select('input[type=radio]')
|
||
] == expected_options
|
||
|
||
|
||
@pytest.mark.parametrize('organisation_type, expected_options, branding_type', (
|
||
('central', [
|
||
('govuk_and_org', 'GOV.UK and Test Organisation'),
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
], 'email'),
|
||
('central', [
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
], 'letter'),
|
||
))
|
||
def test_show_branding_request_page_when_no_branding_is_set_but_organisation_exists_central_org(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_email_branding,
|
||
mock_get_letter_branding_by_id,
|
||
mock_get_service_organisation,
|
||
organisation_type,
|
||
expected_options,
|
||
branding_type
|
||
):
|
||
service_one['{}_branding'.format(branding_type)] = None
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(organisation_type=organisation_type),
|
||
)
|
||
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type=branding_type
|
||
)
|
||
|
||
assert mock_get_email_branding.called is False
|
||
assert mock_get_letter_branding_by_id.called is False
|
||
|
||
assert [
|
||
(
|
||
radio['value'],
|
||
page.select_one('label[for={}]'.format(radio['id'])).text.strip()
|
||
)
|
||
for radio in page.select('input[type=radio]')
|
||
] == expected_options
|
||
|
||
|
||
def test_show_email_branding_request_page_when_email_branding_is_set(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_email_branding,
|
||
mock_get_service_organisation,
|
||
active_user_with_permissions,
|
||
):
|
||
service_one['email_branding'] = sample_uuid()
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(),
|
||
)
|
||
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type="email"
|
||
)
|
||
assert [
|
||
(
|
||
radio['value'],
|
||
page.select_one('label[for={}]'.format(radio['id'])).text.strip()
|
||
)
|
||
for radio in page.select('input[type=radio]')
|
||
] == [
|
||
('govuk', 'GOV.UK'),
|
||
('govuk_and_org', 'GOV.UK and Test Organisation'),
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
]
|
||
|
||
|
||
def test_show_letter_branding_request_page_when_letter_branding_is_set(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_letter_branding_by_id,
|
||
mock_get_service_organisation,
|
||
active_user_with_permissions,
|
||
):
|
||
service_one['letter_branding'] = sample_uuid()
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(),
|
||
)
|
||
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type="letter"
|
||
)
|
||
assert [
|
||
(
|
||
radio['value'],
|
||
page.select_one('label[for={}]'.format(radio['id'])).text.strip()
|
||
)
|
||
for radio in page.select('input[type=radio]')
|
||
] == [
|
||
('organisation', 'Test Organisation'),
|
||
('something_else', 'Something else'),
|
||
]
|
||
|
||
|
||
@pytest.mark.parametrize('branding_type', ['email', 'letter'])
|
||
@pytest.mark.parametrize('from_template,back_link_url', [
|
||
(None, '/services/{}/service-settings'.format(SERVICE_ONE_ID),),
|
||
(TEMPLATE_ONE_ID, '/services/{}/templates/{}'.format(SERVICE_ONE_ID, TEMPLATE_ONE_ID),)
|
||
])
|
||
def test_back_link_on_branding_request_page(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_email_branding,
|
||
mock_get_letter_branding_by_id,
|
||
active_user_with_permissions,
|
||
from_template,
|
||
back_link_url,
|
||
branding_type,
|
||
):
|
||
if from_template:
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type=branding_type, from_template=from_template
|
||
)
|
||
else:
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type=branding_type
|
||
)
|
||
|
||
back_link = page.select('a[class=govuk-back-link]')
|
||
assert back_link[0].attrs['href'] == back_link_url
|
||
|
||
|
||
@pytest.mark.parametrize('branding_type', ['email', 'letter'])
|
||
def test_show_branding_request_page_when_branding_is_same_as_org(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
mock_get_email_branding,
|
||
mock_get_letter_branding_by_id,
|
||
mock_get_service_organisation,
|
||
active_user_with_permissions,
|
||
branding_type
|
||
):
|
||
service_one['{}_branding'.format(branding_type)] = sample_uuid()
|
||
if branding_type == 'email':
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(email_branding_id=service_one['email_branding']),
|
||
)
|
||
else:
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(letter_branding_id=service_one['letter_branding']),
|
||
)
|
||
|
||
page = client_request.get(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type=branding_type
|
||
)
|
||
|
||
# Central government organisations who have their own default
|
||
# branding will do so because they’re exempt from GOV.UK.
|
||
# We also don’t show their organisation’s branding because they
|
||
# have it already. So ‘Something else’ is the only option.
|
||
assert not page.select('input[type=radio]')
|
||
assert page.select_one('textarea')['name'] == 'something_else'
|
||
|
||
|
||
@pytest.mark.parametrize('data, requested_branding', (
|
||
(
|
||
{
|
||
'options': 'govuk',
|
||
},
|
||
'GOV.UK',
|
||
),
|
||
(
|
||
{
|
||
'options': 'govuk',
|
||
'something_else': 'ignored',
|
||
},
|
||
'GOV.UK',
|
||
),
|
||
(
|
||
{
|
||
'options': 'something_else',
|
||
'something_else': 'Homer Simpson'
|
||
},
|
||
'Something else\n\nHomer Simpson'
|
||
),
|
||
pytest.param(
|
||
{
|
||
'options': 'something_else',
|
||
},
|
||
'[Missing details]',
|
||
marks=pytest.mark.xfail(raises=AssertionError),
|
||
),
|
||
pytest.param(
|
||
{'options': 'foo'},
|
||
'Nope',
|
||
marks=pytest.mark.xfail(raises=AssertionError),
|
||
),
|
||
))
|
||
@pytest.mark.parametrize('org_name, expected_organisation', (
|
||
(None, 'Can’t tell (domain is user.gov.uk)'),
|
||
('Test Organisation', 'Test Organisation'),
|
||
))
|
||
def test_submit_email_branding_request(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
data,
|
||
requested_branding,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_email_branding,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
org_name,
|
||
expected_organisation,
|
||
):
|
||
service_one['email_branding'] = sample_uuid()
|
||
mocker.patch(
|
||
'app.models.service.Service.organisation_id',
|
||
new_callable=PropertyMock,
|
||
return_value=ORGANISATION_ID if org_name else None,
|
||
)
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(name=org_name),
|
||
)
|
||
|
||
zendesk = mocker.patch(
|
||
'app.main.views.service_settings.zendesk_client.create_ticket',
|
||
autospec=True,
|
||
)
|
||
|
||
page = client_request.post(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type="email",
|
||
_data=data,
|
||
_follow_redirects=True,
|
||
)
|
||
|
||
zendesk.assert_called_once_with(
|
||
message='\n'.join([
|
||
'Organisation: {}',
|
||
'Service: service one',
|
||
'http://localhost/services/596364a0-858e-42c8-9062-a8fe822260eb',
|
||
'',
|
||
'---',
|
||
'Current branding: Organisation name',
|
||
'Branding requested: {}\n',
|
||
]).format(expected_organisation, requested_branding),
|
||
subject='Email branding request - service one',
|
||
ticket_type='question',
|
||
user_email='test@user.gov.uk',
|
||
user_name='Test User',
|
||
tags=['notify_action', 'notify_branding'],
|
||
)
|
||
assert normalize_spaces(page.select_one('.banner-default').text) == (
|
||
'Thanks for your branding request. We’ll get back to you '
|
||
'within one working day.'
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('data, requested_branding', (
|
||
(
|
||
{
|
||
'options': 'something_else',
|
||
'something_else': 'Homer Simpson'
|
||
},
|
||
'Something else\n\nHomer Simpson'
|
||
),
|
||
pytest.param(
|
||
{
|
||
'options': 'something_else',
|
||
},
|
||
'[Missing details]',
|
||
marks=pytest.mark.xfail(raises=AssertionError),
|
||
),
|
||
pytest.param(
|
||
{'options': 'foo'},
|
||
'Nope',
|
||
marks=pytest.mark.xfail(raises=AssertionError),
|
||
),
|
||
))
|
||
@pytest.mark.parametrize('org_name, expected_organisation', (
|
||
(None, 'Can’t tell (domain is user.gov.uk)'),
|
||
('Test Organisation', 'Test Organisation'),
|
||
))
|
||
def test_submit_letter_branding_request(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
data,
|
||
requested_branding,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_letter_branding_by_id,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
org_name,
|
||
expected_organisation,
|
||
):
|
||
service_one['letter_branding'] = sample_uuid()
|
||
|
||
mocker.patch(
|
||
'app.models.service.Service.organisation_id',
|
||
new_callable=PropertyMock,
|
||
return_value=ORGANISATION_ID if org_name else None,
|
||
)
|
||
mocker.patch(
|
||
'app.organisations_client.get_organisation',
|
||
return_value=organisation_json(name=org_name),
|
||
)
|
||
|
||
zendesk = mocker.patch(
|
||
'app.main.views.service_settings.zendesk_client.create_ticket',
|
||
autospec=True,
|
||
)
|
||
|
||
page = client_request.post(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type="letter",
|
||
_data=data,
|
||
_follow_redirects=True,
|
||
)
|
||
|
||
zendesk.assert_called_once_with(
|
||
message='\n'.join([
|
||
'Organisation: {}',
|
||
'Service: service one',
|
||
'http://localhost/services/596364a0-858e-42c8-9062-a8fe822260eb',
|
||
'',
|
||
'---',
|
||
'Current branding: HM Government',
|
||
'Branding requested: {}\n',
|
||
]).format(expected_organisation, requested_branding),
|
||
subject='Letter branding request - service one',
|
||
ticket_type='question',
|
||
user_email='test@user.gov.uk',
|
||
user_name='Test User',
|
||
tags=['notify_action', 'notify_branding'],
|
||
)
|
||
assert normalize_spaces(page.select_one('.banner-default').text) == (
|
||
'Thanks for your branding request. We’ll get back to you '
|
||
'within one working day.'
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('branding_type', ['email', 'letter'])
|
||
@pytest.mark.parametrize('from_template', [
|
||
None,
|
||
TEMPLATE_ONE_ID
|
||
])
|
||
def test_submit_letter_branding_request_redirects_if_from_template_is_set(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_letter_branding_by_id,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
from_template,
|
||
branding_type,
|
||
|
||
):
|
||
mocker.patch('app.main.views.service_settings.zendesk_client.create_ticket', autospec=True)
|
||
data = {'options': 'something_else', 'something_else': 'Homer Simpson'}
|
||
|
||
if from_template:
|
||
client_request.post(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type="letter", from_template=from_template,
|
||
_data=data,
|
||
_expected_redirect=url_for(
|
||
'main.view_template', service_id=SERVICE_ONE_ID, template_id=from_template, _external=True
|
||
)
|
||
)
|
||
else:
|
||
client_request.post(
|
||
'.branding_request', service_id=SERVICE_ONE_ID, branding_type="letter",
|
||
_data=data,
|
||
_expected_redirect=url_for('main.service_settings', service_id=SERVICE_ONE_ID, _external=True)
|
||
)
|
||
|
||
|
||
@pytest.mark.parametrize('branding_type,current_branding', [
|
||
('email', 'GOV.UK'), ('letter', 'no')
|
||
])
|
||
def test_submit_branding_when_something_else_is_only_option(
|
||
client_request,
|
||
service_one,
|
||
mocker,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_email_branding,
|
||
mock_get_letter_branding_by_id,
|
||
branding_type,
|
||
current_branding,
|
||
):
|
||
zendesk = mocker.patch(
|
||
'app.main.views.service_settings.zendesk_client.create_ticket',
|
||
autospec=True,
|
||
)
|
||
|
||
client_request.post(
|
||
'.branding_request',
|
||
service_id=SERVICE_ONE_ID, branding_type=branding_type,
|
||
_data={
|
||
'something_else': 'Homer Simpson',
|
||
},
|
||
)
|
||
|
||
assert (
|
||
'Current branding: {}\n'
|
||
'Branding requested: Something else\n'
|
||
'\n'
|
||
'Homer Simpson'.format(current_branding)
|
||
) in zendesk.call_args_list[0][1]['message']
|
||
|
||
|
||
def test_service_settings_links_to_branding_request_page_for_letters(
|
||
mocker,
|
||
service_one,
|
||
client_request,
|
||
active_user_with_permissions,
|
||
no_reply_to_email_addresses,
|
||
no_letter_contact_blocks,
|
||
single_sms_sender,
|
||
mock_get_service_settings_page_common,
|
||
mock_get_organisation,
|
||
):
|
||
service_one["restricted"] is False
|
||
service_one['permissions'].append('letter')
|
||
page = client_request.get(
|
||
'.service_settings', service_id=SERVICE_ONE_ID
|
||
)
|
||
assert len(page.find_all('a', attrs={'href': '/services/{}/branding-request/letter'.format(SERVICE_ONE_ID)})) == 1
|
||
|
||
|
||
def test_show_service_data_retention(
|
||
platform_admin_client,
|
||
service_one,
|
||
mock_get_service_data_retention,
|
||
|
||
):
|
||
|
||
mock_get_service_data_retention.return_value[0]['days_of_retention'] = 5
|
||
|
||
response = platform_admin_client.get(url_for('main.data_retention', service_id=service_one['id']))
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
rows = page.select('tbody tr')
|
||
assert len(rows) == 1
|
||
assert normalize_spaces(rows[0].text) == 'Email 5 days Change'
|
||
|
||
|
||
def test_view_add_service_data_retention(
|
||
platform_admin_client,
|
||
service_one,
|
||
|
||
):
|
||
response = platform_admin_client.get(url_for('main.add_data_retention', service_id=service_one['id']))
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert normalize_spaces(page.select_one('input')['value']) == "email"
|
||
assert page.find('input', attrs={'name': 'days_of_retention'})
|
||
|
||
|
||
def test_add_service_data_retention(
|
||
platform_admin_client,
|
||
service_one,
|
||
mock_create_service_data_retention
|
||
):
|
||
response = platform_admin_client.post(url_for(
|
||
'main.add_data_retention',
|
||
service_id=service_one['id']),
|
||
data={'notification_type': "email", 'days_of_retention': 5}
|
||
)
|
||
assert response.status_code == 302
|
||
settings_url = url_for(
|
||
'main.data_retention', service_id=service_one['id'], _external=True)
|
||
assert settings_url == response.location
|
||
assert mock_create_service_data_retention.called
|
||
|
||
|
||
def test_update_service_data_retention(
|
||
platform_admin_client,
|
||
service_one,
|
||
fake_uuid,
|
||
mock_get_service_data_retention,
|
||
mock_update_service_data_retention,
|
||
):
|
||
response = platform_admin_client.post(
|
||
url_for(
|
||
'main.edit_data_retention',
|
||
service_id=service_one['id'],
|
||
data_retention_id=str(fake_uuid)),
|
||
data={'days_of_retention': 5}
|
||
)
|
||
assert response.status_code == 302
|
||
settings_url = url_for(
|
||
'main.data_retention', service_id=service_one['id'], _external=True)
|
||
assert settings_url == response.location
|
||
assert mock_update_service_data_retention.called
|
||
|
||
|
||
def test_update_service_data_retention_return_validation_error_for_negative_days_of_retention(
|
||
platform_admin_client,
|
||
service_one,
|
||
fake_uuid,
|
||
mock_get_service_data_retention,
|
||
mock_update_service_data_retention,
|
||
):
|
||
response = platform_admin_client.post(
|
||
url_for(
|
||
'main.edit_data_retention',
|
||
service_id=service_one['id'],
|
||
data_retention_id=fake_uuid
|
||
),
|
||
data={'days_of_retention': -5}
|
||
)
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert 'Must be between 3 and 90' in page.find('span', class_='govuk-error-message').text
|
||
assert mock_get_service_data_retention.called
|
||
assert not mock_update_service_data_retention.called
|
||
|
||
|
||
def test_update_service_data_retention_populates_form(
|
||
platform_admin_client,
|
||
service_one,
|
||
fake_uuid,
|
||
mock_get_service_data_retention,
|
||
):
|
||
|
||
mock_get_service_data_retention.return_value[0]['days_of_retention'] = 5
|
||
response = platform_admin_client.get(url_for(
|
||
'main.edit_data_retention',
|
||
service_id=service_one['id'],
|
||
data_retention_id=fake_uuid
|
||
))
|
||
assert response.status_code == 200
|
||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||
assert page.find('input', attrs={'name': 'days_of_retention'})['value'] == '5'
|