mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 16:24:08 -04:00
Merge pull request #2987 from alphagov/org-trial-services
move trial mode services from org dashboard to separate page
This commit is contained in:
@@ -46,6 +46,7 @@ from app.extensions import (
|
|||||||
statsd_client,
|
statsd_client,
|
||||||
zendesk_client,
|
zendesk_client,
|
||||||
)
|
)
|
||||||
|
from app.models.organisation import Organisation
|
||||||
from app.models.service import Service
|
from app.models.service import Service
|
||||||
from app.models.user import AnonymousUser
|
from app.models.user import AnonymousUser
|
||||||
from app.navigation import (
|
from app.navigation import (
|
||||||
@@ -502,7 +503,7 @@ def load_organisation_before_request():
|
|||||||
|
|
||||||
if org_id:
|
if org_id:
|
||||||
try:
|
try:
|
||||||
_request_ctx_stack.top.organisation = organisations_client.get_organisation(org_id)
|
_request_ctx_stack.top.organisation = Organisation.from_id(org_id)
|
||||||
except HTTPError as exc:
|
except HTTPError as exc:
|
||||||
# if org id isn't real, then 404 rather than 500ing later because we expect org to be set
|
# if org id isn't real, then 404 rather than 500ing later because we expect org to be set
|
||||||
if exc.status_code == 404:
|
if exc.status_code == 404:
|
||||||
|
|||||||
@@ -70,14 +70,24 @@ def add_organisation():
|
|||||||
@login_required
|
@login_required
|
||||||
@user_has_permissions()
|
@user_has_permissions()
|
||||||
def organisation_dashboard(org_id):
|
def organisation_dashboard(org_id):
|
||||||
organisation_services = organisations_client.get_organisation_services(org_id)
|
for service in current_organisation.live_services:
|
||||||
for service in organisation_services:
|
|
||||||
has_permission = current_user.has_permission_for_service(service['id'], 'view_activity')
|
has_permission = current_user.has_permission_for_service(service['id'], 'view_activity')
|
||||||
service.update({'has_permission_to_view': has_permission})
|
service.update({'has_permission_to_view': has_permission})
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'views/organisations/organisation/index.html',
|
'views/organisations/organisation/index.html',
|
||||||
organisation_services=organisation_services
|
organisation_services=current_organisation.live_services
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/organisations/<org_id>/trial-services", methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@user_is_platform_admin
|
||||||
|
def organisation_trial_mode_services(org_id):
|
||||||
|
return render_template(
|
||||||
|
'views/organisations/organisation/trial-mode-services.html',
|
||||||
|
search_form=SearchByNameForm(),
|
||||||
|
services=current_organisation.trial_services
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -85,18 +95,10 @@ def organisation_dashboard(org_id):
|
|||||||
@login_required
|
@login_required
|
||||||
@user_has_permissions()
|
@user_has_permissions()
|
||||||
def manage_org_users(org_id):
|
def manage_org_users(org_id):
|
||||||
users = sorted(
|
|
||||||
user_api_client.get_users_for_organisation(org_id=org_id) + [
|
|
||||||
invite for invite in org_invite_api_client.get_invites_for_organisation(org_id=org_id)
|
|
||||||
if invite.status != 'accepted'
|
|
||||||
],
|
|
||||||
key=lambda user: user.email_address,
|
|
||||||
)
|
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'views/organisations/organisation/users/index.html',
|
'views/organisations/organisation/users/index.html',
|
||||||
users=users,
|
users=current_organisation.team_members,
|
||||||
show_search_box=(len(users) > 7),
|
show_search_box=(len(current_organisation.team_members) > 7),
|
||||||
form=SearchUsersForm(),
|
form=SearchUsersForm(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -183,16 +185,16 @@ def organisation_settings(org_id):
|
|||||||
|
|
||||||
email_branding = 'GOV.UK'
|
email_branding = 'GOV.UK'
|
||||||
|
|
||||||
if current_organisation['email_branding_id']:
|
if current_organisation.email_branding_id:
|
||||||
email_branding = email_branding_client.get_email_branding(
|
email_branding = email_branding_client.get_email_branding(
|
||||||
current_organisation['email_branding_id']
|
current_organisation.email_branding_id
|
||||||
)['email_branding']['name']
|
)['email_branding']['name']
|
||||||
|
|
||||||
letter_branding = None
|
letter_branding = None
|
||||||
|
|
||||||
if current_organisation['letter_branding_id']:
|
if current_organisation.letter_branding_id:
|
||||||
letter_branding = letter_branding_client.get_letter_branding(
|
letter_branding = letter_branding_client.get_letter_branding(
|
||||||
current_organisation['letter_branding_id']
|
current_organisation.letter_branding_id
|
||||||
)['name']
|
)['name']
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
@@ -209,7 +211,7 @@ def edit_organisation_name(org_id):
|
|||||||
form = RenameOrganisationForm()
|
form = RenameOrganisationForm()
|
||||||
|
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
form.name.data = current_organisation.get('name')
|
form.name.data = current_organisation.name
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
unique_name = organisations_client.is_organisation_name_unique(org_id, form.name.data)
|
unique_name = organisations_client.is_organisation_name_unique(org_id, form.name.data)
|
||||||
@@ -232,12 +234,12 @@ def edit_organisation_name(org_id):
|
|||||||
def edit_organisation_type(org_id):
|
def edit_organisation_type(org_id):
|
||||||
|
|
||||||
form = OrganisationOrganisationTypeForm(
|
form = OrganisationOrganisationTypeForm(
|
||||||
organisation_type=current_organisation['organisation_type']
|
organisation_type=current_organisation.organisation_type
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
organisations_client.update_organisation(
|
organisations_client.update_organisation(
|
||||||
current_organisation['id'],
|
current_organisation.id,
|
||||||
organisation_type=form.organisation_type.data,
|
organisation_type=form.organisation_type.data,
|
||||||
)
|
)
|
||||||
return redirect(url_for('.organisation_settings', org_id=org_id))
|
return redirect(url_for('.organisation_settings', org_id=org_id))
|
||||||
@@ -259,12 +261,12 @@ def edit_organisation_crown_status(org_id):
|
|||||||
True: 'crown',
|
True: 'crown',
|
||||||
False: 'non-crown',
|
False: 'non-crown',
|
||||||
None: 'unknown',
|
None: 'unknown',
|
||||||
}.get(current_organisation['crown'])
|
}.get(current_organisation.crown)
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
organisations_client.update_organisation(
|
organisations_client.update_organisation(
|
||||||
current_organisation['id'],
|
current_organisation.id,
|
||||||
crown={
|
crown={
|
||||||
'crown': True,
|
'crown': True,
|
||||||
'non-crown': False,
|
'non-crown': False,
|
||||||
@@ -290,12 +292,12 @@ def edit_organisation_agreement(org_id):
|
|||||||
True: 'yes',
|
True: 'yes',
|
||||||
False: 'no',
|
False: 'no',
|
||||||
None: 'unknown',
|
None: 'unknown',
|
||||||
}.get(current_organisation['agreement_signed'])
|
}.get(current_organisation.agreement_signed)
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
organisations_client.update_organisation(
|
organisations_client.update_organisation(
|
||||||
current_organisation['id'],
|
current_organisation.id,
|
||||||
agreement_signed={
|
agreement_signed={
|
||||||
'yes': True,
|
'yes': True,
|
||||||
'no': False,
|
'no': False,
|
||||||
@@ -320,7 +322,7 @@ def edit_organisation_email_branding(org_id):
|
|||||||
|
|
||||||
form = SetEmailBranding(
|
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_organisation['email_branding_id'],
|
current_branding=current_organisation.email_branding_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
@@ -369,7 +371,7 @@ def edit_organisation_letter_branding(org_id):
|
|||||||
|
|
||||||
form = SetLetterBranding(
|
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_organisation['letter_branding_id'],
|
current_branding=current_organisation.letter_branding_id,
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
@@ -426,7 +428,7 @@ def edit_organisation_domains(org_id):
|
|||||||
)
|
)
|
||||||
return redirect(url_for('.organisation_settings', org_id=org_id))
|
return redirect(url_for('.organisation_settings', org_id=org_id))
|
||||||
|
|
||||||
form.populate(current_organisation.get('domains', []))
|
form.populate(current_organisation.domains)
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'views/organisations/organisation/settings/edit-domains.html',
|
'views/organisations/organisation/settings/edit-domains.html',
|
||||||
@@ -447,7 +449,7 @@ def confirm_edit_organisation_name(org_id):
|
|||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
try:
|
try:
|
||||||
organisations_client.update_organisation_name(
|
organisations_client.update_organisation_name(
|
||||||
current_organisation['id'],
|
current_organisation.id,
|
||||||
name=session['organisation_name_change'],
|
name=session['organisation_name_change'],
|
||||||
)
|
)
|
||||||
except HTTPError as e:
|
except HTTPError as e:
|
||||||
|
|||||||
@@ -1018,16 +1018,16 @@ def request_letter_branding(service_id):
|
|||||||
@user_is_platform_admin
|
@user_is_platform_admin
|
||||||
def link_service_to_organisation(service_id):
|
def link_service_to_organisation(service_id):
|
||||||
|
|
||||||
organisations = organisations_client.get_organisations()
|
all_organisations = organisations_client.get_organisations()
|
||||||
current_organisation = organisations_client.get_service_organisation(service_id).get('id', None)
|
current_linked_organisation = organisations_client.get_service_organisation(service_id).get('id', None)
|
||||||
|
|
||||||
form = LinkOrganisationsForm(
|
form = LinkOrganisationsForm(
|
||||||
choices=convert_dictionary_to_wtforms_choices_format(organisations, 'id', 'name'),
|
choices=convert_dictionary_to_wtforms_choices_format(all_organisations, 'id', 'name'),
|
||||||
organisations=current_organisation
|
organisations=current_linked_organisation
|
||||||
)
|
)
|
||||||
|
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
if form.organisations.data != current_organisation:
|
if form.organisations.data != current_linked_organisation:
|
||||||
organisations_client.update_service_organisation(
|
organisations_client.update_service_organisation(
|
||||||
service_id,
|
service_id,
|
||||||
form.organisations.data
|
form.organisations.data
|
||||||
@@ -1036,7 +1036,7 @@ def link_service_to_organisation(service_id):
|
|||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'views/service-settings/link-service-to-organisation.html',
|
'views/service-settings/link-service-to-organisation.html',
|
||||||
has_organisations=organisations,
|
has_organisations=all_organisations,
|
||||||
form=form,
|
form=form,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
from flask import Markup, abort
|
from flask import Markup, abort
|
||||||
|
from werkzeug.utils import cached_property
|
||||||
|
|
||||||
from app.models import JSONModel
|
from app.models import JSONModel
|
||||||
|
from app.notify_client.organisations_api_client import organisations_client
|
||||||
|
|
||||||
|
|
||||||
class Organisation(JSONModel):
|
class Organisation(JSONModel):
|
||||||
@@ -21,6 +23,10 @@ class Organisation(JSONModel):
|
|||||||
'request_to_go_live_notes',
|
'request_to_go_live_notes',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_id(cls, org_id):
|
||||||
|
return cls(organisations_client.get_organisation(org_id))
|
||||||
|
|
||||||
def __init__(self, _dict):
|
def __init__(self, _dict):
|
||||||
|
|
||||||
super().__init__(_dict)
|
super().__init__(_dict)
|
||||||
@@ -111,3 +117,34 @@ class Organisation(JSONModel):
|
|||||||
if self.crown is None:
|
if self.crown is None:
|
||||||
abort(404)
|
abort(404)
|
||||||
return self.crown
|
return self.crown
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def services(self):
|
||||||
|
return organisations_client.get_organisation_services(self.id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def live_services(self):
|
||||||
|
return [s for s in self.services if s['active'] and not s['restricted']]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def trial_services(self):
|
||||||
|
return [s for s in self.services if not s['active'] or s['restricted']]
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def active_users(self):
|
||||||
|
# need to put this here to prevent cyclical import
|
||||||
|
from app.notify_client.user_api_client import user_api_client
|
||||||
|
return user_api_client.get_users_for_organisation(org_id=self.id)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def invited_users(self):
|
||||||
|
# need to put this here to prevent cyclical import
|
||||||
|
from app.notify_client.org_invite_api_client import org_invite_api_client
|
||||||
|
return org_invite_api_client.get_invites_for_organisation(org_id=self.id)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def team_members(self):
|
||||||
|
return sorted(
|
||||||
|
self.active_users + [i for i in self.invited_users if i.status != 'accepted'],
|
||||||
|
key=lambda user: user.email_address,
|
||||||
|
)
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ class HeaderNavigation(Navigation):
|
|||||||
'old_terms',
|
'old_terms',
|
||||||
'old_using_notify',
|
'old_using_notify',
|
||||||
'organisation_dashboard',
|
'organisation_dashboard',
|
||||||
|
'organisation_trial_mode_services',
|
||||||
'organisation_settings',
|
'organisation_settings',
|
||||||
'organisation_preview_email_branding',
|
'organisation_preview_email_branding',
|
||||||
'organisation_preview_letter_branding',
|
'organisation_preview_letter_branding',
|
||||||
@@ -498,6 +499,7 @@ class MainNavigation(Navigation):
|
|||||||
'old_terms',
|
'old_terms',
|
||||||
'old_using_notify',
|
'old_using_notify',
|
||||||
'organisation_dashboard',
|
'organisation_dashboard',
|
||||||
|
'organisation_trial_mode_services',
|
||||||
'organisation_preview_email_branding',
|
'organisation_preview_email_branding',
|
||||||
'organisation_preview_letter_branding',
|
'organisation_preview_letter_branding',
|
||||||
'organisation_settings',
|
'organisation_settings',
|
||||||
@@ -716,6 +718,7 @@ class CaseworkNavigation(Navigation):
|
|||||||
'old_terms',
|
'old_terms',
|
||||||
'old_using_notify',
|
'old_using_notify',
|
||||||
'organisation_dashboard',
|
'organisation_dashboard',
|
||||||
|
'organisation_trial_mode_services',
|
||||||
'organisation_preview_email_branding',
|
'organisation_preview_email_branding',
|
||||||
'organisation_preview_letter_branding',
|
'organisation_preview_letter_branding',
|
||||||
'organisation_settings',
|
'organisation_settings',
|
||||||
@@ -876,6 +879,9 @@ class OrgNavigation(Navigation):
|
|||||||
'invite_org_user',
|
'invite_org_user',
|
||||||
'manage_org_users',
|
'manage_org_users',
|
||||||
'remove_user_from_organisation',
|
'remove_user_from_organisation',
|
||||||
|
},
|
||||||
|
'trial-services': {
|
||||||
|
'organisation_trial_mode_services',
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,5 +3,8 @@
|
|||||||
<li><a href="{{ url_for('.organisation_dashboard', org_id=current_org.id) }}" {{ org_navigation.is_selected('dashboard') }}>Services</a></li>
|
<li><a href="{{ url_for('.organisation_dashboard', org_id=current_org.id) }}" {{ org_navigation.is_selected('dashboard') }}>Services</a></li>
|
||||||
<li><a href="{{ url_for('.manage_org_users', org_id=current_org.id) }}" {{ org_navigation.is_selected('team-members') }}>Team members</a></li>
|
<li><a href="{{ url_for('.manage_org_users', org_id=current_org.id) }}" {{ org_navigation.is_selected('team-members') }}>Team members</a></li>
|
||||||
<li><a href="{{ url_for('.organisation_settings', org_id=current_org.id) }}" {{ org_navigation.is_selected('settings') }}>Settings</a></li>
|
<li><a href="{{ url_for('.organisation_settings', org_id=current_org.id) }}" {{ org_navigation.is_selected('settings') }}>Settings</a></li>
|
||||||
|
{% if current_user.platform_admin %}
|
||||||
|
<li><a href="{{ url_for('.organisation_trial_mode_services', org_id=current_org.id) }}" {{ org_navigation.is_selected('trial-services') }}>Trial services</a></li>
|
||||||
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{% extends "org_template.html" %}
|
||||||
|
{% from "components/live-search.html" import live_search %}
|
||||||
|
|
||||||
|
{% block org_page_title %}
|
||||||
|
Services
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block maincolumn_content %}
|
||||||
|
|
||||||
|
<h1 class="heading-medium">
|
||||||
|
Trial mode services
|
||||||
|
</h1>
|
||||||
|
{{ live_search(target_selector='.browse-list-item', show=True, form=search_form, label='Search by name') }}
|
||||||
|
<ul>
|
||||||
|
{% for service in services %}
|
||||||
|
<li class="browse-list-item">
|
||||||
|
<a href="{{ url_for('main.service_dashboard', service_id=service.id) }}" class="browse-list-link">{{ service['name'] }}</a>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
690
tests/app/main/views/organisations/test_organisation.py
Normal file
690
tests/app/main/views/organisations/test_organisation.py
Normal file
@@ -0,0 +1,690 @@
|
|||||||
|
from unittest.mock import Mock
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
from flask import url_for
|
||||||
|
from notifications_python_client.errors import HTTPError
|
||||||
|
|
||||||
|
from tests import organisation_json, service_json
|
||||||
|
from tests.conftest import (
|
||||||
|
ORGANISATION_ID,
|
||||||
|
SERVICE_ONE_ID,
|
||||||
|
active_user_with_permissions,
|
||||||
|
normalize_spaces,
|
||||||
|
platform_admin_user,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_organisation_page_shows_all_organisations(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
mocker
|
||||||
|
):
|
||||||
|
orgs = [
|
||||||
|
{'id': '1', 'name': 'Test 1', 'active': True},
|
||||||
|
{'id': '2', 'name': 'Test 2', 'active': True},
|
||||||
|
{'id': '3', 'name': 'Test 3', 'active': False},
|
||||||
|
]
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
'app.organisations_client.get_organisations', return_value=orgs
|
||||||
|
)
|
||||||
|
response = logged_in_platform_admin_client.get(
|
||||||
|
url_for('.organisations')
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
|
||||||
|
assert normalize_spaces(
|
||||||
|
page.select_one('h1').text
|
||||||
|
) == "Organisations"
|
||||||
|
|
||||||
|
for index, org in enumerate(orgs):
|
||||||
|
assert page.select('a.browse-list-link')[index].text == org['name']
|
||||||
|
if not org['active']:
|
||||||
|
assert page.select_one('.table-field-status-default,heading-medium').text == '- archived'
|
||||||
|
assert normalize_spaces(
|
||||||
|
page.select_one('a.button-secondary').text
|
||||||
|
) == 'New organisation'
|
||||||
|
|
||||||
|
|
||||||
|
def test_view_organisation_shows_the_correct_organisation(
|
||||||
|
client_request,
|
||||||
|
mocker
|
||||||
|
):
|
||||||
|
org = {'id': ORGANISATION_ID, 'name': 'Test 1', 'active': True}
|
||||||
|
mocker.patch(
|
||||||
|
'app.organisations_client.get_organisation', return_value=org
|
||||||
|
)
|
||||||
|
mocker.patch(
|
||||||
|
'app.organisations_client.get_organisation_services', return_value=[]
|
||||||
|
)
|
||||||
|
|
||||||
|
page = client_request.get(
|
||||||
|
'.organisation_dashboard',
|
||||||
|
org_id=ORGANISATION_ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert normalize_spaces(page.select_one('h1').text) == 'Services'
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_new_organisation(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
mocker,
|
||||||
|
fake_uuid
|
||||||
|
):
|
||||||
|
mock_create_organisation = mocker.patch(
|
||||||
|
'app.organisations_client.create_organisation'
|
||||||
|
)
|
||||||
|
|
||||||
|
org = {'name': 'new name'}
|
||||||
|
|
||||||
|
logged_in_platform_admin_client.post(
|
||||||
|
url_for('.add_organisation'),
|
||||||
|
content_type='multipart/form-data',
|
||||||
|
data=org
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_create_organisation.assert_called_once_with(name=org['name'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_organisation_services_shows_live_services_only(
|
||||||
|
client_request,
|
||||||
|
mock_get_organisation,
|
||||||
|
mocker,
|
||||||
|
active_user_with_permissions,
|
||||||
|
fake_uuid,
|
||||||
|
):
|
||||||
|
mocker.patch(
|
||||||
|
'app.organisations_client.get_organisation_services',
|
||||||
|
return_value=[
|
||||||
|
service_json(id_='1', name='1', restricted=False, active=True), # live
|
||||||
|
service_json(id_='2', name='2', restricted=True, active=True), # trial
|
||||||
|
service_json(id_='3', name='3', restricted=True, active=False), # trial, now archived
|
||||||
|
service_json(id_='4', name='4', restricted=False, active=False), # was live, now archived
|
||||||
|
service_json(id_=SERVICE_ONE_ID, name='5', restricted=False, active=True), # live, member of
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
client_request.login(active_user_with_permissions)
|
||||||
|
page = client_request.get('.organisation_dashboard', org_id=ORGANISATION_ID)
|
||||||
|
|
||||||
|
services = page.select('.browse-list-item')
|
||||||
|
assert len(services) == 2
|
||||||
|
|
||||||
|
assert normalize_spaces(services[0].text) == '1'
|
||||||
|
assert normalize_spaces(services[1].text) == '5'
|
||||||
|
assert services[0].find('a') is None
|
||||||
|
assert services[1].find('a')['href'] == url_for('main.service_dashboard', service_id=SERVICE_ONE_ID)
|
||||||
|
|
||||||
|
|
||||||
|
def test_organisation_trial_mode_services_shows_all_non_live_services(
|
||||||
|
client_request,
|
||||||
|
platform_admin_user,
|
||||||
|
mock_get_organisation,
|
||||||
|
mocker,
|
||||||
|
fake_uuid,
|
||||||
|
):
|
||||||
|
mocker.patch(
|
||||||
|
'app.organisations_client.get_organisation_services',
|
||||||
|
return_value=[
|
||||||
|
service_json(id_='1', name='1', restricted=False, active=True), # live
|
||||||
|
service_json(id_='2', name='2', restricted=True, active=True), # trial
|
||||||
|
service_json(id_='3', name='3', restricted=False, active=False), # archived
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
client_request.login(platform_admin_user)
|
||||||
|
page = client_request.get(
|
||||||
|
'.organisation_trial_mode_services',
|
||||||
|
org_id=ORGANISATION_ID,
|
||||||
|
_test_page_title=False
|
||||||
|
)
|
||||||
|
|
||||||
|
services = page.select('.browse-list-item')
|
||||||
|
assert len(services) == 2
|
||||||
|
|
||||||
|
assert normalize_spaces(services[0].text) == '2'
|
||||||
|
assert normalize_spaces(services[1].text) == '3'
|
||||||
|
assert services[0].find('a')['href'] == url_for('main.service_dashboard', service_id='2')
|
||||||
|
assert services[1].find('a')['href'] == url_for('main.service_dashboard', service_id='3')
|
||||||
|
|
||||||
|
|
||||||
|
def test_organisation_trial_mode_services_doesnt_work_if_not_platform_admin(
|
||||||
|
client_request,
|
||||||
|
mock_get_organisation,
|
||||||
|
):
|
||||||
|
client_request.get(
|
||||||
|
'.organisation_trial_mode_services',
|
||||||
|
org_id=ORGANISATION_ID,
|
||||||
|
_expected_status=403
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
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 == '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(
|
||||||
|
client_request,
|
||||||
|
platform_admin_user,
|
||||||
|
mock_get_organisation,
|
||||||
|
organisation_one
|
||||||
|
):
|
||||||
|
expected_rows = [
|
||||||
|
'Label Value Action',
|
||||||
|
'Organisation name Org 1 Change',
|
||||||
|
|
||||||
|
'Label Value Action',
|
||||||
|
'Organisation type Not set Change',
|
||||||
|
'Crown organisation Yes Change',
|
||||||
|
'Data sharing and financial agreement Not signed Change',
|
||||||
|
'Request to go live notes None Change',
|
||||||
|
'Default email branding GOV.UK Change',
|
||||||
|
'Default letter branding No branding Change',
|
||||||
|
'Known email domains None Change',
|
||||||
|
]
|
||||||
|
|
||||||
|
client_request.login(platform_admin_user)
|
||||||
|
page = client_request.get('.organisation_settings', org_id=organisation_one['id'])
|
||||||
|
|
||||||
|
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())
|
||||||
|
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 won’t 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-2': 'example.gov.uk',
|
||||||
|
'domains-3': '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(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
organisation_one,
|
||||||
|
mock_get_organisation,
|
||||||
|
mock_organisation_name_is_unique
|
||||||
|
):
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for('.edit_organisation_name', org_id=organisation_one['id']),
|
||||||
|
data={'name': 'TestNewOrgName'}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.location == url_for(
|
||||||
|
'.confirm_edit_organisation_name',
|
||||||
|
org_id=organisation_one['id'],
|
||||||
|
_external=True
|
||||||
|
)
|
||||||
|
assert mock_organisation_name_is_unique.called
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_organisation_with_incorrect_input(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
organisation_one,
|
||||||
|
mock_get_organisation,
|
||||||
|
):
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for('.edit_organisation_name', org_id=organisation_one['id']),
|
||||||
|
data={'name': ''}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
|
||||||
|
assert normalize_spaces(
|
||||||
|
page.select_one('.error-message').text
|
||||||
|
) == "Can’t be empty"
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_organisation_with_non_unique_name(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
organisation_one,
|
||||||
|
mock_get_organisation,
|
||||||
|
mock_organisation_name_is_not_unique
|
||||||
|
):
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for('.edit_organisation_name', org_id=organisation_one['id']),
|
||||||
|
data={'name': 'TestNewOrgName'}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
|
||||||
|
assert normalize_spaces(
|
||||||
|
page.select_one('.error-message').text
|
||||||
|
) == 'This organisation name is already in use'
|
||||||
|
|
||||||
|
assert mock_organisation_name_is_not_unique.called
|
||||||
|
|
||||||
|
|
||||||
|
def test_confirm_update_organisation(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
organisation_one,
|
||||||
|
mock_get_organisation,
|
||||||
|
mock_verify_password,
|
||||||
|
mock_update_organisation,
|
||||||
|
mocker
|
||||||
|
):
|
||||||
|
with logged_in_platform_admin_client.session_transaction() as session:
|
||||||
|
session['organisation_name_change'] = 'newName'
|
||||||
|
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for(
|
||||||
|
'.confirm_edit_organisation_name',
|
||||||
|
org_id=organisation_one['id'],
|
||||||
|
data={'password', 'validPassword'}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.location == url_for('.organisation_settings', org_id=organisation_one['id'], _external=True)
|
||||||
|
|
||||||
|
mock_update_organisation.assert_called_with(
|
||||||
|
organisation_one['id'],
|
||||||
|
name=session['organisation_name_change']
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_confirm_update_organisation_with_incorrect_password(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
organisation_one,
|
||||||
|
mock_get_organisation,
|
||||||
|
mocker
|
||||||
|
):
|
||||||
|
with logged_in_platform_admin_client.session_transaction() as session:
|
||||||
|
session['organisation_name_change'] = 'newName'
|
||||||
|
|
||||||
|
mocker.patch('app.user_api_client.verify_password', return_value=False)
|
||||||
|
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for(
|
||||||
|
'.confirm_edit_organisation_name',
|
||||||
|
org_id=organisation_one['id']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
|
||||||
|
assert normalize_spaces(
|
||||||
|
page.select_one('.error-message').text
|
||||||
|
) == 'Invalid password'
|
||||||
|
|
||||||
|
|
||||||
|
def test_confirm_update_organisation_with_name_already_in_use(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
organisation_one,
|
||||||
|
mock_get_organisation,
|
||||||
|
mock_verify_password,
|
||||||
|
mocker
|
||||||
|
):
|
||||||
|
with logged_in_platform_admin_client.session_transaction() as session:
|
||||||
|
session['organisation_name_change'] = 'newName'
|
||||||
|
|
||||||
|
mocker.patch(
|
||||||
|
'app.organisations_client.update_organisation_name',
|
||||||
|
side_effect=HTTPError(
|
||||||
|
response=Mock(
|
||||||
|
status_code=400,
|
||||||
|
json={'result': 'error', 'message': 'Organisation name already exists'}
|
||||||
|
),
|
||||||
|
message="Organisation name already exists"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for(
|
||||||
|
'.confirm_edit_organisation_name',
|
||||||
|
org_id=organisation_one['id']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.location == url_for('main.edit_organisation_name', org_id=organisation_one['id'], _external=True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_edit_organisation_go_live_notes_page(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
mock_get_organisation,
|
||||||
|
organisation_one,
|
||||||
|
):
|
||||||
|
response = logged_in_platform_admin_client.get(
|
||||||
|
url_for(
|
||||||
|
'.edit_organisation_go_live_notes',
|
||||||
|
org_id=organisation_one['id']
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
||||||
|
|
||||||
|
assert page.find('textarea', id='request_to_go_live_notes')
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('input_note,saved_note', [
|
||||||
|
('Needs permission', 'Needs permission'),
|
||||||
|
(' ', None)
|
||||||
|
])
|
||||||
|
def test_post_edit_organisation_go_live_notes_updates_go_live_notes(
|
||||||
|
logged_in_platform_admin_client,
|
||||||
|
mock_get_organisation,
|
||||||
|
mock_update_organisation,
|
||||||
|
organisation_one,
|
||||||
|
input_note,
|
||||||
|
saved_note,
|
||||||
|
):
|
||||||
|
response = logged_in_platform_admin_client.post(
|
||||||
|
url_for(
|
||||||
|
'.edit_organisation_go_live_notes',
|
||||||
|
org_id=organisation_one['id'],
|
||||||
|
),
|
||||||
|
data={'request_to_go_live_notes': input_note}
|
||||||
|
)
|
||||||
|
|
||||||
|
mock_update_organisation.assert_called_once_with(
|
||||||
|
organisation_one['id'],
|
||||||
|
request_to_go_live_notes=saved_note
|
||||||
|
)
|
||||||
|
assert response.status_code == 302
|
||||||
|
assert response.location == url_for(
|
||||||
|
'.organisation_settings',
|
||||||
|
org_id=organisation_one['id'],
|
||||||
|
_external=True
|
||||||
|
)
|
||||||
@@ -1,119 +1,12 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from unittest.mock import ANY, Mock
|
from unittest.mock import ANY
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from bs4 import BeautifulSoup
|
from bs4 import BeautifulSoup
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
from notifications_python_client.errors import HTTPError
|
|
||||||
|
|
||||||
from app.models.user import InvitedOrgUser
|
from app.models.user import InvitedOrgUser
|
||||||
from tests import organisation_json
|
from tests.conftest import ORGANISATION_ID, normalize_spaces
|
||||||
from tests.conftest import (
|
|
||||||
ORGANISATION_ID,
|
|
||||||
active_user_with_permissions,
|
|
||||||
normalize_spaces,
|
|
||||||
platform_admin_user,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_organisation_page_shows_all_organisations(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
mocker
|
|
||||||
):
|
|
||||||
orgs = [
|
|
||||||
{'id': '1', 'name': 'Test 1', 'active': True},
|
|
||||||
{'id': '2', 'name': 'Test 2', 'active': True},
|
|
||||||
{'id': '3', 'name': 'Test 3', 'active': False},
|
|
||||||
]
|
|
||||||
|
|
||||||
mocker.patch(
|
|
||||||
'app.organisations_client.get_organisations', return_value=orgs
|
|
||||||
)
|
|
||||||
response = logged_in_platform_admin_client.get(
|
|
||||||
url_for('.organisations')
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
|
|
||||||
assert normalize_spaces(
|
|
||||||
page.select_one('h1').text
|
|
||||||
) == "Organisations"
|
|
||||||
|
|
||||||
for index, org in enumerate(orgs):
|
|
||||||
assert page.select('a.browse-list-link')[index].text == org['name']
|
|
||||||
if not org['active']:
|
|
||||||
assert page.select_one('.table-field-status-default,heading-medium').text == '- archived'
|
|
||||||
assert normalize_spaces(
|
|
||||||
page.select_one('a.button-secondary').text
|
|
||||||
) == 'New organisation'
|
|
||||||
|
|
||||||
|
|
||||||
def test_view_organisation_shows_the_correct_organisation(
|
|
||||||
client_request,
|
|
||||||
mocker
|
|
||||||
):
|
|
||||||
org = {'id': ORGANISATION_ID, 'name': 'Test 1', 'active': True}
|
|
||||||
mocker.patch(
|
|
||||||
'app.organisations_client.get_organisation', return_value=org
|
|
||||||
)
|
|
||||||
mocker.patch(
|
|
||||||
'app.organisations_client.get_organisation_services', return_value=[]
|
|
||||||
)
|
|
||||||
|
|
||||||
page = client_request.get(
|
|
||||||
'.organisation_dashboard',
|
|
||||||
org_id=ORGANISATION_ID,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert normalize_spaces(page.select_one('h1').text) == 'Services'
|
|
||||||
|
|
||||||
|
|
||||||
def test_create_new_organisation(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
mocker,
|
|
||||||
fake_uuid
|
|
||||||
):
|
|
||||||
mock_create_organisation = mocker.patch(
|
|
||||||
'app.organisations_client.create_organisation'
|
|
||||||
)
|
|
||||||
|
|
||||||
org = {'name': 'new name'}
|
|
||||||
|
|
||||||
logged_in_platform_admin_client.post(
|
|
||||||
url_for('.add_organisation'),
|
|
||||||
content_type='multipart/form-data',
|
|
||||||
data=org
|
|
||||||
)
|
|
||||||
|
|
||||||
mock_create_organisation.assert_called_once_with(name=org['name'])
|
|
||||||
|
|
||||||
|
|
||||||
def test_organisation_services_show(
|
|
||||||
client_request,
|
|
||||||
mock_get_organisation,
|
|
||||||
mock_get_organisation_services,
|
|
||||||
mocker,
|
|
||||||
fake_uuid,
|
|
||||||
):
|
|
||||||
page = client_request.get(
|
|
||||||
'.organisation_dashboard',
|
|
||||||
org_id=ORGANISATION_ID,
|
|
||||||
)
|
|
||||||
|
|
||||||
assert len(page.select('.browse-list-item')) == 3
|
|
||||||
|
|
||||||
for i in range(0, 2):
|
|
||||||
service_name = mock_get_organisation_services(mock_get_organisation['id'])[i]['name']
|
|
||||||
service_id = mock_get_organisation_services(mock_get_organisation['id'])[i]['id']
|
|
||||||
|
|
||||||
assert normalize_spaces(page.select('.browse-list-item')[i].text) == service_name
|
|
||||||
if i > 1:
|
|
||||||
assert normalize_spaces(
|
|
||||||
page.select('.browse-list-item a')[i]['href']
|
|
||||||
) == '/services/{}'.format(service_id)
|
|
||||||
else:
|
|
||||||
assert page.select('.browse-list-item')[i].find('a') is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_view_team_members(
|
def test_view_team_members(
|
||||||
@@ -467,532 +360,3 @@ def test_verified_org_user_redirects_to_dashboard(
|
|||||||
org_id=invited_org_user['organisation'],
|
org_id=invited_org_user['organisation'],
|
||||||
_external=True
|
_external=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
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 == '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(
|
|
||||||
client_request,
|
|
||||||
platform_admin_user,
|
|
||||||
mock_get_organisation,
|
|
||||||
organisation_one
|
|
||||||
):
|
|
||||||
expected_rows = [
|
|
||||||
'Label Value Action',
|
|
||||||
'Organisation name Org 1 Change',
|
|
||||||
|
|
||||||
'Label Value Action',
|
|
||||||
'Organisation type Not set Change',
|
|
||||||
'Crown organisation Yes Change',
|
|
||||||
'Data sharing and financial agreement Not signed Change',
|
|
||||||
'Request to go live notes None Change',
|
|
||||||
'Default email branding GOV.UK Change',
|
|
||||||
'Default letter branding No branding Change',
|
|
||||||
'Known email domains None Change',
|
|
||||||
]
|
|
||||||
|
|
||||||
client_request.login(platform_admin_user)
|
|
||||||
page = client_request.get('.organisation_settings', org_id=organisation_one['id'])
|
|
||||||
|
|
||||||
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())
|
|
||||||
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 won’t 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-2': 'example.gov.uk',
|
|
||||||
'domains-3': '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(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
organisation_one,
|
|
||||||
mock_get_organisation,
|
|
||||||
mock_organisation_name_is_unique
|
|
||||||
):
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for('.edit_organisation_name', org_id=organisation_one['id']),
|
|
||||||
data={'name': 'TestNewOrgName'}
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 302
|
|
||||||
assert response.location == url_for(
|
|
||||||
'.confirm_edit_organisation_name',
|
|
||||||
org_id=organisation_one['id'],
|
|
||||||
_external=True
|
|
||||||
)
|
|
||||||
assert mock_organisation_name_is_unique.called
|
|
||||||
|
|
||||||
|
|
||||||
def test_update_organisation_with_incorrect_input(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
organisation_one,
|
|
||||||
mock_get_organisation,
|
|
||||||
):
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for('.edit_organisation_name', org_id=organisation_one['id']),
|
|
||||||
data={'name': ''}
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
|
|
||||||
assert normalize_spaces(
|
|
||||||
page.select_one('.error-message').text
|
|
||||||
) == "Can’t be empty"
|
|
||||||
|
|
||||||
|
|
||||||
def test_update_organisation_with_non_unique_name(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
organisation_one,
|
|
||||||
mock_get_organisation,
|
|
||||||
mock_organisation_name_is_not_unique
|
|
||||||
):
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for('.edit_organisation_name', org_id=organisation_one['id']),
|
|
||||||
data={'name': 'TestNewOrgName'}
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
|
|
||||||
assert normalize_spaces(
|
|
||||||
page.select_one('.error-message').text
|
|
||||||
) == 'This organisation name is already in use'
|
|
||||||
|
|
||||||
assert mock_organisation_name_is_not_unique.called
|
|
||||||
|
|
||||||
|
|
||||||
def test_confirm_update_organisation(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
organisation_one,
|
|
||||||
mock_get_organisation,
|
|
||||||
mock_verify_password,
|
|
||||||
mock_update_organisation,
|
|
||||||
mocker
|
|
||||||
):
|
|
||||||
with logged_in_platform_admin_client.session_transaction() as session:
|
|
||||||
session['organisation_name_change'] = 'newName'
|
|
||||||
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for(
|
|
||||||
'.confirm_edit_organisation_name',
|
|
||||||
org_id=organisation_one['id'],
|
|
||||||
data={'password', 'validPassword'}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 302
|
|
||||||
assert response.location == url_for('.organisation_settings', org_id=organisation_one['id'], _external=True)
|
|
||||||
|
|
||||||
mock_update_organisation.assert_called_with(
|
|
||||||
organisation_one['id'],
|
|
||||||
name=session['organisation_name_change']
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_confirm_update_organisation_with_incorrect_password(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
organisation_one,
|
|
||||||
mock_get_organisation,
|
|
||||||
mocker
|
|
||||||
):
|
|
||||||
with logged_in_platform_admin_client.session_transaction() as session:
|
|
||||||
session['organisation_name_change'] = 'newName'
|
|
||||||
|
|
||||||
mocker.patch('app.user_api_client.verify_password', return_value=False)
|
|
||||||
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for(
|
|
||||||
'.confirm_edit_organisation_name',
|
|
||||||
org_id=organisation_one['id']
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
|
|
||||||
assert normalize_spaces(
|
|
||||||
page.select_one('.error-message').text
|
|
||||||
) == 'Invalid password'
|
|
||||||
|
|
||||||
|
|
||||||
def test_confirm_update_organisation_with_name_already_in_use(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
organisation_one,
|
|
||||||
mock_get_organisation,
|
|
||||||
mock_verify_password,
|
|
||||||
mocker
|
|
||||||
):
|
|
||||||
with logged_in_platform_admin_client.session_transaction() as session:
|
|
||||||
session['organisation_name_change'] = 'newName'
|
|
||||||
|
|
||||||
mocker.patch(
|
|
||||||
'app.organisations_client.update_organisation_name',
|
|
||||||
side_effect=HTTPError(
|
|
||||||
response=Mock(
|
|
||||||
status_code=400,
|
|
||||||
json={'result': 'error', 'message': 'Organisation name already exists'}
|
|
||||||
),
|
|
||||||
message="Organisation name already exists"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for(
|
|
||||||
'.confirm_edit_organisation_name',
|
|
||||||
org_id=organisation_one['id']
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 302
|
|
||||||
assert response.location == url_for('main.edit_organisation_name', org_id=organisation_one['id'], _external=True)
|
|
||||||
|
|
||||||
|
|
||||||
def test_get_edit_organisation_go_live_notes_page(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
mock_get_organisation,
|
|
||||||
organisation_one,
|
|
||||||
):
|
|
||||||
response = logged_in_platform_admin_client.get(
|
|
||||||
url_for(
|
|
||||||
'.edit_organisation_go_live_notes',
|
|
||||||
org_id=organisation_one['id']
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
assert response.status_code == 200
|
|
||||||
page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
|
|
||||||
|
|
||||||
assert page.find('textarea', id='request_to_go_live_notes')
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('input_note,saved_note', [
|
|
||||||
('Needs permission', 'Needs permission'),
|
|
||||||
(' ', None)
|
|
||||||
])
|
|
||||||
def test_post_edit_organisation_go_live_notes_updates_go_live_notes(
|
|
||||||
logged_in_platform_admin_client,
|
|
||||||
mock_get_organisation,
|
|
||||||
mock_update_organisation,
|
|
||||||
organisation_one,
|
|
||||||
input_note,
|
|
||||||
saved_note,
|
|
||||||
):
|
|
||||||
response = logged_in_platform_admin_client.post(
|
|
||||||
url_for(
|
|
||||||
'.edit_organisation_go_live_notes',
|
|
||||||
org_id=organisation_one['id'],
|
|
||||||
),
|
|
||||||
data={'request_to_go_live_notes': input_note}
|
|
||||||
)
|
|
||||||
|
|
||||||
mock_update_organisation.assert_called_once_with(
|
|
||||||
organisation_one['id'],
|
|
||||||
request_to_go_live_notes=saved_note
|
|
||||||
)
|
|
||||||
assert response.status_code == 302
|
|
||||||
assert response.location == url_for(
|
|
||||||
'.organisation_settings',
|
|
||||||
org_id=organisation_one['id'],
|
|
||||||
_external=True
|
|
||||||
)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user