1134 - Changing all instances of the word "brackets" to "parenthesis"

This commit is contained in:
Jonathan Bobel
2025-03-20 10:29:29 -04:00
parent a5ddf8038b
commit fe098eca22
20 changed files with 92 additions and 69 deletions

View File

@@ -61,7 +61,7 @@ class ValidEmail:
class NoCommasInPlaceHolders: class NoCommasInPlaceHolders:
def __init__(self, message="You cannot put commas between double brackets"): def __init__(self, message="You cannot put commas between double parenthesis"):
self.message = message self.message = message
def __call__(self, form, field): def __call__(self, form, field):
@@ -127,7 +127,7 @@ class LettersNumbersSingleQuotesFullStopsAndUnderscoresOnly:
def __call__(self, form, field): def __call__(self, form, field):
if field.data and not re.match(self.regex, field.data): if field.data and not re.match(self.regex, field.data):
raise ValidationError(self.message) raise ValidationError(self.parenthesis)
class DoesNotStartWithDoubleZero: class DoesNotStartWithDoubleZero:

View File

@@ -698,7 +698,9 @@ def _get_content_count_error_and_message_for_template(template):
# Check for blocked characters # Check for blocked characters
if contains_blocked_characters(template.content): if contains_blocked_characters(template.content):
warning = f"{s1}{s2}" warning = f"{s1}{s2}"
return False, Markup(warning) # 🚨 ONLY show the warning, hiding "Will be charged..." return False, Markup(
warning
) # 🚨 ONLY show the warning, hiding "Will be charged..."
# If message is too long, return the length error # If message is too long, return the length error
if template.is_message_too_long(): if template.is_message_too_long():

View File

@@ -7,7 +7,7 @@
</h3> </h3>
<div id="m-a2" class="usa-accordion__content usa-prose"> <div id="m-a2" class="usa-accordion__content usa-prose">
<p class="usa-body"> <p class="usa-body">
Use double brackets and ?? to define optional content. Use double parenthesis and ?? to define optional content.
</p> </p>
<p class="bottom-gutter-1-3"> <p class="bottom-gutter-1-3">
For example if you only want to show something to people who are under For example if you only want to show something to people who are under

View File

@@ -7,11 +7,10 @@
</h3> </h3>
<div id="personalization" class="usa-accordion__content usa-prose"> <div id="personalization" class="usa-accordion__content usa-prose">
<p class="bottom-gutter-1-3"> <p class="bottom-gutter-1-3">
Use double brackets to personalize your message: Use double parenthesis to personalize your message:
</p> </p>
{{ usaInsetText({ {{ usaInsetText({
"text": "Hello ((first name)), your reference is ((ref number))", "text": "Hello ((first name)), your reference is ((ref number))",
"classes": ""}) "classes": ""})
}} }}
</div> </div>

View File

