Skip to content

Commit e5866d3

Browse files
committed
Add tests for the inline svg tag helper
1 parent ad9a191 commit e5866d3

File tree

3 files changed

+218
-7
lines changed

3 files changed

+218
-7
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
using Microsoft.AspNetCore.Hosting;
2+
using Microsoft.AspNetCore.Razor.TagHelpers;
3+
using Microsoft.Extensions.FileProviders;
4+
using Microsoft.Extensions.Logging;
5+
using Microsoft.Extensions.Options;
6+
using Moq;
7+
using NUnit.Framework;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.IO;
11+
using System.Text;
12+
using System.Threading.Tasks;
13+
using Umbraco.Cms.Core.Configuration.Models;
14+
using Umbraco.Cms.Core.IO;
15+
using Umbraco.Cms.Core.Models.PublishedContent;
16+
using Umbraco.Cms.Core.Routing;
17+
18+
namespace Our.Umbraco.TagHelpers.Tests
19+
{
20+
public class InlineSvgTagHelperTests
21+
{
22+
private TagHelperContext _context = null!;
23+
private TagHelperOutput _output = null!;
24+
25+
[SetUp]
26+
public void Setup()
27+
{
28+
var attributes = new TagHelperAttributeList
29+
{
30+
{ "src", "test-src" },
31+
{ "media-item", "test-media" }
32+
};
33+
_context = new TagHelperContext(attributes, new Dictionary<object, object>(), "test");
34+
_output = new TagHelperOutput("umb-svg", attributes, (result, encoder) =>
35+
{
36+
var content = new DefaultTagHelperContent();
37+
content.SetContent("Something else");
38+
return Task.FromResult<TagHelperContent>(content);
39+
});
40+
}
41+
42+
[Test]
43+
public void NoOutputIfNoMediaOrFileSet()
44+
{
45+
var tagHelper = new InlineSvgTagHelper(null, null, null);
46+
47+
tagHelper.Process(_context, _output);
48+
49+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
50+
}
51+
52+
[Test]
53+
public void NoOutputIfBothMediaAndFileSet()
54+
{
55+
var umbContent = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media);
56+
var tagHelper = new InlineSvgTagHelper(null, null, null)
57+
{
58+
FileSource = "test.svg",
59+
MediaItem = umbContent
60+
};
61+
62+
tagHelper.Process(_context, _output);
63+
64+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
65+
}
66+
67+
[Test]
68+
public void NoOutputIfFileNotSvg()
69+
{
70+
var tagHelper = new InlineSvgTagHelper(null, null, null)
71+
{
72+
FileSource = "test.notsvg"
73+
};
74+
75+
tagHelper.Process(_context, _output);
76+
77+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
78+
}
79+
80+
[Test]
81+
public void NoOutputIfFileNotFound()
82+
{
83+
var fileProvider = new Mock<IFileProvider>();
84+
fileProvider.Setup(p => p.GetFileInfo(It.IsAny<string>())).Returns(Mock.Of<IFileInfo>(f => !f.Exists));
85+
var hostEnv = Mock.Of<IWebHostEnvironment>(e => e.WebRootFileProvider == fileProvider.Object);
86+
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null)
87+
{
88+
FileSource = "test.svg"
89+
};
90+
91+
tagHelper.Process(_context, _output);
92+
93+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
94+
}
95+
96+
[Test]
97+
public void ExpectedOutputIfValidFile()
98+
{
99+
var fileProvider = new Mock<IFileProvider>();
100+
fileProvider.Setup(p => p.GetFileInfo(It.IsAny<string>())).Returns(Mock.Of<IFileInfo>(f => f.Exists && f.CreateReadStream() == new MemoryStream(Encoding.UTF8.GetBytes("test svg"))));
101+
var hostEnv = Mock.Of<IWebHostEnvironment>(e => e.WebRootFileProvider == fileProvider.Object);
102+
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null)
103+
{
104+
FileSource = "test.svg"
105+
};
106+
107+
tagHelper.Process(_context, _output);
108+
109+
Assert.IsNull(_output?.TagName);
110+
Assert.AreEqual(_output.Content.GetContent(), "test svg");
111+
Assert.IsFalse(_output.Attributes.ContainsName("src"));
112+
Assert.IsFalse(_output.Attributes.ContainsName("media-item"));
113+
}
114+
115+
[Test]
116+
public void NoOutputIfMediaUrlNull()
117+
{
118+
var urlProvider = new Mock<IPublishedUrlProvider>();
119+
urlProvider.Setup(p => p.GetMediaUrl(It.IsAny<IPublishedContent>(), It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns((string)null!);
120+
var tagHelper = new InlineSvgTagHelper(null, null, urlProvider.Object)
121+
{
122+
MediaItem = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media)
123+
};
124+
125+
tagHelper.Process(_context, _output);
126+
127+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
128+
}
129+
130+
[Test]
131+
public void NoOutputIfMediaNotSvg()
132+
{
133+
var umbContent = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media);
134+
var urlProvider = new Mock<IPublishedUrlProvider>();
135+
urlProvider.Setup(p => p.GetMediaUrl(umbContent, It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns("test.notsvg");
136+
var tagHelper = new InlineSvgTagHelper(null, null, urlProvider.Object)
137+
{
138+
MediaItem = umbContent
139+
};
140+
141+
tagHelper.Process(_context, _output);
142+
143+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
144+
}
145+
146+
[Test]
147+
public void NoOutputIfMediaNotFound()
148+
{
149+
var umbContent = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media);
150+
var urlProvider = new Mock<IPublishedUrlProvider>();
151+
urlProvider.Setup(p => p.GetMediaUrl(umbContent, It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns("test.svg");
152+
var fileSystem = Mock.Of<IFileSystem>(fs => !fs.FileExists(It.IsAny<string>()));
153+
var tagHelper = new InlineSvgTagHelper(
154+
new MediaFileManager(fileSystem, null, null, null, null, Mock.Of<IOptions<ContentSettings>>()),
155+
null,
156+
urlProvider.Object)
157+
{
158+
MediaItem = umbContent
159+
};
160+
161+
tagHelper.Process(_context, _output);
162+
163+
Assert.IsTrue(_output.Content.IsEmptyOrWhiteSpace);
164+
}
165+
166+
[Test]
167+
public void ExpectedOutputIfValidMedia()
168+
{
169+
var umbContent = Mock.Of<IPublishedContent>(c => c.ContentType.ItemType == PublishedItemType.Media);
170+
var urlProvider = new Mock<IPublishedUrlProvider>();
171+
urlProvider.Setup(p => p.GetMediaUrl(umbContent, It.IsAny<UrlMode>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Uri>())).Returns("test.svg");
172+
var fileSystem = Mock.Of<IFileSystem>(fs => fs.FileExists(It.IsAny<string>()) && fs.OpenFile(It.IsAny<string>()) == new MemoryStream(Encoding.UTF8.GetBytes("test svg")));
173+
var tagHelper = new InlineSvgTagHelper(
174+
new MediaFileManager(fileSystem, null, null, null, null, Mock.Of<IOptions<ContentSettings>>()),
175+
null,
176+
urlProvider.Object)
177+
{
178+
MediaItem = umbContent
179+
};
180+
181+
tagHelper.Process(_context, _output);
182+
183+
Assert.IsNull(_output?.TagName);
184+
Assert.AreEqual("test svg", _output.Content.GetContent());
185+
Assert.IsFalse(_output.Attributes.ContainsName("src"));
186+
Assert.IsFalse(_output.Attributes.ContainsName("media-item"));
187+
}
188+
189+
[Test]
190+
public void SanitizesJavascript()
191+
{
192+
var fileProvider = new Mock<IFileProvider>();
193+
fileProvider
194+
.Setup(p => p.GetFileInfo(It.IsAny<string>()))
195+
.Returns(Mock.Of<IFileInfo>(f => f.Exists && f.CreateReadStream() == new MemoryStream(Encoding.UTF8.GetBytes("<a xlink:href=\"javascript:alert('test');\">Click here</a><script attr=\"test\">test</script>end"))));
196+
var hostEnv = Mock.Of<IWebHostEnvironment>(e => e.WebRootFileProvider == fileProvider.Object);
197+
var tagHelper = new InlineSvgTagHelper(null, hostEnv, null)
198+
{
199+
FileSource = "test.svg"
200+
};
201+
202+
tagHelper.Process(_context, _output);
203+
204+
Assert.AreEqual("<a xlink:href=\"syntax:error:alert('test');\">Click here</a>end", _output.Content.GetContent());
205+
}
206+
}
207+
}

Our.Umbraco.TagHelpers.Tests/Our.Umbraco.TagHelpers.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="2.2.0" />
1111
<PackageReference Include="Microsoft.AspNetCore.Razor" Version="2.2.0" />
1212
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />
13+
<PackageReference Include="Moq" Version="4.18.2" />
1314
<PackageReference Include="NUnit" Version="3.13.2" />
1415
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
1516
<PackageReference Include="coverlet.collector" Version="3.1.0">

Our.Umbraco.TagHelpers/InlineSvgTagHelper.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,27 @@
55
using System.Text.RegularExpressions;
66
using Umbraco.Cms.Core.IO;
77
using Umbraco.Cms.Core.Models.PublishedContent;
8+
using Umbraco.Cms.Core.Routing;
89
using Umbraco.Extensions;
910

1011
namespace Our.Umbraco.TagHelpers
1112
{
1213
/// <summary>
13-
/// This allows you to inline an SVG file into the DOM
14+
/// This allows you to inline an SVG file into the DOM
1415
/// from a file on disk or an Umbraco Media Item
1516
/// </summary>
1617
[HtmlTargetElement("our-svg")]
1718
public class InlineSvgTagHelper : TagHelper
1819
{
1920
private MediaFileManager _mediaFileManager;
2021
private IWebHostEnvironment _webHostEnvironment;
22+
private IPublishedUrlProvider _urlProvider;
2123

22-
public InlineSvgTagHelper(MediaFileManager mediaFileManager, IWebHostEnvironment webHostEnvironment)
24+
public InlineSvgTagHelper(MediaFileManager mediaFileManager, IWebHostEnvironment webHostEnvironment, IPublishedUrlProvider urlProvider)
2325
{
2426
_mediaFileManager = mediaFileManager;
2527
_webHostEnvironment = webHostEnvironment;
28+
_urlProvider = urlProvider;
2629
}
2730

2831
/// <summary>
@@ -59,8 +62,8 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
5962
{
6063
// Check Umbraco Media Item that is picked/used
6164
// has a file that uses a .svg file extension
62-
var mediaItemPath = MediaItem.Url();
63-
if(mediaItemPath.EndsWith(".svg", StringComparison.InvariantCultureIgnoreCase) == false)
65+
var mediaItemPath = MediaItem.Url(_urlProvider);
66+
if (mediaItemPath?.EndsWith(".svg", StringComparison.InvariantCultureIgnoreCase) != true)
6467
{
6568
output.SuppressOutput();
6669
return;
@@ -101,11 +104,11 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
101104
return;
102105
}
103106

104-
fileContents = File.ReadAllText(file.PhysicalPath);
107+
using var reader = new StreamReader(file.CreateReadStream());
108+
fileContents = reader.ReadToEnd();
105109
}
106110

107-
108-
// Sanatize SVG (Is there anything in Umbraco to reuse)
111+
// Sanitize SVG (Is there anything in Umbraco to reuse)
109112
// https://stackoverflow.com/questions/65247336/is-there-anyway-to-sanitize-svg-file-in-c-any-libraries-anything/65375485#65375485
110113
var cleanedFileContents = Regex.Replace(fileContents,
111114
@"<script.*?script>",

0 commit comments

Comments
 (0)