mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-24 00:07:02 -04:00
Merge pull request #3527 from alphagov/broadcast-end-time
Let users choose when to end a broadcast
This commit is contained in:
@@ -7,12 +7,14 @@
|
|||||||
|
|
||||||
let states = {
|
let states = {
|
||||||
'initial': Hogan.compile(`
|
'initial': Hogan.compile(`
|
||||||
<div class="radio-select__column">
|
{{#showNowAsDefault}}
|
||||||
<div class="multiple-choice js-multiple-choice">
|
<div class="radio-select__column">
|
||||||
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
|
<div class="multiple-choice js-multiple-choice">
|
||||||
<label class="block-label js-block-label" for="{{name}}-0">Now</label>
|
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
|
||||||
|
<label class="block-label js-block-label" for="{{name}}-0">Now</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/showNowAsDefault}}
|
||||||
<div class="radio-select__column">
|
<div class="radio-select__column">
|
||||||
{{#categories}}
|
{{#categories}}
|
||||||
<input type='button' class='govuk-button govuk-button--secondary radio-select__button--category' value='{{.}}' />
|
<input type='button' class='govuk-button govuk-button--secondary radio-select__button--category' value='{{.}}' />
|
||||||
@@ -20,12 +22,14 @@
|
|||||||
</div>
|
</div>
|
||||||
`),
|
`),
|
||||||
'choose': Hogan.compile(`
|
'choose': Hogan.compile(`
|
||||||
<div class="radio-select__column">
|
{{#showNowAsDefault}}
|
||||||
<div class="multiple-choice js-multiple-choice js-initial-option">
|
<div class="radio-select__column">
|
||||||
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
|
<div class="multiple-choice js-multiple-choice js-initial-option">
|
||||||
<label for="{{name}}-0">Now</label>
|
<input checked="checked" id="{{name}}-0" name="{{name}}" type="radio" value="">
|
||||||
|
<label for="{{name}}-0">Now</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/showNowAsDefault}}
|
||||||
<div class="radio-select__column">
|
<div class="radio-select__column">
|
||||||
{{#choices}}
|
{{#choices}}
|
||||||
<div class="multiple-choice js-multiple-choice js-option">
|
<div class="multiple-choice js-multiple-choice js-option">
|
||||||
@@ -37,12 +41,14 @@
|
|||||||
</div>
|
</div>
|
||||||
`),
|
`),
|
||||||
'chosen': Hogan.compile(`
|
'chosen': Hogan.compile(`
|
||||||
<div class="radio-select__column">
|
{{#showNowAsDefault}}
|
||||||
<div class="multiple-choice js-multiple-choice js-initial-option">
|
<div class="radio-select__column">
|
||||||
<input id="{{name}}-0" name="{{name}}" type="radio" value="">
|
<div class="multiple-choice js-multiple-choice js-initial-option">
|
||||||
<label for="{{name}}-0">Now</label>
|
<input id="{{name}}-0" name="{{name}}" type="radio" value="">
|
||||||
|
<label for="{{name}}-0">Now</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/showNowAsDefault}}
|
||||||
<div class="radio-select__column">
|
<div class="radio-select__column">
|
||||||
{{#choices}}
|
{{#choices}}
|
||||||
<div class="multiple-choice js-multiple-choice">
|
<div class="multiple-choice js-multiple-choice">
|
||||||
@@ -80,10 +86,15 @@
|
|||||||
let categories = $component.data('categories').split(',');
|
let categories = $component.data('categories').split(',');
|
||||||
let name = $component.find('input').eq(0).attr('name');
|
let name = $component.find('input').eq(0).attr('name');
|
||||||
let mousedownOption = null;
|
let mousedownOption = null;
|
||||||
|
let showNowAsDefault = (
|
||||||
|
$component.data('show-now-as-default').toString() === 'true' ?
|
||||||
|
{'name': name} : false
|
||||||
|
);
|
||||||
const reset = () => {
|
const reset = () => {
|
||||||
render('initial', {
|
render('initial', {
|
||||||
'categories': categories,
|
'categories': categories,
|
||||||
'name': name
|
'name': name,
|
||||||
|
'showNowAsDefault': showNowAsDefault
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const selectOption = (value) => {
|
const selectOption = (value) => {
|
||||||
@@ -91,7 +102,8 @@
|
|||||||
'choices': choices.filter(
|
'choices': choices.filter(
|
||||||
element => element.value == value
|
element => element.value == value
|
||||||
),
|
),
|
||||||
'name': name
|
'name': name,
|
||||||
|
'showNowAsDefault': showNowAsDefault
|
||||||
});
|
});
|
||||||
focusSelected(component);
|
focusSelected(component);
|
||||||
};
|
};
|
||||||
@@ -119,7 +131,8 @@
|
|||||||
'choices': choices.filter(
|
'choices': choices.filter(
|
||||||
element => element.label.toLowerCase().indexOf(day) > -1
|
element => element.label.toLowerCase().indexOf(day) > -1
|
||||||
),
|
),
|
||||||
'name': name
|
'name': name,
|
||||||
|
'showNowAsDefault': showNowAsDefault
|
||||||
});
|
});
|
||||||
focusSelected(component);
|
focusSelected(component);
|
||||||
|
|
||||||
@@ -153,7 +166,8 @@
|
|||||||
'choices': choices.filter(
|
'choices': choices.filter(
|
||||||
element => element.value == $selection.eq(0).attr('value')
|
element => element.value == $selection.eq(0).attr('value')
|
||||||
),
|
),
|
||||||
'name': name
|
'name': name,
|
||||||
|
'showNowAsDefault': showNowAsDefault
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -174,7 +188,8 @@
|
|||||||
|
|
||||||
render('initial', {
|
render('initial', {
|
||||||
'categories': categories,
|
'categories': categories,
|
||||||
'name': name
|
'name': name,
|
||||||
|
'showNowAsDefault': showNowAsDefault
|
||||||
});
|
});
|
||||||
|
|
||||||
$component.css({'height': 'auto'});
|
$component.css({'height': 'auto'});
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ def get_next_hours_until(until):
|
|||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
hours = int((until - now).total_seconds() / (60 * 60))
|
hours = int((until - now).total_seconds() / (60 * 60))
|
||||||
return [
|
return [
|
||||||
(now + timedelta(hours=i)).replace(minute=0, second=0).replace(tzinfo=pytz.utc)
|
(now + timedelta(hours=i)).replace(minute=0, second=0, microsecond=0).replace(tzinfo=pytz.utc)
|
||||||
for i in range(1, hours + 1)
|
for i in range(1, hours + 1)
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -979,6 +979,24 @@ class ChooseTimeForm(StripWhitespaceForm):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ChooseBroadcastDurationForm(StripWhitespaceForm):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.finishes_at.choices = [
|
||||||
|
get_time_value_and_label(hour) for hour in get_next_hours_until(
|
||||||
|
get_furthest_possible_scheduled_time()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
self.finishes_at.categories = get_next_days_until(
|
||||||
|
get_furthest_possible_scheduled_time()
|
||||||
|
)
|
||||||
|
|
||||||
|
finishes_at = RadioField(
|
||||||
|
'When should this broadcast end?',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CreateKeyForm(StripWhitespaceForm):
|
class CreateKeyForm(StripWhitespaceForm):
|
||||||
def __init__(self, existing_keys, *args, **kwargs):
|
def __init__(self, existing_keys, *args, **kwargs):
|
||||||
self.existing_key_names = [
|
self.existing_key_names = [
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
from flask import abort, jsonify, redirect, render_template, request, url_for
|
from flask import abort, jsonify, redirect, render_template, url_for
|
||||||
|
|
||||||
from app import current_service
|
from app import current_service
|
||||||
from app.main import main
|
from app.main import main
|
||||||
from app.main.forms import BroadcastAreaForm, SearchByNameForm
|
from app.main.forms import (
|
||||||
|
BroadcastAreaForm,
|
||||||
|
ChooseBroadcastDurationForm,
|
||||||
|
SearchByNameForm,
|
||||||
|
)
|
||||||
from app.models.broadcast_message import BroadcastMessage, BroadcastMessages
|
from app.models.broadcast_message import BroadcastMessage, BroadcastMessages
|
||||||
from app.utils import service_has_permission, user_has_permissions
|
from app.utils import service_has_permission, user_has_permissions
|
||||||
|
|
||||||
@@ -141,15 +145,19 @@ def preview_broadcast_message(service_id, broadcast_message_id):
|
|||||||
broadcast_message_id,
|
broadcast_message_id,
|
||||||
service_id=current_service.id,
|
service_id=current_service.id,
|
||||||
)
|
)
|
||||||
if request.method == 'POST':
|
form = ChooseBroadcastDurationForm()
|
||||||
broadcast_message.request_approval()
|
|
||||||
|
if form.validate_on_submit():
|
||||||
|
broadcast_message.request_approval(until=form.finishes_at.data)
|
||||||
return redirect(url_for(
|
return redirect(url_for(
|
||||||
'.broadcast_dashboard',
|
'.broadcast_dashboard',
|
||||||
service_id=current_service.id,
|
service_id=current_service.id,
|
||||||
))
|
))
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'views/broadcast/preview-message.html',
|
'views/broadcast/preview-message.html',
|
||||||
broadcast_message=broadcast_message,
|
broadcast_message=broadcast_message,
|
||||||
|
form=form,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime
|
||||||
|
|
||||||
from notifications_utils.broadcast_areas import broadcast_area_libraries
|
from notifications_utils.broadcast_areas import broadcast_area_libraries
|
||||||
from notifications_utils.template import BroadcastPreviewTemplate
|
from notifications_utils.template import BroadcastPreviewTemplate
|
||||||
@@ -33,7 +33,6 @@ class BroadcastMessage(JSONModel):
|
|||||||
'approved_by_id',
|
'approved_by_id',
|
||||||
'cancelled_by_id',
|
'cancelled_by_id',
|
||||||
}
|
}
|
||||||
DEFAULT_TTL = timedelta(hours=72)
|
|
||||||
|
|
||||||
libraries = broadcast_area_libraries
|
libraries = broadcast_area_libraries
|
||||||
|
|
||||||
@@ -132,9 +131,9 @@ class BroadcastMessage(JSONModel):
|
|||||||
data=kwargs,
|
data=kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
def request_approval(self):
|
def request_approval(self, until):
|
||||||
self._update(
|
self._update(
|
||||||
finishes_at=(datetime.utcnow() + self.DEFAULT_TTL).isoformat(),
|
finishes_at=until,
|
||||||
)
|
)
|
||||||
self._set_status_to('pending-approval')
|
self._set_status_to('pending-approval')
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
{% macro radio_select(
|
{% macro radio_select(
|
||||||
field,
|
field,
|
||||||
hint=None,
|
hint=None,
|
||||||
wrapping_class='form-group'
|
wrapping_class='form-group',
|
||||||
|
show_now_as_default=True
|
||||||
) %}
|
) %}
|
||||||
<div class="{{ wrapping_class }} {% if field.errors %} form-group-error{% endif %}">
|
<div class="{{ wrapping_class }} {% if field.errors %} form-group-error{% endif %}">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
</span>
|
</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</legend>
|
</legend>
|
||||||
<div class="radio-select" data-module="radio-select" data-categories="{{ field.categories|join(',') }}">
|
<div class="radio-select" data-module="radio-select" data-categories="{{ field.categories|join(',') }}" data-show-now-as-default="{{ show_now_as_default|string|lower }}">
|
||||||
<div class="radio-select-column">
|
<div class="radio-select-column">
|
||||||
{% for option in field %}
|
{% for option in field %}
|
||||||
<div class="multiple-choice">
|
<div class="multiple-choice">
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
{% from "components/button/macro.njk" import govukButton %}
|
{% from "components/button/macro.njk" import govukButton %}
|
||||||
{% from "components/form.html" import form_wrapper %}
|
{% from "components/form.html" import form_wrapper %}
|
||||||
{% from "components/page-header.html" import page_header %}
|
{% from "components/page-header.html" import page_header %}
|
||||||
{% from "components/page-footer.html" import sticky_page_footer %}
|
{% from "components/page-footer.html" import page_footer %}
|
||||||
|
{% from "components/radios.html" import radio_select %}
|
||||||
|
|
||||||
{% extends "withnav_template.html" %}
|
{% extends "withnav_template.html" %}
|
||||||
|
|
||||||
@@ -28,7 +29,11 @@
|
|||||||
{{ broadcast_message.template|string }}
|
{{ broadcast_message.template|string }}
|
||||||
|
|
||||||
{% call form_wrapper() %}
|
{% call form_wrapper() %}
|
||||||
{{ sticky_page_footer('Submit for approval') }}
|
{{ radio_select(
|
||||||
|
form.finishes_at,
|
||||||
|
show_now_as_default=False
|
||||||
|
) }}
|
||||||
|
{{ page_footer('Submit for approval') }}
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -11,19 +11,19 @@ def test_form_contains_next_24h(app_):
|
|||||||
|
|
||||||
# Friday
|
# Friday
|
||||||
assert choices[0] == ('', 'Now')
|
assert choices[0] == ('', 'Now')
|
||||||
assert choices[1] == ('2016-01-01T12:00:00.061258', 'Today at midday')
|
assert choices[1] == ('2016-01-01T12:00:00', 'Today at midday')
|
||||||
assert choices[13] == ('2016-01-02T00:00:00.061258', 'Today at midnight')
|
assert choices[13] == ('2016-01-02T00:00:00', 'Today at midnight')
|
||||||
|
|
||||||
# Saturday
|
# Saturday
|
||||||
assert choices[14] == ('2016-01-02T01:00:00.061258', 'Tomorrow at 1am')
|
assert choices[14] == ('2016-01-02T01:00:00', 'Tomorrow at 1am')
|
||||||
assert choices[37] == ('2016-01-03T00:00:00.061258', 'Tomorrow at midnight')
|
assert choices[37] == ('2016-01-03T00:00:00', 'Tomorrow at midnight')
|
||||||
|
|
||||||
# Sunday
|
# Sunday
|
||||||
assert choices[38] == ('2016-01-03T01:00:00.061258', 'Sunday at 1am')
|
assert choices[38] == ('2016-01-03T01:00:00', 'Sunday at 1am')
|
||||||
|
|
||||||
# Monday
|
# Monday
|
||||||
assert choices[84] == ('2016-01-04T23:00:00.061258', 'Monday at 11pm')
|
assert choices[84] == ('2016-01-04T23:00:00', 'Monday at 11pm')
|
||||||
assert choices[85] == ('2016-01-05T00:00:00.061258', 'Monday at midnight')
|
assert choices[85] == ('2016-01-05T00:00:00', 'Monday at midnight')
|
||||||
|
|
||||||
with pytest.raises(IndexError):
|
with pytest.raises(IndexError):
|
||||||
assert choices[
|
assert choices[
|
||||||
|
|||||||
@@ -278,22 +278,79 @@ def test_remove_broadcast_area_page(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('end_time', (
|
||||||
|
|
||||||
|
# Before now
|
||||||
|
pytest.param('2020-02-02T02:00:00', marks=pytest.mark.xfail),
|
||||||
|
|
||||||
|
# End of the current hour
|
||||||
|
pytest.param('2020-02-02T03:00:00'),
|
||||||
|
|
||||||
|
# Midnight 3 days ahead
|
||||||
|
pytest.param('2020-02-06T00:00:00'),
|
||||||
|
|
||||||
|
# 1am 4 days ahead
|
||||||
|
pytest.param('2020-02-06T01:00:00', marks=pytest.mark.xfail),
|
||||||
|
|
||||||
|
))
|
||||||
|
@freeze_time('2020-02-02 02:02:02')
|
||||||
def test_preview_broadcast_message_page(
|
def test_preview_broadcast_message_page(
|
||||||
client_request,
|
client_request,
|
||||||
service_one,
|
service_one,
|
||||||
mock_get_draft_broadcast_message,
|
mock_get_draft_broadcast_message,
|
||||||
mock_get_broadcast_template,
|
mock_get_broadcast_template,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
|
end_time,
|
||||||
):
|
):
|
||||||
service_one['permissions'] += ['broadcast']
|
service_one['permissions'] += ['broadcast']
|
||||||
client_request.get(
|
|
||||||
|
page = client_request.get(
|
||||||
'.preview_broadcast_message',
|
'.preview_broadcast_message',
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
broadcast_message_id=fake_uuid,
|
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('.broadcast-message-wrapper').text
|
||||||
|
) == (
|
||||||
|
'This is a test'
|
||||||
|
)
|
||||||
|
|
||||||
|
form = page.select_one('form')
|
||||||
|
assert form['method'] == 'post'
|
||||||
|
assert 'action' not in form
|
||||||
|
|
||||||
|
radio_choices = [
|
||||||
|
choice['value'] for choice in form.select('input[type=radio][name=finishes_at]')
|
||||||
|
]
|
||||||
|
assert len(radio_choices) == 94
|
||||||
|
assert end_time in radio_choices
|
||||||
|
|
||||||
|
|
||||||
@freeze_time('2020-02-02 02:02:02.222222')
|
@pytest.mark.parametrize('end_time', (
|
||||||
|
|
||||||
|
# Before now
|
||||||
|
pytest.param('2020-02-02T02:00:00', marks=pytest.mark.xfail),
|
||||||
|
|
||||||
|
# End of the current hour
|
||||||
|
pytest.param('2020-02-02T03:00:00'),
|
||||||
|
|
||||||
|
# Midnight 3 days ahead
|
||||||
|
pytest.param('2020-02-06T00:00:00'),
|
||||||
|
|
||||||
|
# 1am 4 days ahead
|
||||||
|
pytest.param('2020-02-06T01:00:00', marks=pytest.mark.xfail),
|
||||||
|
|
||||||
|
))
|
||||||
|
@freeze_time('2020-02-02 02:02:02')
|
||||||
def test_start_broadcasting(
|
def test_start_broadcasting(
|
||||||
client_request,
|
client_request,
|
||||||
service_one,
|
service_one,
|
||||||
@@ -302,24 +359,54 @@ def test_start_broadcasting(
|
|||||||
mock_update_broadcast_message,
|
mock_update_broadcast_message,
|
||||||
mock_update_broadcast_message_status,
|
mock_update_broadcast_message_status,
|
||||||
fake_uuid,
|
fake_uuid,
|
||||||
|
end_time,
|
||||||
|
):
|
||||||
|
service_one['permissions'] += ['broadcast']
|
||||||
|
client_request.post(
|
||||||
|
'.preview_broadcast_message',
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
broadcast_message_id=fake_uuid,
|
||||||
|
_data={
|
||||||
|
'finishes_at': end_time,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
mock_update_broadcast_message.assert_called_once_with(
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
broadcast_message_id=fake_uuid,
|
||||||
|
data={
|
||||||
|
'finishes_at': end_time,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
mock_update_broadcast_message_status.assert_called_once_with(
|
||||||
|
'pending-approval',
|
||||||
|
service_id=SERVICE_ONE_ID,
|
||||||
|
broadcast_message_id=fake_uuid,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_start_broadcasting_shows_validation_error(
|
||||||
|
client_request,
|
||||||
|
service_one,
|
||||||
|
mock_get_draft_broadcast_message,
|
||||||
|
mock_get_broadcast_template,
|
||||||
|
mock_update_broadcast_message,
|
||||||
|
mock_update_broadcast_message_status,
|
||||||
|
fake_uuid,
|
||||||
):
|
):
|
||||||
service_one['permissions'] += ['broadcast']
|
service_one['permissions'] += ['broadcast']
|
||||||
client_request.post(
|
page = client_request.post(
|
||||||
'.preview_broadcast_message',
|
'.preview_broadcast_message',
|
||||||
service_id=SERVICE_ONE_ID,
|
service_id=SERVICE_ONE_ID,
|
||||||
broadcast_message_id=fake_uuid,
|
broadcast_message_id=fake_uuid,
|
||||||
),
|
_data={},
|
||||||
mock_update_broadcast_message.assert_called_once_with(
|
_expected_status=200,
|
||||||
service_id=SERVICE_ONE_ID,
|
|
||||||
broadcast_message_id=fake_uuid,
|
|
||||||
data={
|
|
||||||
'finishes_at': '2020-02-05T02:02:02.222222',
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
mock_update_broadcast_message_status.assert_called_once_with(
|
assert mock_update_broadcast_message.called is False
|
||||||
'pending-approval',
|
assert mock_update_broadcast_message_status.called is False
|
||||||
service_id=SERVICE_ONE_ID,
|
assert normalize_spaces(
|
||||||
broadcast_message_id=fake_uuid,
|
page.select_one('form fieldset legend .error-message').text
|
||||||
|
) == (
|
||||||
|
'Select an option'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,11 +68,12 @@ describe('RadioSelect', () => {
|
|||||||
|
|
||||||
hours.forEach((hour, idx) => {
|
hours.forEach((hour, idx) => {
|
||||||
const hourLabel = getHourLabel(hour);
|
const hourLabel = getHourLabel(hour);
|
||||||
|
const num = idx + 1;
|
||||||
|
|
||||||
result +=
|
result +=
|
||||||
`<div class="multiple-choice">
|
`<div class="multiple-choice">
|
||||||
<input id="scheduled_for-${idx}" name="scheduled_for" type="radio" value="2019-05-${dayAsNumber}T${hour}:00:00.459156">
|
<input id="scheduled_for-${num}" name="scheduled_for" type="radio" value="2019-05-${dayAsNumber}T${hour}:00:00.459156">
|
||||||
<label for="scheduled_for-${idx}">
|
<label for="scheduled_for-${num}">
|
||||||
${day} at ${hourLabel}
|
${day} at ${hourLabel}
|
||||||
</label>
|
</label>
|
||||||
</div>`;
|
</div>`;
|
||||||
@@ -99,7 +100,7 @@ describe('RadioSelect', () => {
|
|||||||
<legend class="form-label">
|
<legend class="form-label">
|
||||||
When should Notify send these messages?
|
When should Notify send these messages?
|
||||||
</legend>
|
</legend>
|
||||||
<div class="radio-select" data-module="radio-select" data-categories="${CATEGORIES.join(',')}">
|
<div class="radio-select" data-module="radio-select" data-categories="${CATEGORIES.join(',')}" data-show-now-as-default="true">
|
||||||
<div class="radio-select__column">
|
<div class="radio-select__column">
|
||||||
<div class="multiple-choice">
|
<div class="multiple-choice">
|
||||||
<input checked="" id="scheduled_for-0" name="scheduled_for" type="radio" value="">
|
<input checked="" id="scheduled_for-0" name="scheduled_for" type="radio" value="">
|
||||||
@@ -114,7 +115,7 @@ describe('RadioSelect', () => {
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>`;
|
</fieldset>`;
|
||||||
|
|
||||||
originalOptionsForAllCategories = Array.from(document.querySelector('.radio-select__column:nth-child(2) .multiple-choice'))
|
originalOptionsForAllCategories = Array.from(document.querySelectorAll('.radio-select__column:nth-child(2) .multiple-choice'))
|
||||||
.map(option => getDataFromOption(option));
|
.map(option => getDataFromOption(option));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -122,30 +123,60 @@ describe('RadioSelect', () => {
|
|||||||
document.body.innerHTML = '';
|
document.body.innerHTML = '';
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when the page has loaded it should have a button for each category", () => {
|
describe("when the page has loaded", () => {
|
||||||
|
|
||||||
let categoryButtons;
|
describe("if the 'data-show-now-as-default' attribute", () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
test("is set to true the module should have a 'Now' option", () => {
|
||||||
|
|
||||||
// start module
|
// default is for it to be set to true
|
||||||
window.GOVUK.modules.start();
|
|
||||||
|
|
||||||
categoryButtons = document.querySelectorAll('.radio-select__column:nth-child(2) .radio-select__button--category');
|
// start module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
expect(document.querySelectorAll('.radio-select__column').length).toEqual(2);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("is set to false the module should not have a 'Now' option", () => {
|
||||||
|
|
||||||
|
document.querySelector('.radio-select').setAttribute('data-show-now-as-default', 'false');
|
||||||
|
|
||||||
|
// start module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
expect(document.querySelectorAll('.radio-select__column').length).toEqual(1);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("the number of buttons should match the categories", () => {
|
describe("it should have a button for each category", () => {
|
||||||
|
|
||||||
expect(categoryButtons.length).toBe(CATEGORIES.length);
|
let categoryButtons;
|
||||||
|
|
||||||
});
|
beforeEach(() => {
|
||||||
|
|
||||||
test("each button's text should match their category", () => {
|
// start module
|
||||||
|
window.GOVUK.modules.start();
|
||||||
|
|
||||||
|
categoryButtons = document.querySelectorAll('.radio-select__column:nth-child(2) .radio-select__button--category');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("the number of buttons should match the categories", () => {
|
||||||
|
|
||||||
|
expect(categoryButtons.length).toBe(CATEGORIES.length);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("each button's text should match their category", () => {
|
||||||
|
|
||||||
|
// check the buttons have the right text
|
||||||
|
CATEGORIES.forEach((category, idx) => {
|
||||||
|
expect(categoryButtons[idx].getAttribute('value')).toEqual(category);
|
||||||
|
});
|
||||||
|
|
||||||
// check the buttons have the right text
|
|
||||||
CATEGORIES.forEach((category, idx) => {
|
|
||||||
expect(categoryButtons[idx].getAttribute('value')).toEqual(category);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -158,10 +189,13 @@ describe('RadioSelect', () => {
|
|||||||
|
|
||||||
describe(`clicking the button for ${category} should`, () => {
|
describe(`clicking the button for ${category} should`, () => {
|
||||||
|
|
||||||
|
const categoryRegExp = new RegExp('^' + category);
|
||||||
|
let originalOptionsForcategory;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
||||||
// get all the options in the original page for this category
|
// get all the options in the original page for this category
|
||||||
originalOptionsForCategory = originalOptionsForAllCategories.filter(option => option.label === category);
|
originalOptionsForCategory = originalOptionsForAllCategories.filter(option => categoryRegExp.test(option.label));
|
||||||
|
|
||||||
// start module
|
// start module
|
||||||
window.GOVUK.modules.start();
|
window.GOVUK.modules.start();
|
||||||
@@ -173,7 +207,7 @@ describe('RadioSelect', () => {
|
|||||||
test("show the options for it, with the right label and value", () => {
|
test("show the options for it, with the right label and value", () => {
|
||||||
|
|
||||||
// check options this reveals against those originally in the page for this category
|
// check options this reveals against those originally in the page for this category
|
||||||
const options = document.querySelector('.radio-select__column:nth-child(2) .multiple-choice');
|
const options = document.querySelectorAll('.radio-select__column:nth-child(2) .multiple-choice');
|
||||||
|
|
||||||
const optionsThatMatchOriginals = Array.from(options).filter((option, idx) => {
|
const optionsThatMatchOriginals = Array.from(options).filter((option, idx) => {
|
||||||
const optionData = getDataFromOption(option);
|
const optionData = getDataFromOption(option);
|
||||||
|
|||||||
Reference in New Issue
Block a user