@@ -4,7 +4,7 @@
Send a document by email Send a document by email
</h2> </h2>
<p class="usa-body"> <p class="usa-body">
Use double brackets to add a placeholder field to your template. This will contain a secure link to download the document. Use double parenthesis to add a placeholder field to your template. This will contain a secure link to download the document.
</p> </p>
{{ usaInsetText({ {{ usaInsetText({
"text": "Download your document at: ((link_to_file))", "text": "Download your document at: ((link_to_file))",

View File

@@ -102,7 +102,7 @@ Error
<div class="usa-alert usa-alert--error" role="alert"> <div class="usa-alert usa-alert--error" role="alert">
<div class="usa-alert__body"> <div class="usa-alert__body">
<h1 class="usa-alert__heading banner-title" data-module="track-error" data-error-type="Missing placeholder columns" <h1 class="usa-alert__heading banner-title" data-module="track-error" data-error-type="Missing placeholder columns"
data-error-label="{{ upload_id }}">Your column names need to match the double brackets in your template</h1> data-error-label="{{ upload_id }}">Your column names need to match the double parenthesis in your template</h1>
<p class="usa-alert__text"> <p class="usa-alert__text">
Your file is missing {{ recipients.missing_column_headers | formatted_list( Your file is missing {{ recipients.missing_column_headers | formatted_list(
conjunction='and', conjunction='and',

View File

@@ -61,7 +61,7 @@
<ol class="list list-number"> <ol class="list list-number">
<li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li> <li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li>
<li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li> <li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li>
<li>Add a placeholder using double brackets. For example: Hello ((first&nbsp;name)), your reference is ((ref&nbsp;number)).</li> <li>Add a placeholder using double parenthesis. For example: Hello ((first&nbsp;name)), your reference is ((ref&nbsp;number)).</li>
<li>Select <b class="bold">Save</b>.</li> <li>Select <b class="bold">Save</b>.</li>
</ol> </ol>
@@ -81,7 +81,7 @@
<ol class="list list-number"> <ol class="list list-number">
<li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li> <li>Go to the {{ service_link(current_service, 'main.choose_template', 'templates') }} page.</li>
<li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li> <li>Add a new template or choose an existing template and select <b class="bold">Edit</b>.</li>
<li>Use double brackets and ?? to define optional content. For example, if you only want to show something to people who are under 18: ((under18??Please get your application signed by a parent or guardian.))</li> <li>Use double parenthesis and ?? to define optional content. For example, if you only want to show something to people who are under 18: ((under18??Please get your application signed by a parent or guardian.))</li>
<li>Select <b class="bold">Save</b>.</li> <li>Select <b class="bold">Save</b>.</li>
</ol> </ol>

View File

@@ -59,7 +59,7 @@ your recipient to manage their benefits and increase follow-through.</p>
<h3>To personalize your content</h3> <h3>To personalize your content</h3>
<ol class="list"> <ol class="list">
<li>Add a placeholder to your content by placing two brackets around the personalized elements.</li> <li>Add a placeholder to your content by placing two parenthesis around the personalized elements.</li>
<li>You can manually enter the personalized content or you can upload a spreadsheet with the details and let Notify do the <li>You can manually enter the personalized content or you can upload a spreadsheet with the details and let Notify do the
work for you.</li> work for you.</li>
</ol> </ol>
@@ -78,7 +78,7 @@ all or part of the message contingent upon specific criteria associated with the
<h3>To add conditional content</h3> <h3>To add conditional content</h3>
<ol class="list"> <ol class="list">
<li>Use two brackets and ?? to define the conditional content.</li> <li>Use two parenthesis and ?? to define the conditional content.</li>
<li>You can manually enter the conditional content or you can upload a spreadsheet with the personal details and let Notify <li>You can manually enter the conditional content or you can upload a spreadsheet with the personal details and let Notify
do the work for you.</li> do the work for you.</li>
</ol> </ol>

View File

@@ -14,7 +14,7 @@ from notifications_utils.insensitive_dict import InsensitiveDict
class Placeholder: class Placeholder:
def __init__(self, body): def __init__(self, body):
# body shouldnt include leading/trailing brackets, like (( and )) # body shouldnt include leading/trailing parenthesis, like (( and ))
self.body = body.lstrip("(").rstrip(")") self.body = body.lstrip("(").rstrip(")")
@classmethod @classmethod
@@ -70,14 +70,16 @@ class Field:
conditional_placeholder_tag = ( conditional_placeholder_tag = (
"<span class='placeholder-conditional'>(({}??</span>{}))" "<span class='placeholder-conditional'>(({}??</span>{}))"
) )
placeholder_tag_no_brackets = "<span class='placeholder-no-brackets'>{}</span>" placeholder_tag_no_parenthesis = (
"<span class='placeholder-no-parenthesis'>{}</span>"
)
placeholder_tag_redacted = "<span class='placeholder-redacted'>hidden</span>" placeholder_tag_redacted = "<span class='placeholder-redacted'>hidden</span>"
def __init__( def __init__(
self, self,
content, content,
values=None, values=None,
with_brackets=True, with_parenthesis=True,
html="strip", html="strip",
markdown_lists=False, markdown_lists=False,
redact_missing_personalisation=False, redact_missing_personalisation=False,
@@ -85,8 +87,8 @@ class Field:
self.content = content self.content = content
self.values = values self.values = values
self.markdown_lists = markdown_lists self.markdown_lists = markdown_lists
if not with_brackets: if not with_parenthesis:
self.placeholder_tag = self.placeholder_tag_no_brackets self.placeholder_tag = self.placeholder_tag_no_parenthesis
self.sanitizer = { self.sanitizer = {
"strip": strip_html, "strip": strip_html,
"escape": escape_html, "escape": escape_html,
@@ -198,7 +200,7 @@ class PlainTextField(Field):
placeholder_tag = "(({}))" placeholder_tag = "(({}))"
conditional_placeholder_tag = "(({}??{}))" conditional_placeholder_tag = "(({}??{}))"
placeholder_tag_no_brackets = "{}" placeholder_tag_no_parenthesis = "{}"
placeholder_tag_redacted = "[hidden]" placeholder_tag_redacted = "[hidden]"

View File

@@ -169,7 +169,7 @@
border-radius: 1.05em; border-radius: 1.05em;
} }
.placeholder-no-brackets { .placeholder-no-parenthesis {
display: inline; display: inline;
background: #FD0; background: #FD0;
color: #000; color: #000;

View File

@@ -68,7 +68,7 @@ class SanitiseText:
if decomposed != "" and "<" not in decomposed: if decomposed != "" and "<" not in decomposed:
# decomposition lists the unicode code points a character is made up of, if it's made up of multiple # decomposition lists the unicode code points a character is made up of, if it's made up of multiple
# points. For example the á character returns '0061 0301', as in, the character a, followed by a combining # points. For example the á character returns '0061 0301', as in, the character a, followed by a combining
# acute accent. The decomposition might, however, also contain a decomposition mapping in angle brackets. # acute accent. The decomposition might, however, also contain a decomposition mapping in angle parenthesis.
# For a full list of the types, see here: https://www.compart.com/en/unicode/decomposition. # For a full list of the types, see here: https://www.compart.com/en/unicode/decomposition.
# If it's got a mapping, we're not sure how best to downgrade it, so just see if it's in the # If it's got a mapping, we're not sure how best to downgrade it, so just see if it's in the
# REPLACEMENT_CHARACTERS map. If not, then it's probably a letter with a modifier, eg á # REPLACEMENT_CHARACTERS map. If not, then it's probably a letter with a modifier, eg á

View File

@@ -376,7 +376,7 @@ class SMSPreviewTemplate(BaseSMSTemplate):
"recipient": Field( "recipient": Field(
"((phone number))", "((phone number))",
self.values, self.values,
with_brackets=False, with_parenthesis=False,
html="escape", html="escape",
), ),
"show_recipient": self.show_recipient, "show_recipient": self.show_recipient,
@@ -691,7 +691,7 @@ class EmailPreviewTemplate(BaseEmailTemplate):
"from_address": self.from_address, "from_address": self.from_address,
"reply_to": self.reply_to, "reply_to": self.reply_to,
"recipient": Field( "recipient": Field(
"((email address))", self.values, with_brackets=False "((email address))", self.values, with_parenthesis=False
), ),
"show_recipient": self.show_recipient, "show_recipient": self.show_recipient,
} }
@@ -779,7 +779,7 @@ class BaseLetterTemplate(SubjectMixin, Template):
self.address_block, self.address_block,
self.values, self.values,
html="escape", html="escape",
with_brackets=False, with_parenthesis=False,
).splitlines() ).splitlines()
@property @property

View File

@@ -56,7 +56,7 @@ def test_for_commas_in_placeholders(
): ):
with pytest.raises(ValidationError) as error: with pytest.raises(ValidationError) as error:
NoCommasInPlaceHolders()(None, _gen_mock_field("Hello ((name,date))")) NoCommasInPlaceHolders()(None, _gen_mock_field("Hello ((name,date))"))
assert str(error.value) == "You cannot put commas between double brackets" assert str(error.value) == "You cannot put commas between double parenthesis"
NoCommasInPlaceHolders()(None, _gen_mock_field("Hello ((name))")) NoCommasInPlaceHolders()(None, _gen_mock_field("Hello ((name))"))

View File

@@ -775,7 +775,7 @@ def test_upload_csv_file_with_very_long_placeholder_shows_check_page_with_errors
+12028675109 +12028675109
""", """,
( (
"Your column names need to match the double brackets in your template " "Your column names need to match the double parenthesis in your template "
"Your file is missing a column called name." "Your file is missing a column called name."
), ),
), ),

View File

@@ -1748,7 +1748,12 @@ def test_can_create_email_template_with_emoji(
@pytest.mark.parametrize( @pytest.mark.parametrize(
("template_type", "expected_error"), ("template_type", "expected_error"),
[ [
("sms", ("Please remove the unaccepted character 🍜 in your message, then save again")), (
"sms",
(
"Please remove the unaccepted character 🍜 in your message, then save again"
),
),
], ],
) )
def test_should_not_create_sms_template_with_emoji( def test_should_not_create_sms_template_with_emoji(
@@ -1773,14 +1778,21 @@ def test_should_not_create_sms_template_with_emoji(
_expected_status=200, _expected_status=200,
) )
# print(page.main.prettify()) # print(page.main.prettify())
assert expected_error in normalize_spaces(page.select_one("#template_content-error").text) assert expected_error in normalize_spaces(
page.select_one("#template_content-error").text
)
assert mock_create_service_template.called is False assert mock_create_service_template.called is False
@pytest.mark.parametrize( @pytest.mark.parametrize(
("template_type", "expected_error"), ("template_type", "expected_error"),
[ [
("sms", ("Please remove the unaccepted character 🍔 in your message, then save again")), (
"sms",
(
"Please remove the unaccepted character 🍔 in your message, then save again"
),
),
], ],
) )
def test_should_not_update_sms_template_with_emoji( def test_should_not_update_sms_template_with_emoji(

View File

@@ -232,8 +232,8 @@ def test_bleach_doesnt_try_to_make_valid_html_before_cleaning():
# We let users use &amp; because its often pasted in URLs # We let users use &amp; because its often pasted in URLs
("?a=1&amp;b=2", "?a=1&amp;b=2"), ("?a=1&amp;b=2", "?a=1&amp;b=2"),
# We let users use &lpar; and &rpar; because otherwise its # We let users use &lpar; and &rpar; because otherwise its
# impossible to put brackets in the body of conditional placeholders # impossible to put parenthesis in the body of conditional placeholders
("((var??&lpar;in brackets&rpar;))", "((var??&lpar;in brackets&rpar;))"), ("((var??&lpar;in parenthesis&rpar;))", "((var??&lpar;in parenthesis&rpar;))"),
], ],
) )
def test_escaping_html_entities( def test_escaping_html_entities(

View File

@@ -44,9 +44,9 @@ def test_makes_links_out_of_URLs(url):
), ),
), ),
( (
("this link is in brackets (http://example.com)"), ("this link is in parenthesis (http://example.com)"),
( (
"this link is in brackets " "this link is in parenthesis "
'(<a style="word-wrap: break-word; color: #1D70B8;" href="http://example.com">http://example.com</a>)' '(<a style="word-wrap: break-word; color: #1D70B8;" href="http://example.com">http://example.com</a>)'
), ),
), ),

View File

@@ -8,8 +8,8 @@ from notifications_utils.field import Placeholder
@pytest.mark.parametrize( @pytest.mark.parametrize(
("body", "expected"), ("body", "expected"),
[ [
("((with-brackets))", "with-brackets"), ("((with-parenthesis))", "with-parenthesis"),
("without-brackets", "without-brackets"), ("without-parenthesis", "without-parenthesis"),
], ],
) )
def test_placeholder_returns_name(body, expected): def test_placeholder_returns_name(body, expected):

View File

@@ -136,7 +136,7 @@ invalid_email_addresses = (
"local-with--apostrophe@domain.com", "local-with--apostrophe@domain.com",
"local-with-”-quotes@domain.com", "local-with-”-quotes@domain.com",
"domain-starts-with-a-dot@.domain.com", "domain-starts-with-a-dot@.domain.com",
"brackets(in)local@domain.com", "parenthesis(in)local@domain.com",
"email-too-long-{}@example.com".format("a" * 320), "email-too-long-{}@example.com".format("a" * 320),
"incorrect-punycode@xn---something.com", "incorrect-punycode@xn---something.com",
) )

View File

@@ -894,13 +894,13 @@ def test_phone_templates_normalise_whitespace(template_class):
( (
{}, {},
[ [
"<span class='placeholder-no-brackets'>address line 1</span>", "<span class='placeholder-no-parenthesis'>address line 1</span>",
"<span class='placeholder-no-brackets'>address line 2</span>", "<span class='placeholder-no-parenthesis'>address line 2</span>",
"<span class='placeholder-no-brackets'>address line 3</span>", "<span class='placeholder-no-parenthesis'>address line 3</span>",
"<span class='placeholder-no-brackets'>address line 4</span>", "<span class='placeholder-no-parenthesis'>address line 4</span>",
"<span class='placeholder-no-brackets'>address line 5</span>", "<span class='placeholder-no-parenthesis'>address line 5</span>",
"<span class='placeholder-no-brackets'>address line 6</span>", "<span class='placeholder-no-parenthesis'>address line 6</span>",
"<span class='placeholder-no-brackets'>address line 7</span>", "<span class='placeholder-no-parenthesis'>address line 7</span>",
], ],
), ),
( (
@@ -910,12 +910,12 @@ def test_phone_templates_normalise_whitespace(template_class):
}, },
[ [
"123 Fake Street", "123 Fake Street",
"<span class='placeholder-no-brackets'>address line 2</span>", "<span class='placeholder-no-parenthesis'>address line 2</span>",
"<span class='placeholder-no-brackets'>address line 3</span>", "<span class='placeholder-no-parenthesis'>address line 3</span>",
"<span class='placeholder-no-brackets'>address line 4</span>", "<span class='placeholder-no-parenthesis'>address line 4</span>",
"<span class='placeholder-no-brackets'>address line 5</span>", "<span class='placeholder-no-parenthesis'>address line 5</span>",
"United Kingdom", "United Kingdom",
"<span class='placeholder-no-brackets'>address line 7</span>", "<span class='placeholder-no-parenthesis'>address line 7</span>",
], ],
), ),
( (
@@ -1129,13 +1129,13 @@ def test_letter_image_renderer(
"image_url": "http://example.com/endpoint.png", "image_url": "http://example.com/endpoint.png",
"page_numbers": expected_page_numbers, "page_numbers": expected_page_numbers,
"address": [ "address": [
"<span class='placeholder-no-brackets'>address line 1</span>", "<span class='placeholder-no-parenthesis'>address line 1</span>",
"<span class='placeholder-no-brackets'>address line 2</span>", "<span class='placeholder-no-parenthesis'>address line 2</span>",
"<span class='placeholder-no-brackets'>address line 3</span>", "<span class='placeholder-no-parenthesis'>address line 3</span>",
"<span class='placeholder-no-brackets'>address line 4</span>", "<span class='placeholder-no-parenthesis'>address line 4</span>",
"<span class='placeholder-no-brackets'>address line 5</span>", "<span class='placeholder-no-parenthesis'>address line 5</span>",
"<span class='placeholder-no-brackets'>address line 6</span>", "<span class='placeholder-no-parenthesis'>address line 6</span>",
"<span class='placeholder-no-brackets'>address line 7</span>", "<span class='placeholder-no-parenthesis'>address line 7</span>",
], ],
"contact_block": "10 Downing Street", "contact_block": "10 Downing Street",
"date": "12 December 2012", "date": "12 December 2012",
@@ -1838,7 +1838,7 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
mock.call( mock.call(
"subject", {}, html="escape", redact_missing_personalisation=False "subject", {}, html="escape", redact_missing_personalisation=False
), ),
mock.call("((email address))", {}, with_brackets=False), mock.call("((email address))", {}, with_parenthesis=False),
], ],
), ),
( (
@@ -1855,7 +1855,9 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"sms", "sms",
{}, {},
[ [
mock.call("((phone number))", {}, with_brackets=False, html="escape"), mock.call(
"((phone number))", {}, with_parenthesis=False, html="escape"
),
mock.call( mock.call(
"content", {}, html="escape", redact_missing_personalisation=False "content", {}, html="escape", redact_missing_personalisation=False
), ),
@@ -1874,7 +1876,9 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"broadcast", "broadcast",
{}, {},
[ [
mock.call("((phone number))", {}, with_brackets=False, html="escape"), mock.call(
"((phone number))", {}, with_parenthesis=False, html="escape"
),
mock.call( mock.call(
"content", {}, html="escape", redact_missing_personalisation=False "content", {}, html="escape", redact_missing_personalisation=False
), ),
@@ -1906,7 +1910,7 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"((address line 7))" "((address line 7))"
), ),
{}, {},
with_brackets=False, with_parenthesis=False,
html="escape", html="escape",
), ),
mock.call( mock.call(
@@ -1937,7 +1941,7 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"((address line 7))" "((address line 7))"
), ),
{}, {},
with_brackets=False, with_parenthesis=False,
html="escape", html="escape",
), ),
mock.call( mock.call(
@@ -1973,7 +1977,7 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
mock.call( mock.call(
"subject", {}, html="escape", redact_missing_personalisation=True "subject", {}, html="escape", redact_missing_personalisation=True
), ),
mock.call("((email address))", {}, with_brackets=False), mock.call("((email address))", {}, with_parenthesis=False),
], ],
), ),
( (
@@ -1981,7 +1985,9 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"sms", "sms",
{"redact_missing_personalisation": True}, {"redact_missing_personalisation": True},
[ [
mock.call("((phone number))", {}, with_brackets=False, html="escape"), mock.call(
"((phone number))", {}, with_parenthesis=False, html="escape"
),
mock.call( mock.call(
"content", {}, html="escape", redact_missing_personalisation=True "content", {}, html="escape", redact_missing_personalisation=True
), ),
@@ -1992,7 +1998,9 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"broadcast", "broadcast",
{"redact_missing_personalisation": True}, {"redact_missing_personalisation": True},
[ [
mock.call("((phone number))", {}, with_brackets=False, html="escape"), mock.call(
"((phone number))", {}, with_parenthesis=False, html="escape"
),
mock.call( mock.call(
"content", {}, html="escape", redact_missing_personalisation=True "content", {}, html="escape", redact_missing_personalisation=True
), ),
@@ -2034,7 +2042,7 @@ def test_is_message_empty_email_and_letter_templates_tries_not_to_count_chars(
"((address line 7))" "((address line 7))"
), ),
{}, {},
with_brackets=False, with_parenthesis=False,
html="escape", html="escape",
), ),
mock.call( mock.call(
@@ -2488,7 +2496,7 @@ def test_email_preview_shows_reply_to_address(extra_args):
@pytest.mark.parametrize( @pytest.mark.parametrize(
("template_values", "expected_content"), ("template_values", "expected_content"),
[ [
({}, "<span class='placeholder-no-brackets'>email address</span>"), ({}, "<span class='placeholder-no-parenthesis'>email address</span>"),
({"email address": "test@example.com"}, "test@example.com"), ({"email address": "test@example.com"}, "test@example.com"),
], ],
) )
@@ -2558,11 +2566,11 @@ def test_email_preview_shows_recipient_address(
( (
"<ul>" "<ul>"
"<li>line 1</li>" "<li>line 1</li>"
'<li><span class="placeholder-no-brackets">address line 2</span></li>' '<li><span class="placeholder-no-parenthesis">address line 2</span></li>'
'<li><span class="placeholder-no-brackets">address line 3</span></li>' '<li><span class="placeholder-no-parenthesis">address line 3</span></li>'
'<li><span class="placeholder-no-brackets">address line 4</span></li>' '<li><span class="placeholder-no-parenthesis">address line 4</span></li>'
'<li><span class="placeholder-no-brackets">address line 5</span></li>' '<li><span class="placeholder-no-parenthesis">address line 5</span></li>'
'<li><span class="placeholder-no-brackets">address line 6</span></li>' '<li><span class="placeholder-no-parenthesis">address line 6</span></li>'
# Postcode is not normalised until the address is complete # Postcode is not normalised until the address is complete
"<li>n1 4wq</li>" "<li>n1 4wq</li>"
"</ul>" "</ul>"