Merge pull request #904 from alphagov/make-settings-page-a-table

Make settings page a table and do a better job of explaining the reply to address/text message sender
This commit is contained in:
Chris Hill-Scott
2016-08-26 15:49:49 +01:00
committed by GitHub
14 changed files with 348 additions and 390 deletions

View File

@@ -35,6 +35,10 @@
margin-bottom: $gutter-half; margin-bottom: $gutter-half;
} }
.bottom-gutter-2 {
margin-bottom: $gutter * 2;
}
.align-with-heading { .align-with-heading {
display: block; display: block;
text-align: center; text-align: center;

View File

@@ -327,17 +327,21 @@ class ProviderForm(Form):
class ServiceReplyToEmailFrom(Form): class ServiceReplyToEmailFrom(Form):
email_address = email_address() email_address = email_address(label='Email reply to address')
class ServiceSmsSender(Form): class ServiceSmsSender(Form):
sms_sender = StringField('', validators=[Length(max=11, sms_sender = StringField(
message="Text message sender can't be longer than 11 characters")]) 'Text message sender',
validators=[
Length(max=11, message="Enter fewer than 11 characters")
]
)
def validate_sms_sender(form, field): def validate_sms_sender(form, field):
import re import re
if field.data and not re.match('^[a-zA-Z0-9\s]+$', field.data): if field.data and not re.match('^[a-zA-Z0-9\s]+$', field.data):
raise ValidationError('Text message sender can only contain alpha-numeric characters') raise ValidationError('Use letters and numbers only')
class ServiceBrandingOrg(Form): class ServiceBrandingOrg(Form):

View File

@@ -34,7 +34,14 @@ from app import user_api_client, current_service, organisations_client
@login_required @login_required
@user_has_permissions('manage_settings', admin_override=True) @user_has_permissions('manage_settings', admin_override=True)
def service_settings(service_id): def service_settings(service_id):
return render_template('views/service-settings.html') if current_service['organisation']:
organisation = organisations_client.get_organisation(current_service['organisation'])['organisation']
else:
organisation = None
return render_template(
'views/service-settings.html',
organisation=organisation
)
@main.route("/services/<service_id>/service-settings/name", methods=['GET', 'POST']) @main.route("/services/<service_id>/service-settings/name", methods=['GET', 'POST'])
@@ -157,41 +164,6 @@ def service_switch_research_mode(service_id):
return redirect(url_for('.service_settings', service_id=service_id)) return redirect(url_for('.service_settings', service_id=service_id))
@main.route("/services/<service_id>/service-settings/status", methods=['GET', 'POST'])
@login_required
@user_has_permissions('manage_settings', admin_override=True)
def service_status_change(service_id):
if request.method == 'GET':
return render_template(
'views/service-settings/status.html'
)
elif request.method == 'POST':
return redirect(url_for('.service_status_change_confirm', service_id=service_id))
@main.route("/services/<service_id>/service-settings/status/confirm", methods=['GET', 'POST'])
@login_required
@user_has_permissions('manage_settings', admin_override=True)
def service_status_change_confirm(service_id):
# Validate password for form
def _check_password(pwd):
return user_api_client.verify_password(current_user.id, pwd)
form = ConfirmPasswordForm(_check_password)
if form.validate_on_submit():
service_api_client.update_service(
current_service['id'],
active=True
)
return redirect(url_for('.service_settings', service_id=service_id))
return render_template(
'views/service-settings/confirm.html',
heading='Turn off all outgoing notifications',
destructive=True,
form=form)
@main.route("/services/<service_id>/service-settings/delete", methods=['GET', 'POST']) @main.route("/services/<service_id>/service-settings/delete", methods=['GET', 'POST'])
@login_required @login_required
@user_has_permissions('manage_settings', admin_override=True) @user_has_permissions('manage_settings', admin_override=True)
@@ -233,12 +205,10 @@ def service_set_reply_to_email(service_id):
if request.method == 'GET': if request.method == 'GET':
form.email_address.data = current_service.get('reply_to_email_address') form.email_address.data = current_service.get('reply_to_email_address')
if form.validate_on_submit(): if form.validate_on_submit():
message = 'Reply to email set to {}'.format(form.email_address.data)
service_api_client.update_service( service_api_client.update_service(
current_service['id'], current_service['id'],
reply_to_email_address=form.email_address.data reply_to_email_address=form.email_address.data
) )
flash(message, 'default_with_tick')
return redirect(url_for('.service_settings', service_id=service_id)) return redirect(url_for('.service_settings', service_id=service_id))
return render_template( return render_template(
'views/service-settings/set-reply-to-email.html', 'views/service-settings/set-reply-to-email.html',
@@ -253,15 +223,10 @@ def service_set_sms_sender(service_id):
if request.method == 'GET': if request.method == 'GET':
form.sms_sender.data = current_service.get('sms_sender') form.sms_sender.data = current_service.get('sms_sender')
if form.validate_on_submit(): if form.validate_on_submit():
if form.sms_sender.data:
message = 'Text message sender set to {}'.format(form.sms_sender.data)
else:
message = 'Text message sender removed'
service_api_client.update_service( service_api_client.update_service(
current_service['id'], current_service['id'],
sms_sender=form.sms_sender.data or None sms_sender=form.sms_sender.data or None
) )
flash(message, 'default_with_tick')
return redirect(url_for('.service_settings', service_id=service_id)) return redirect(url_for('.service_settings', service_id=service_id))
return render_template( return render_template(
'views/service-settings/set-sms-sender.html', 'views/service-settings/set-sms-sender.html',

View File

@@ -15,5 +15,8 @@ class OrganisationsClient(BaseAPIClient):
self.client_id = app.config['ADMIN_CLIENT_USER_NAME'] self.client_id = app.config['ADMIN_CLIENT_USER_NAME']
self.secret = app.config['ADMIN_CLIENT_SECRET'] self.secret = app.config['ADMIN_CLIENT_SECRET']
def get_organisation(self, id):
return self.get(url='/organisation/{}'.format(id))
def get_organisations(self): def get_organisations(self):
return self.get(url='/organisation')['organisations'] return self.get(url='/organisation')['organisations']

View File

@@ -73,8 +73,8 @@
</td> </td>
{% endmacro %} {% endmacro %}
{% macro text_field(text) -%} {% macro text_field(text, status='') -%}
{% call field() %} {% call field(status=status) %}
{{ text }} {{ text }}
{% endcall %} {% endcall %}
{%- endmacro %} {%- endmacro %}
@@ -85,6 +85,12 @@
{% endcall %} {% endcall %}
{%- endmacro %} {%- endmacro %}
{% macro edit_field(text, link) -%}
{% call field(align='right') %}
<a href="{{ link }}">{{ text }}</a>
{% endcall %}
{%- endmacro %}
{% macro boolean_field(yes) -%} {% macro boolean_field(yes) -%}
{% call field(status='yes' if yes else 'no') %} {% call field(status='yes' if yes else 'no') %}
{{ "Yes" if yes else "No" }} {{ "Yes" if yes else "No" }}

View File

@@ -1,61 +1,99 @@
{% extends "withnav_template.html" %} {% extends "withnav_template.html" %}
{% from "components/browse-list.html" import browse_list %} {% from "components/browse-list.html" import browse_list %}
{% from "components/table.html" import mapping_table, row, text_field, edit_field, field %}
{% block page_title %} {% block page_title %}
Service settings GOV.UK Notify Settings GOV.UK Notify
{% endblock %} {% endblock %}
{% block maincolumn_content %} {% block maincolumn_content %}
<h1 class="heading-large">Settings</h1> <h1 class="heading-large">Settings</h1>
{{ browse_list([ <div class="bottom-gutter-2">
{
'title': 'Change your service name', {% call mapping_table(
'link': url_for('.service_name_change', service_id=current_service.id) caption='Settings',
}, field_headings=['Label', 'Value', 'Action'],
{ field_headings_visible=False,
'title': 'Set email reply to address', caption_visible=False
'link': url_for('.service_set_reply_to_email', service_id=current_service.id) ) %}
}, {% call row() %}
{ {{ text_field('Service name' )}}
'title': 'Set email branding', {{ text_field(current_service.name) }}
'link': url_for('.service_set_branding_and_org', service_id=current_service.id) {{ edit_field('Change', url_for('.service_name_change', service_id=current_service.id)) }}
} if current_user.has_permissions([], admin_override=True) else {}, {% endcall %}
{ {% call row() %}
'title': 'Set text message sender name', {{ text_field('Email reply to address')}}
'link': url_for('.service_set_sms_sender', service_id=current_service.id) {{ text_field(
}, current_service.reply_to_email_address,
{ status='' if current_service.reply_to_email_address else 'default'
'title': 'Request to go live and turn off trial mode', ) }}
'link': url_for('.service_request_to_go_live', service_id=current_service.id), {{ edit_field('Change', url_for('.service_set_reply_to_email', service_id=current_service.id)) }}
'hint': 'A live service can send notifications to any phone number or email address', {% endcall %}
} if current_service.restricted else { {% call row() %}
}, {{ text_field('Text message sender')}}
{ {{ text_field(current_service.sms_sender or '40604') }}
'title': 'Temporarily suspend API keys', {{ edit_field('Change', url_for('.service_set_sms_sender', service_id=current_service.id)) }}
'link': url_for('.service_status_change', service_id=current_service.id), {% endcall %}
'destructive': True {% endcall %}
} if not current_service.active else { </div>
'title': 'Reactivate API keys',
'link': url_for('.service_status_change', service_id=current_service.id) <div class="bottom-gutter-2">
},
{ <h2 class="heading-medium">Your service is in trial mode</h2>
'title': 'Make service live',
'link': url_for('.service_switch_live', service_id=current_service.id) <ul class='list list-bullet'>
} if current_service.restricted and current_user.has_permissions([], admin_override=True) else { <li>you can only send messages to yourself</li>
'title': 'Revert service to trial', <li>you can add people to your team, then you can send messages to them too</li>
'link': url_for('.service_switch_live', service_id=current_service.id) <li>you can only send 50 messages per day</li>
} if not current_service.restricted and current_user.has_permissions([], admin_override=True) else { </ul>
},
{ <p>
'title': 'Put service into research mode', To remove these restrictions
'link': url_for('.service_switch_research_mode', service_id=current_service.id) <a href="{{ url_for('.service_request_to_go_live', service_id=current_service.id) }}">request to go live</a>.
} if not current_service.research_mode and current_user.has_permissions([], admin_override=True) else { </p>
'title': 'Take service out of research mode',
'link': url_for('.service_switch_research_mode', service_id=current_service.id) </div>
} if current_service.research_mode and current_user.has_permissions([], admin_override=True) else {
} {% if current_user.has_permissions([], admin_override=True) %}
]) }}
<h2 class="heading-medium">Platform admin settings</h2>
{% call mapping_table(
caption='Settings',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False,
caption_visible=False
) %}
{% call row() %}
{{ text_field('Email branding' )}}
{% call field() %}
{% if current_service.branding == 'govuk' %}
GOV.UK
{% elif current_service.branding == 'both' %}
GOV.UK and {{ organisation.name if organisation else None }}
{% elif current_service.branding == 'org' %}
Only {{ organisation.name if organisation else None }}
{% endif %}
{% endcall %}
{{ edit_field('Change', url_for('.service_set_branding_and_org', service_id=current_service.id)) }}
{% endcall %}
{% endcall %}
<ul>
<li class="bottom-gutter">
<a href="{{ url_for('.service_switch_live', service_id=current_service.id) }}" class="button">
{{ 'Make service live' if current_service.restricted else 'Revert service to trial mode' }}
</a>
</li>
<li>
<a href="{{ url_for('.service_switch_research_mode', service_id=current_service.id) }}" class="button">
{{ 'Take service out of research mode' if current_service.research_mode else 'Put into research mode' }}
</a>
</li>
</ul>
{% endif %}
{% endblock %} {% endblock %}

View File

@@ -10,26 +10,22 @@
<h1 class="heading-large">Change your service name</h1> <h1 class="heading-large">Change your service name</h1>
<div class="grid-row">
<div class="column-three-quarters">
<div class="form-group"> <div class="form-group">
<p>Users will see your service name:</p> <p>Users will see your service name:</p>
<ul class="list-bullet"> <ul class="list-bullet">
<li>at the start of every text message, eg Vehicle tax: we received your payment, thank you</li> <li>at the start of every text message, eg Vehicle tax: we received your payment, thank you</li>
<li>as your email sender name</li> <li>as your email sender name</li>
</ul> </ul>
</div>
<form method="post">
{{ textbox(form.name) }}
{{ page_footer(
'Save',
back_link=url_for('.service_settings', service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>
</div>
</div> </div>
<form method="post">
{{ textbox(form.name) }}
{{ page_footer(
'Save',
back_link=url_for('.service_settings', service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>
{% endblock %} {% endblock %}

View File

@@ -16,7 +16,8 @@
{{ branding_radios(form.organisation, branding_dict=branding_dict) }} {{ branding_radios(form.organisation, branding_dict=branding_dict) }}
{{ page_footer( {{ page_footer(
'Save', 'Save',
back_link=url_for('.service_settings', service_id=current_service.id) back_link=url_for('.service_settings', service_id=current_service.id),
back_link_text='Back to settings'
) }} ) }}
</form> </form>
</div> </div>

View File

@@ -3,26 +3,40 @@
{% from "components/page-footer.html" import page_footer %} {% from "components/page-footer.html" import page_footer %}
{% block page_title %} {% block page_title %}
Request to go live GOV.UK Notify Email reply to address GOV.UK Notify
{% endblock %} {% endblock %}
{% block maincolumn_content %} {% block maincolumn_content %}
<div class="grid-row"> <h1 class="heading-large">
<div class="column-three-quarters"> Email reply to address
<h1 class="heading-large">Set email reply to address</h1> </h1>
<form method="post"> <p>
{{ textbox( Your emails will be sent from
form.email_address, {{ current_service.email_from }}@notifications.service.gov.uk.
width='1-1', This is so they have the best chance of being delivered.
safe_error_message=True This email address cant receive replies.
) }} </p>
{{ page_footer( <p>
'Save', Set up a separate email address to receive replies from
back_link=url_for('.service_settings', service_id=current_service.id) your users, then enter it here.
) }} </p>
</form> {% if current_service.restricted %}
</div> <p>
</div> Your service cant go live until youve done this.
</p>
{% endif %}
<form method="post">
{{ textbox(
form.email_address,
width='2-3',
safe_error_message=True
) }}
{{ page_footer(
'Save',
back_link=url_for('.service_settings', service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>
{% endblock %} {% endblock %}

View File

@@ -8,21 +8,33 @@
{% block maincolumn_content %} {% block maincolumn_content %}
<div class="grid-row"> <h1 class="heading-large">Text message sender</h1>
<div class="column-three-quarters"> <p>
<h1 class="heading-large">Set text message sender name</h1> This appears instead of a phone number when a user receives a
<form method="post"> text message from your service.
{{ textbox( <p>
form.sms_sender, If you leave this blank:
width='1-1', </p>
safe_error_message=True <ul class="list list-bullet">
) }} <li>
{{ page_footer( your messages will be sent from 40604 (a shortcode thats
'Save', reserved for government use)
back_link=url_for('.service_settings', service_id=current_service.id) </li>
) }} <li>
</form> each message will begin with {{ current_service.name }}:
</div> </li>
</div> </ul>
<form method="post">
{{ textbox(
form.sms_sender,
width='1-4',
hint='Up to 11 characters, letters, numbers and spaces only'
) }}
{{ page_footer(
'Save',
back_link=url_for('.service_settings', service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>
{% endblock %} {% endblock %}

View File

@@ -1,38 +0,0 @@
{% extends "withnav_template.html" %}
{% from "components/page-footer.html" import page_footer %}
{% block page_title %}
Temporrily suspend API keys GOV.UK Notify
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Temporarily suspend API keys</h1>
<div class="grid-row">
<div class="column-three-quarters">
<p>
Youll still be able to send notifications to yourself by uploading a
CSV file.
</p>
<p>
You can start sending notifications again when youre ready.
</p>
<form method="post">
{{ page_footer(
'Suspend API keys',
destructive=True,
back_link=url_for('.service_settings', service_id=current_service.id),
back_link_text='Back to settings'
) }}
</form>
</div>
</div>
{% endblock %}

View File

@@ -137,8 +137,8 @@ def test_sms_sender_form_validation(app_, mock_get_user_by_email):
form.sms_sender.data = 'morethanelevenchars' form.sms_sender.data = 'morethanelevenchars'
form.validate() form.validate()
assert "Text message sender can't be longer than 11 characters" == form.errors['sms_sender'][0] assert "Enter fewer than 11 characters" == form.errors['sms_sender'][0]
form.sms_sender.data = '###########' form.sms_sender.data = '###########'
form.validate() form.validate()
assert 'Text message sender can only contain alpha-numeric characters' == form.errors['sms_sender'][0] assert 'Use letters and numbers only' == form.errors['sms_sender'][0]

View File

@@ -9,19 +9,49 @@ from unittest.mock import ANY, Mock
from werkzeug.exceptions import InternalServerError from werkzeug.exceptions import InternalServerError
def test_should_show_overview(app_, def test_should_show_overview(
active_user_with_permissions, app_,
mocker, active_user_with_permissions,
service_one): mocker,
with app_.test_request_context(): service_one,
with app_.test_client() as client: mock_get_organisation
client.login(active_user_with_permissions, mocker, service_one) ):
response = client.get(url_for( with app_.test_request_context(), app_.test_client() as client:
'main.service_settings', service_id=service_one['id'])) client.login(active_user_with_permissions, mocker, service_one)
assert response.status_code == 200 response = client.get(url_for(
resp_data = response.get_data(as_text=True) 'main.service_settings', service_id=service_one['id']
assert 'Service settings' in resp_data ))
app.service_api_client.get_service.assert_called_with(service_one['id']) assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
assert page.find('h1').text == 'Settings'
for index, row in enumerate([
'Service name service one Change',
'Email reply to address None Change',
'Text message sender 40604 Change'
]):
assert row == " ".join(page.find_all('tr')[index + 1].text.split())
app.service_api_client.get_service.assert_called_with(service_one['id'])
def test_should_show_overview_for_service_with_more_things_set(
app_,
active_user_with_permissions,
mocker,
service_with_reply_to_addresses,
mock_get_organisation
):
with app_.test_request_context(), app_.test_client() as client:
client.login(active_user_with_permissions, mocker, service_with_reply_to_addresses)
response = client.get(url_for(
'main.service_settings', service_id=service_with_reply_to_addresses['id']
))
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
for index, row in enumerate([
'Service name service one Change',
'Email reply to address test@example.com Change',
'Text message sender elevenchars Change'
]):
assert row == " ".join(page.find_all('tr')[index + 1].text.split())
def test_should_show_service_name(app_, def test_should_show_service_name(app_,
@@ -63,14 +93,17 @@ def test_should_redirect_after_change_service_name(app_,
assert mock_get_services.called assert mock_get_services.called
def test_switch_service_to_live(app_, def test_switch_service_to_live(
service_one, app_,
mock_login, service_one,
mock_get_user, mock_login,
active_user_with_permissions, mock_get_user,
mock_get_service, active_user_with_permissions,
mock_update_service, mock_get_service,
mock_has_permissions): mock_update_service,
mock_has_permissions,
mock_get_organisation
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
client.login(active_user_with_permissions) client.login(active_user_with_permissions)
@@ -87,14 +120,17 @@ def test_switch_service_to_live(app_,
) )
def test_switch_service_to_restricted(app_, def test_switch_service_to_restricted(
service_one, app_,
mock_login, service_one,
mock_get_user, mock_login,
active_user_with_permissions, mock_get_user,
mock_get_live_service, active_user_with_permissions,
mock_update_service, mock_get_live_service,
mock_has_permissions): mock_update_service,
mock_has_permissions,
mock_get_organisation
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
client.login(active_user_with_permissions) client.login(active_user_with_permissions)
@@ -148,12 +184,15 @@ def test_should_show_service_name_confirmation(app_,
app.service_api_client.get_service.assert_called_with(service_one['id']) app.service_api_client.get_service.assert_called_with(service_one['id'])
def test_should_redirect_after_service_name_confirmation(app_, def test_should_redirect_after_service_name_confirmation(
active_user_with_permissions, app_,
service_one, active_user_with_permissions,
mocker, service_one,
mock_update_service, mocker,
mock_verify_password): mock_update_service,
mock_verify_password,
mock_get_organisation
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
client.login(active_user_with_permissions, mocker, service_one) client.login(active_user_with_permissions, mocker, service_one)
@@ -222,12 +261,13 @@ def test_should_show_request_to_go_live(app_,
def test_should_redirect_after_request_to_go_live( def test_should_redirect_after_request_to_go_live(
app_, app_,
api_user_active, api_user_active,
mock_get_user, mock_get_user,
mock_get_service, mock_get_service,
mock_has_permissions, mock_has_permissions,
mocker mock_get_organisation,
mocker
): ):
mock_post = mocker.patch( mock_post = mocker.patch(
'app.main.views.feedback.requests.post', 'app.main.views.feedback.requests.post',
@@ -262,12 +302,12 @@ def test_should_redirect_after_request_to_go_live(
def test_log_error_on_request_to_go_live( def test_log_error_on_request_to_go_live(
app_, app_,
api_user_active, api_user_active,
mock_get_user, mock_get_user,
mock_get_service, mock_get_service,
mock_has_permissions, mock_has_permissions,
mocker mocker
): ):
mock_post = mocker.patch( mock_post = mocker.patch(
'app.main.views.service_settings.requests.post', 'app.main.views.service_settings.requests.post',
@@ -293,95 +333,6 @@ def test_log_error_on_request_to_go_live(
) )
def test_should_show_status_page(app_,
api_user_active,
mock_get_service,
mock_get_user,
mock_get_user_by_email,
mock_login,
mock_has_permissions,
fake_uuid):
with app_.test_request_context():
with app_.test_client() as client:
client.login(api_user_active)
service_id = fake_uuid
response = client.get(url_for(
'main.service_status_change', service_id=service_id))
assert response.status_code == 200
resp_data = response.get_data(as_text=True)
assert 'Suspend API keys' in resp_data
assert mock_get_service.called
def test_should_show_redirect_after_status_change(app_,
api_user_active,
mock_get_service,
mock_get_user,
mock_get_user_by_email,
mock_login,
mock_has_permissions,
fake_uuid):
with app_.test_request_context():
with app_.test_client() as client:
client.login(api_user_active)
service_id = fake_uuid
response = client.post(url_for(
'main.service_status_change', service_id=service_id))
assert response.status_code == 302
redirect_url = url_for(
'main.service_status_change_confirm', service_id=service_id, _external=True)
assert redirect_url == response.location
assert mock_get_service.called
def test_should_show_status_confirmation(app_,
api_user_active,
mock_get_service,
mock_get_user,
mock_get_user_by_email,
mock_login,
mock_has_permissions,
fake_uuid):
with app_.test_request_context():
with app_.test_client() as client:
client.login(api_user_active)
service_id = fake_uuid
response = client.get(url_for(
'main.service_status_change_confirm', service_id=service_id))
assert response.status_code == 200
resp_data = response.get_data(as_text=True)
assert 'Turn off all outgoing notifications' in resp_data
assert mock_get_service.called
def test_should_redirect_after_status_confirmation(app_,
api_user_active,
mock_get_service,
mock_update_service,
mock_get_user,
mock_get_user_by_email,
mock_login,
mock_verify_password,
mock_has_permissions,
fake_uuid):
with app_.test_request_context():
with app_.test_client() as client:
client.login(api_user_active)
service_id = fake_uuid
response = client.post(url_for(
'main.service_status_change_confirm', service_id=service_id))
assert response.status_code == 302
settings_url = url_for(
'main.service_settings', service_id=service_id, _external=True)
assert settings_url == response.location
assert mock_get_service.called
assert mock_update_service.called
def test_should_show_delete_page(app_, def test_should_show_delete_page(app_,
api_user_active, api_user_active,
mock_login, mock_login,
@@ -468,14 +419,12 @@ def test_should_redirect_delete_confirmation(app_,
assert mock_delete_service.called assert mock_delete_service.called
def test_route_permissions(mocker, app_, api_user_active, service_one): def test_route_permissions(mocker, app_, api_user_active, service_one, mock_get_organisation):
routes = [ routes = [
'main.service_settings', 'main.service_settings',
'main.service_name_change', 'main.service_name_change',
'main.service_name_change_confirm', 'main.service_name_change_confirm',
'main.service_request_to_go_live', 'main.service_request_to_go_live',
'main.service_status_change',
'main.service_status_change_confirm',
'main.service_delete', 'main.service_delete',
'main.service_delete_confirm'] 'main.service_delete_confirm']
with app_.test_request_context(): with app_.test_request_context():
@@ -491,7 +440,7 @@ def test_route_permissions(mocker, app_, api_user_active, service_one):
service_one) service_one)
def test_route_invalid_permissions(mocker, app_, api_user_active, service_one): def test_route_invalid_permissions(mocker, app_, api_user_active, service_one, mock_get_organisation):
routes = [ routes = [
'main.service_settings', 'main.service_settings',
'main.service_name_change', 'main.service_name_change',
@@ -499,8 +448,6 @@ def test_route_invalid_permissions(mocker, app_, api_user_active, service_one):
'main.service_request_to_go_live', 'main.service_request_to_go_live',
'main.service_switch_live', 'main.service_switch_live',
'main.service_switch_research_mode', 'main.service_switch_research_mode',
'main.service_status_change',
'main.service_status_change_confirm',
'main.service_delete', 'main.service_delete',
'main.service_delete_confirm'] 'main.service_delete_confirm']
with app_.test_request_context(): with app_.test_request_context():
@@ -516,14 +463,12 @@ def test_route_invalid_permissions(mocker, app_, api_user_active, service_one):
service_one) service_one)
def test_route_for_platform_admin(mocker, app_, platform_admin_user, service_one): def test_route_for_platform_admin(mocker, app_, platform_admin_user, service_one, mock_get_organisation):
routes = [ routes = [
'main.service_settings', 'main.service_settings',
'main.service_name_change', 'main.service_name_change',
'main.service_name_change_confirm', 'main.service_name_change_confirm',
'main.service_request_to_go_live', 'main.service_request_to_go_live',
'main.service_status_change',
'main.service_status_change_confirm',
'main.service_delete', 'main.service_delete',
'main.service_delete_confirm' 'main.service_delete_confirm'
] ]
@@ -557,11 +502,13 @@ def test_route_for_platform_admin_update_service(mocker, app_, platform_admin_us
def test_set_reply_to_email_address( def test_set_reply_to_email_address(
app_, app_,
active_user_with_permissions, active_user_with_permissions,
mocker, mocker,
mock_update_service, mock_update_service,
service_one): service_one,
mock_get_organisation
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
client.login(active_user_with_permissions, mocker, service_one) client.login(active_user_with_permissions, mocker, service_one)
@@ -650,14 +597,16 @@ def test_switch_service_from_research_mode_to_normal(
def test_shows_research_mode_indicator( def test_shows_research_mode_indicator(
app_, app_,
service_one, service_one,
mock_login, mock_login,
mock_get_user, mock_get_user,
active_user_with_permissions, active_user_with_permissions,
mock_get_service, mock_get_service,
mock_has_permissions, mock_has_permissions,
mocker): mock_get_organisation,
mocker
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
service = service_json( service = service_json(
@@ -682,14 +631,16 @@ def test_shows_research_mode_indicator(
def test_does_not_show_research_mode_indicator( def test_does_not_show_research_mode_indicator(
app_, app_,
service_one, service_one,
mock_login, mock_login,
mock_get_user, mock_get_user,
active_user_with_permissions, active_user_with_permissions,
mock_get_service, mock_get_service,
mock_has_permissions, mock_has_permissions,
mocker): mock_get_organisation,
mocker
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
client.login(active_user_with_permissions) client.login(active_user_with_permissions)
@@ -702,11 +653,13 @@ def test_does_not_show_research_mode_indicator(
def test_set_text_message_sender( def test_set_text_message_sender(
app_, app_,
active_user_with_permissions, active_user_with_permissions,
mocker, mocker,
mock_update_service, mock_update_service,
service_one): service_one,
mock_get_organisation
):
with app_.test_request_context(): with app_.test_request_context():
with app_.test_client() as client: with app_.test_client() as client:
client.login(active_user_with_permissions, mocker, service_one) client.login(active_user_with_permissions, mocker, service_one)
@@ -737,34 +690,6 @@ def test_if_sms_sender_set_then_form_populated(app_,
assert page.find(id='sms_sender')['value'] == 'elevenchars' assert page.find(id='sms_sender')['value'] == 'elevenchars'
@pytest.mark.parametrize("sender, expected_flash_message", [
("elevenchars", 'Text message sender set to elevenchars'),
('', 'Text message sender removed')
])
def test_set_text_message_sender_flash_messages(
app_,
active_user_with_permissions,
mocker,
mock_update_service,
service_one,
sender,
expected_flash_message):
with app_.test_request_context():
with app_.test_client() as client:
client.login(active_user_with_permissions, mocker, service_one)
data = {"sms_sender": sender}
response = client.post(url_for('main.service_set_sms_sender', service_id=service_one['id']),
data=data,
follow_redirects=True)
assert response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
element = page.find('div', {"class": "banner-default-with-tick"})
assert element.text.strip() == expected_flash_message
def test_should_show_branding( def test_should_show_branding(
mocker, app_, platform_admin_user, service_one, mock_get_organisations mocker, app_, platform_admin_user, service_one, mock_get_organisations
): ):

View File

@@ -43,6 +43,17 @@ def service_one(api_user_active):
return service_json(SERVICE_ONE_ID, 'service one', [api_user_active.id]) return service_json(SERVICE_ONE_ID, 'service one', [api_user_active.id])
@pytest.fixture(scope='function')
def service_with_reply_to_addresses(api_user_active):
return service_json(
SERVICE_ONE_ID,
'service one',
[api_user_active.id],
reply_to_email_address='test@example.com',
sms_sender='elevenchars',
)
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def mock_send_sms(request, mocker): def mock_send_sms(request, mocker):
return mocker.patch("app.service_api_client.send_sms") return mocker.patch("app.service_api_client.send_sms")
@@ -1136,3 +1147,20 @@ def mock_get_organisations(mocker):
return mocker.patch( return mocker.patch(
'app.organisations_client.get_organisations', side_effect=_get_organisations 'app.organisations_client.get_organisations', side_effect=_get_organisations
) )
@pytest.fixture(scope='function')
def mock_get_organisation(mocker):
def _get_organisation(id):
return {
'organisation': {
'logo': 'example.png',
'name': 'Organisation name',
'id': 'organisation-id',
'colour': '#f00'
}
}
return mocker.patch(
'app.organisations_client.get_organisation', side_effect=_get_organisation
)