Allow editing of an organisation’s details

Adds a user interface for updating all the columns added in
https://github.com/alphagov/notifications-api/pull/2368

Sorry for the mega commit 😓
This commit is contained in:
Chris Hill-Scott
2019-03-22 14:23:24 +00:00
parent 307e959fd6
commit 936883bf7b
19 changed files with 1246 additions and 125 deletions
+61 -5
View File
@@ -243,9 +243,9 @@ class ForgivingIntegerField(StringField):
return super().__call__(value=value, **kwargs) return super().__call__(value=value, **kwargs)
def organisation_type(): def organisation_type(label='Who runs this service?'):
return RadioField( return RadioField(
'Who runs this service?', label,
choices=[ choices=[
('central', 'Central government'), ('central', 'Central government'),
('local', 'Local government'), ('local', 'Local government'),
@@ -530,6 +530,62 @@ class RenameOrganisationForm(StripWhitespaceForm):
]) ])
class OrganisationOrganisationTypeForm(StripWhitespaceForm):
organisation_type = organisation_type(label='What type of organisation is this?')
class OrganisationCrownStatusForm(StripWhitespaceForm):
crown_status = RadioField(
(
'Is this organisation a crown body?'
),
choices=[
('crown', 'Yes'),
('non-crown', 'No'),
('unknown', 'Not sure'),
],
validators=[
DataRequired(message='Cant be empty')
],
)
class OrganisationAgreementSignedForm(StripWhitespaceForm):
agreement_signed = RadioField(
(
'Has this organisation signed the agreement?'
),
choices=[
('yes', 'Yes'),
('no', 'No'),
('unknown', 'No (but we have some service-specific agreements in place)'),
],
validators=[
DataRequired(message='Cant be empty')
],
)
class OrganisationDomainsForm(StripWhitespaceForm):
def populate(self, domains_list):
for index, value in enumerate(domains_list):
self.domains[index].data = value
domains = FieldList(
StripWhitespaceStringField(
'',
validators=[
Optional(),
],
default=''
),
min_entries=10,
max_entries=10,
label="Domain names"
)
class CreateServiceForm(StripWhitespaceForm): class CreateServiceForm(StripWhitespaceForm):
name = StringField( name = StringField(
u'Whats your service called?', u'Whats your service called?',
@@ -895,7 +951,7 @@ class ServiceSwitchChannelForm(ServiceOnOffSettingForm):
super().__init__(name, *args, **kwargs) super().__init__(name, *args, **kwargs)
class ServiceSetEmailBranding(StripWhitespaceForm): class SetEmailBranding(StripWhitespaceForm):
branding_style = RadioFieldWithNoneOption( branding_style = RadioFieldWithNoneOption(
'Branding style', 'Branding style',
@@ -920,12 +976,12 @@ class ServiceSetEmailBranding(StripWhitespaceForm):
) )
class ServiceSetLetterBranding(ServiceSetEmailBranding): class SetLetterBranding(SetEmailBranding):
# form is the same, but instead of GOV.UK we have None as a valid option # form is the same, but instead of GOV.UK we have None as a valid option
DEFAULT = (FieldWithNoneOption.NONE_OPTION_VALUE, 'None') DEFAULT = (FieldWithNoneOption.NONE_OPTION_VALUE, 'None')
class ServicePreviewBranding(StripWhitespaceForm): class PreviewBranding(StripWhitespaceForm):
branding_style = HiddenFieldWithNoneOption('branding_style') branding_style = HiddenFieldWithNoneOption('branding_style')
+234
View File
@@ -5,6 +5,8 @@ from werkzeug.exceptions import abort
from app import ( from app import (
current_organisation, current_organisation,
email_branding_client,
letter_branding_client,
org_invite_api_client, org_invite_api_client,
organisations_client, organisations_client,
user_api_client, user_api_client,
@@ -14,9 +16,18 @@ from app.main.forms import (
ConfirmPasswordForm, ConfirmPasswordForm,
CreateOrUpdateOrganisation, CreateOrUpdateOrganisation,
InviteOrgUserForm, InviteOrgUserForm,
OrganisationAgreementSignedForm,
OrganisationCrownStatusForm,
OrganisationDomainsForm,
OrganisationOrganisationTypeForm,
PreviewBranding,
RenameOrganisationForm, RenameOrganisationForm,
SearchByNameForm,
SearchUsersForm, SearchUsersForm,
SetEmailBranding,
SetLetterBranding,
) )
from app.main.views.service_settings import get_branding_as_value_and_label
from app.utils import user_has_permissions, user_is_platform_admin from app.utils import user_has_permissions, user_is_platform_admin
@@ -165,8 +176,25 @@ def cancel_invited_org_user(org_id, invited_user_id):
@login_required @login_required
@user_has_permissions() @user_has_permissions()
def organisation_settings(org_id): def organisation_settings(org_id):
email_branding = 'GOV.UK'
if current_organisation['email_branding_id']:
email_branding = email_branding_client.get_email_branding(
current_organisation['email_branding_id']
)['email_branding']['name']
letter_branding = None
if current_organisation['letter_branding_id']:
letter_branding = letter_branding_client.get_letter_branding(
current_organisation['letter_branding_id']
)['name']
return render_template( return render_template(
'views/organisations/organisation/settings/index.html', 'views/organisations/organisation/settings/index.html',
email_branding=email_branding,
letter_branding=letter_branding,
) )
@@ -193,6 +221,212 @@ def edit_organisation_name(org_id):
) )
@main.route("/organisations/<org_id>/settings/edit-type", methods=['GET', 'POST'])
@login_required
@user_has_permissions()
@user_is_platform_admin
def edit_organisation_type(org_id):
form = OrganisationOrganisationTypeForm(
organisation_type=current_organisation['organisation_type']
)
if form.validate_on_submit():
organisations_client.update_organisation(
current_organisation['id'],
organisation_type=form.organisation_type.data,
)
return redirect(url_for('.organisation_settings', org_id=org_id))
return render_template(
'views/organisations/organisation/settings/edit-type.html',
form=form,
)
@main.route("/organisations/<org_id>/settings/edit-crown-status", methods=['GET', 'POST'])
@login_required
@user_has_permissions()
@user_is_platform_admin
def edit_organisation_crown_status(org_id):
form = OrganisationCrownStatusForm(
crown_status={
True: 'crown',
False: 'non-crown',
None: 'unknown',
}.get(current_organisation['crown'])
)
if form.validate_on_submit():
organisations_client.update_organisation(
current_organisation['id'],
crown={
'crown': True,
'non-crown': False,
'unknown': None,
}.get(form.crown_status.data),
)
return redirect(url_for('.organisation_settings', org_id=org_id))
return render_template(
'views/organisations/organisation/settings/edit-crown-status.html',
form=form,
)
@main.route("/organisations/<org_id>/settings/edit-agreement", methods=['GET', 'POST'])
@login_required
@user_has_permissions()
@user_is_platform_admin
def edit_organisation_agreement(org_id):
form = OrganisationAgreementSignedForm(
agreement_signed={
True: 'yes',
False: 'no',
None: 'unknown',
}.get(current_organisation['agreement_signed'])
)
if form.validate_on_submit():
organisations_client.update_organisation(
current_organisation['id'],
agreement_signed={
'yes': True,
'no': False,
'unknown': None,
}.get(form.agreement_signed.data),
)
return redirect(url_for('.organisation_settings', org_id=org_id))
return render_template(
'views/organisations/organisation/settings/edit-agreement.html',
form=form,
)
@main.route("/organisations/<org_id>/settings/set-email-branding", methods=['GET', 'POST'])
@login_required
@user_has_permissions()
@user_is_platform_admin
def edit_organisation_email_branding(org_id):
email_branding = email_branding_client.get_all_email_branding()
form = SetEmailBranding(
all_branding_options=get_branding_as_value_and_label(email_branding),
current_branding=current_organisation['email_branding_id'],
)
if form.validate_on_submit():
return redirect(url_for(
'.organisation_preview_email_branding',
org_id=org_id,
branding_style=form.branding_style.data,
))
return render_template(
'views/organisations/organisation/settings/set-email-branding.html',
form=form,
search_form=SearchByNameForm()
)
@main.route("/organisations/<org_id>/settings/preview-email-branding", methods=['GET', 'POST'])
@login_required
@user_has_permissions()
@user_is_platform_admin
def organisation_preview_email_branding(org_id):
branding_style = request.args.get('branding_style', None)
form = PreviewBranding(branding_style=branding_style)
if form.validate_on_submit():
organisations_client.update_organisation(
org_id,
email_branding_id=form.branding_style.data
)
return redirect(url_for('.organisation_settings', org_id=org_id))
return render_template(
'views/organisations/organisation/settings/preview-email-branding.html',
form=form,
action=url_for('main.organisation_preview_email_branding', org_id=org_id),
)
@main.route("/organisations/<org_id>/settings/set-letter-branding", methods=['GET', 'POST'])
@login_required
@user_is_platform_admin
def edit_organisation_letter_branding(org_id):
letter_branding = letter_branding_client.get_all_letter_branding()
form = SetLetterBranding(
all_branding_options=get_branding_as_value_and_label(letter_branding),
current_branding=current_organisation['letter_branding_id'],
)
if form.validate_on_submit():
return redirect(url_for(
'.organisation_preview_letter_branding',
org_id=org_id,
branding_style=form.branding_style.data,
))
return render_template(
'views/organisations/organisation/settings/set-letter-branding.html',
form=form,
search_form=SearchByNameForm()
)
@main.route("/organisations/<org_id>/settings/preview-letter-branding", methods=['GET', 'POST'])
@login_required
@user_is_platform_admin
def organisation_preview_letter_branding(org_id):
branding_style = request.args.get('branding_style')
form = PreviewBranding(branding_style=branding_style)
if form.validate_on_submit():
organisations_client.update_organisation(
org_id,
letter_branding_id=form.branding_style.data
)
return redirect(url_for('.organisation_settings', org_id=org_id))
return render_template(
'views/organisations/organisation/settings/preview-letter-branding.html',
form=form,
action=url_for('main.organisation_preview_letter_branding', org_id=org_id),
)
@main.route("/organisations/<org_id>/settings/edit-organisation-domains", methods=['GET', 'POST'])
@login_required
@user_has_permissions()
@user_is_platform_admin
def edit_organisation_domains(org_id):
form = OrganisationDomainsForm()
if form.validate_on_submit():
organisations_client.update_organisation(
org_id,
domains=list(filter(None, form.domains.data)),
)
return redirect(url_for('.organisation_settings', org_id=org_id))
form.populate(current_organisation.get('domains', []))
return render_template(
'views/organisations/organisation/settings/edit-domains.html',
form=form,
)
@main.route("/organisations/<org_id>/settings/edit-name/confirm", methods=['GET', 'POST']) @main.route("/organisations/<org_id>/settings/edit-name/confirm", methods=['GET', 'POST'])
@login_required @login_required
@user_has_permissions() @user_has_permissions()
+7 -7
View File
@@ -35,6 +35,7 @@ from app.main.forms import (
InternationalSMSForm, InternationalSMSForm,
LinkOrganisationsForm, LinkOrganisationsForm,
OrganisationTypeForm, OrganisationTypeForm,
PreviewBranding,
RenameServiceForm, RenameServiceForm,
SearchByNameForm, SearchByNameForm,
ServiceContactDetailsForm, ServiceContactDetailsForm,
@@ -44,12 +45,11 @@ from app.main.forms import (
ServiceInboundNumberForm, ServiceInboundNumberForm,
ServiceLetterContactBlockForm, ServiceLetterContactBlockForm,
ServiceOnOffSettingForm, ServiceOnOffSettingForm,
ServicePreviewBranding,
ServiceReplyToEmailForm, ServiceReplyToEmailForm,
ServiceSetEmailBranding,
ServiceSetLetterBranding,
ServiceSmsSenderForm, ServiceSmsSenderForm,
ServiceSwitchChannelForm, ServiceSwitchChannelForm,
SetEmailBranding,
SetLetterBranding,
SMSPrefixForm, SMSPrefixForm,
branding_options_dict, branding_options_dict,
) )
@@ -811,7 +811,7 @@ def set_free_sms_allowance(service_id):
def service_set_email_branding(service_id): def service_set_email_branding(service_id):
email_branding = email_branding_client.get_all_email_branding() email_branding = email_branding_client.get_all_email_branding()
form = ServiceSetEmailBranding( form = SetEmailBranding(
all_branding_options=get_branding_as_value_and_label(email_branding), all_branding_options=get_branding_as_value_and_label(email_branding),
current_branding=current_service.email_branding_id, current_branding=current_service.email_branding_id,
) )
@@ -836,7 +836,7 @@ def service_set_email_branding(service_id):
def service_preview_email_branding(service_id): def service_preview_email_branding(service_id):
branding_style = request.args.get('branding_style', None) branding_style = request.args.get('branding_style', None)
form = ServicePreviewBranding(branding_style=branding_style) form = PreviewBranding(branding_style=branding_style)
if form.validate_on_submit(): if form.validate_on_submit():
current_service.update( current_service.update(
@@ -858,7 +858,7 @@ def service_preview_email_branding(service_id):
def service_set_letter_branding(service_id): def service_set_letter_branding(service_id):
letter_branding = letter_branding_client.get_all_letter_branding() letter_branding = letter_branding_client.get_all_letter_branding()
form = ServiceSetLetterBranding( form = SetLetterBranding(
all_branding_options=get_branding_as_value_and_label(letter_branding), all_branding_options=get_branding_as_value_and_label(letter_branding),
current_branding=current_service.letter_branding_id, current_branding=current_service.letter_branding_id,
) )
@@ -883,7 +883,7 @@ def service_set_letter_branding(service_id):
def service_preview_letter_branding(service_id): def service_preview_letter_branding(service_id):
branding_style = request.args.get('branding_style') branding_style = request.args.get('branding_style')
form = ServicePreviewBranding(branding_style=branding_style) form = PreviewBranding(branding_style=branding_style)
if form.validate_on_submit(): if form.validate_on_submit():
current_service.update( current_service.update(
+37
View File
@@ -154,7 +154,13 @@ class HeaderNavigation(Navigation):
'download_agreement', 'download_agreement',
'download_notifications_csv', 'download_notifications_csv',
'edit_data_retention', 'edit_data_retention',
'edit_organisation_agreement',
'edit_organisation_crown_status',
'edit_organisation_domains',
'edit_organisation_email_branding',
'edit_organisation_letter_branding',
'edit_organisation_name', 'edit_organisation_name',
'edit_organisation_type',
'edit_provider', 'edit_provider',
'edit_service_template', 'edit_service_template',
'edit_template_postage', 'edit_template_postage',
@@ -194,6 +200,8 @@ class HeaderNavigation(Navigation):
'old_using_notify', 'old_using_notify',
'organisation_dashboard', 'organisation_dashboard',
'organisation_settings', 'organisation_settings',
'organisation_preview_email_branding',
'organisation_preview_letter_branding',
'privacy', 'privacy',
'public_agreement', 'public_agreement',
'public_download_agreement', 'public_download_agreement',
@@ -428,7 +436,13 @@ class MainNavigation(Navigation):
'download_agreement', 'download_agreement',
'download_notifications_csv', 'download_notifications_csv',
'edit_data_retention', 'edit_data_retention',
'edit_organisation_agreement',
'edit_organisation_crown_status',
'edit_organisation_email_branding',
'edit_organisation_domains',
'edit_organisation_letter_branding',
'edit_organisation_name', 'edit_organisation_name',
'edit_organisation_type',
'edit_provider', 'edit_provider',
'edit_user_org_permissions', 'edit_user_org_permissions',
'email_branding', 'email_branding',
@@ -462,6 +476,8 @@ class MainNavigation(Navigation):
'old_terms', 'old_terms',
'old_using_notify', 'old_using_notify',
'organisation_dashboard', 'organisation_dashboard',
'organisation_preview_email_branding',
'organisation_preview_letter_branding',
'organisation_settings', 'organisation_settings',
'organisations', 'organisations',
'platform_admin', 'platform_admin',
@@ -590,6 +606,11 @@ class CaseworkNavigation(Navigation):
'choose_service', 'choose_service',
'choose_template_to_copy', 'choose_template_to_copy',
'clear_cache', 'clear_cache',
'edit_organisation_agreement',
'edit_organisation_crown_status',
'edit_organisation_domains',
'edit_organisation_email_branding',
'edit_organisation_letter_branding',
'confirm_edit_organisation_name', 'confirm_edit_organisation_name',
'confirm_edit_user_email', 'confirm_edit_user_email',
'confirm_edit_user_mobile_number', 'confirm_edit_user_mobile_number',
@@ -613,7 +634,11 @@ class CaseworkNavigation(Navigation):
'download_agreement', 'download_agreement',
'download_notifications_csv', 'download_notifications_csv',
'edit_data_retention', 'edit_data_retention',
'edit_organisation_agreement',
'edit_organisation_crown_status',
'edit_organisation_domains',
'edit_organisation_name', 'edit_organisation_name',
'edit_organisation_type',
'edit_provider', 'edit_provider',
'edit_service_template', 'edit_service_template',
'edit_template_postage', 'edit_template_postage',
@@ -659,6 +684,8 @@ class CaseworkNavigation(Navigation):
'old_terms', 'old_terms',
'old_using_notify', 'old_using_notify',
'organisation_dashboard', 'organisation_dashboard',
'organisation_preview_email_branding',
'organisation_preview_letter_branding',
'organisation_settings', 'organisation_settings',
'organisations', 'organisations',
'platform_admin', 'platform_admin',
@@ -791,8 +818,18 @@ class OrgNavigation(Navigation):
}, },
'settings': { 'settings': {
'confirm_edit_organisation_name', 'confirm_edit_organisation_name',
'edit_organisation_agreement',
'edit_organisation_crown_status',
'edit_organisation_domains',
'edit_organisation_email_branding',
'edit_organisation_letter_branding',
'edit_organisation_domains',
'edit_organisation_name', 'edit_organisation_name',
'edit_organisation_type',
'organisation_preview_email_branding',
'organisation_preview_letter_branding',
'organisation_settings', 'organisation_settings',
}, },
'team-members': { 'team-members': {
'edit_user_org_permissions', 'edit_user_org_permissions',
@@ -15,11 +15,11 @@ class OrganisationsClient(NotifyAdminAPIClient):
} }
return self.post(url="/organisations", data=data) return self.post(url="/organisations", data=data)
def update_organisation(self, org_id, **kwargs):
return self.post(url="/organisations/{}".format(org_id), data=kwargs)
def update_organisation_name(self, org_id, name): def update_organisation_name(self, org_id, name):
data = { return self.update_organisation(org_id, name=name)
"name": name
}
return self.post(url="/organisations/{}".format(org_id), data=data)
def get_service_organisation(self, service_id): def get_service_organisation(self, service_id):
return self.get(url="/service/{}/organisation".format(service_id)) return self.get(url="/service/{}/organisation".format(service_id))
@@ -0,0 +1,28 @@
{% from "components/radios.html" import radios %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
{% extends "org_template.html" %}
{% block org_page_title %}
Data sharing and financial agreement
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Data sharing and financial agreement</h1>
<div class="grid-row">
<div class="column-five-sixths">
{% call form_wrapper() %}
{{ radios(
form.agreement_signed,
option_hints={
'yes': 'Users will be told their organisation has already signed the agreement',
'no': 'Users will be prompted to sign the agreement before they can go live',
'unknown': 'Users wont be prompted to sign the agreement'
}
) }}
{{ page_footer('Save') }}
{% endcall %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,21 @@
{% from "components/radios.html" import radios %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
{% extends "org_template.html" %}
{% block org_page_title %}
Crown organisation
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Crown organisation</h1>
<div class="grid-row">
<div class="column-five-sixths">
{% call form_wrapper() %}
{{ radios(form.crown_status) }}
{{ page_footer('Save') }}
{% endcall %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,31 @@
{% from "components/radios.html" import radios %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/list-entry.html" import list_entry %}
{% from "components/form.html" import form_wrapper %}
{% extends "org_template.html" %}
{% block org_page_title %}
Known email domains
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Known email domains</h1>
<div class="grid-row">
<div class="column-five-sixths">
<p>
If a users email addresses ends with one of these domains then
any services they create will be associated with this organisation.
</p>
{% call form_wrapper() %}
{{ list_entry(
form.domains,
item_name='domain',
autocomplete=False,
hint='For example cabinet-office.gov.uk'
) }}
{{ page_footer('Save') }}
{% endcall %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,21 @@
{% from "components/radios.html" import radios %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
{% extends "org_template.html" %}
{% block org_page_title %}
Organisation type
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Organisation type</h1>
<div class="grid-row">
<div class="column-five-sixths">
{% call form_wrapper() %}
{{ radios(form.organisation_type) }}
{{ page_footer('Save') }}
{% endcall %}
</div>
</div>
{% endblock %}
@@ -1,5 +1,5 @@
{% extends "org_template.html" %} {% extends "org_template.html" %}
{% from "components/table.html" import mapping_table, row, text_field, edit_field with context %} {% from "components/table.html" import mapping_table, optional_text_field, row, text_field, edit_field with context %}
{% block org_page_title %} {% block org_page_title %}
Organisation settings Organisation settings
@@ -24,4 +24,92 @@
}} }}
{% endcall %} {% endcall %}
{% endcall %} {% endcall %}
</div>
{% if current_user.platform_admin %}
<h2 class="heading-medium">Platform admin settings</h2>
<div class="bottom-gutter-3-2 dashboard-table body-copy-table">
{% call mapping_table(
caption='Platform admin settings',
field_headings=['Label', 'Value', 'Action'],
field_headings_visible=False,
caption_visible=False
) %}
{% call row() %}
{{ text_field('Organisation type') }}
{{ optional_text_field({
'central': 'Central government',
'local': 'Local government',
'nhs': 'NHS',
}.get(current_org.organisation_type)) }}
{{ edit_field(
'Change',
url_for('.edit_organisation_type', org_id=current_org.id)
)
}}
{% endcall %}
{% call row() %}
{{ text_field('Crown organisation') }}
{{ optional_text_field(
{
True: 'Yes',
False: 'No',
}.get(current_org.crown),
default='Not sure'
) }}
{{ edit_field(
'Change',
url_for('.edit_organisation_crown_status', org_id=current_org.id)
)
}}
{% endcall %}
{% call row() %}
{{ text_field('Data sharing and financial agreement') }}
{{ text_field(
{
True: 'Signed',
False: 'Not signed',
None: 'Not signed (but we have some service-specific agreements in place)'
}.get(current_org.agreement_signed)
) }}
{{ edit_field(
'Change',
url_for('.edit_organisation_agreement', org_id=current_org.id)
)
}}
{% endcall %}
{% call row() %}
{{ text_field('Default email branding') }}
{{ text_field(email_branding) }}
{{ edit_field(
'Change',
url_for('.edit_organisation_email_branding', org_id=current_org.id)
)
}}
{% endcall %}
{% call row() %}
{{ text_field('Default letter branding') }}
{{ optional_text_field(
letter_branding,
default='No branding'
) }}
{{ edit_field(
'Change',
url_for('.edit_organisation_letter_branding', org_id=current_org.id)
)
}}
{% endcall %}
{% call row() %}
{{ text_field('Known email domains') }}
{{ optional_text_field(current_org.domains or None, default='None') }}
{{ edit_field(
'Change',
url_for('.edit_organisation_domains', org_id=current_org.id)
)
}}
{% endcall %}
{% endcall %}
</div>
{% endif %}
{% endblock %} {% endblock %}
@@ -0,0 +1,23 @@
{% extends "org_template.html" %}
{% from "components/form.html" import form_wrapper %}
{% block org_page_title %}
Preview email branding
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Preview email branding</h1>
<div class="grid-row">
<div class="column-full">
<iframe src="{{ url_for('main.email_template', branding_style=form.branding_style.data) }}" class="branding-preview"></iframe>
{% call form_wrapper(action=action) %}
<div class="form-group">
{{ form.hidden_tag() }}
<div class="page-footer">
<button type="submit" class="button">Save</button>
</div>
</div>
{% endcall %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,22 @@
{% extends "org_template.html" %}
{% from "components/form.html" import form_wrapper %}
{% from "components/page-footer.html" import page_footer %}
{% block per_page_title %}
Preview letter branding
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Preview letter branding</h1>
<div class="grid-row">
<div class="column-full">
<iframe src="{{ url_for('main.letter_template', branding_style=form.branding_style.data) }}" class="branding-preview"></iframe>
{% call form_wrapper(action=action) %}
<div class="form-group">
{{ form.hidden_tag() }}
{{ page_footer('Save') }}
</div>
{% endcall %}
</div>
</div>
{% endblock %}
@@ -0,0 +1,30 @@
{% extends "org_template.html" %}
{% from "components/radios.html" import radios %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/live-search.html" import live_search %}
{% from "components/form.html" import form_wrapper %}
{% block org_page_title %}
Default email branding
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Default email branding</h1>
{% call form_wrapper(data_kwargs={'preview-type': 'email'}) %}
<div class="grid-row">
<div class="column-full preview-pane">
</div>
</div>
<div class="grid-row">
<div class="column-full">
{{ live_search(target_selector='.multiple-choice', show=True, form=search_form, label='Search branding styles by name') }}
{{ radios(form.branding_style) }}
</div>
</div>
<div class="js-stick-at-bottom-when-scrolling">
{{ page_footer('Preview') }}
</div>
{% endcall %}
{% endblock %}
@@ -0,0 +1,30 @@
{% extends "org_template.html" %}
{% from "components/radios.html" import radios %}
{% from "components/live-search.html" import live_search %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/form.html" import form_wrapper %}
{% block org_page_title %}
Default letter branding
{% endblock %}
{% block maincolumn_content %}
<h1 class="heading-large">Default letter branding</h1>
{% call form_wrapper(data_kwargs={'preview-type': 'letter'}) %}
<div class="grid-row">
<div class="column-full preview-pane">
</div>
</div>
<div class="grid-row">
<div class="column-full">
{{ live_search(target_selector='.multiple-choice', show=True, form=search_form, label='Search by name') }}
{{ radios(form.branding_style, hide_legend=True) }}
</div>
</div>
<div class="js-stick-at-bottom-when-scrolling">
{{ page_footer('Preview') }}
</div>
{% endcall %}
{% endblock %}
@@ -1,10 +1,10 @@
{% extends "views/platform-admin/_base_template.html" %} {% extends "withnav_template.html" %}
{% from "components/form.html" import form_wrapper %} {% from "components/form.html" import form_wrapper %}
{% block service_page_title %} {% block service_page_title %}
Preview email branding Preview email branding
{% endblock %} {% endblock %}
{% block platform_admin_content %} {% block maincolumn_content %}
<h1 class="heading-large">Preview email branding</h1> <h1 class="heading-large">Preview email branding</h1>
<div class="grid-row"> <div class="grid-row">
@@ -15,7 +15,6 @@
{{ form.hidden_tag() }} {{ form.hidden_tag() }}
<div class="page-footer"> <div class="page-footer">
<button type="submit" class="button">Save</button> <button type="submit" class="button">Save</button>
<a class="page-footer-back-link" href="{{ url_for('main.service_settings', service_id=service_id) }}">Back to service settings</a>
</div> </div>
</div> </div>
{% endcall %} {% endcall %}
+13 -2
View File
@@ -186,7 +186,10 @@ def organisation_json(
users=None, users=None,
active=True, active=True,
created_at=None, created_at=None,
services=None services=None,
letter_branding_id=None,
email_branding_id=None,
domains=None,
): ):
if users is None: if users is None:
users = [] users = []
@@ -198,7 +201,15 @@ def organisation_json(
'active': active, 'active': active,
'users': users, 'users': users,
'services': services, 'services': services,
'created_at': created_at or str(datetime.utcnow()) 'created_at': created_at or str(datetime.utcnow()),
'email_branding_id': email_branding_id,
'letter_branding_id': letter_branding_id,
'organisation_type': '',
'crown': True,
'agreement_signed': False,
'agreement_signed_at': None,
'agreement_signed_by': None,
'domains': domains or [],
} }
@@ -7,7 +7,13 @@ from flask import url_for
from notifications_python_client.errors import HTTPError from notifications_python_client.errors import HTTPError
from app.models.user import InvitedOrgUser from app.models.user import InvitedOrgUser
from tests.conftest import ORGANISATION_ID, normalize_spaces from tests import organisation_json
from tests.conftest import (
ORGANISATION_ID,
active_user_with_permissions,
normalize_spaces,
platform_admin_user,
)
def test_organisation_page_shows_all_organisations( def test_organisation_page_shows_all_organisations(
@@ -467,6 +473,26 @@ def test_verified_org_user_redirects_to_dashboard(
def test_organisation_settings( def test_organisation_settings(
client_request,
mock_get_organisation,
organisation_one
):
expected_rows = [
'Label Value Action',
'Organisation name Org 1 Change',
]
page = client_request.get('.organisation_settings', org_id=organisation_one['id'])
assert page.find('h1').text == 'Organisation 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())
mock_get_organisation.assert_called_with(organisation_one['id'])
def test_organisation_settings_for_platform_admin(
logged_in_platform_admin_client, logged_in_platform_admin_client,
mock_get_organisation, mock_get_organisation,
organisation_one organisation_one
@@ -474,6 +500,14 @@ def test_organisation_settings(
expected_rows = [ expected_rows = [
'Label Value Action', 'Label Value Action',
'Organisation name Org 1 Change', 'Organisation name Org 1 Change',
'Label Value Action',
'Organisation type Not set Change',
'Crown organisation Yes Change',
'Data sharing and financial agreement Signed Change',
'Default email branding Not set Change',
'Default letter branding Not set Change',
'Known email domains None Change',
] ]
response = logged_in_platform_admin_client.get(url_for('.organisation_settings', org_id=organisation_one['id'])) response = logged_in_platform_admin_client.get(url_for('.organisation_settings', org_id=organisation_one['id']))
@@ -489,6 +523,277 @@ def test_organisation_settings(
mock_get_organisation.assert_called_with(organisation_one['id']) mock_get_organisation.assert_called_with(organisation_one['id'])
@pytest.mark.parametrize('endpoint, expected_options, expected_selected', (
(
'.edit_organisation_type',
(
('central', 'Central government'),
('local', 'Local government'),
('nhs', 'NHS'),
),
None,
),
(
'.edit_organisation_crown_status',
(
('crown', 'Yes'),
('non-crown', 'No'),
('unknown', 'Not sure'),
),
'crown',
),
(
'.edit_organisation_agreement',
(
('yes', (
'Yes '
'Users will be told their organisation has already signed the agreement'
)),
('no', (
'No '
'Users will be prompted to sign the agreement before they can go live'
)),
('unknown', (
'No (but we have some service-specific agreements in place) '
'Users wont be prompted to sign the agreement'
)),
),
'no',
),
))
@pytest.mark.parametrize('user', (
pytest.param(
platform_admin_user,
),
pytest.param(
active_user_with_permissions,
marks=pytest.mark.xfail
),
))
def test_view_organisation_settings(
client_request,
fake_uuid,
organisation_one,
mock_get_organisation,
endpoint,
expected_options,
expected_selected,
user,
):
client_request.login(user(fake_uuid))
page = client_request.get(endpoint, org_id=organisation_one['id'])
radios = page.select('input[type=radio]')
for index, option in enumerate(expected_options):
label = page.select_one('label[for={}]'.format(radios[index]['id']))
assert (
radios[index]['value'],
normalize_spaces(label.text),
) == option
if expected_selected:
assert page.select_one('input[checked]')['value'] == expected_selected
else:
assert not page.select_one('input[checked]')
@pytest.mark.parametrize('endpoint, post_data, expected_persisted', (
(
'.edit_organisation_type',
{'organisation_type': 'central'},
{'organisation_type': 'central'},
),
(
'.edit_organisation_type',
{'organisation_type': 'local'},
{'organisation_type': 'local'},
),
(
'.edit_organisation_type',
{'organisation_type': 'nhs'},
{'organisation_type': 'nhs'},
),
(
'.edit_organisation_crown_status',
{'crown_status': 'crown'},
{'crown': True},
),
(
'.edit_organisation_crown_status',
{'crown_status': 'non-crown'},
{'crown': False},
),
(
'.edit_organisation_crown_status',
{'crown_status': 'unknown'},
{'crown': None},
),
(
'.edit_organisation_agreement',
{'agreement_signed': 'yes'},
{'agreement_signed': True},
),
(
'.edit_organisation_agreement',
{'agreement_signed': 'no'},
{'agreement_signed': False},
),
(
'.edit_organisation_agreement',
{'agreement_signed': 'unknown'},
{'agreement_signed': None},
),
))
@pytest.mark.parametrize('user', (
pytest.param(
platform_admin_user,
),
pytest.param(
active_user_with_permissions,
marks=pytest.mark.xfail
),
))
def test_update_organisation_settings(
client_request,
fake_uuid,
organisation_one,
mock_get_organisation,
mock_update_organisation,
endpoint,
post_data,
expected_persisted,
user,
):
client_request.login(user(fake_uuid))
client_request.post(
endpoint,
org_id=organisation_one['id'],
_data=post_data,
_expected_status=302,
_expected_redirect=url_for(
'main.organisation_settings',
org_id=organisation_one['id'],
_external=True,
),
)
mock_update_organisation.assert_called_once_with(
organisation_one['id'],
**expected_persisted,
)
@pytest.mark.parametrize('user', (
pytest.param(
platform_admin_user,
),
pytest.param(
active_user_with_permissions,
marks=pytest.mark.xfail
),
))
def test_view_organisation_domains(
mocker,
client_request,
fake_uuid,
user,
):
client_request.login(user(fake_uuid))
mocker.patch(
'app.organisations_client.get_organisation',
side_effect=lambda org_id: organisation_json(
org_id,
'Org 1',
domains=['example.gov.uk', 'test.example.gov.uk'],
)
)
page = client_request.get(
'main.edit_organisation_domains',
org_id=ORGANISATION_ID,
)
assert [textbox['value'] for textbox in page.select('input[type=text]')] == [
'example.gov.uk',
'test.example.gov.uk',
'',
'',
'',
'',
'',
'',
'',
'',
]
@pytest.mark.parametrize('post_data, expected_persisted', (
(
{
'domains-0': 'example.gov.uk',
'domains-5': 'test.gov.uk',
},
{
'domains': [
'example.gov.uk',
'test.gov.uk',
]
}
),
(
{
'domains-0': '',
'domains-1': '',
'domains-2': '',
},
{
'domains': []
}
),
))
@pytest.mark.parametrize('user', (
pytest.param(
platform_admin_user,
),
pytest.param(
active_user_with_permissions,
marks=pytest.mark.xfail
),
))
def test_update_organisation_domains(
client_request,
fake_uuid,
organisation_one,
mock_get_organisation,
mock_update_organisation,
post_data,
expected_persisted,
user,
):
client_request.login(user(fake_uuid))
client_request.post(
'main.edit_organisation_domains',
org_id=ORGANISATION_ID,
_data=post_data,
_expected_status=302,
_expected_redirect=url_for(
'main.organisation_settings',
org_id=organisation_one['id'],
_external=True,
),
)
mock_update_organisation.assert_called_once_with(
ORGANISATION_ID,
**expected_persisted,
)
def test_update_organisation_name( def test_update_organisation_name(
logged_in_platform_admin_client, logged_in_platform_admin_client,
organisation_one, organisation_one,
@@ -553,7 +858,7 @@ def test_confirm_update_organisation(
organisation_one, organisation_one,
mock_get_organisation, mock_get_organisation,
mock_verify_password, mock_verify_password,
mock_update_organisation_name, mock_update_organisation,
mocker mocker
): ):
with logged_in_platform_admin_client.session_transaction() as session: with logged_in_platform_admin_client.session_transaction() as session:
@@ -570,7 +875,7 @@ def test_confirm_update_organisation(
assert response.status_code == 302 assert response.status_code == 302
assert response.location == url_for('.organisation_settings', org_id=organisation_one['id'], _external=True) assert response.location == url_for('.organisation_settings', org_id=organisation_one['id'], _external=True)
mock_update_organisation_name.assert_called_with( mock_update_organisation.assert_called_with(
organisation_one['id'], organisation_one['id'],
name=session['organisation_name_change'] name=session['organisation_name_change']
) )
+262 -74
View File
@@ -11,8 +11,14 @@ from notifications_utils.clients.zendesk.zendesk_client import ZendeskClient
import app import app
from app.utils import email_safe from app.utils import email_safe
from tests import sample_uuid, service_json, validate_route_permission from tests import (
organisation_json,
sample_uuid,
service_json,
validate_route_permission,
)
from tests.conftest import ( from tests.conftest import (
ORGANISATION_ID,
SERVICE_ONE_ID, SERVICE_ONE_ID,
active_user_no_api_key_permission, active_user_no_api_key_permission,
active_user_no_settings_permission, active_user_no_settings_permission,
@@ -2415,20 +2421,44 @@ def test_service_set_letter_branding_platform_admin_only(
(str(UUID(int=1)), 'Land Registry'), (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( def test_service_set_letter_branding_prepopulates(
logged_in_platform_admin_client, mocker,
client_request,
platform_admin_user,
service_one, service_one,
mock_get_organisation,
mock_get_all_letter_branding, mock_get_all_letter_branding,
letter_branding, letter_branding,
expected_selected, expected_selected,
expected_items, expected_items,
endpoint,
extra_args,
): ):
service_one['letter_branding'] = letter_branding service_one['letter_branding'] = letter_branding
response = logged_in_platform_admin_client.get( mocker.patch(
url_for('main.service_set_letter_branding', service_id=service_one['id']) '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 response.status_code == 200
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
assert len(page.select('input[checked]')) == 1 assert len(page.select('input[checked]')) == 1
assert page.select('input[checked]')[0]['value'] == expected_selected assert page.select('input[checked]')[0]['value'] == expected_selected
@@ -2446,36 +2476,70 @@ def test_service_set_letter_branding_prepopulates(
(str(UUID(int=1)), str(UUID(int=1))), (str(UUID(int=1)), str(UUID(int=1))),
('__NONE__', None), ('__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( def test_service_set_letter_branding_redirects_to_preview_page_when_form_submitted(
logged_in_platform_admin_client, client_request,
service_one, platform_admin_user,
mock_get_organisation,
mock_get_all_letter_branding, mock_get_all_letter_branding,
selected_letter_branding, selected_letter_branding,
expected_post_data expected_post_data,
endpoint,
extra_args,
expected_redirect,
): ):
response = logged_in_platform_admin_client.post( client_request.login(platform_admin_user)
url_for('main.service_set_letter_branding', service_id=service_one['id']), client_request.post(
data={'branding_style': selected_letter_branding}, 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
) )
assert response.status_code == 302
assert response.location == url_for(
@pytest.mark.parametrize('endpoint, extra_args', (
(
'main.service_preview_letter_branding', 'main.service_preview_letter_branding',
service_id=service_one['id'], {'service_id': SERVICE_ONE_ID},
branding_style=expected_post_data, ),
_external=True) (
'main.organisation_preview_letter_branding',
{'org_id': ORGANISATION_ID},
),
))
def test_service_preview_letter_branding_shows_preview_letter( def test_service_preview_letter_branding_shows_preview_letter(
logged_in_platform_admin_client, client_request,
service_one, platform_admin_user,
mock_get_organisation,
mock_get_all_letter_branding, mock_get_all_letter_branding,
endpoint,
extra_args,
): ):
response = logged_in_platform_admin_client.get( client_request.login(platform_admin_user)
url_for('main.service_preview_letter_branding', service_id=service_one['id'], branding_style='hm-government')
page = client_request.get(
endpoint,
branding_style='hm-government',
**extra_args
) )
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
assert response.status_code == 200
assert page.find('iframe')['src'] == url_for('main.letter_template', branding_style='hm-government') assert page.find('iframe')['src'] == url_for('main.letter_template', branding_style='hm-government')
@@ -2483,21 +2547,60 @@ def test_service_preview_letter_branding_shows_preview_letter(
(str(UUID(int=1)), str(UUID(int=1))), (str(UUID(int=1)), str(UUID(int=1))),
('__NONE__', None), ('__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( def test_service_preview_letter_branding_saves(
logged_in_platform_admin_client, client_request,
service_one, platform_admin_user,
mock_get_organisation,
mock_update_service, mock_update_service,
mock_update_organisation,
mock_get_all_letter_branding, mock_get_all_letter_branding,
selected_letter_branding, selected_letter_branding,
expected_post_data expected_post_data,
endpoint,
extra_args,
expected_redirect,
): ):
response = logged_in_platform_admin_client.post( client_request.login(platform_admin_user)
url_for('main.service_preview_letter_branding', service_id=service_one['id']), client_request.post(
data={'branding_style': selected_letter_branding} endpoint,
_data={'branding_style': selected_letter_branding},
_expected_status=302,
_expected_redirect=url_for(
expected_redirect,
_external=True,
**extra_args
),
**extra_args
) )
assert response.status_code == 302
assert response.location == url_for('main.service_settings', service_id=service_one['id'], _external=True) if endpoint == 'main.service_preview_letter_branding':
mock_update_service.assert_called_once_with(service_one['id'], letter_branding=expected_post_data) 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,
)
assert mock_update_service.called is False
else:
raise Exception
@pytest.mark.parametrize('current_branding, expected_values, expected_labels', [ @pytest.mark.parametrize('current_branding, expected_values, expected_labels', [
@@ -2512,20 +2615,41 @@ def test_service_preview_letter_branding_saves(
'org 5', 'GOV.UK', 'org 1', 'org 2', 'org 3', 'org 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( def test_should_show_branding_styles(
logged_in_platform_admin_client, mocker,
client_request,
platform_admin_user,
service_one, service_one,
mock_get_all_email_branding, mock_get_all_email_branding,
current_branding, current_branding,
expected_values, expected_values,
expected_labels, expected_labels,
endpoint,
extra_args,
): ):
service_one['email_branding'] = current_branding service_one['email_branding'] = current_branding
response = logged_in_platform_admin_client.get(url_for( mocker.patch(
'main.service_set_email_branding', service_id=service_one['id'] 'app.organisations_client.get_organisation',
)) side_effect=lambda org_id: organisation_json(
assert response.status_code == 200 org_id,
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') '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"}) branding_style_choices = page.find_all('input', attrs={"name": "branding_style"})
radio_labels = [ radio_labels = [
@@ -2551,39 +2675,74 @@ def test_should_show_branding_styles(
app.service_api_client.get_service.assert_called_once_with(service_one['id']) 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( def test_should_send_branding_and_organisations_to_preview(
logged_in_platform_admin_client, client_request,
platform_admin_user,
service_one, service_one,
mock_get_organisation,
mock_get_all_email_branding, mock_get_all_email_branding,
mock_update_service, mock_update_service,
endpoint,
extra_args,
expected_redirect,
): ):
response = logged_in_platform_admin_client.post( client_request.login(platform_admin_user)
url_for( client_request.post(
'main.service_set_email_branding', service_id=service_one['id'] endpoint,
),
data={ data={
'branding_type': 'org', 'branding_type': 'org',
'branding_style': '1' 'branding_style': '1'
} },
_expected_status=302,
_expected_location=url_for(
expected_redirect,
branding_style='1',
_external=True,
**extra_args
),
**extra_args
) )
assert response.status_code == 302
assert response.location == url_for('main.service_preview_email_branding',
service_id=service_one['id'], branding_style='1',
_external=True)
mock_get_all_email_branding.assert_called_once_with() 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( def test_should_preview_email_branding(
logged_in_platform_admin_client, client_request,
service_one, platform_admin_user,
mock_get_organisation,
endpoint,
extra_args,
): ):
response = logged_in_platform_admin_client.get(url_for( client_request.login(platform_admin_user)
'main.service_preview_email_branding', service_id=service_one['id'], page = client_request.get(
branding_type='org', branding_style='1' endpoint,
)) branding_type='org',
assert response.status_code == 200 branding_style='1',
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') **extra_args
)
iframe = page.find('iframe', attrs={"class": "branding-preview"}) iframe = page.find('iframe', attrs={"class": "branding-preview"})
iframeURLComponents = urlparse(iframe['src']) iframeURLComponents = urlparse(iframe['src'])
iframeQString = parse_qs(iframeURLComponents.query) iframeQString = parse_qs(iframeURLComponents.query)
@@ -2592,37 +2751,66 @@ def test_should_preview_email_branding(
assert iframeURLComponents.path == '/_email' assert iframeURLComponents.path == '/_email'
assert iframeQString['branding_style'] == ['1'] assert iframeQString['branding_style'] == ['1']
app.service_api_client.get_service.assert_called_once_with(service_one['id'])
@pytest.mark.parametrize('posted_value, submitted_value', ( @pytest.mark.parametrize('posted_value, submitted_value', (
('1', '1'), ('1', '1'),
('__NONE__', None), ('__NONE__', None),
pytest.param('None', None, marks=pytest.mark.xfail(raises=AssertionError)), 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( def test_should_set_branding_and_organisations(
logged_in_platform_admin_client, client_request,
platform_admin_user,
service_one, service_one,
mock_get_organisation,
mock_update_service, mock_update_service,
mock_update_organisation,
posted_value, posted_value,
submitted_value, submitted_value,
endpoint,
extra_args,
expected_redirect,
): ):
response = logged_in_platform_admin_client.post( client_request.login(platform_admin_user)
url_for( client_request.post(
'main.service_preview_email_branding', service_id=service_one['id'] endpoint,
), _data={
data={
'branding_style': posted_value 'branding_style': posted_value
} },
_expected_status=302,
_expected_redirect=url_for(
expected_redirect,
_external=True,
**extra_args
),
**extra_args
) )
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( if endpoint == 'main.service_preview_email_branding':
service_one['id'], mock_update_service.assert_called_once_with(
email_branding=submitted_value 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
)
assert mock_update_service.called is False
else:
raise Exception
@pytest.mark.parametrize('method', ['get', 'post']) @pytest.mark.parametrize('method', ['get', 'post'])
+23 -26
View File
@@ -3100,34 +3100,27 @@ def organisation_one(api_user_active):
def mock_get_organisations(mocker): def mock_get_organisations(mocker):
def _get_organisations(): def _get_organisations():
return [ return [
{ organisation_json('7aa5d4e9-4385-4488-a489-07812ba13383', 'Org 1'),
'name': 'Org 1', organisation_json('7aa5d4e9-4385-4488-a489-07812ba13384', 'Org 2'),
'id': '7aa5d4e9-4385-4488-a489-07812ba13383', organisation_json('7aa5d4e9-4385-4488-a489-07812ba13385', 'Org 3'),
'active': True
},
{
'name': 'Org 2',
'id': '7aa5d4e9-4385-4488-a489-07812ba13384',
'active': True
},
{
'name': 'Org 3',
'id': '7aa5d4e9-4385-4488-a489-07812ba13385',
'active': True
}
] ]
return mocker.patch('app.organisations_client.get_organisations', side_effect=_get_organisations) return mocker.patch('app.organisations_client.get_organisations', side_effect=_get_organisations)
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def mock_get_organisation(mocker): def mock_get_organisation(
mocker,
email_branding_id=None,
letter_branding_id=None,
):
def _get_organisation(org_id): def _get_organisation(org_id):
return { return organisation_json(
'name': 'Org 1', org_id,
'id': org_id, 'Org 1',
'active': True email_branding_id=email_branding_id,
} letter_branding_id=letter_branding_id,
)
return mocker.patch('app.organisations_client.get_organisation', side_effect=_get_organisation) return mocker.patch('app.organisations_client.get_organisation', side_effect=_get_organisation)
@@ -3135,11 +3128,7 @@ def mock_get_organisation(mocker):
@pytest.fixture(scope='function') @pytest.fixture(scope='function')
def mock_get_service_organisation(mocker): def mock_get_service_organisation(mocker):
def _get_service_organisation(service_id): def _get_service_organisation(service_id):
return { return organisation_json('7aa5d4e9-4385-4488-a489-07812ba13383', 'Org 1')
'name': 'Org 1',
'id': '7aa5d4e9-4385-4488-a489-07812ba13383',
'active': True
}
return mocker.patch('app.organisations_client.get_service_organisation', side_effect=_get_service_organisation) return mocker.patch('app.organisations_client.get_service_organisation', side_effect=_get_service_organisation)
@@ -3269,6 +3258,14 @@ def mock_update_organisation_name(mocker):
return mocker.patch('app.organisations_client.update_organisation_name', side_effect=_update_org_name) return mocker.patch('app.organisations_client.update_organisation_name', side_effect=_update_org_name)
@pytest.fixture(scope='function')
def mock_update_organisation(mocker):
def _update_org(organisation_id, **kwargs):
return
return mocker.patch('app.organisations_client.update_organisation', side_effect=_update_org)
@pytest.fixture @pytest.fixture
def mock_get_organisations_and_services_for_user(mocker, organisation_one, api_user_active): def mock_get_organisations_and_services_for_user(mocker, organisation_one, api_user_active):
def _get_orgs_and_services(user_id): def _get_orgs_and_services(user_id):