2020-07-14 13:39:29 +01:00
|
|
|
|
import json
|
2020-08-05 16:01:21 +01:00
|
|
|
|
import uuid
|
2020-09-02 14:54:00 +01:00
|
|
|
|
from collections import namedtuple
|
2020-07-31 16:20:37 +01:00
|
|
|
|
from functools import partial
|
2020-07-14 13:39:29 +01:00
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
import pytest
|
|
|
|
|
|
from flask import url_for
|
2020-07-09 10:33:50 +01:00
|
|
|
|
from freezegun import freeze_time
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
2020-07-10 14:06:00 +01:00
|
|
|
|
from tests import broadcast_message_json, sample_uuid, user_json
|
2021-03-18 23:02:32 +00:00
|
|
|
|
from tests.app.broadcast_areas.custom_polygons import BRISTOL, SKYE
|
2020-07-08 16:02:16 +01:00
|
|
|
|
from tests.conftest import SERVICE_ONE_ID, normalize_spaces
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
2020-07-09 10:33:50 +01:00
|
|
|
|
sample_uuid = sample_uuid()
|
|
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
2020-07-20 09:27:46 +01:00
|
|
|
|
@pytest.mark.parametrize('endpoint, extra_args, expected_get_status, expected_post_status', (
|
|
|
|
|
|
(
|
|
|
|
|
|
'.broadcast_dashboard', {},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.broadcast_dashboard_updates', {},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
2020-10-13 11:40:20 +01:00
|
|
|
|
(
|
|
|
|
|
|
'.broadcast_dashboard_previous', {},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
2020-11-20 15:42:52 +00:00
|
|
|
|
(
|
|
|
|
|
|
'.new_broadcast', {},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.write_new_broadcast', {},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
2020-07-20 09:27:46 +01:00
|
|
|
|
(
|
|
|
|
|
|
'.broadcast',
|
|
|
|
|
|
{'template_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.preview_broadcast_areas', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.choose_broadcast_library', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.choose_broadcast_area', {'broadcast_message_id': sample_uuid, 'library_slug': 'countries'},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
2020-08-10 13:19:16 +01:00
|
|
|
|
'.remove_broadcast_area', {'broadcast_message_id': sample_uuid, 'area_slug': 'countries-E92000001'},
|
2020-07-20 09:27:46 +01:00
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.preview_broadcast_message', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast', {'broadcast_message_id': sample_uuid},
|
2020-07-20 09:27:46 +01:00
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
2020-10-15 13:15:22 +01:00
|
|
|
|
(
|
|
|
|
|
|
'.view_previous_broadcast', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
2020-07-20 09:27:46 +01:00
|
|
|
|
(
|
|
|
|
|
|
'.cancel_broadcast_message', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
2020-07-06 10:53:14 +01:00
|
|
|
|
))
|
|
|
|
|
|
def test_broadcast_pages_403_without_permission(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
extra_args,
|
2020-07-20 09:27:46 +01:00
|
|
|
|
expected_get_status,
|
|
|
|
|
|
expected_post_status,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-20 09:27:46 +01:00
|
|
|
|
_expected_status=expected_get_status,
|
|
|
|
|
|
**extra_args
|
|
|
|
|
|
)
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_status=expected_post_status,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
**extra_args
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-06 15:08:47 +01:00
|
|
|
|
@pytest.mark.parametrize('user_is_platform_admin', [True, False])
|
2020-08-10 12:26:33 +01:00
|
|
|
|
@pytest.mark.parametrize('endpoint, extra_args, expected_get_status, expected_post_status', (
|
2020-11-20 15:42:52 +00:00
|
|
|
|
(
|
|
|
|
|
|
'.new_broadcast', {},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.write_new_broadcast', {},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
2020-08-10 12:26:33 +01:00
|
|
|
|
(
|
|
|
|
|
|
'.broadcast',
|
|
|
|
|
|
{'template_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.preview_broadcast_areas', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.choose_broadcast_library', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.choose_broadcast_area', {'broadcast_message_id': sample_uuid, 'library_slug': 'countries'},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.remove_broadcast_area', {'broadcast_message_id': sample_uuid, 'area_slug': 'england'},
|
|
|
|
|
|
403, 405,
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'.preview_broadcast_message', {'broadcast_message_id': sample_uuid},
|
|
|
|
|
|
403, 403,
|
|
|
|
|
|
),
|
|
|
|
|
|
))
|
|
|
|
|
|
def test_broadcast_pages_403_for_user_without_permission(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_view_permissions,
|
2021-04-06 15:08:47 +01:00
|
|
|
|
platform_admin_user_no_service_permissions,
|
2020-08-10 12:26:33 +01:00
|
|
|
|
endpoint,
|
|
|
|
|
|
extra_args,
|
|
|
|
|
|
expected_get_status,
|
|
|
|
|
|
expected_post_status,
|
2021-04-06 15:08:47 +01:00
|
|
|
|
user_is_platform_admin
|
2020-08-10 12:26:33 +01:00
|
|
|
|
):
|
2021-04-06 15:08:47 +01:00
|
|
|
|
"""
|
2021-04-20 17:18:33 +01:00
|
|
|
|
Checks that users without permissions, including admin users, cannot create or edit broadcasts.
|
2021-04-06 15:08:47 +01:00
|
|
|
|
"""
|
2020-08-10 12:26:33 +01:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2021-04-06 15:08:47 +01:00
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
client_request.login(platform_admin_user_no_service_permissions)
|
|
|
|
|
|
else:
|
|
|
|
|
|
client_request.login(active_user_view_permissions)
|
2020-08-10 12:26:33 +01:00
|
|
|
|
client_request.get(
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_status=expected_get_status,
|
|
|
|
|
|
**extra_args
|
|
|
|
|
|
)
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_status=expected_post_status,
|
|
|
|
|
|
**extra_args
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-20 17:18:33 +01:00
|
|
|
|
@pytest.mark.parametrize('user_is_platform_admin', [True, False])
|
|
|
|
|
|
def test_user_cannot_accept_broadcast_without_permission(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
platform_admin_user_no_service_permissions,
|
|
|
|
|
|
user_is_platform_admin
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
client_request.login(platform_admin_user_no_service_permissions)
|
|
|
|
|
|
else:
|
|
|
|
|
|
client_request.login(active_user_view_permissions)
|
|
|
|
|
|
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.approve_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-20 17:24:26 +01:00
|
|
|
|
@pytest.mark.parametrize('user_is_platform_admin', [True, False])
|
|
|
|
|
|
def test_user_cannot_reject_broadcast_without_permission(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
platform_admin_user_no_service_permissions,
|
|
|
|
|
|
user_is_platform_admin
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
client_request.login(platform_admin_user_no_service_permissions)
|
|
|
|
|
|
else:
|
|
|
|
|
|
client_request.login(active_user_view_permissions)
|
|
|
|
|
|
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.reject_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-06 15:08:47 +01:00
|
|
|
|
def test_cancel_broadcast_page_403_for_user_without_permission(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_view_permissions,
|
|
|
|
|
|
):
|
|
|
|
|
|
"""
|
|
|
|
|
|
separate test for cancel_broadcast endpoint, because admin users are allowed to cancel broadcasts
|
|
|
|
|
|
"""
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
mocker.patch('app.user_api_client.get_user', return_value=active_user_view_permissions)
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.cancel_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
**{'broadcast_message_id': sample_uuid}
|
|
|
|
|
|
)
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.cancel_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_status=403,
|
|
|
|
|
|
**{'broadcast_message_id': sample_uuid}
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-19 14:54:50 +01:00
|
|
|
|
@pytest.mark.parametrize('step_index, expected_link_text, expected_link_href', (
|
|
|
|
|
|
(1, 'Continue', partial(url_for, '.broadcast_tour', step_index=2)),
|
|
|
|
|
|
(2, 'Continue', partial(url_for, '.broadcast_tour', step_index=3)),
|
|
|
|
|
|
(3, 'Continue', partial(url_for, '.broadcast_tour', step_index=4)),
|
2020-08-25 11:31:25 +01:00
|
|
|
|
(4, 'Continue', partial(url_for, '.broadcast_tour', step_index=5)),
|
2020-10-13 11:42:32 +01:00
|
|
|
|
(5, 'Continue', partial(url_for, '.service_dashboard')),
|
|
|
|
|
|
(6, 'Continue', partial(url_for, '.service_dashboard')),
|
2020-08-19 14:54:50 +01:00
|
|
|
|
))
|
|
|
|
|
|
def test_broadcast_tour_pages_have_continue_link(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
step_index,
|
|
|
|
|
|
expected_link_text,
|
|
|
|
|
|
expected_link_href,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.broadcast_tour',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
step_index=step_index,
|
|
|
|
|
|
)
|
|
|
|
|
|
link = page.select_one('.banner-tour a')
|
|
|
|
|
|
assert normalize_spaces(link.text) == expected_link_text
|
|
|
|
|
|
assert link['href'] == expected_link_href(service_id=SERVICE_ONE_ID)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('step_index', (
|
|
|
|
|
|
pytest.param(1, marks=pytest.mark.xfail),
|
|
|
|
|
|
pytest.param(2, marks=pytest.mark.xfail),
|
|
|
|
|
|
pytest.param(3, marks=pytest.mark.xfail),
|
2020-08-25 11:31:25 +01:00
|
|
|
|
pytest.param(4, marks=pytest.mark.xfail),
|
|
|
|
|
|
5,
|
2020-09-21 09:41:19 +01:00
|
|
|
|
6,
|
2020-08-19 14:54:50 +01:00
|
|
|
|
))
|
|
|
|
|
|
def test_broadcast_tour_page_4_shows_service_name(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
step_index,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.broadcast_tour',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
step_index=step_index,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.select_one('.navigation-service').text) == (
|
|
|
|
|
|
'service one Training'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-04 10:52:09 +00:00
|
|
|
|
@pytest.mark.parametrize('trial_mode, allowed_broadcast_provider, selector, expected_text, expected_tagged_text', (
|
2020-09-22 14:52:15 +01:00
|
|
|
|
(
|
|
|
|
|
|
True,
|
2020-12-04 10:52:09 +00:00
|
|
|
|
None,
|
2020-09-22 14:52:15 +01:00
|
|
|
|
'.navigation-service-type.navigation-service-type--training',
|
|
|
|
|
|
'service one Training Switch service',
|
|
|
|
|
|
'Training',
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
False,
|
2020-12-04 10:52:09 +00:00
|
|
|
|
None,
|
2020-09-22 14:52:15 +01:00
|
|
|
|
'.navigation-service-type.navigation-service-type--live',
|
|
|
|
|
|
'service one Live Switch service',
|
|
|
|
|
|
'Live',
|
|
|
|
|
|
),
|
2020-12-04 10:52:09 +00:00
|
|
|
|
|
|
|
|
|
|
(
|
|
|
|
|
|
True,
|
|
|
|
|
|
'vodafone',
|
|
|
|
|
|
'.navigation-service-type.navigation-service-type--training',
|
|
|
|
|
|
'service one Training (vodafone) Switch service',
|
|
|
|
|
|
'Training (vodafone)',
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
False,
|
|
|
|
|
|
'vodafone',
|
|
|
|
|
|
'.navigation-service-type.navigation-service-type--live',
|
|
|
|
|
|
'service one Live (vodafone) Switch service',
|
|
|
|
|
|
'Live (vodafone)',
|
|
|
|
|
|
),
|
2020-09-22 14:52:15 +01:00
|
|
|
|
))
|
|
|
|
|
|
def test_broadcast_service_shows_live_or_training(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_no_broadcast_messages,
|
|
|
|
|
|
mock_get_service_templates_when_no_templates_exist,
|
|
|
|
|
|
trial_mode,
|
2020-12-04 10:52:09 +00:00
|
|
|
|
allowed_broadcast_provider,
|
2020-09-22 14:52:15 +01:00
|
|
|
|
selector,
|
|
|
|
|
|
expected_text,
|
|
|
|
|
|
expected_tagged_text,
|
|
|
|
|
|
):
|
2020-12-04 10:52:09 +00:00
|
|
|
|
service_one['allowed_broadcast_provider'] = allowed_broadcast_provider
|
2020-09-22 14:52:15 +01:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
service_one['restricted'] = trial_mode
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.broadcast_dashboard',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(
|
|
|
|
|
|
page.select_one('.navigation-service').text
|
|
|
|
|
|
) == (
|
|
|
|
|
|
expected_text
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(
|
|
|
|
|
|
page.select_one('.navigation-service').select_one(selector).text
|
|
|
|
|
|
) == (
|
|
|
|
|
|
expected_tagged_text
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-21 09:41:19 +01:00
|
|
|
|
@pytest.mark.parametrize('step_index', (0, 7))
|
2020-08-19 14:54:50 +01:00
|
|
|
|
def test_broadcast_tour_page_404s_out_of_range(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
step_index,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.broadcast_tour',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
step_index=step_index,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-08 11:39:04 +01:00
|
|
|
|
def test_dashboard_redirects_to_broadcast_dashboard(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.service_dashboard',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_expected_redirect=url_for(
|
|
|
|
|
|
'.broadcast_dashboard',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-09 15:48:56 +01:00
|
|
|
|
def test_empty_broadcast_dashboard(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-08-10 12:26:33 +01:00
|
|
|
|
active_user_view_permissions,
|
2020-07-09 15:48:56 +01:00
|
|
|
|
mock_get_no_broadcast_messages,
|
2020-08-03 13:37:34 +01:00
|
|
|
|
mock_get_service_templates_when_no_templates_exist,
|
2020-07-09 15:48:56 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.broadcast_dashboard',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
2020-10-26 11:18:30 +00:00
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == (
|
|
|
|
|
|
'Current alerts'
|
|
|
|
|
|
)
|
2020-07-09 15:48:56 +01:00
|
|
|
|
assert [
|
2020-10-27 15:16:27 +00:00
|
|
|
|
normalize_spaces(row.text) for row in page.select('.table-empty-message')
|
2020-07-09 15:48:56 +01:00
|
|
|
|
] == [
|
2020-10-26 11:18:30 +00:00
|
|
|
|
'You do not have any current alerts',
|
2020-07-09 15:48:56 +01:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@freeze_time('2020-02-20 02:20')
|
2020-07-08 11:34:16 +01:00
|
|
|
|
def test_broadcast_dashboard(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 15:48:56 +01:00
|
|
|
|
mock_get_broadcast_messages,
|
2020-08-03 13:37:34 +01:00
|
|
|
|
mock_get_service_templates,
|
2020-07-08 11:34:16 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2020-07-09 15:48:56 +01:00
|
|
|
|
page = client_request.get(
|
2020-07-08 11:34:16 +01:00
|
|
|
|
'.broadcast_dashboard',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 15:48:56 +01:00
|
|
|
|
)
|
2020-07-22 15:15:23 +01:00
|
|
|
|
|
2020-10-27 15:16:27 +00:00
|
|
|
|
assert len(page.select('.ajax-block-container')) == len(page.select('h1')) == 1
|
2020-10-13 11:41:22 +01:00
|
|
|
|
|
2020-07-09 15:48:56 +01:00
|
|
|
|
assert [
|
2020-10-27 15:16:27 +00:00
|
|
|
|
normalize_spaces(row.text)
|
|
|
|
|
|
for row in page.select('.ajax-block-container')[0].select('.file-list')
|
2020-07-09 15:48:56 +01:00
|
|
|
|
] == [
|
2020-10-27 15:16:27 +00:00
|
|
|
|
'Half an hour ago This is a test Waiting for approval England Scotland',
|
|
|
|
|
|
'Hour and a half ago This is a test Waiting for approval England Scotland',
|
|
|
|
|
|
'Example template This is a test Live since today at 2:20am England Scotland',
|
|
|
|
|
|
'Example template This is a test Live since today at 1:20am England Scotland',
|
2020-07-17 08:07:40 +01:00
|
|
|
|
]
|
|
|
|
|
|
|
2020-11-20 15:42:52 +00:00
|
|
|
|
button = page.select_one(
|
|
|
|
|
|
'.js-stick-at-bottom-when-scrolling a.govuk-button.govuk-button--secondary'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(button.text) == 'New alert'
|
|
|
|
|
|
assert button['href'] == url_for(
|
|
|
|
|
|
'main.new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-14 18:13:18 +01:00
|
|
|
|
@pytest.mark.parametrize("user_is_platform_admin", [True, False])
|
2021-01-18 16:46:13 +00:00
|
|
|
|
@pytest.mark.parametrize('endpoint', (
|
2021-04-08 13:09:29 +01:00
|
|
|
|
'.broadcast_dashboard', '.broadcast_dashboard_previous', '.broadcast_dashboard_rejected',
|
2021-01-18 16:46:13 +00:00
|
|
|
|
))
|
2020-11-20 15:42:52 +00:00
|
|
|
|
def test_broadcast_dashboard_does_not_have_button_for_view_only_user(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_view_permissions,
|
2021-04-14 18:13:18 +01:00
|
|
|
|
platform_admin_user_no_service_permissions,
|
2020-11-20 15:42:52 +00:00
|
|
|
|
mock_get_broadcast_messages,
|
2021-01-18 16:46:13 +00:00
|
|
|
|
endpoint,
|
2021-04-14 18:13:18 +01:00
|
|
|
|
user_is_platform_admin
|
2020-11-20 15:42:52 +00:00
|
|
|
|
):
|
2021-04-14 18:13:18 +01:00
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
client_request.login(platform_admin_user_no_service_permissions)
|
|
|
|
|
|
else:
|
|
|
|
|
|
client_request.login(active_user_view_permissions)
|
|
|
|
|
|
|
2020-11-20 15:42:52 +00:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
2021-01-18 16:46:13 +00:00
|
|
|
|
endpoint,
|
2020-11-20 15:42:52 +00:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert not page.select('a.govuk-button')
|
|
|
|
|
|
|
2020-07-08 11:34:16 +01:00
|
|
|
|
|
2020-07-14 13:39:29 +01:00
|
|
|
|
@freeze_time('2020-02-20 02:20')
|
|
|
|
|
|
def test_broadcast_dashboard_json(
|
|
|
|
|
|
logged_in_client,
|
|
|
|
|
|
service_one,
|
2020-08-10 12:26:33 +01:00
|
|
|
|
active_user_view_permissions,
|
2020-07-14 13:39:29 +01:00
|
|
|
|
mock_get_broadcast_messages,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
response = logged_in_client.get(url_for(
|
|
|
|
|
|
'.broadcast_dashboard_updates',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
|
|
|
|
|
|
|
|
|
|
|
json_response = json.loads(response.get_data(as_text=True))
|
|
|
|
|
|
|
2020-10-26 11:18:30 +00:00
|
|
|
|
assert json_response.keys() == {'current_broadcasts'}
|
2020-07-14 13:39:29 +01:00
|
|
|
|
|
2020-10-26 11:20:32 +00:00
|
|
|
|
assert 'Waiting for approval' in json_response['current_broadcasts']
|
2020-10-26 11:18:30 +00:00
|
|
|
|
assert 'Live since today at 2:20am' in json_response['current_broadcasts']
|
2020-07-14 13:39:29 +01:00
|
|
|
|
|
|
|
|
|
|
|
2020-10-13 11:40:20 +01:00
|
|
|
|
@freeze_time('2020-02-20 02:20')
|
|
|
|
|
|
def test_previous_broadcasts_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_broadcast_messages,
|
|
|
|
|
|
mock_get_service_templates,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.broadcast_dashboard_previous',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(page.select_one('main h1').text) == (
|
|
|
|
|
|
'Previous alerts'
|
|
|
|
|
|
)
|
2020-10-27 15:16:27 +00:00
|
|
|
|
assert len(page.select('.ajax-block-container')) == 1
|
2020-10-13 11:40:20 +01:00
|
|
|
|
assert [
|
2020-10-27 15:16:27 +00:00
|
|
|
|
normalize_spaces(row.text)
|
|
|
|
|
|
for row in page.select('.ajax-block-container')[0].select('.file-list')
|
2020-10-13 11:40:20 +01:00
|
|
|
|
] == [
|
2021-04-08 13:46:40 +01:00
|
|
|
|
'Example template This is a test Yesterday at 2:20pm England Scotland',
|
|
|
|
|
|
'Example template This is a test Yesterday at 2:20am England Scotland',
|
2020-10-13 11:40:20 +01:00
|
|
|
|
]
|
|
|
|
|
|
|
2021-01-18 16:46:13 +00:00
|
|
|
|
button = page.select_one(
|
|
|
|
|
|
'.js-stick-at-bottom-when-scrolling a.govuk-button.govuk-button--secondary'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(button.text) == 'New alert'
|
|
|
|
|
|
assert button['href'] == url_for(
|
|
|
|
|
|
'main.new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2020-10-13 11:40:20 +01:00
|
|
|
|
|
2021-04-08 13:09:29 +01:00
|
|
|
|
@freeze_time('2020-02-20 02:20')
|
|
|
|
|
|
def test_rejected_broadcasts_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_broadcast_messages,
|
|
|
|
|
|
mock_get_service_templates,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.broadcast_dashboard_rejected',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(page.select_one('main h1').text) == (
|
|
|
|
|
|
'Rejected alerts'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert len(page.select('.ajax-block-container')) == 1
|
|
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(row.text)
|
|
|
|
|
|
for row in page.select('.ajax-block-container')[0].select('.file-list')
|
|
|
|
|
|
] == [
|
2021-04-08 13:46:40 +01:00
|
|
|
|
'Example template This is a test Today at 1:20am England Scotland',
|
2021-04-08 13:09:29 +01:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
button = page.select_one(
|
|
|
|
|
|
'.js-stick-at-bottom-when-scrolling a.govuk-button.govuk-button--secondary'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(button.text) == 'New alert'
|
|
|
|
|
|
assert button['href'] == url_for(
|
|
|
|
|
|
'main.new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-11-20 15:42:52 +00:00
|
|
|
|
def test_new_broadcast_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == 'New alert'
|
|
|
|
|
|
|
|
|
|
|
|
form = page.select_one('form')
|
|
|
|
|
|
assert form['method'] == 'post'
|
|
|
|
|
|
assert 'action' not in form
|
|
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
|
(
|
|
|
|
|
|
choice.select_one('input')['name'],
|
|
|
|
|
|
choice.select_one('input')['value'],
|
|
|
|
|
|
normalize_spaces(choice.select_one('label').text),
|
|
|
|
|
|
)
|
|
|
|
|
|
for choice in form.select('.govuk-radios__item')
|
|
|
|
|
|
] == [
|
|
|
|
|
|
('content', 'freeform', 'Write your own message'),
|
|
|
|
|
|
('content', 'template', 'Use a template'),
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('value, expected_redirect_endpoint', (
|
|
|
|
|
|
('freeform', 'main.write_new_broadcast'),
|
|
|
|
|
|
('template', 'main.choose_template'),
|
|
|
|
|
|
))
|
|
|
|
|
|
def test_new_broadcast_page_redirects(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
value,
|
|
|
|
|
|
expected_redirect_endpoint,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_data={
|
|
|
|
|
|
'content': value,
|
|
|
|
|
|
},
|
|
|
|
|
|
_expected_redirect=url_for(
|
|
|
|
|
|
expected_redirect_endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_new_broadcast_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.write_new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == 'New alert'
|
|
|
|
|
|
|
|
|
|
|
|
form = page.select_one('form')
|
|
|
|
|
|
assert form['method'] == 'post'
|
|
|
|
|
|
assert 'action' not in form
|
|
|
|
|
|
|
|
|
|
|
|
assert page.select_one('input[type=text]')['name'] == 'name'
|
|
|
|
|
|
|
|
|
|
|
|
assert page.select_one('textarea')['name'] == 'template_content'
|
|
|
|
|
|
assert page.select_one('textarea')['data-module'] == 'enhanced-textbox'
|
|
|
|
|
|
assert page.select_one('textarea')['data-highlight-placeholders'] == 'false'
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
page.select_one('[data-module=update-status]')['data-updates-url']
|
|
|
|
|
|
) == url_for(
|
|
|
|
|
|
'.count_content_length',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_type='broadcast',
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
page.select_one('[data-module=update-status]')['data-target']
|
|
|
|
|
|
) == (
|
|
|
|
|
|
page.select_one('textarea')['id']
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'template_content'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
page.select_one('[data-module=update-status]')['aria-live']
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'polite'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_write_new_broadcast_posts(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_create_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.write_new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_data={
|
|
|
|
|
|
'name': 'My new alert',
|
|
|
|
|
|
'template_content': 'This is a test',
|
|
|
|
|
|
},
|
|
|
|
|
|
_expected_redirect=url_for(
|
|
|
|
|
|
'.preview_broadcast_areas',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_create_broadcast_message.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
reference='My new alert',
|
|
|
|
|
|
content='This is a test',
|
|
|
|
|
|
template_id=None,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('content, expected_error_message', (
|
|
|
|
|
|
('', 'Cannot be empty'),
|
|
|
|
|
|
('ŵ' * 616, 'Content must be 615 characters or fewer because it contains ŵ'),
|
|
|
|
|
|
('w' * 1_396, 'Content must be 1,395 characters or fewer'),
|
|
|
|
|
|
('hello ((name))', 'You can’t use ((double brackets)) to personalise this message'),
|
|
|
|
|
|
))
|
|
|
|
|
|
def test_write_new_broadcast_bad_content(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_create_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
content,
|
|
|
|
|
|
expected_error_message,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.post(
|
|
|
|
|
|
'.write_new_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_data={
|
|
|
|
|
|
'name': 'My new alert',
|
|
|
|
|
|
'template_content': content,
|
|
|
|
|
|
},
|
|
|
|
|
|
_expected_status=200,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(
|
|
|
|
|
|
page.select_one('.error-message').text
|
|
|
|
|
|
) == (
|
|
|
|
|
|
expected_error_message
|
|
|
|
|
|
)
|
|
|
|
|
|
assert mock_create_broadcast_message.called is False
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
def test_broadcast_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mock_create_broadcast_message,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
template_id=fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
_expected_redirect=url_for(
|
|
|
|
|
|
'.preview_broadcast_areas',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
|
|
|
|
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
@pytest.mark.parametrize('areas_selected, areas_listed, estimates', (
|
|
|
|
|
|
([
|
|
|
|
|
|
'ctry19-E92000001',
|
|
|
|
|
|
'ctry19-S92000003',
|
|
|
|
|
|
], [
|
|
|
|
|
|
'England remove',
|
|
|
|
|
|
'Scotland remove',
|
|
|
|
|
|
], [
|
Update shapes to bring in fixes for Bristol
I emailed the Geography team at the ONS:
> Hi geography team,
>
> I work on GOV.UK Notify, which is a service run by Government Digital Service (part of the Cabinet Office). I was given your email address by [redacted] who’s been helping answer some of my questions on the cross-government Slack.
>
> We’re using some of the boundary datasets from the Open Geography Portal, and mostly they’ve been excellent.
>
> In the abstract, the problem we’re trying to solve is, given a point outside an area, what is the minimum distance to a point within that area. So, for example, if a crow was somewhere in Cardiff, what’s the shortest distance it would have to fly to reach somewhere in the Bristol local authority district?
>
> We’ve noticed some problems with the data that means our calculations would be wrong. We’ve noticed this around Torquay, Norwich and Bristol. Here are some screenshots of Bristol, from the generalised and full resolution boundaries:
>
> The artefacts I’ve highlighted are closer to Cardiff than any actual part of the land area of Bristol. They are either:
> - in the sea
> - land that’s part of North Somerset
>
> I suspect that this is being caused by the process of clipping the actual region of Bristol (which, unusually, extends into the water) to the mean high water line.
>
> I’ve worked around this by filtering out any polygons that are smaller than ~7,500m². It’s a bit hacky because parts of the Scilly Isles start disappearing. That’s not a problem for what I’m working on, but it would be nice to not need the hack.
>
> So my questions would be:
>
> - Is there a better way to remove these artefacts than filtering by area?
> - Is there a plan to remove these artefacts from the data in future releases?
>
> Thanks in advance,
> Chris
They emailed back to say:
> Hi Chris
>
> Thank you for your enquiry.
>
> We have completed the amendments to the LAD MAY 2020 BFC and BGC boundaries as mentioned so you should be able to download them from the portal now.
>
> Hope this helps.
>
> Kind regards
> [redacted]
This commit brings in the files they’ve updated. We still have to do
some filtering (but now at a higher resolution) because they haven’t
fixed Norwich yet. I’ll email them separately about that.
2020-09-24 14:37:28 +01:00
|
|
|
|
'An area of 177,439.8 square miles Will get the alert',
|
Vary bleed amount based on population density
There are basically two kinds of 4G masts:
Frequency | Range | Bandwidth
----------|-------------|----------------------------------
800MHz | Long (500m) | Low (can handle a bit of traffic)
1800Mhz | Short (5km) | High (can handle lots of traffic)
The 1800Mhz masts are better in terms of how much traffic they can
handle and how fast a connection they provide. But because they have
quite short range, it’s only economical to install them in very built up
areas†.
In more rural areas the 800MHz masts are better because they cover a
wider area, and have enough bandwidth for the lower population density.
The net effect of this is that cell broadcasts in rural areas are likely
to bleed further, because the masts they are being broadcast from are
less precise.
We can use population density as a proxy for how likely it is to be
covered by 1800Mhz masts, and therefore how much bleed we should expect.
So this commit varies the amount of bleed shown based on the population
density.
I came up with the formula based on 3 fixed points:
- The most remote areas (for example the Scottish Highlands) should have
the highest average bleed, estimated at 5km
- An town, like Crewe, should have about the same bleed as we were
estimating before (1.5km) – Pete D thinks this is about right based on
his knowledge of the area around his office in Crewe
- The most built up areas, like London boroughs, could have as little as
500m of bleed
Based on these three figures I came up with the following formula, which
roughly gives the right bleed distance (`b`) for each of their population
densities (`d`):
```
b = 5900 - (log10(d) × 1_250)
```
Plotted on a curve it looks like this:
This is based on averages – remember that the UI shows where is _likely_
to receive the alert, based on bleed, not where it’s _possible_ to
receive the alert.
Here’s what it looks like on the map:
---
†There are some additional subtleties which make this not strictly true:
- The 800Mhz masts are also used in built up areas to fill in the gaps
between the areas covered by the 1800Mhz masts
- Switching between masts is inefficient, so if you’re moving fast
through a built up area (for example on a train) your phone will only
use the 800MHz masts so that you have to handoff from one mast to
another less often
2021-03-12 09:17:42 +00:00
|
|
|
|
'An extra area of 6,392.3 square miles is Likely to get the alert',
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
'40,000,000 phones estimated',
|
|
|
|
|
|
]),
|
|
|
|
|
|
([
|
|
|
|
|
|
'wd20-E05003224',
|
|
|
|
|
|
'wd20-E05003225',
|
|
|
|
|
|
'wd20-E05003227',
|
|
|
|
|
|
'wd20-E05003228',
|
|
|
|
|
|
'wd20-E05003229',
|
|
|
|
|
|
], [
|
|
|
|
|
|
'Penrith Carleton remove',
|
|
|
|
|
|
'Penrith East remove',
|
|
|
|
|
|
'Penrith Pategill remove',
|
|
|
|
|
|
'Penrith South remove',
|
|
|
|
|
|
'Penrith West remove',
|
|
|
|
|
|
], [
|
|
|
|
|
|
'An area of 6.3 square miles Will get the alert',
|
Vary bleed amount based on population density
There are basically two kinds of 4G masts:
Frequency | Range | Bandwidth
----------|-------------|----------------------------------
800MHz | Long (500m) | Low (can handle a bit of traffic)
1800Mhz | Short (5km) | High (can handle lots of traffic)
The 1800Mhz masts are better in terms of how much traffic they can
handle and how fast a connection they provide. But because they have
quite short range, it’s only economical to install them in very built up
areas†.
In more rural areas the 800MHz masts are better because they cover a
wider area, and have enough bandwidth for the lower population density.
The net effect of this is that cell broadcasts in rural areas are likely
to bleed further, because the masts they are being broadcast from are
less precise.
We can use population density as a proxy for how likely it is to be
covered by 1800Mhz masts, and therefore how much bleed we should expect.
So this commit varies the amount of bleed shown based on the population
density.
I came up with the formula based on 3 fixed points:
- The most remote areas (for example the Scottish Highlands) should have
the highest average bleed, estimated at 5km
- An town, like Crewe, should have about the same bleed as we were
estimating before (1.5km) – Pete D thinks this is about right based on
his knowledge of the area around his office in Crewe
- The most built up areas, like London boroughs, could have as little as
500m of bleed
Based on these three figures I came up with the following formula, which
roughly gives the right bleed distance (`b`) for each of their population
densities (`d`):
```
b = 5900 - (log10(d) × 1_250)
```
Plotted on a curve it looks like this:
This is based on averages – remember that the UI shows where is _likely_
to receive the alert, based on bleed, not where it’s _possible_ to
receive the alert.
Here’s what it looks like on the map:
---
†There are some additional subtleties which make this not strictly true:
- The 800Mhz masts are also used in built up areas to fill in the gaps
between the areas covered by the 1800Mhz masts
- Switching between masts is inefficient, so if you’re moving fast
through a built up area (for example on a train) your phone will only
use the 800MHz masts so that you have to handoff from one mast to
another less often
2021-03-12 09:17:42 +00:00
|
|
|
|
'An extra area of 22.6 square miles is Likely to get the alert',
|
|
|
|
|
|
'9,000 to 40,000 phones',
|
|
|
|
|
|
]),
|
|
|
|
|
|
([
|
|
|
|
|
|
'lad20-E09000019',
|
|
|
|
|
|
], [
|
|
|
|
|
|
'Islington remove',
|
|
|
|
|
|
], [
|
|
|
|
|
|
'An area of 9.7 square miles Will get the alert',
|
2021-03-19 15:28:13 +00:00
|
|
|
|
'An extra area of 4.7 square miles is Likely to get the alert',
|
Vary bleed amount based on population density
There are basically two kinds of 4G masts:
Frequency | Range | Bandwidth
----------|-------------|----------------------------------
800MHz | Long (500m) | Low (can handle a bit of traffic)
1800Mhz | Short (5km) | High (can handle lots of traffic)
The 1800Mhz masts are better in terms of how much traffic they can
handle and how fast a connection they provide. But because they have
quite short range, it’s only economical to install them in very built up
areas†.
In more rural areas the 800MHz masts are better because they cover a
wider area, and have enough bandwidth for the lower population density.
The net effect of this is that cell broadcasts in rural areas are likely
to bleed further, because the masts they are being broadcast from are
less precise.
We can use population density as a proxy for how likely it is to be
covered by 1800Mhz masts, and therefore how much bleed we should expect.
So this commit varies the amount of bleed shown based on the population
density.
I came up with the formula based on 3 fixed points:
- The most remote areas (for example the Scottish Highlands) should have
the highest average bleed, estimated at 5km
- An town, like Crewe, should have about the same bleed as we were
estimating before (1.5km) – Pete D thinks this is about right based on
his knowledge of the area around his office in Crewe
- The most built up areas, like London boroughs, could have as little as
500m of bleed
Based on these three figures I came up with the following formula, which
roughly gives the right bleed distance (`b`) for each of their population
densities (`d`):
```
b = 5900 - (log10(d) × 1_250)
```
Plotted on a curve it looks like this:
This is based on averages – remember that the UI shows where is _likely_
to receive the alert, based on bleed, not where it’s _possible_ to
receive the alert.
Here’s what it looks like on the map:
---
†There are some additional subtleties which make this not strictly true:
- The 800Mhz masts are also used in built up areas to fill in the gaps
between the areas covered by the 1800Mhz masts
- Switching between masts is inefficient, so if you’re moving fast
through a built up area (for example on a train) your phone will only
use the 800MHz masts so that you have to handoff from one mast to
another less often
2021-03-12 09:17:42 +00:00
|
|
|
|
'200,000 to 300,000 phones',
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
]),
|
|
|
|
|
|
))
|
2020-07-06 10:53:14 +01:00
|
|
|
|
def test_preview_broadcast_areas_page(
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
mocker,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
fake_uuid,
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
areas_selected,
|
|
|
|
|
|
areas_listed,
|
|
|
|
|
|
estimates,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
status='draft',
|
|
|
|
|
|
areas=areas_selected,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2020-09-08 16:35:03 +01:00
|
|
|
|
page = client_request.get(
|
2020-07-06 10:53:14 +01:00
|
|
|
|
'.preview_broadcast_areas',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
2020-09-08 16:35:03 +01:00
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(item.text)
|
|
|
|
|
|
for item in page.select('ul.area-list li.area-list-item')
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
] == areas_listed
|
2020-09-08 16:35:03 +01:00
|
|
|
|
|
2020-10-05 13:47:21 +01:00
|
|
|
|
assert len(page.select('#area-list-map')) == 1
|
2020-09-08 16:35:03 +01:00
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(item.text)
|
2020-10-05 13:47:21 +01:00
|
|
|
|
for item in page.select('ul li.area-list-key')
|
Make estimated phone count clearer
We’ve had some feedback from user research that difference between
‘will get alert’ and ‘likely to get alert’ is not clear, and it’s hard
to tell if the latter is inclusive of the former. This leads people to
question the validity of these numbers, which is important, because an
the estimate should give you some idea of the impact of what you’re
about to do.
This commit reformats the number as a range, for example 1,000 to 2,000
phones.
If the range is small, eg 40,000,000 to 40,800,000 then this suggests
a false level of accuracy. So instead we just give one number and say
it’s an estimate, eg ‘40,000,000 phones estimated’
2020-09-24 15:52:18 +01:00
|
|
|
|
] == estimates
|
2020-09-08 16:35:03 +01:00
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
2021-03-18 23:02:32 +00:00
|
|
|
|
@pytest.mark.parametrize('polygons, expected_list_items', (
|
|
|
|
|
|
(
|
|
|
|
|
|
[
|
|
|
|
|
|
[[1, 2], [3, 4], [5, 6]],
|
|
|
|
|
|
[[7, 8], [9, 10], [11, 12]],
|
|
|
|
|
|
],
|
|
|
|
|
|
[
|
|
|
|
|
|
'An area of 722.3 square miles Will get the alert',
|
|
|
|
|
|
'An extra area of 1,498.5 square miles is Likely to get the alert',
|
|
|
|
|
|
'Unknown number of phones',
|
|
|
|
|
|
]
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
[BRISTOL],
|
|
|
|
|
|
[
|
|
|
|
|
|
'An area of 6.6 square miles Will get the alert',
|
|
|
|
|
|
'An extra area of 6.4 square miles is Likely to get the alert',
|
|
|
|
|
|
'70,000 to 100,000 phones',
|
|
|
|
|
|
]
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
[SKYE],
|
|
|
|
|
|
[
|
|
|
|
|
|
'An area of 3,205.0 square miles Will get the alert',
|
|
|
|
|
|
'An extra area of 763.4 square miles is Likely to get the alert',
|
|
|
|
|
|
'4,000 to 5,000 phones',
|
|
|
|
|
|
]
|
|
|
|
|
|
),
|
|
|
|
|
|
))
|
2021-01-26 10:14:04 +00:00
|
|
|
|
def test_preview_broadcast_areas_page_with_custom_polygons(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
fake_uuid,
|
2021-03-18 23:02:32 +00:00
|
|
|
|
polygons,
|
|
|
|
|
|
expected_list_items,
|
2021-01-26 10:14:04 +00:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
status='draft',
|
|
|
|
|
|
areas=['Area one', 'Area two', 'Area three'],
|
2021-03-18 23:02:32 +00:00
|
|
|
|
simple_polygons=polygons,
|
2021-01-26 10:14:04 +00:00
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.preview_broadcast_areas',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(item.text)
|
|
|
|
|
|
for item in page.select('ul.area-list li.area-list-item')
|
|
|
|
|
|
] == [
|
|
|
|
|
|
'Area one remove', 'Area two remove', 'Area three remove',
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
assert len(page.select('#area-list-map')) == 1
|
|
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(item.text)
|
|
|
|
|
|
for item in page.select('ul li.area-list-key')
|
2021-03-18 23:02:32 +00:00
|
|
|
|
] == expected_list_items
|
2021-01-26 10:14:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
@pytest.mark.parametrize('areas, expected_list', (
|
|
|
|
|
|
([], [
|
|
|
|
|
|
'Countries',
|
|
|
|
|
|
'Local authorities',
|
2021-02-19 10:43:24 +00:00
|
|
|
|
'Test areas',
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
]),
|
|
|
|
|
|
([
|
|
|
|
|
|
# Countries have no parent areas
|
|
|
|
|
|
'ctry19-E92000001',
|
|
|
|
|
|
'ctry19-S92000003',
|
|
|
|
|
|
], [
|
|
|
|
|
|
'Countries',
|
|
|
|
|
|
'Local authorities',
|
2021-02-19 10:43:24 +00:00
|
|
|
|
'Test areas',
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
]),
|
|
|
|
|
|
([
|
|
|
|
|
|
# If you’ve chosen the whole of a county or unitary authority
|
|
|
|
|
|
# there’s no reason to also pick districts of it
|
|
|
|
|
|
'ctyua19-E10000013', # Gloucestershire, a county
|
|
|
|
|
|
'lad20-E06000052', # Cornwall, a unitary authority
|
|
|
|
|
|
], [
|
|
|
|
|
|
'Countries',
|
|
|
|
|
|
'Local authorities',
|
2021-02-19 10:43:24 +00:00
|
|
|
|
'Test areas',
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
]),
|
|
|
|
|
|
([
|
|
|
|
|
|
'wd20-E05004299', # Pitville, in Cheltenham, in Gloucestershire
|
|
|
|
|
|
'wd20-E05004290', # Benhall and the Reddings, in Cheltenham, in Gloucestershire
|
|
|
|
|
|
'wd20-E05010951', # Abbeymead, in Gloucester, in Gloucestershire
|
|
|
|
|
|
'wd20-S13002775', # Shetland Central, in Shetland Isles
|
|
|
|
|
|
'lad20-E07000037', # High Peak, a district in Derbyshire
|
|
|
|
|
|
], [
|
|
|
|
|
|
'Cheltenham',
|
|
|
|
|
|
'Derbyshire',
|
|
|
|
|
|
'Gloucester',
|
|
|
|
|
|
'Gloucestershire',
|
|
|
|
|
|
'Shetland Islands',
|
|
|
|
|
|
# ---
|
|
|
|
|
|
'Countries',
|
|
|
|
|
|
'Local authorities',
|
2021-02-19 10:43:24 +00:00
|
|
|
|
'Test areas',
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
]),
|
|
|
|
|
|
))
|
2020-07-06 10:53:14 +01:00
|
|
|
|
def test_choose_broadcast_library_page(
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
mocker,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
fake_uuid,
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
areas,
|
|
|
|
|
|
expected_list,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
status='draft',
|
|
|
|
|
|
areas=areas,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2020-07-08 16:02:16 +01:00
|
|
|
|
page = client_request.get(
|
2020-07-06 10:53:14 +01:00
|
|
|
|
'.choose_broadcast_library',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
)
|
2020-08-10 13:04:03 +01:00
|
|
|
|
|
2020-08-13 12:27:55 +01:00
|
|
|
|
assert [
|
2020-08-10 13:04:03 +01:00
|
|
|
|
normalize_spaces(title.text)
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
for title in page.select('main a.govuk-link')
|
|
|
|
|
|
] == expected_list
|
2020-08-10 13:04:03 +01:00
|
|
|
|
|
2020-08-13 12:27:55 +01:00
|
|
|
|
assert normalize_spaces(page.select('.file-list-hint-large')[0].text) == (
|
2020-09-09 17:35:17 +01:00
|
|
|
|
'England, Northern Ireland, Scotland and Wales'
|
2020-08-11 11:33:27 +01:00
|
|
|
|
)
|
2020-08-10 13:04:03 +01:00
|
|
|
|
|
2020-07-08 16:02:16 +01:00
|
|
|
|
assert page.select_one('a.file-list-filename-large.govuk-link')['href'] == url_for(
|
|
|
|
|
|
'.choose_broadcast_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-08-13 12:27:55 +01:00
|
|
|
|
library_slug='ctry19',
|
2020-07-08 16:02:16 +01:00
|
|
|
|
)
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
Suggest previously-used areas when adding new area
If you’re adding another area to your broadcast it’s likely to be close
to one of the areas you’ve already added.
But we make you start by choosing a library, then you have to find the
local authority again from the long list. This is clunky, and it
interrupts the task the user is trying to complete.
We thought about redirecting you somewhere deep into the hierarchy,
perhaps by sending you to either:
- the parent of the last area you’d chosen
- the common ancestor of all the areas you’d chosen
This approach would however mean you’d need a way to navigate back up
the hierarchy if we’d dropped you in the wrong place. And we don’t have
a pattern for that at the moment.
So instead this commit adds some ‘shortcuts’ to the chose library page,
giving you a choice of all the parents of the areas you’ve currently
selected. In most cases this will be one (unitary authority) or two
(county and district) choices, but it will scale to adding areas from
multiple different authorities.
It does mean an extra click compared to the redirect approach, but this
is still fewer, easier clicks compared to now.
This meant a couple of under-the-hood changes:
- making `BroadcastArea`s hashable so it’s possible to do
`set([BroadcastArea(…), BroadcastArea(…), BroadcastArea(…)])`
- making `BroadcastArea`s aware of which library they live in, so we can
link to the correct _Choose area_ page
2020-09-21 18:55:46 +01:00
|
|
|
|
def test_suggested_area_has_correct_link(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
status='draft',
|
|
|
|
|
|
areas=[
|
|
|
|
|
|
'wd20-E05004299', # Pitville, a ward of Cheltenham
|
|
|
|
|
|
],
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.choose_broadcast_library',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
link = page.select_one('main a.govuk-link')
|
|
|
|
|
|
|
|
|
|
|
|
assert link.text == 'Cheltenham'
|
|
|
|
|
|
assert link['href'] == url_for(
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
|
|
|
|
|
area_slug='lad20-E07000078',
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
def test_choose_broadcast_area_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2020-07-31 16:20:37 +01:00
|
|
|
|
page = client_request.get(
|
2020-07-06 10:53:14 +01:00
|
|
|
|
'.choose_broadcast_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-08-13 12:25:22 +01:00
|
|
|
|
library_slug='ctry19',
|
2020-07-06 10:53:14 +01:00
|
|
|
|
)
|
2020-08-13 17:33:58 +01:00
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == (
|
|
|
|
|
|
'Choose countries'
|
|
|
|
|
|
)
|
2020-07-31 16:20:37 +01:00
|
|
|
|
assert [
|
|
|
|
|
|
(
|
|
|
|
|
|
choice.select_one('input')['value'],
|
|
|
|
|
|
normalize_spaces(choice.select_one('label').text),
|
|
|
|
|
|
)
|
|
|
|
|
|
for choice in page.select('form[method=post] .govuk-checkboxes__item')
|
|
|
|
|
|
] == [
|
2020-08-13 12:25:22 +01:00
|
|
|
|
('ctry19-E92000001', 'England'),
|
|
|
|
|
|
('ctry19-N92000002', 'Northern Ireland'),
|
|
|
|
|
|
('ctry19-S92000003', 'Scotland'),
|
|
|
|
|
|
('ctry19-W92000004', 'Wales'),
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_choose_broadcast_area_page_for_area_with_sub_areas(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.choose_broadcast_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
)
|
2020-08-13 17:33:58 +01:00
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == (
|
|
|
|
|
|
'Choose a local authority'
|
|
|
|
|
|
)
|
2020-08-12 16:33:00 +01:00
|
|
|
|
live_search = page.select_one("[data-module=live-search]")
|
|
|
|
|
|
assert live_search['data-targets'] == '.file-list-item'
|
|
|
|
|
|
assert live_search.select_one('input')['type'] == 'search'
|
2020-07-31 16:20:37 +01:00
|
|
|
|
partial_url_for = partial(
|
|
|
|
|
|
url_for,
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
)
|
|
|
|
|
|
choices = [
|
|
|
|
|
|
(
|
|
|
|
|
|
choice.select_one('a.file-list-filename-large')['href'],
|
|
|
|
|
|
normalize_spaces(choice.text),
|
|
|
|
|
|
)
|
|
|
|
|
|
for choice in page.select('.file-list-item')
|
|
|
|
|
|
]
|
2020-09-07 21:57:05 +01:00
|
|
|
|
assert len(choices) == 394
|
2020-09-15 13:53:38 +01:00
|
|
|
|
|
|
|
|
|
|
assert choices[0] == (partial_url_for(area_slug='lad20-S12000033'), 'Aberdeen City',)
|
|
|
|
|
|
# note: we don't populate prev_area_slug query param, so the back link will come here rather than to a county page,
|
|
|
|
|
|
# even though ashford belongs to kent
|
|
|
|
|
|
assert choices[12] == (partial_url_for(area_slug='lad20-E07000105'), 'Ashford',)
|
|
|
|
|
|
assert choices[-1] == (partial_url_for(area_slug='lad20-E06000014'), 'York',)
|
2020-07-31 16:20:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
def test_choose_broadcast_sub_area_page_for_district_shows_checkboxes_for_wards(
|
2020-07-31 16:20:37 +01:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
2020-08-13 12:25:22 +01:00
|
|
|
|
area_slug='lad20-S12000033',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == (
|
|
|
|
|
|
'Choose an area of Aberdeen City'
|
|
|
|
|
|
)
|
2020-08-12 16:33:00 +01:00
|
|
|
|
live_search = page.select_one("[data-module=live-search]")
|
2020-08-26 10:59:29 +01:00
|
|
|
|
assert live_search['data-targets'] == '#sub-areas .govuk-checkboxes__item'
|
2020-08-12 16:33:00 +01:00
|
|
|
|
assert live_search.select_one('input')['type'] == 'search'
|
2020-08-26 10:59:29 +01:00
|
|
|
|
all_choices = [
|
2020-07-31 16:20:37 +01:00
|
|
|
|
(
|
|
|
|
|
|
choice.select_one('input')['value'],
|
|
|
|
|
|
normalize_spaces(choice.select_one('label').text),
|
|
|
|
|
|
)
|
|
|
|
|
|
for choice in page.select('form[method=post] .govuk-checkboxes__item')
|
|
|
|
|
|
]
|
2020-08-26 10:59:29 +01:00
|
|
|
|
sub_choices = [
|
|
|
|
|
|
(
|
|
|
|
|
|
choice.select_one('input')['value'],
|
|
|
|
|
|
normalize_spaces(choice.select_one('label').text),
|
|
|
|
|
|
)
|
|
|
|
|
|
for choice in page.select('form[method=post] #sub-areas .govuk-checkboxes__item')
|
|
|
|
|
|
]
|
|
|
|
|
|
assert all_choices[:3] == [
|
2020-07-31 16:20:37 +01:00
|
|
|
|
('y', 'All of Aberdeen City'),
|
2020-08-13 12:25:22 +01:00
|
|
|
|
('wd20-S13002845', 'Airyhall/Broomhill/Garthdee'),
|
|
|
|
|
|
('wd20-S13002836', 'Bridge of Don'),
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]
|
2020-08-26 10:59:29 +01:00
|
|
|
|
assert sub_choices[:3] == [
|
|
|
|
|
|
('wd20-S13002845', 'Airyhall/Broomhill/Garthdee'),
|
|
|
|
|
|
('wd20-S13002836', 'Bridge of Don'),
|
|
|
|
|
|
('wd20-S13002835', 'Dyce/Bucksburn/Danestone'),
|
|
|
|
|
|
]
|
|
|
|
|
|
assert all_choices[-1:] == sub_choices[-1:] == [
|
2020-08-13 12:25:22 +01:00
|
|
|
|
('wd20-S13002846', 'Torry/Ferryhill'),
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
2020-09-15 13:53:38 +01:00
|
|
|
|
@pytest.mark.parametrize('prev_area_slug, expected_back_link_url, expected_back_link_extra_kwargs', [
|
|
|
|
|
|
(
|
|
|
|
|
|
'ctyua19-E10000016',
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
{
|
|
|
|
|
|
'area_slug': 'ctyua19-E10000016' # Kent
|
|
|
|
|
|
}
|
|
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
None,
|
|
|
|
|
|
'.choose_broadcast_area',
|
|
|
|
|
|
{}
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
])
|
|
|
|
|
|
def test_choose_broadcast_sub_area_page_for_district_has_back_link(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
prev_area_slug,
|
|
|
|
|
|
expected_back_link_url,
|
|
|
|
|
|
expected_back_link_extra_kwargs
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=str(uuid.UUID(int=0)),
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
|
|
|
|
|
area_slug='lad20-E07000105', # Ashford
|
|
|
|
|
|
prev_area_slug=prev_area_slug,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == (
|
|
|
|
|
|
'Choose an area of Ashford'
|
|
|
|
|
|
)
|
|
|
|
|
|
back_link = page.select_one('.govuk-back-link')
|
|
|
|
|
|
assert back_link['href'] == url_for(
|
|
|
|
|
|
expected_back_link_url,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=str(uuid.UUID(int=0)),
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
|
|
|
|
|
**expected_back_link_extra_kwargs
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
def test_choose_broadcast_sub_area_page_for_county_shows_links_for_districts(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
|
|
|
|
|
area_slug='ctyua19-E10000016', # Kent
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.select_one('h1').text) == (
|
|
|
|
|
|
'Choose an area of Kent'
|
|
|
|
|
|
)
|
|
|
|
|
|
live_search = page.select_one("[data-module=live-search]")
|
|
|
|
|
|
assert live_search['data-targets'] == '.file-list-item'
|
|
|
|
|
|
assert live_search.select_one('input')['type'] == 'search'
|
|
|
|
|
|
all_choices_checkbox = [
|
|
|
|
|
|
(
|
|
|
|
|
|
choice.select_one('input')['value'],
|
|
|
|
|
|
normalize_spaces(choice.select_one('label').text),
|
|
|
|
|
|
)
|
|
|
|
|
|
for choice in page.select('form[method=post] .govuk-checkboxes__item')
|
|
|
|
|
|
]
|
|
|
|
|
|
districts = [
|
|
|
|
|
|
(
|
|
|
|
|
|
district['href'],
|
|
|
|
|
|
district.text,
|
|
|
|
|
|
)
|
|
|
|
|
|
for district in page.select('form[method=post] a')
|
|
|
|
|
|
]
|
|
|
|
|
|
assert all_choices_checkbox == [
|
|
|
|
|
|
('y', 'All of Kent'),
|
|
|
|
|
|
]
|
|
|
|
|
|
assert len(districts) == 12
|
|
|
|
|
|
assert districts[0][0] == url_for(
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
2020-09-15 13:53:38 +01:00
|
|
|
|
area_slug='lad20-E07000105',
|
|
|
|
|
|
prev_area_slug='ctyua19-E10000016', # Kent
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
)
|
|
|
|
|
|
assert districts[0][1] == 'Ashford'
|
|
|
|
|
|
assert districts[-1][0] == url_for(
|
|
|
|
|
|
'main.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
2020-09-15 13:53:38 +01:00
|
|
|
|
area_slug='lad20-E07000116',
|
|
|
|
|
|
prev_area_slug='ctyua19-E10000016', # Kent
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
)
|
|
|
|
|
|
assert districts[-1][1] == 'Tunbridge Wells'
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-09 10:33:50 +01:00
|
|
|
|
def test_add_broadcast_area(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
2020-09-02 14:54:00 +01:00
|
|
|
|
mocker
|
2020-07-09 10:33:50 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2020-09-02 14:54:00 +01:00
|
|
|
|
polygon_class = namedtuple("polygon_class", ["as_coordinate_pairs_lat_long"])
|
|
|
|
|
|
coordinates = [[50.1, 0.1], [50.2, 0.2], [50.3, 0.2]]
|
|
|
|
|
|
polygons = polygon_class(as_coordinate_pairs_lat_long=coordinates)
|
|
|
|
|
|
mocker.patch('app.models.broadcast_message.BroadcastMessage.get_simple_polygons', return_value=polygons)
|
|
|
|
|
|
|
2020-07-09 10:33:50 +01:00
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.choose_broadcast_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-08-13 12:25:22 +01:00
|
|
|
|
library_slug='ctry19',
|
2020-07-09 10:33:50 +01:00
|
|
|
|
_data={
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'areas': ['ctry19-E92000001', 'ctry19-W92000004']
|
2020-07-09 10:33:50 +01:00
|
|
|
|
}
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_update_broadcast_message.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
data={
|
2020-09-02 14:54:00 +01:00
|
|
|
|
'areas': ['ctry19-E92000001', 'ctry19-S92000003', 'ctry19-W92000004'], 'simple_polygons': coordinates
|
2020-07-09 10:33:50 +01:00
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-31 16:20:37 +01:00
|
|
|
|
@pytest.mark.parametrize('post_data, expected_selected', (
|
|
|
|
|
|
({
|
|
|
|
|
|
'select_all': 'y',
|
|
|
|
|
|
'areas': [
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'wd20-S13002845',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]
|
|
|
|
|
|
}, [
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'lad20-S12000033',
|
|
|
|
|
|
# wd20-S13002845 is ignored because the user chose ‘Select all…’
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]),
|
|
|
|
|
|
({
|
|
|
|
|
|
'areas': [
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'wd20-S13002845',
|
|
|
|
|
|
'wd20-S13002836',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]
|
|
|
|
|
|
}, [
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'wd20-S13002845',
|
|
|
|
|
|
'wd20-S13002836',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
]),
|
|
|
|
|
|
))
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
def test_add_broadcast_sub_area_district_view(
|
2020-07-31 16:20:37 +01:00
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
post_data,
|
|
|
|
|
|
expected_selected,
|
2020-09-02 14:54:00 +01:00
|
|
|
|
mocker
|
2020-07-31 16:20:37 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2020-09-02 14:54:00 +01:00
|
|
|
|
polygon_class = namedtuple("polygon_class", ["as_coordinate_pairs_lat_long"])
|
|
|
|
|
|
coordinates = [[50.1, 0.1], [50.2, 0.2], [50.3, 0.2]]
|
|
|
|
|
|
polygons = polygon_class(as_coordinate_pairs_lat_long=coordinates)
|
|
|
|
|
|
mocker.patch('app.models.broadcast_message.BroadcastMessage.get_simple_polygons', return_value=polygons)
|
|
|
|
|
|
|
2020-07-31 16:20:37 +01:00
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
2020-08-13 12:25:22 +01:00
|
|
|
|
area_slug='lad20-S12000033',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
_data=post_data,
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_update_broadcast_message.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
data={
|
2020-09-02 14:54:00 +01:00
|
|
|
|
'simple_polygons': coordinates,
|
2020-07-31 16:20:37 +01:00
|
|
|
|
'areas': [
|
|
|
|
|
|
# These two areas are on the broadcast already
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'ctry19-E92000001',
|
|
|
|
|
|
'ctry19-S92000003',
|
2020-07-31 16:20:37 +01:00
|
|
|
|
] + expected_selected
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
add counties page
What was previously ward -> local authority is now a ward -> local
authority -> county. County only covers rural counties and not
metropolitan boroughs and other unitary authorities. Previously, there
was a page full of local authorities (unitary authorities and
districts), and each one of those would have a list of electoral wards.
However, now there are counties that contain a list of districts - so
this needs a new page - a checkbox for "select the county" and then a
list of links to district pages.
If you want to select multiple districts, you'll need to go into each
one of those sub-sections in turn and click select all.
Needed to tweak the query to retrieve the list of areas in a list for a
library. Previously, it just returned anything at top level (ie: didn't
have a parent). However, rural districts now have parents (the rural
counties themselves). So the query now returns "everything that isn't a
leaf node", or in more specific terms, everything that has at least
other row referring to it as a parent. So no electoral wards, since
they dont have any children, but yes to districts and counties.
2020-09-04 15:22:32 +01:00
|
|
|
|
def test_add_broadcast_sub_area_county_view(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
polygon_class = namedtuple("polygon_class", ["as_coordinate_pairs_lat_long"])
|
|
|
|
|
|
coordinates = [[50.1, 0.1], [50.2, 0.2], [50.3, 0.2]]
|
|
|
|
|
|
polygons = polygon_class(as_coordinate_pairs_lat_long=coordinates)
|
|
|
|
|
|
mocker.patch('app.models.broadcast_message.BroadcastMessage.get_simple_polygons', return_value=polygons)
|
|
|
|
|
|
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.choose_broadcast_sub_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
library_slug='wd20-lad20-ctyua19',
|
|
|
|
|
|
area_slug='ctyua19-E10000016', # Kent
|
|
|
|
|
|
_data={'select_all': 'y'},
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_update_broadcast_message.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
data={
|
|
|
|
|
|
'simple_polygons': coordinates,
|
|
|
|
|
|
'areas': [
|
|
|
|
|
|
# These two areas are on the broadcast already
|
|
|
|
|
|
'ctry19-E92000001',
|
|
|
|
|
|
'ctry19-S92000003',
|
|
|
|
|
|
] + [
|
|
|
|
|
|
'ctyua19-E10000016'
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
def test_remove_broadcast_area_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
2020-09-02 14:54:00 +01:00
|
|
|
|
mocker,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2020-09-02 14:54:00 +01:00
|
|
|
|
polygon_class = namedtuple("polygon_class", ["as_coordinate_pairs_lat_long"])
|
|
|
|
|
|
coordinates = [[50.1, 0.1], [50.2, 0.2], [50.3, 0.2]]
|
|
|
|
|
|
polygons = polygon_class(as_coordinate_pairs_lat_long=coordinates)
|
|
|
|
|
|
mocker.patch('app.models.broadcast_message.BroadcastMessage.get_simple_polygons', return_value=polygons)
|
|
|
|
|
|
|
2020-07-06 10:53:14 +01:00
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.remove_broadcast_area',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-08-13 12:25:22 +01:00
|
|
|
|
area_slug='ctry19-E92000001',
|
2020-07-06 10:53:14 +01:00
|
|
|
|
_expected_redirect=url_for(
|
|
|
|
|
|
'.preview_broadcast_areas',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
2020-07-09 10:33:50 +01:00
|
|
|
|
)
|
|
|
|
|
|
mock_update_broadcast_message.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
data={
|
2020-09-02 14:54:00 +01:00
|
|
|
|
'simple_polygons': coordinates,
|
2020-08-13 12:25:22 +01:00
|
|
|
|
'areas': ['ctry19-S92000003']
|
2020-07-09 10:33:50 +01:00
|
|
|
|
},
|
|
|
|
|
|
)
|
2020-07-06 10:53:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_preview_broadcast_message_page(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
2020-07-06 10:53:14 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2020-07-16 10:49:21 +01:00
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2020-07-06 10:53:14 +01:00
|
|
|
|
'.preview_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-09 10:33:50 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-16 10:49:21 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(area.text)
|
|
|
|
|
|
for area in page.select('.area-list-item.area-list-item--unremoveable')
|
|
|
|
|
|
] == [
|
|
|
|
|
|
'England',
|
|
|
|
|
|
'Scotland',
|
|
|
|
|
|
]
|
|
|
|
|
|
|
2020-10-06 10:09:25 +01:00
|
|
|
|
assert normalize_spaces(
|
|
|
|
|
|
page.select_one('h2.broadcast-message-heading').text
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Emergency alert'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2020-07-16 10:49:21 +01:00
|
|
|
|
assert normalize_spaces(
|
|
|
|
|
|
page.select_one('.broadcast-message-wrapper').text
|
|
|
|
|
|
) == (
|
2020-10-06 10:09:25 +01:00
|
|
|
|
'Emergency alert '
|
2020-07-16 10:49:21 +01:00
|
|
|
|
'This is a test'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
form = page.select_one('form')
|
|
|
|
|
|
assert form['method'] == 'post'
|
|
|
|
|
|
assert 'action' not in form
|
|
|
|
|
|
|
2020-07-09 10:33:50 +01:00
|
|
|
|
|
2020-07-16 10:49:21 +01:00
|
|
|
|
@freeze_time('2020-02-02 02:02:02')
|
2020-07-09 10:33:50 +01:00
|
|
|
|
def test_start_broadcasting(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
mock_update_broadcast_message_status,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.post(
|
|
|
|
|
|
'.preview_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-08-03 15:46:23 +01:00
|
|
|
|
_expected_redirect=url_for(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'main.view_current_broadcast',
|
2020-08-03 15:46:23 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
2020-07-09 10:33:50 +01:00
|
|
|
|
),
|
|
|
|
|
|
mock_update_broadcast_message_status.assert_called_once_with(
|
2020-07-17 08:07:43 +01:00
|
|
|
|
'pending-approval',
|
2020-07-09 10:33:50 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
2020-07-10 09:16:36 +01:00
|
|
|
|
|
|
|
|
|
|
|
2021-01-27 11:24:22 +00:00
|
|
|
|
@pytest.mark.parametrize('endpoint, created_by_api, extra_fields, expected_paragraphs', (
|
|
|
|
|
|
('.view_current_broadcast', False, {
|
2020-07-10 14:06:00 +01:00
|
|
|
|
'status': 'broadcasting',
|
|
|
|
|
|
'finishes_at': '2020-02-23T23:23:23.000000',
|
|
|
|
|
|
}, [
|
2020-10-14 14:16:16 +01:00
|
|
|
|
'Live since 20 February at 8:20pm Stop broadcasting',
|
2020-10-14 14:00:12 +01:00
|
|
|
|
'Prepared by Alice and approved by Bob.',
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'Broadcasting stops tomorrow at 11:23pm.'
|
2020-07-10 14:06:00 +01:00
|
|
|
|
]),
|
2021-01-27 11:24:22 +00:00
|
|
|
|
('.view_current_broadcast', True, {
|
|
|
|
|
|
'status': 'broadcasting',
|
|
|
|
|
|
'finishes_at': '2020-02-23T23:23:23.000000',
|
|
|
|
|
|
}, [
|
|
|
|
|
|
'Live since 20 February at 8:20pm Stop broadcasting',
|
|
|
|
|
|
'Created from an API call and approved by Alice.',
|
|
|
|
|
|
'Broadcasting stops tomorrow at 11:23pm.'
|
|
|
|
|
|
]),
|
|
|
|
|
|
('.view_previous_broadcast', False, {
|
2020-07-10 14:06:00 +01:00
|
|
|
|
'status': 'broadcasting',
|
|
|
|
|
|
'finishes_at': '2020-02-22T22:20:20.000000', # 2 mins before now()
|
|
|
|
|
|
}, [
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'Broadcast on 20 February at 8:20pm.',
|
2020-10-14 14:00:12 +01:00
|
|
|
|
'Prepared by Alice and approved by Bob.',
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'Finished broadcasting today at 10:20pm.'
|
2020-07-10 14:06:00 +01:00
|
|
|
|
]),
|
2021-01-27 11:24:22 +00:00
|
|
|
|
('.view_previous_broadcast', True, {
|
|
|
|
|
|
'status': 'broadcasting',
|
|
|
|
|
|
'finishes_at': '2020-02-22T22:20:20.000000', # 2 mins before now()
|
|
|
|
|
|
}, [
|
|
|
|
|
|
'Broadcast on 20 February at 8:20pm.',
|
|
|
|
|
|
'Created from an API call and approved by Alice.',
|
|
|
|
|
|
'Finished broadcasting today at 10:20pm.'
|
|
|
|
|
|
]),
|
|
|
|
|
|
('.view_previous_broadcast', False, {
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'status': 'completed',
|
2020-07-10 14:06:00 +01:00
|
|
|
|
'finishes_at': '2020-02-21T21:21:21.000000',
|
|
|
|
|
|
}, [
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'Broadcast on 20 February at 8:20pm.',
|
2020-10-14 14:00:12 +01:00
|
|
|
|
'Prepared by Alice and approved by Bob.',
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'Finished broadcasting yesterday at 9:21pm.',
|
2020-07-10 14:06:00 +01:00
|
|
|
|
]),
|
2021-01-27 11:24:22 +00:00
|
|
|
|
('.view_previous_broadcast', False, {
|
2020-07-10 14:06:00 +01:00
|
|
|
|
'status': 'cancelled',
|
|
|
|
|
|
'cancelled_by_id': sample_uuid,
|
|
|
|
|
|
'cancelled_at': '2020-02-21T21:21:21.000000',
|
|
|
|
|
|
}, [
|
2020-10-14 14:05:14 +01:00
|
|
|
|
'Broadcast on 20 February at 8:20pm.',
|
|
|
|
|
|
'Prepared by Alice and approved by Bob.',
|
|
|
|
|
|
'Stopped by Carol yesterday at 9:21pm.',
|
2020-07-10 14:06:00 +01:00
|
|
|
|
]),
|
2021-04-08 13:34:29 +01:00
|
|
|
|
('.view_rejected_broadcast', False, {
|
|
|
|
|
|
'status': 'rejected',
|
|
|
|
|
|
'updated_at': '2020-02-21T21:21:21.000000',
|
|
|
|
|
|
}, [
|
|
|
|
|
|
'Rejected yesterday at 9:21pm.',
|
|
|
|
|
|
'Prepared by Alice and approved by Bob.',
|
|
|
|
|
|
]),
|
2020-07-10 14:06:00 +01:00
|
|
|
|
))
|
|
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_view_broadcast_message_page(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
2020-10-15 13:24:57 +01:00
|
|
|
|
endpoint,
|
2021-01-27 11:24:22 +00:00
|
|
|
|
created_by_api,
|
2020-07-10 14:06:00 +01:00
|
|
|
|
extra_fields,
|
|
|
|
|
|
expected_paragraphs,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
2021-01-27 11:24:22 +00:00
|
|
|
|
created_by_id=None if created_by_api else fake_uuid,
|
2020-07-10 14:06:00 +01:00
|
|
|
|
approved_by_id=fake_uuid,
|
|
|
|
|
|
starts_at='2020-02-20T20:20:20.000000',
|
|
|
|
|
|
**extra_fields
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch('app.user_api_client.get_user', side_effect=[
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
user_json(name='Alice'),
|
|
|
|
|
|
user_json(name='Bob'),
|
|
|
|
|
|
user_json(name='Carol'),
|
|
|
|
|
|
])
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2020-10-15 13:24:57 +01:00
|
|
|
|
endpoint,
|
2020-07-10 14:06:00 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert [
|
|
|
|
|
|
normalize_spaces(p.text) for p in page.select('main p.govuk-body')
|
|
|
|
|
|
] == expected_paragraphs
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-10-15 13:24:57 +01:00
|
|
|
|
@pytest.mark.parametrize('endpoint', (
|
|
|
|
|
|
'.view_current_broadcast',
|
|
|
|
|
|
'.view_previous_broadcast',
|
2021-04-08 13:09:29 +01:00
|
|
|
|
'.view_rejected_broadcast',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
))
|
2020-10-26 11:06:27 +00:00
|
|
|
|
@pytest.mark.parametrize('status, expected_highlighted_navigation_item, expected_back_link_endpoint', (
|
2020-10-15 13:24:57 +01:00
|
|
|
|
(
|
|
|
|
|
|
'pending-approval',
|
|
|
|
|
|
'Current alerts',
|
2020-10-26 11:06:27 +00:00
|
|
|
|
'.broadcast_dashboard',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'broadcasting',
|
|
|
|
|
|
'Current alerts',
|
2020-10-26 11:06:27 +00:00
|
|
|
|
'.broadcast_dashboard',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'completed',
|
|
|
|
|
|
'Previous alerts',
|
2020-10-26 11:06:27 +00:00
|
|
|
|
'.broadcast_dashboard_previous',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'cancelled',
|
|
|
|
|
|
'Previous alerts',
|
2020-10-26 11:06:27 +00:00
|
|
|
|
'.broadcast_dashboard_previous',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
),
|
|
|
|
|
|
(
|
|
|
|
|
|
'rejected',
|
2021-04-08 13:09:29 +01:00
|
|
|
|
'Rejected alerts',
|
|
|
|
|
|
'.broadcast_dashboard_rejected',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
),
|
|
|
|
|
|
))
|
|
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_view_broadcast_message_shows_correct_highlighted_navigation(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
status,
|
|
|
|
|
|
expected_highlighted_navigation_item,
|
2020-10-26 11:06:27 +00:00
|
|
|
|
expected_back_link_endpoint,
|
2020-10-15 13:24:57 +01:00
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
approved_by_id=fake_uuid,
|
|
|
|
|
|
starts_at='2020-02-20T20:20:20.000000',
|
|
|
|
|
|
finishes_at='2021-12-21T21:21:21.000000',
|
|
|
|
|
|
cancelled_at='2021-01-01T01:01:01.000000',
|
2021-04-08 13:34:29 +01:00
|
|
|
|
updated_at='2021-01-01T01:01:01.000000',
|
2020-10-15 13:24:57 +01:00
|
|
|
|
status=status,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_follow_redirects=True
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert normalize_spaces(
|
|
|
|
|
|
page.select_one('.navigation .selected').text
|
|
|
|
|
|
) == (
|
|
|
|
|
|
expected_highlighted_navigation_item
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2020-10-26 11:06:27 +00:00
|
|
|
|
assert page.select_one('.govuk-back-link')['href'] == url_for(
|
|
|
|
|
|
expected_back_link_endpoint,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2020-10-15 13:24:57 +01:00
|
|
|
|
|
2020-07-17 08:07:44 +01:00
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_view_pending_broadcast(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-08-05 16:01:21 +01:00
|
|
|
|
active_user_with_permissions,
|
2020-07-17 08:07:44 +01:00
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
2020-08-20 10:08:33 +01:00
|
|
|
|
finishes_at=None,
|
2020-07-17 08:07:44 +01:00
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2020-08-05 16:01:21 +01:00
|
|
|
|
mocker.patch('app.user_api_client.get_user', side_effect=[
|
|
|
|
|
|
active_user_with_permissions, # Current user
|
|
|
|
|
|
user_json(id_=uuid.uuid4()), # User who created broadcast
|
|
|
|
|
|
])
|
2020-07-17 08:07:44 +01:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-07-17 08:07:44 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner').text)
|
|
|
|
|
|
) == (
|
2020-08-21 11:26:02 +01:00
|
|
|
|
'Test User wants to broadcast Example template '
|
|
|
|
|
|
'Start broadcasting now Reject this alert'
|
2020-07-17 08:07:44 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
form = page.select_one('form.banner')
|
|
|
|
|
|
assert form['method'] == 'post'
|
|
|
|
|
|
assert 'action' not in form
|
|
|
|
|
|
assert form.select_one('button[type=submit]')
|
|
|
|
|
|
|
2020-07-17 08:07:44 +01:00
|
|
|
|
link = form.select_one('a.govuk-link.govuk-link--destructive')
|
2020-08-21 11:26:02 +01:00
|
|
|
|
assert link.text == 'Reject this alert'
|
2020-07-17 08:07:44 +01:00
|
|
|
|
assert link['href'] == url_for(
|
|
|
|
|
|
'.reject_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-08-05 16:01:21 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-01-15 15:11:43 +00:00
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_view_pending_broadcast_without_template(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=None,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at=None,
|
|
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
reference='No template test',
|
|
|
|
|
|
content='Uh-oh',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch('app.user_api_client.get_user', side_effect=[
|
|
|
|
|
|
active_user_with_permissions, # Current user
|
|
|
|
|
|
user_json(id_=uuid.uuid4()), # User who created broadcast
|
|
|
|
|
|
])
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.view_current_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Test User wants to broadcast No template test '
|
|
|
|
|
|
'Start broadcasting now Reject this alert'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.broadcast-message-wrapper').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Emergency alert '
|
|
|
|
|
|
'Uh-oh'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-01-27 11:24:22 +00:00
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_view_pending_broadcast_from_api_call(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=None,
|
|
|
|
|
|
created_by_id=None, # No user created this broadcast
|
|
|
|
|
|
finishes_at=None,
|
|
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
reference='abc123',
|
|
|
|
|
|
content='Uh-oh',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.view_current_broadcast',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'An API call wants to broadcast abc123 '
|
|
|
|
|
|
'Start broadcasting now Reject this alert'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.broadcast-message-wrapper').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Emergency alert '
|
|
|
|
|
|
'Uh-oh'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-08-05 16:01:21 +01:00
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_cant_approve_own_broadcast(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
2020-08-21 11:26:02 +01:00
|
|
|
|
service_one['restricted'] = False
|
2020-08-05 16:01:21 +01:00
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at='2020-02-23T23:23:23.000000',
|
|
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch('app.user_api_client.get_user', side_effect=[
|
|
|
|
|
|
active_user_with_permissions, # Current user
|
|
|
|
|
|
active_user_with_permissions, # User who created broadcast (the same)
|
|
|
|
|
|
])
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-08-05 16:01:21 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
2020-08-21 11:26:02 +01:00
|
|
|
|
normalize_spaces(page.select_one('.banner h1').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Example template is waiting for approval'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner p').text)
|
2020-08-05 16:01:21 +01:00
|
|
|
|
) == (
|
2020-08-21 11:26:02 +01:00
|
|
|
|
'You need another member of your team to approve your alert.'
|
2020-08-05 16:01:21 +01:00
|
|
|
|
)
|
2020-08-21 11:26:02 +01:00
|
|
|
|
assert not page.select('form')
|
2020-08-05 16:01:21 +01:00
|
|
|
|
|
2020-08-21 11:26:02 +01:00
|
|
|
|
link = page.select_one('.banner a.govuk-link.govuk-link--destructive')
|
|
|
|
|
|
assert link.text == 'Withdraw this alert'
|
|
|
|
|
|
assert link['href'] == url_for(
|
|
|
|
|
|
'.reject_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_can_approve_own_broadcast_in_trial_mode(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at='2020-02-23T23:23:23.000000',
|
|
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
mocker.patch('app.user_api_client.get_user', side_effect=[
|
|
|
|
|
|
active_user_with_permissions, # Current user
|
|
|
|
|
|
active_user_with_permissions, # User who created broadcast (the same)
|
|
|
|
|
|
])
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-08-21 11:26:02 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner h1').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Example template is waiting for approval'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner p').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'When you use a live account you’ll need another member of '
|
|
|
|
|
|
'your team to approve your alert.'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner details summary').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Approve your own alert'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner details ').text)
|
|
|
|
|
|
) == (
|
|
|
|
|
|
'Approve your own alert '
|
|
|
|
|
|
'Because you’re in training mode you can approve your own '
|
|
|
|
|
|
'alerts, to see how it works. '
|
|
|
|
|
|
'No real alerts will be broadcast to anyone’s phone. '
|
|
|
|
|
|
'Start broadcasting now '
|
|
|
|
|
|
'Cancel this alert'
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
form = page.select_one('.banner details form')
|
|
|
|
|
|
assert form['method'] == 'post'
|
|
|
|
|
|
assert 'action' not in form
|
|
|
|
|
|
assert normalize_spaces(form.select_one('button[type=submit]').text) == (
|
|
|
|
|
|
'Start broadcasting now'
|
|
|
|
|
|
)
|
2020-08-05 16:01:21 +01:00
|
|
|
|
|
|
|
|
|
|
link = page.select_one('.banner a.govuk-link.govuk-link--destructive')
|
2020-08-21 11:26:02 +01:00
|
|
|
|
assert link.text == 'Cancel this alert'
|
2020-08-05 16:01:21 +01:00
|
|
|
|
assert link['href'] == url_for(
|
|
|
|
|
|
'.reject_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-17 08:07:44 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
2020-07-17 08:07:44 +01:00
|
|
|
|
|
2020-08-10 12:13:11 +01:00
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
2021-04-14 18:13:18 +01:00
|
|
|
|
@pytest.mark.parametrize("user_is_platform_admin", [True, False])
|
2020-08-10 12:13:11 +01:00
|
|
|
|
def test_view_only_user_cant_approve_broadcast(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
active_user_with_permissions,
|
|
|
|
|
|
active_user_view_permissions,
|
2021-04-14 18:13:18 +01:00
|
|
|
|
platform_admin_user_no_service_permissions,
|
2020-08-10 12:13:11 +01:00
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
2021-04-14 18:13:18 +01:00
|
|
|
|
user_is_platform_admin
|
2020-08-10 12:13:11 +01:00
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at='2020-02-23T23:23:23.000000',
|
|
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2021-04-14 18:13:18 +01:00
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
current_user = platform_admin_user_no_service_permissions
|
|
|
|
|
|
else:
|
|
|
|
|
|
current_user = active_user_view_permissions
|
2020-08-10 12:13:11 +01:00
|
|
|
|
mocker.patch('app.user_api_client.get_user', side_effect=[
|
2021-04-14 18:13:18 +01:00
|
|
|
|
current_user, # Current user
|
2020-08-10 12:13:11 +01:00
|
|
|
|
active_user_with_permissions, # User who created broadcast
|
|
|
|
|
|
])
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
page = client_request.get(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-08-10 12:13:11 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert (
|
|
|
|
|
|
normalize_spaces(page.select_one('.banner').text)
|
|
|
|
|
|
) == (
|
2020-08-21 11:26:02 +01:00
|
|
|
|
'This alert is waiting for approval '
|
|
|
|
|
|
'You don’t have permission to approve alerts.'
|
2020-08-10 12:13:11 +01:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert not page.select_one('form')
|
|
|
|
|
|
assert not page.select_one('.banner a')
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-09-21 09:41:19 +01:00
|
|
|
|
@pytest.mark.parametrize('trial_mode, initial_status, expected_approval, expected_redirect', (
|
|
|
|
|
|
(True, 'draft', False, partial(
|
|
|
|
|
|
url_for,
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-09-21 09:41:19 +01:00
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
)),
|
|
|
|
|
|
(True, 'pending-approval', True, partial(
|
|
|
|
|
|
url_for,
|
|
|
|
|
|
'.broadcast_tour',
|
|
|
|
|
|
step_index=6,
|
|
|
|
|
|
)),
|
|
|
|
|
|
(False, 'pending-approval', True, partial(
|
|
|
|
|
|
url_for,
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-09-21 09:41:19 +01:00
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
)),
|
|
|
|
|
|
(True, 'rejected', False, partial(
|
|
|
|
|
|
url_for,
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-09-21 09:41:19 +01:00
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
)),
|
|
|
|
|
|
(True, 'broadcasting', False, partial(
|
|
|
|
|
|
url_for,
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-09-21 09:41:19 +01:00
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
)),
|
|
|
|
|
|
(True, 'cancelled', False, partial(
|
|
|
|
|
|
url_for,
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-09-21 09:41:19 +01:00
|
|
|
|
broadcast_message_id=sample_uuid,
|
|
|
|
|
|
)),
|
2020-07-17 08:07:44 +01:00
|
|
|
|
))
|
|
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
2020-09-21 09:41:19 +01:00
|
|
|
|
def test_request_approval(
|
2020-07-17 08:07:44 +01:00
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message_status,
|
|
|
|
|
|
initial_status,
|
|
|
|
|
|
expected_approval,
|
2020-09-21 09:41:19 +01:00
|
|
|
|
trial_mode,
|
|
|
|
|
|
expected_redirect,
|
2020-07-17 08:07:44 +01:00
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at='2020-02-23T23:23:23.000000',
|
|
|
|
|
|
status=initial_status,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
2020-09-21 09:41:19 +01:00
|
|
|
|
service_one['restricted'] = trial_mode
|
2020-07-17 08:07:44 +01:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
client_request.post(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-07-17 08:07:44 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-09-21 09:41:19 +01:00
|
|
|
|
_expected_redirect=expected_redirect(
|
2020-07-17 08:07:44 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if expected_approval:
|
|
|
|
|
|
mock_update_broadcast_message.assert_called_once_with(
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
data={
|
|
|
|
|
|
'starts_at': '2020-02-22T22:22:22',
|
2021-02-12 15:49:16 +00:00
|
|
|
|
'finishes_at': '2020-02-23T02:22:22',
|
2020-07-17 08:07:44 +01:00
|
|
|
|
},
|
|
|
|
|
|
)
|
|
|
|
|
|
mock_update_broadcast_message_status.assert_called_once_with(
|
|
|
|
|
|
'broadcasting',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
else:
|
|
|
|
|
|
assert mock_update_broadcast_message.called is False
|
|
|
|
|
|
assert mock_update_broadcast_message_status.called is False
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-07-17 08:07:44 +01:00
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_reject_broadcast(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message_status,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at='2020-02-23T23:23:23.000000',
|
|
|
|
|
|
status='pending-approval',
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.reject_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_expected_redirect=url_for(
|
|
|
|
|
|
'.broadcast_dashboard',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert mock_update_broadcast_message.called is False
|
|
|
|
|
|
|
|
|
|
|
|
mock_update_broadcast_message_status.assert_called_once_with(
|
|
|
|
|
|
'rejected',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('initial_status', (
|
|
|
|
|
|
'draft',
|
|
|
|
|
|
'rejected',
|
|
|
|
|
|
'broadcasting',
|
|
|
|
|
|
'cancelled',
|
|
|
|
|
|
))
|
|
|
|
|
|
@freeze_time('2020-02-22T22:22:22.000000')
|
|
|
|
|
|
def test_cant_reject_broadcast_in_wrong_state(
|
|
|
|
|
|
mocker,
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
mock_update_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message_status,
|
|
|
|
|
|
initial_status,
|
|
|
|
|
|
):
|
|
|
|
|
|
mocker.patch(
|
|
|
|
|
|
'app.broadcast_message_api_client.get_broadcast_message',
|
|
|
|
|
|
return_value=broadcast_message_json(
|
|
|
|
|
|
id_=fake_uuid,
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
template_id=fake_uuid,
|
|
|
|
|
|
created_by_id=fake_uuid,
|
|
|
|
|
|
finishes_at='2020-02-23T23:23:23.000000',
|
|
|
|
|
|
status=initial_status,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
|
|
|
|
|
|
client_request.get(
|
|
|
|
|
|
'.reject_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-07-17 08:07:44 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
)
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
assert mock_update_broadcast_message.called is False
|
|
|
|
|
|
assert mock_update_broadcast_message_status.called is False
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-10-15 13:15:22 +01:00
|
|
|
|
@pytest.mark.parametrize('endpoint', (
|
|
|
|
|
|
'.view_current_broadcast',
|
|
|
|
|
|
'.view_previous_broadcast',
|
|
|
|
|
|
))
|
2020-07-10 14:06:00 +01:00
|
|
|
|
def test_no_view_page_for_draft(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
fake_uuid,
|
2020-10-15 13:15:22 +01:00
|
|
|
|
endpoint,
|
2020-07-10 14:06:00 +01:00
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
client_request.get(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
endpoint,
|
2020-07-10 14:06:00 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_expected_status=404,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-06 15:08:47 +01:00
|
|
|
|
@pytest.mark.parametrize("user_is_platform_admin", [True, False])
|
2020-07-10 09:16:36 +01:00
|
|
|
|
def test_cancel_broadcast(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
2020-07-20 09:27:44 +01:00
|
|
|
|
mock_get_live_broadcast_message,
|
|
|
|
|
|
mock_get_broadcast_template,
|
2020-07-10 09:16:36 +01:00
|
|
|
|
mock_update_broadcast_message_status,
|
2021-04-06 15:08:47 +01:00
|
|
|
|
platform_admin_user_no_service_permissions,
|
2020-07-10 09:16:36 +01:00
|
|
|
|
fake_uuid,
|
2021-04-06 15:08:47 +01:00
|
|
|
|
user_is_platform_admin
|
2020-07-10 09:16:36 +01:00
|
|
|
|
):
|
2021-04-06 15:08:47 +01:00
|
|
|
|
"""
|
|
|
|
|
|
users with 'send_messages' permissions and platform admins should be able to cancel broadcasts.
|
|
|
|
|
|
"""
|
2020-07-10 09:16:36 +01:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2021-04-06 15:08:47 +01:00
|
|
|
|
|
|
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
client_request.login(platform_admin_user_no_service_permissions)
|
|
|
|
|
|
|
2020-07-20 09:27:44 +01:00
|
|
|
|
page = client_request.get(
|
|
|
|
|
|
'.cancel_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
|
|
|
|
|
assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
|
|
|
|
|
|
'Are you sure you want to stop this broadcast now? '
|
|
|
|
|
|
'Yes, stop broadcasting'
|
|
|
|
|
|
)
|
|
|
|
|
|
form = page.select_one('form')
|
|
|
|
|
|
assert form['method'] == 'post'
|
|
|
|
|
|
assert 'action' not in form
|
|
|
|
|
|
assert normalize_spaces(form.select_one('button[type=submit]').text) == (
|
|
|
|
|
|
'Yes, stop broadcasting'
|
|
|
|
|
|
)
|
|
|
|
|
|
assert mock_update_broadcast_message_status.called is False
|
|
|
|
|
|
assert url_for(
|
|
|
|
|
|
'.cancel_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
) not in page
|
|
|
|
|
|
|
|
|
|
|
|
|
2021-04-06 15:08:47 +01:00
|
|
|
|
@pytest.mark.parametrize("user_is_platform_admin", [True, False])
|
2020-07-20 09:27:44 +01:00
|
|
|
|
def test_confirm_cancel_broadcast(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_live_broadcast_message,
|
|
|
|
|
|
mock_get_broadcast_template,
|
|
|
|
|
|
mock_update_broadcast_message_status,
|
2021-04-06 15:08:47 +01:00
|
|
|
|
platform_admin_user_no_service_permissions,
|
2020-07-20 09:27:44 +01:00
|
|
|
|
fake_uuid,
|
2021-04-06 15:08:47 +01:00
|
|
|
|
user_is_platform_admin
|
2020-07-20 09:27:44 +01:00
|
|
|
|
):
|
2021-04-06 15:08:47 +01:00
|
|
|
|
"""
|
|
|
|
|
|
users with 'send_messages' permissions and platform admins should be able to cancel broadcasts.
|
|
|
|
|
|
"""
|
2020-07-20 09:27:44 +01:00
|
|
|
|
service_one['permissions'] += ['broadcast']
|
2021-04-06 15:08:47 +01:00
|
|
|
|
|
|
|
|
|
|
if user_is_platform_admin:
|
|
|
|
|
|
client_request.login(platform_admin_user_no_service_permissions)
|
|
|
|
|
|
|
2020-07-20 09:27:44 +01:00
|
|
|
|
client_request.post(
|
2020-07-10 09:16:36 +01:00
|
|
|
|
'.cancel_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_previous_broadcast',
|
2020-07-10 09:16:36 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
2020-07-10 14:22:06 +01:00
|
|
|
|
broadcast_message_id=fake_uuid,
|
2020-07-10 09:16:36 +01:00
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
2020-07-20 09:27:44 +01:00
|
|
|
|
)
|
2020-07-10 09:16:36 +01:00
|
|
|
|
mock_update_broadcast_message_status.assert_called_once_with(
|
|
|
|
|
|
'cancelled',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
)
|
2020-07-20 09:27:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('method', ('post', 'get'))
|
|
|
|
|
|
def test_cant_cancel_broadcast_in_a_different_state(
|
|
|
|
|
|
client_request,
|
|
|
|
|
|
service_one,
|
|
|
|
|
|
mock_get_draft_broadcast_message,
|
|
|
|
|
|
mock_update_broadcast_message_status,
|
|
|
|
|
|
fake_uuid,
|
|
|
|
|
|
method,
|
|
|
|
|
|
):
|
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
|
getattr(client_request, method)(
|
|
|
|
|
|
'.cancel_broadcast_message',
|
|
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_expected_redirect=url_for(
|
2020-10-15 13:15:22 +01:00
|
|
|
|
'.view_current_broadcast',
|
2020-07-20 09:27:44 +01:00
|
|
|
|
service_id=SERVICE_ONE_ID,
|
|
|
|
|
|
broadcast_message_id=fake_uuid,
|
|
|
|
|
|
_external=True,
|
|
|
|
|
|
),
|
|
|
|
|
|
)
|
|
|
|
|
|
assert mock_update_broadcast_message_status.called is False
|