* Support querystring and anchor for local links in Delivery API output (#20142) * Support querystring and anchor for local links in Delivery API output * Add default implementation for backwards compat * Add default implementation for backwards compat (also on the interface) * Fix default implementation * Add extra tests proving that querystring/postfix can be handled for local links in both legacy and current format.
This commit is contained in:
@@ -10,6 +10,7 @@ using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Infrastructure.DeliveryApi;
|
||||
using Umbraco.Extensions;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.DeliveryApi;
|
||||
|
||||
@@ -127,12 +128,15 @@ public class RichTextParserTests : PropertyValueConverterTests
|
||||
Assert.AreEqual("the original something", span.Attributes.First().Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseElement_CanParseContentLink()
|
||||
[TestCase(null)]
|
||||
[TestCase("")]
|
||||
[TestCase("#some-anchor")]
|
||||
[TestCase("?something=true")]
|
||||
public void ParseElement_CanParseContentLink(string? postfix)
|
||||
{
|
||||
var parser = CreateRichTextElementParser();
|
||||
|
||||
var element = parser.Parse($"<p><a href=\"/{{localLink:umb://document/{_contentKey:N}}}\"></a></p>", RichTextBlockModel.Empty) as RichTextRootElement;
|
||||
var element = parser.Parse($"<p><a href=\"/{{localLink:umb://document/{_contentKey:N}}}{postfix}\"></a></p>", RichTextBlockModel.Empty) as RichTextRootElement;
|
||||
Assert.IsNotNull(element);
|
||||
var link = element.Elements.OfType<RichTextGenericElement>().Single().Elements.Single() as RichTextGenericElement;
|
||||
Assert.IsNotNull(link);
|
||||
@@ -142,6 +146,7 @@ public class RichTextParserTests : PropertyValueConverterTests
|
||||
var route = link.Attributes.First().Value as IApiContentRoute;
|
||||
Assert.IsNotNull(route);
|
||||
Assert.AreEqual("/some-content-path", route.Path);
|
||||
Assert.AreEqual(postfix.NullOrWhiteSpaceAsNull(), route.QueryString);
|
||||
Assert.AreEqual(_contentRootKey, route.StartItem.Id);
|
||||
Assert.AreEqual("the-root-path", route.StartItem.Path);
|
||||
}
|
||||
@@ -176,6 +181,22 @@ public class RichTextParserTests : PropertyValueConverterTests
|
||||
Assert.AreEqual("https://some.where/else/", link.Attributes.First().Value);
|
||||
}
|
||||
|
||||
[TestCase("#some-anchor")]
|
||||
[TestCase("?something=true")]
|
||||
public void ParseElement_CanHandleNonLocalLink_WithPostfix(string postfix)
|
||||
{
|
||||
var parser = CreateRichTextElementParser();
|
||||
|
||||
var element = parser.Parse($"<p><a href=\"https://some.where/else/{postfix}\"></a></p>", RichTextBlockModel.Empty) as RichTextRootElement;
|
||||
Assert.IsNotNull(element);
|
||||
var link = element.Elements.OfType<RichTextGenericElement>().Single().Elements.Single() as RichTextGenericElement;
|
||||
Assert.IsNotNull(link);
|
||||
Assert.AreEqual("a", link.Tag);
|
||||
Assert.AreEqual(1, link.Attributes.Count);
|
||||
Assert.AreEqual("href", link.Attributes.First().Key);
|
||||
Assert.AreEqual($"https://some.where/else/{postfix}", link.Attributes.First().Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseElement_LinkTextIsWrappedInTextElement()
|
||||
{
|
||||
@@ -459,12 +480,51 @@ public class RichTextParserTests : PropertyValueConverterTests
|
||||
{
|
||||
var parser = CreateRichTextMarkupParser();
|
||||
|
||||
var result = parser.Parse($"<p><a href=\"/{{localLink:{_contentKey:N}}}\" type=\"document\"></a></p>");
|
||||
Assert.IsTrue(result.Contains("href=\"/some-content-path\""));
|
||||
Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\""));
|
||||
Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseMarkup_CanParseLegacyContentLink()
|
||||
{
|
||||
var parser = CreateRichTextMarkupParser();
|
||||
|
||||
var result = parser.Parse($"<p><a href=\"/{{localLink:umb://document/{_contentKey:N}}}\"></a></p>");
|
||||
Assert.IsTrue(result.Contains("href=\"/some-content-path\""));
|
||||
Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\""));
|
||||
Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\""));
|
||||
}
|
||||
|
||||
[TestCase("#some-anchor")]
|
||||
[TestCase("?something=true")]
|
||||
[TestCase("#!some-hashbang")]
|
||||
[TestCase("?something=true#some-anchor")]
|
||||
public void ParseMarkup_CanParseContentLink_WithPostfix(string postfix)
|
||||
{
|
||||
var parser = CreateRichTextMarkupParser();
|
||||
|
||||
var result = parser.Parse($"<p><a href=\"/{{localLink:{_contentKey:N}}}{postfix}\" type=\"document\"></a></p>");
|
||||
Assert.IsTrue(result.Contains($"href=\"/some-content-path{postfix}\""));
|
||||
Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\""));
|
||||
Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\""));
|
||||
}
|
||||
|
||||
[TestCase("#some-anchor")]
|
||||
[TestCase("?something=true")]
|
||||
[TestCase("#!some-hashbang")]
|
||||
[TestCase("?something=true#some-anchor")]
|
||||
public void ParseMarkup_CanParseLegacyContentLink_WithPostfix(string postfix)
|
||||
{
|
||||
var parser = CreateRichTextMarkupParser();
|
||||
|
||||
var result = parser.Parse($"<p><a href=\"/{{localLink:umb://document/{_contentKey:N}}}{postfix}\"></a></p>");
|
||||
Assert.IsTrue(result.Contains($"href=\"/some-content-path{postfix}\""));
|
||||
Assert.IsTrue(result.Contains("data-start-item-path=\"the-root-path\""));
|
||||
Assert.IsTrue(result.Contains($"data-start-item-id=\"{_contentRootKey:D}\""));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseMarkup_CanParseMediaLink()
|
||||
{
|
||||
@@ -485,6 +545,8 @@ public class RichTextParserTests : PropertyValueConverterTests
|
||||
}
|
||||
|
||||
[TestCase("<p><a href=\"https://some.where/else/\"></a></p>")]
|
||||
[TestCase("<p><a href=\"https://some.where/else/#some-anchor\"></a></p>")]
|
||||
[TestCase("<p><a href=\"https://some.where/else/?something=true\"></a></p>")]
|
||||
[TestCase("<p><img src=\"https://some.where/something.png?rmode=max&width=500\"></p>")]
|
||||
public void ParseMarkup_CanHandleNonLocalReferences(string html)
|
||||
{
|
||||
|
||||
@@ -79,6 +79,45 @@ public class ApiRichTextMarkupParserTests
|
||||
Assert.AreEqual(expectedOutput, parsedHtml);
|
||||
}
|
||||
|
||||
[TestCase("#some-anchor")]
|
||||
[TestCase("?something=true")]
|
||||
[TestCase("#!some-hashbang")]
|
||||
[TestCase("?something=true#some-anchor")]
|
||||
public void Can_Parse_LocalLinks_With_Postfix(string postfix)
|
||||
{
|
||||
var key1 = Guid.Parse("eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f");
|
||||
var data1 = new MockData()
|
||||
.WithKey(key1)
|
||||
.WithRoutePath($"/self/{postfix}")
|
||||
.WithRouteStartPath("self");
|
||||
|
||||
var key2 = Guid.Parse("cc143afe-4cbf-46e5-b399-c9f451384373");
|
||||
var data2 = new MockData()
|
||||
.WithKey(key2)
|
||||
.WithRoutePath($"/other/{postfix}")
|
||||
.WithRouteStartPath("other");
|
||||
|
||||
var mockData = new Dictionary<Guid, MockData>
|
||||
{
|
||||
{ key1, data1 },
|
||||
{ key2, data2 },
|
||||
};
|
||||
|
||||
var parser = BuildDefaultSut(mockData);
|
||||
|
||||
var html =
|
||||
$@"<p>Rich text outside of the blocks with a link to <a type=""document"" href=""/{{localLink:eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f}}{postfix}"" title=""itself"">itself</a><br><br></p>
|
||||
<p>and to the <a type=""document"" href=""/{{localLink:cc143afe-4cbf-46e5-b399-c9f451384373}}{postfix}"" title=""other page"">other page</a></p>";
|
||||
|
||||
var expectedOutput =
|
||||
$@"<p>Rich text outside of the blocks with a link to <a href=""/self/{postfix}"" title=""itself"" data-start-item-path=""self"" data-start-item-id=""eed5fc6b-96fd-45a5-a0f1-b1adfb483c2f"">itself</a><br><br></p>
|
||||
<p>and to the <a href=""/other/{postfix}"" title=""other page"" data-start-item-path=""other"" data-start-item-id=""cc143afe-4cbf-46e5-b399-c9f451384373"">other page</a></p>";
|
||||
|
||||
var parsedHtml = parser.Parse(html);
|
||||
|
||||
Assert.AreEqual(expectedOutput, parsedHtml);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Can_Parse_Inline_LocalImages()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user