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',
'Free text message allowance 250,000 Change free text message allowance',
'Email branding GOV.UK Change email branding (admin view)',
'Letter branding Not set Change letter branding (admin view)',
'Data retention email 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',
'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')[9].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')[9].find_all('td')[1].div)
assert 'foo
bar' in div
assert '