diff --git a/app/main/forms.py b/app/main/forms.py
index b276f8215..823137497 100644
--- a/app/main/forms.py
+++ b/app/main/forms.py
@@ -40,6 +40,7 @@ from wtforms.validators import URL, DataRequired, Length, Optional, Regexp
from app import format_thousands
from app.main.validators import (
+ BroadcastLength,
CommonlyUsedPassword,
CsvFileValidator,
DoesNotStartWithDoubleZero,
@@ -1324,6 +1325,7 @@ class BroadcastTemplateForm(SMSTemplateForm):
def validate_template_content(self, field):
OnlySMSCharacters(template_type='broadcast')(None, field)
NoPlaceholders()(None, field)
+ BroadcastLength()(None, field)
class LetterAddressForm(StripWhitespaceForm):
diff --git a/app/main/validators.py b/app/main/validators.py
index 104b4a932..8e091b0f7 100644
--- a/app/main/validators.py
+++ b/app/main/validators.py
@@ -7,6 +7,7 @@ from notifications_utils.recipients import (
validate_email_address,
)
from notifications_utils.sanitise_text import SanitiseSMS
+from notifications_utils.template import BroadcastMessageTemplate
from wtforms import ValidationError
from app.main._commonly_used_passwords import commonly_used_passwords
@@ -120,6 +121,28 @@ class NoPlaceholders:
raise ValidationError(self.message)
+class BroadcastLength:
+
+ def __call__(self, form, field):
+ template = BroadcastMessageTemplate({
+ 'template_type': 'broadcast',
+ 'content': field.data,
+ })
+
+ if template.content_too_long:
+ non_gsm_characters = list(sorted(template.non_gsm_characters))
+ if non_gsm_characters:
+ raise ValidationError(
+ f'Content must be {template.max_content_count:,.0f} '
+ f'characters or fewer because it contains '
+ f'{formatted_list(non_gsm_characters, conjunction="and", before_each="", after_each="")}'
+ )
+ raise ValidationError(
+ f'Content must be {template.max_content_count:,.0f} '
+ f'characters or fewer'
+ )
+
+
class LettersNumbersFullStopsAndUnderscoresOnly:
regex = re.compile(r'^[a-zA-Z0-9\s\._]+$')
diff --git a/app/templates/views/edit-broadcast-template.html b/app/templates/views/edit-broadcast-template.html
index 8c5d7cfe9..21b0374d3 100644
--- a/app/templates/views/edit-broadcast-template.html
+++ b/app/templates/views/edit-broadcast-template.html
@@ -24,7 +24,7 @@
}) }}
- {{ textbox(form.template_content, highlight_placeholders=False, width='1-1', rows=5) }}
+ {{ textbox(form.template_content, highlight_placeholders=False, autosize=True, width='1-1', rows=5) }}
{{ sticky_page_footer('Save') }}
diff --git a/requirements-app.txt b/requirements-app.txt
index da31bf0d3..a18e37063 100644
--- a/requirements-app.txt
+++ b/requirements-app.txt
@@ -24,7 +24,7 @@ Shapely==1.7.1
awscli-cwlogs>=1.4,<1.5
itsdangerous==1.1.0
-git+https://github.com/alphagov/notifications-utils.git@43.5.8#egg=notifications-utils==43.5.8
+git+https://github.com/alphagov/notifications-utils.git@43.6.0#egg=notifications-utils==43.6.0
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
diff --git a/requirements.txt b/requirements.txt
index 2f41e058e..f824f7542 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -26,7 +26,7 @@ Shapely==1.7.1
awscli-cwlogs>=1.4,<1.5
itsdangerous==1.1.0
-git+https://github.com/alphagov/notifications-utils.git@43.5.8#egg=notifications-utils==43.5.8
+git+https://github.com/alphagov/notifications-utils.git@43.6.0#egg=notifications-utils==43.6.0
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
# gds-metrics requires prometheseus 0.2.0, override that requirement as later versions bring significant performance gains
diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py
index 5560622c8..a45fcb06e 100644
--- a/tests/app/main/views/test_templates.py
+++ b/tests/app/main/views/test_templates.py
@@ -480,6 +480,7 @@ def test_broadcast_template_doesnt_highlight_placeholders(
service_id=SERVICE_ONE_ID,
template_id=fake_uuid,
)
+ assert page.select_one('textarea')['data-module'] == 'enhanced-textbox'
assert page.select_one('textarea')['data-highlight-placeholders'] == 'false'
@@ -1865,6 +1866,37 @@ def test_should_not_update_too_big_template(
assert "Content has a character count greater than the limit of 459" in page.text
+@pytest.mark.parametrize('content, expected_error', (
+ (("ŴŶ" * 308), (
+ 'Content must be 615 characters or fewer because it contains Ŵ and Ŷ'
+ )),
+ (("ab" * 698), (
+ 'Content must be 1,395 characters or fewer'
+ )),
+))
+def test_should_not_create_too_big_template_for_broadcasts(
+ client_request,
+ service_one,
+ content,
+ expected_error,
+):
+ service_one['permissions'] = ['broadcast']
+ page = client_request.post(
+ '.add_service_template',
+ service_id=SERVICE_ONE_ID,
+ template_type='broadcast',
+ _data={
+ 'name': 'New name',
+ 'template_content': content,
+ 'template_type': 'broadcast',
+ 'service': SERVICE_ONE_ID,
+ 'process_type': 'normal'
+ },
+ _expected_status=200,
+ )
+ assert normalize_spaces(page.select_one('.error-message').text) == expected_error
+
+
def test_should_redirect_when_saving_a_template_email(
client_request,
mock_get_service_email_template,