Skip to content

Commit

Permalink
Fix the preview formatting when a variable appears in a link url (#344)
Browse files Browse the repository at this point in the history
* got the tests passing with a placeholder function to detect if the variable is in an href

* added more test cases where the variables are subbed in

* bump utils version
  • Loading branch information
smcmurtry authored Jan 8, 2025
1 parent e137e9f commit 27c9816
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .github/actions/waffles/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ docopt==0.6.2
Flask==2.3.3
markupsafe==2.1.5
setuptools==75.6.0 # required for distutils in Python 3.12
git+https://github.com/cds-snc/[email protected].3#egg=notifications-utils
git+https://github.com/cds-snc/[email protected].4#egg=notifications-utils
16 changes: 15 additions & 1 deletion notifications_utils/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ class Field:
# * body of placeholder - potentially standard or conditional,
# * closing ))
placeholder_pattern = re.compile(r"\({2}" r"(?!\()" r"([\s\S]+?)" r"\){2}")
placeholder_pattern_for_link_url = re.compile(
r"(?<=\]\()" # Lookbehind for markdown link URL pattern
r"\({2}" # Match opening double parentheses
r"(?!\()" # Negative lookahead to enforce consumption of late parenthesis and not early ones
r"([\s\S]+?)" # Body of placeholder - potentially standard or conditional
r"\){2}" # Match closing double parentheses
)

placeholder_tag = "<mark class='placeholder'>(({}))</mark>"
conditional_placeholder_tag = "<mark class='placeholder-conditional'><span class='condition'>(({}??</span>{}))</mark>"
placeholder_tag_translated = "<span class='placeholder-no-brackets'>[{}]</span>"
Expand Down Expand Up @@ -109,6 +117,10 @@ def values(self):
def values(self, value):
self._values = Columns(value) if value else {}

def format_match_in_link_url(self, match):
placeholder = Placeholder.from_match(match)
return placeholder.name

def format_match(self, match):
placeholder = Placeholder.from_match(match)

Expand Down Expand Up @@ -155,7 +167,9 @@ def get_replacement_as_list(self, replacement):

@property
def _raw_formatted(self):
return re.sub(self.placeholder_pattern, self.format_match, self.sanitizer(self.content))
_sanitized_content = self.sanitizer(self.content)
sanitized_content = re.sub(self.placeholder_pattern_for_link_url, self.format_match_in_link_url, _sanitized_content)
return re.sub(self.placeholder_pattern, self.format_match, sanitized_content)

@property
def formatted(self):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "notifications-utils"
version = "53.0.3"
version = "53.0.4"
description = "Shared python code for Notification - Provides logging utils etc."
authors = ["Canadian Digital Service"]
license = "MIT license"
Expand Down
71 changes: 71 additions & 0 deletions tests/test_template.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import pytest
from bs4 import BeautifulSoup
from notifications_utils.template import get_html_email_body


Expand Down Expand Up @@ -40,6 +41,76 @@ def test_lang_tags_in_templates_good_content(good_content: str):
assert '<div lang="fr-ca">' in html


class TestVariablesInLinks:
@pytest.mark.parametrize(
"template_content,variable,expected_html",
[
("((variable))", {}, "((variable))"),
("((variable))", {"variable": "my content"}, "my content"),
],
)
def test_variable(self, template_content, variable, expected_html):
html = BeautifulSoup(str(get_html_email_body(template_content, variable)), "html.parser")
rendered_markdown = html.get_text()
assert rendered_markdown == expected_html

@pytest.mark.parametrize(
"template_content,variable,expected_link_text,expected_href",
[
(
"[link text with ((variable))](https://developer.mozilla.org/en-US/)",
{},
"link text with ((variable))",
"https://developer.mozilla.org/en-US/",
),
(
"[link text with ((variable))](https://developer.mozilla.org/en-US/)",
{"variable": "var"},
"link text with var",
"https://developer.mozilla.org/en-US/",
),
(
"[link with query param](https://developer.mozilla.org/en-US/search?q=asdf)",
{},
"link with query param",
"https://developer.mozilla.org/en-US/search?q=asdf",
),
("[link with variable as url](((url_var)))", {}, "link with variable as url", "url_var"),
(
"[link with variable as url](((url_var)))",
{"url_var": "replaced_variable"},
"link with variable as url",
"replaced_variable",
),
("[link with variable in url](((url_var))/en-US/)", {}, "link with variable in url", "url_var/en-US/"),
(
"[link with variable in url](((url_var))/en-US/)",
{"url_var": "replaced_variable"},
"link with variable in url",
"replaced_variable/en-US/",
),
(
"[link with variable and query param](((url_var))/en-US/search?q=asdf)",
{},
"link with variable and query param",
"url_var/en-US/search?q=asdf",
),
(
"[link with variable and query param](((url_var))/en-US/search?q=asdf)",
{"url_var": "replaced_variable"},
"link with variable and query param",
"replaced_variable/en-US/search?q=asdf",
),
],
)
def test_link_text_with_variable(self, template_content, variable, expected_link_text, expected_href):
html = BeautifulSoup(str(get_html_email_body(template_content, variable)), "html.parser")
href = html.select("a")[0].get_attribute_list("href")[0]
link_text = html.select("a")[0].get_text()
assert href == expected_href
assert link_text == expected_link_text


class TestRTLTags:
def test_rtl_tags_in_templates(self):
content = "[[rtl]]\nRTL content\n[[/rtl]]"
Expand Down

0 comments on commit 27c9816

Please sign in to comment.