Files
notifications-admin/tests/app/main/views/test_broadcast.py
Chris Hill-Scott 5ae53b625b Show broadcasts created by the API
Broadcasts created by the API are different in that:
- they aren’t created by any user, so don’t have a `created_by_id`
- they are created instantly, not in steps, so don’t have an
  `updated_at` time

This commit alters the views to account for when these pieces of
information aren’t present.
2021-01-27 11:34:43 +00:00

2079 lines
59 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import json
import uuid
from collections import namedtuple
from functools import partial
import pytest
from flask import url_for
from freezegun import freeze_time
from tests import broadcast_message_json, sample_uuid, user_json
from tests.conftest import SERVICE_ONE_ID, normalize_spaces
sample_uuid = sample_uuid()
@pytest.mark.parametrize('endpoint, extra_args, expected_get_status, expected_post_status', (
(
'.broadcast_dashboard', {},
403, 405,
),
(
'.broadcast_dashboard_updates', {},
403, 405,
),
(
'.broadcast_dashboard_previous', {},
403, 405,
),
(
'.new_broadcast', {},
403, 403,
),
(
'.write_new_broadcast', {},
403, 403,
),
(
'.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': 'countries-E92000001'},
403, 405,
),
(
'.preview_broadcast_message', {'broadcast_message_id': sample_uuid},
403, 403,
),
(
'.view_current_broadcast', {'broadcast_message_id': sample_uuid},
403, 403,
),
(
'.view_previous_broadcast', {'broadcast_message_id': sample_uuid},
403, 405,
),
(
'.cancel_broadcast_message', {'broadcast_message_id': sample_uuid},
403, 403,
),
))
def test_broadcast_pages_403_without_permission(
client_request,
endpoint,
extra_args,
expected_get_status,
expected_post_status,
):
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
)
@pytest.mark.parametrize('endpoint, extra_args, expected_get_status, expected_post_status', (
(
'.new_broadcast', {},
403, 403,
),
(
'.write_new_broadcast', {},
403, 403,
),
(
'.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,
),
(
'.cancel_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,
endpoint,
extra_args,
expected_get_status,
expected_post_status,
):
service_one['permissions'] += ['broadcast']
mocker.patch('app.user_api_client.get_user', return_value=active_user_view_permissions)
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
)
@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)),
(4, 'Continue', partial(url_for, '.broadcast_tour', step_index=5)),
(5, 'Continue', partial(url_for, '.service_dashboard')),
(6, 'Continue', partial(url_for, '.service_dashboard')),
))
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),
pytest.param(4, marks=pytest.mark.xfail),
5,
6,
))
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'
)
@pytest.mark.parametrize('trial_mode, allowed_broadcast_provider, selector, expected_text, expected_tagged_text', (
(
True,
None,
'.navigation-service-type.navigation-service-type--training',
'service one Training Switch service',
'Training',
),
(
False,
None,
'.navigation-service-type.navigation-service-type--live',
'service one Live Switch service',
'Live',
),
(
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)',
),
))
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,
allowed_broadcast_provider,
selector,
expected_text,
expected_tagged_text,
):
service_one['allowed_broadcast_provider'] = allowed_broadcast_provider
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
)
@pytest.mark.parametrize('step_index', (0, 7))
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,
)
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,
),
),
def test_empty_broadcast_dashboard(
client_request,
service_one,
active_user_view_permissions,
mock_get_no_broadcast_messages,
mock_get_service_templates_when_no_templates_exist,
):
service_one['permissions'] += ['broadcast']
page = client_request.get(
'.broadcast_dashboard',
service_id=SERVICE_ONE_ID,
)
assert normalize_spaces(page.select_one('h1').text) == (
'Current alerts'
)
assert [
normalize_spaces(row.text) for row in page.select('.table-empty-message')
] == [
'You do not have any current alerts',
]
@freeze_time('2020-02-20 02:20')
def test_broadcast_dashboard(
client_request,
service_one,
mock_get_broadcast_messages,
mock_get_service_templates,
):
service_one['permissions'] += ['broadcast']
page = client_request.get(
'.broadcast_dashboard',
service_id=SERVICE_ONE_ID,
)
assert len(page.select('.ajax-block-container')) == len(page.select('h1')) == 1
assert [
normalize_spaces(row.text)
for row in page.select('.ajax-block-container')[0].select('.file-list')
] == [
'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',
]
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,
)
@pytest.mark.parametrize('endpoint', (
'.broadcast_dashboard', '.broadcast_dashboard_previous',
))
def test_broadcast_dashboard_does_not_have_button_for_view_only_user(
client_request,
service_one,
active_user_view_permissions,
mock_get_broadcast_messages,
endpoint,
):
service_one['permissions'] += ['broadcast']
client_request.login(active_user_view_permissions)
page = client_request.get(
endpoint,
service_id=SERVICE_ONE_ID,
)
assert not page.select('a.govuk-button')
@freeze_time('2020-02-20 02:20')
def test_broadcast_dashboard_json(
logged_in_client,
service_one,
active_user_view_permissions,
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))
assert json_response.keys() == {'current_broadcasts'}
assert 'Waiting for approval' in json_response['current_broadcasts']
assert 'Live since today at 2:20am' in json_response['current_broadcasts']
@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'
)
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')
] == [
'Example template This is a test Broadcast yesterday at 2:20pm England Scotland',
'Example template This is a test Broadcast yesterday at 2:20am England Scotland',
]
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,
)
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 cant 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
def test_broadcast_page(
client_request,
service_one,
fake_uuid,
mock_create_broadcast_message,
):
service_one['permissions'] += ['broadcast']
client_request.get(
'.broadcast',
service_id=SERVICE_ONE_ID,
template_id=fake_uuid,
_expected_redirect=url_for(
'.preview_broadcast_areas',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_external=True,
),
),
@pytest.mark.parametrize('areas_selected, areas_listed, estimates', (
([
'ctry19-E92000001',
'ctry19-S92000003',
], [
'England remove',
'Scotland remove',
], [
'An area of 177,439.8 square miles Will get the alert',
'An extra area of 3,058.9 square miles is Likely to get the alert',
'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',
'An extra area of 14.4 square miles is Likely to get the alert',
'9,000 to 30,000 phones',
]),
))
def test_preview_broadcast_areas_page(
mocker,
client_request,
service_one,
fake_uuid,
areas_selected,
areas_listed,
estimates,
):
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=areas_selected,
),
)
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')
] == areas_listed
assert len(page.select('#area-list-map')) == 1
assert [
normalize_spaces(item.text)
for item in page.select('ul li.area-list-key')
] == estimates
def test_preview_broadcast_areas_page_with_custom_polygons(
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=['Area one', 'Area two', 'Area three'],
simple_polygons=[
[[1, 2], [3, 4], [5, 6]],
[[7, 8], [9, 10], [11, 12]],
],
),
)
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')
] == [
'An area of 722.3 square miles Will get the alert',
'An extra area of 1,402.5 square miles is Likely to get the alert',
'Unknown number of phones',
]
@pytest.mark.parametrize('areas, expected_list', (
([], [
'Countries',
'Local authorities',
]),
([
# Countries have no parent areas
'ctry19-E92000001',
'ctry19-S92000003',
], [
'Countries',
'Local authorities',
]),
([
# If youve chosen the whole of a county or unitary authority
# theres no reason to also pick districts of it
'ctyua19-E10000013', # Gloucestershire, a county
'lad20-E06000052', # Cornwall, a unitary authority
], [
'Countries',
'Local authorities',
]),
([
'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',
]),
))
def test_choose_broadcast_library_page(
mocker,
client_request,
service_one,
fake_uuid,
areas,
expected_list,
):
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=areas,
),
)
page = client_request.get(
'.choose_broadcast_library',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
)
assert [
normalize_spaces(title.text)
for title in page.select('main a.govuk-link')
] == expected_list
assert normalize_spaces(page.select('.file-list-hint-large')[0].text) == (
'England, Northern Ireland, Scotland and Wales'
)
assert page.select_one('a.file-list-filename-large.govuk-link')['href'] == url_for(
'.choose_broadcast_area',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
library_slug='ctry19',
)
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',
)
def test_choose_broadcast_area_page(
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,
library_slug='ctry19',
)
assert normalize_spaces(page.select_one('h1').text) == (
'Choose countries'
)
assert [
(
choice.select_one('input')['value'],
normalize_spaces(choice.select_one('label').text),
)
for choice in page.select('form[method=post] .govuk-checkboxes__item')
] == [
('ctry19-E92000001', 'England'),
('ctry19-N92000002', 'Northern Ireland'),
('ctry19-S92000003', 'Scotland'),
('ctry19-W92000004', 'Wales'),
]
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,
library_slug='wd20-lad20-ctyua19',
)
assert normalize_spaces(page.select_one('h1').text) == (
'Choose a local authority'
)
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'
partial_url_for = partial(
url_for,
'main.choose_broadcast_sub_area',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
library_slug='wd20-lad20-ctyua19',
)
choices = [
(
choice.select_one('a.file-list-filename-large')['href'],
normalize_spaces(choice.text),
)
for choice in page.select('.file-list-item')
]
assert len(choices) == 394
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',)
def test_choose_broadcast_sub_area_page_for_district_shows_checkboxes_for_wards(
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='lad20-S12000033',
)
assert normalize_spaces(page.select_one('h1').text) == (
'Choose an area of Aberdeen City'
)
live_search = page.select_one("[data-module=live-search]")
assert live_search['data-targets'] == '#sub-areas .govuk-checkboxes__item'
assert live_search.select_one('input')['type'] == 'search'
all_choices = [
(
choice.select_one('input')['value'],
normalize_spaces(choice.select_one('label').text),
)
for choice in page.select('form[method=post] .govuk-checkboxes__item')
]
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] == [
('y', 'All of Aberdeen City'),
('wd20-S13002845', 'Airyhall/Broomhill/Garthdee'),
('wd20-S13002836', 'Bridge of Don'),
]
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:] == [
('wd20-S13002846', 'Torry/Ferryhill'),
]
@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
)
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',
area_slug='lad20-E07000105',
prev_area_slug='ctyua19-E10000016', # Kent
)
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',
area_slug='lad20-E07000116',
prev_area_slug='ctyua19-E10000016', # Kent
)
assert districts[-1][1] == 'Tunbridge Wells'
def test_add_broadcast_area(
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_area',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
library_slug='ctry19',
_data={
'areas': ['ctry19-E92000001', 'ctry19-W92000004']
}
)
mock_update_broadcast_message.assert_called_once_with(
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
data={
'areas': ['ctry19-E92000001', 'ctry19-S92000003', 'ctry19-W92000004'], 'simple_polygons': coordinates
},
)
@pytest.mark.parametrize('post_data, expected_selected', (
({
'select_all': 'y',
'areas': [
'wd20-S13002845',
]
}, [
'lad20-S12000033',
# wd20-S13002845 is ignored because the user chose Select all…
]),
({
'areas': [
'wd20-S13002845',
'wd20-S13002836',
]
}, [
'wd20-S13002845',
'wd20-S13002836',
]),
))
def test_add_broadcast_sub_area_district_view(
client_request,
service_one,
mock_get_draft_broadcast_message,
mock_update_broadcast_message,
fake_uuid,
post_data,
expected_selected,
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='lad20-S12000033',
_data=post_data,
)
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',
] + expected_selected
},
)
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'
]
},
)
def test_remove_broadcast_area_page(
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.get(
'.remove_broadcast_area',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
area_slug='ctry19-E92000001',
_expected_redirect=url_for(
'.preview_broadcast_areas',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_external=True,
),
)
mock_update_broadcast_message.assert_called_once_with(
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
data={
'simple_polygons': coordinates,
'areas': ['ctry19-S92000003']
},
)
def test_preview_broadcast_message_page(
client_request,
service_one,
mock_get_draft_broadcast_message,
mock_get_broadcast_template,
fake_uuid,
):
service_one['permissions'] += ['broadcast']
page = client_request.get(
'.preview_broadcast_message',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
)
assert [
normalize_spaces(area.text)
for area in page.select('.area-list-item.area-list-item--unremoveable')
] == [
'England',
'Scotland',
]
assert normalize_spaces(
page.select_one('h2.broadcast-message-heading').text
) == (
'Emergency alert'
)
assert normalize_spaces(
page.select_one('.broadcast-message-wrapper').text
) == (
'Emergency alert '
'This is a test'
)
form = page.select_one('form')
assert form['method'] == 'post'
assert 'action' not in form
@freeze_time('2020-02-02 02:02:02')
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,
_expected_redirect=url_for(
'main.view_current_broadcast',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_external=True,
),
),
mock_update_broadcast_message_status.assert_called_once_with(
'pending-approval',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
)
@pytest.mark.parametrize('endpoint, created_by_api, extra_fields, expected_paragraphs', (
('.view_current_broadcast', False, {
'status': 'broadcasting',
'finishes_at': '2020-02-23T23:23:23.000000',
}, [
'Live since 20 February at 8:20pm Stop broadcasting',
'Prepared by Alice and approved by Bob.',
'Broadcasting stops tomorrow at 11:23pm.'
]),
('.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, {
'status': 'broadcasting',
'finishes_at': '2020-02-22T22:20:20.000000', # 2 mins before now()
}, [
'Broadcast on 20 February at 8:20pm.',
'Prepared by Alice and approved by Bob.',
'Finished broadcasting today at 10:20pm.'
]),
('.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, {
'status': 'completed',
'finishes_at': '2020-02-21T21:21:21.000000',
}, [
'Broadcast on 20 February at 8:20pm.',
'Prepared by Alice and approved by Bob.',
'Finished broadcasting yesterday at 9:21pm.',
]),
('.view_previous_broadcast', False, {
'status': 'cancelled',
'cancelled_by_id': sample_uuid,
'cancelled_at': '2020-02-21T21:21:21.000000',
}, [
'Broadcast on 20 February at 8:20pm.',
'Prepared by Alice and approved by Bob.',
'Stopped by Carol yesterday at 9:21pm.',
]),
))
@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,
endpoint,
created_by_api,
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,
created_by_id=None if created_by_api else fake_uuid,
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(
endpoint,
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
@pytest.mark.parametrize('endpoint', (
'.view_current_broadcast',
'.view_previous_broadcast',
))
@pytest.mark.parametrize('status, expected_highlighted_navigation_item, expected_back_link_endpoint', (
(
'pending-approval',
'Current alerts',
'.broadcast_dashboard',
),
(
'broadcasting',
'Current alerts',
'.broadcast_dashboard',
),
(
'completed',
'Previous alerts',
'.broadcast_dashboard_previous',
),
(
'cancelled',
'Previous alerts',
'.broadcast_dashboard_previous',
),
(
'rejected',
'Previous alerts',
'.broadcast_dashboard_previous',
),
))
@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,
expected_back_link_endpoint,
):
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',
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
)
assert page.select_one('.govuk-back-link')['href'] == url_for(
expected_back_link_endpoint,
service_id=SERVICE_ONE_ID,
)
@freeze_time('2020-02-22T22:22:22.000000')
def test_view_pending_broadcast(
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=None,
status='pending-approval',
),
)
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 Example template '
'Start broadcasting now Reject this alert'
)
form = page.select_one('form.banner')
assert form['method'] == 'post'
assert 'action' not in form
assert form.select_one('button[type=submit]')
link = form.select_one('a.govuk-link.govuk-link--destructive')
assert link.text == 'Reject 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_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'
)
@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'
)
@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,
):
service_one['restricted'] = False
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(
'.view_current_broadcast',
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)
) == (
'You need another member of your team to approve your alert.'
)
assert not page.select('form')
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(
'.view_current_broadcast',
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 youll 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 youre in training mode you can approve your own '
'alerts, to see how it works. '
'No real alerts will be broadcast to anyones 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'
)
link = page.select_one('.banner a.govuk-link.govuk-link--destructive')
assert link.text == 'Cancel 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_view_only_user_cant_approve_broadcast(
mocker,
client_request,
service_one,
active_user_with_permissions,
active_user_view_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_view_permissions, # Current user
active_user_with_permissions, # 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)
) == (
'This alert is waiting for approval '
'You dont have permission to approve alerts.'
)
assert not page.select_one('form')
assert not page.select_one('.banner a')
@pytest.mark.parametrize('trial_mode, initial_status, expected_approval, expected_redirect', (
(True, 'draft', False, partial(
url_for,
'.view_current_broadcast',
broadcast_message_id=sample_uuid,
)),
(True, 'pending-approval', True, partial(
url_for,
'.broadcast_tour',
step_index=6,
)),
(False, 'pending-approval', True, partial(
url_for,
'.view_current_broadcast',
broadcast_message_id=sample_uuid,
)),
(True, 'rejected', False, partial(
url_for,
'.view_current_broadcast',
broadcast_message_id=sample_uuid,
)),
(True, 'broadcasting', False, partial(
url_for,
'.view_current_broadcast',
broadcast_message_id=sample_uuid,
)),
(True, 'cancelled', False, partial(
url_for,
'.view_current_broadcast',
broadcast_message_id=sample_uuid,
)),
))
@freeze_time('2020-02-22T22:22:22.000000')
def test_request_approval(
mocker,
client_request,
service_one,
mock_get_broadcast_template,
fake_uuid,
mock_update_broadcast_message,
mock_update_broadcast_message_status,
initial_status,
expected_approval,
trial_mode,
expected_redirect,
):
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['restricted'] = trial_mode
service_one['permissions'] += ['broadcast']
client_request.post(
'.view_current_broadcast',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_expected_redirect=expected_redirect(
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',
'finishes_at': '2020-02-23T22:21:22',
},
)
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
@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(
'.view_current_broadcast',
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
@pytest.mark.parametrize('endpoint', (
'.view_current_broadcast',
'.view_previous_broadcast',
))
def test_no_view_page_for_draft(
client_request,
service_one,
mock_get_draft_broadcast_message,
fake_uuid,
endpoint,
):
service_one['permissions'] += ['broadcast']
client_request.get(
endpoint,
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_expected_status=404,
)
def test_cancel_broadcast(
client_request,
service_one,
mock_get_live_broadcast_message,
mock_get_broadcast_template,
mock_update_broadcast_message_status,
fake_uuid,
):
service_one['permissions'] += ['broadcast']
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
def test_confirm_cancel_broadcast(
client_request,
service_one,
mock_get_live_broadcast_message,
mock_get_broadcast_template,
mock_update_broadcast_message_status,
fake_uuid,
):
service_one['permissions'] += ['broadcast']
client_request.post(
'.cancel_broadcast_message',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_expected_redirect=url_for(
'.view_previous_broadcast',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_external=True,
),
)
mock_update_broadcast_message_status.assert_called_once_with(
'cancelled',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
)
@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(
'.view_current_broadcast',
service_id=SERVICE_ONE_ID,
broadcast_message_id=fake_uuid,
_external=True,
),
)
assert mock_update_broadcast_message_status.called is False