Skip to content

Commit adc7980

Browse files
committed
updates config setting, adds tests, fixes a bug (thank you tests :))
1 parent 2d8127c commit adc7980

File tree

8 files changed

+267
-23
lines changed

8 files changed

+267
-23
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using Microsoft.AspNetCore.Hosting;
2+
using Microsoft.Extensions.Options;
3+
using Moq;
4+
using NUnit.Framework;
5+
using Our.Umbraco.TagHelpers.Configuration;
6+
using Our.Umbraco.TagHelpers.Services;
7+
using System;
8+
using Umbraco.Cms.Core.Cache;
9+
using Umbraco.Cms.Core.Logging;
10+
11+
namespace Our.Umbraco.TagHelpers.Tests
12+
{
13+
public class SelfHostServiceTests
14+
{
15+
private Mock<IProfilingLogger> _loggerMock;
16+
private Mock<IAppPolicyCache> _runtimeCacheMock;
17+
private Mock<IWebHostEnvironment> _hostingEnvironmentMock;
18+
private Mock<IOptions<OurUmbracoTagHelpersConfiguration>> _globalSettingsMock;
19+
private SelfHostService _service;
20+
21+
[SetUp]
22+
public void SetUp()
23+
{
24+
_loggerMock = new Mock<IProfilingLogger>();
25+
_runtimeCacheMock = new Mock<IAppPolicyCache>();
26+
_hostingEnvironmentMock = new Mock<IWebHostEnvironment>();
27+
_globalSettingsMock = new Mock<IOptions<OurUmbracoTagHelpersConfiguration>>();
28+
_globalSettingsMock.SetupGet(x => x.Value).Returns(new OurUmbracoTagHelpersConfiguration
29+
{
30+
OurSelfHost = new SelfHostTagHelperConfiguration
31+
{
32+
RootFolder = "/self-hosted/"
33+
}
34+
});
35+
_service = new SelfHostService(
36+
_loggerMock.Object,
37+
_runtimeCacheMock.Object,
38+
_hostingEnvironmentMock.Object,
39+
_globalSettingsMock.Object
40+
);
41+
}
42+
43+
[Test]
44+
public void GetRemoteFolderPath_GivenUriWithMoreThanTwoSegments_ReturnsFolderPath()
45+
{
46+
// Arrange
47+
var uri = new Uri("http://www.example.com/folder/subfolder/file.jpg");
48+
var expectedFolderPath = "/folder/subfolder";
49+
50+
// Act
51+
var result = _service.GetRemoteFolderPath(uri);
52+
53+
// Assert
54+
Assert.AreEqual(expectedFolderPath, result);
55+
}
56+
57+
[Test]
58+
public void GetRemoteFolderPath_GivenUriWithLessThanTwoSegments_ReturnsEmptyString()
59+
{
60+
// Arrange
61+
var uri = new Uri("http://www.example.com/");
62+
var expectedFolderPath = string.Empty;
63+
64+
// Act
65+
var result = _service.GetRemoteFolderPath(uri);
66+
67+
// Assert
68+
Assert.AreEqual(expectedFolderPath, result);
69+
}
70+
}
71+
}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
using Microsoft.AspNetCore.Razor.TagHelpers;
2+
using Moq;
3+
using NUnit.Framework;
4+
using Our.Umbraco.TagHelpers.Models;
5+
using Our.Umbraco.TagHelpers.Services;
6+
using Our.Umbraco.TagHelpers.Tests.Helpers;
7+
using System.Threading.Tasks;
8+
9+
namespace Our.Umbraco.TagHelpers.Tests
10+
{
11+
[TestFixture]
12+
public class SelfHostTagHelperTests
13+
{
14+
[Test]
15+
public async Task ProcessAsync_SrcAttribute_SetsSrcAttribute()
16+
{
17+
// Arrange
18+
var selfHostServiceMock = new Mock<ISelfHostService>();
19+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
20+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.jpg" });
21+
22+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
23+
tagHelper.SrcAttribute = "https://example.com/test.jpg";
24+
var id = "unique-id";
25+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
26+
var output = new TagHelperOutput("img", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
27+
28+
// Act
29+
await tagHelper.ProcessAsync(tagHelperContext, output);
30+
31+
// Assert
32+
Assert.AreEqual("/media/test.jpg", output.Attributes["src"].Value);
33+
}
34+
35+
[Test]
36+
public async Task ProcessAsync_HrefAttribute_SetsHrefAttribute()
37+
{
38+
// Arrange
39+
var selfHostServiceMock = new Mock<ISelfHostService>();
40+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
41+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.pdf" });
42+
43+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
44+
tagHelper.HrefAttribute = "https://example.com/test.pdf";
45+
var id = "unique-id";
46+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
47+
var output = new TagHelperOutput("a", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
48+
49+
// Act
50+
await tagHelper.ProcessAsync(tagHelperContext, output);
51+
52+
// Assert
53+
Assert.AreEqual("/media/test.pdf", output.Attributes["href"].Value);
54+
}
55+
56+
[Test]
57+
public async Task ProcessAsync_RemovesOurSelfHostAttribute()
58+
{
59+
// Arrange
60+
var selfHostServiceMock = new Mock<ISelfHostService>();
61+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
62+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.jpg" });
63+
64+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
65+
tagHelper.SrcAttribute = "https://example.com/test.jpg";
66+
var id = "unique-id";
67+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
68+
var output = new TagHelperOutput("img", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
69+
70+
// Act
71+
await tagHelper.ProcessAsync(tagHelperContext, output);
72+
73+
// Assert
74+
Assert.IsFalse(output.Attributes.ContainsName("our-self-host"));
75+
}
76+
77+
[Test]
78+
public async Task ProcessAsync_RemovesFolderAttribute()
79+
{
80+
// Arrange
81+
var selfHostServiceMock = new Mock<ISelfHostService>();
82+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
83+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.jpg" });
84+
85+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
86+
tagHelper.SrcAttribute = "https://example.com/test.jpg";
87+
tagHelper.FolderName = "test-folder";
88+
var id = "unique-id";
89+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
90+
var output = new TagHelperOutput("img", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
91+
92+
// Act
93+
await tagHelper.ProcessAsync(tagHelperContext, output);
94+
95+
// Assert
96+
Assert.IsFalse(output.Attributes.ContainsName("folder"));
97+
}
98+
99+
[Test]
100+
public async Task ProcessAsync_RemovesExtAttribute()
101+
{
102+
// Arrange
103+
var selfHostServiceMock = new Mock<ISelfHostService>();
104+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
105+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.jpg" });
106+
107+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
108+
tagHelper.SrcAttribute = "https://example.com/test";
109+
tagHelper.Extension = "jpg";
110+
var id = "unique-id";
111+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
112+
var output = new TagHelperOutput("img", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
113+
114+
// Act
115+
await tagHelper.ProcessAsync(tagHelperContext, output);
116+
117+
// Assert
118+
Assert.IsFalse(output.Attributes.ContainsName("ext"));
119+
}
120+
121+
[Test]
122+
public async Task ProcessAsync_SrcAttribute_EnforcesExtAttribute()
123+
{
124+
// Arrange
125+
var selfHostServiceMock = new Mock<ISelfHostService>();
126+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
127+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.jpg" });
128+
129+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
130+
tagHelper.SrcAttribute = "https://example.com/test";
131+
tagHelper.Extension = "jpg";
132+
var id = "unique-id";
133+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
134+
var output = new TagHelperOutput("img", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
135+
136+
// Act
137+
await tagHelper.ProcessAsync(tagHelperContext, output);
138+
139+
// Assert
140+
Assert.IsTrue(output.Attributes.ContainsName("src") && output.Attributes["src"].Value.ToString().EndsWith(tagHelper.Extension));
141+
}
142+
143+
[Test]
144+
public async Task ProcessAsync_HrefAttribute_EnforcesExtAttribute()
145+
{
146+
// Arrange
147+
var selfHostServiceMock = new Mock<ISelfHostService>();
148+
selfHostServiceMock.Setup(x => x.SelfHostFile(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
149+
.ReturnsAsync(new SelfHostedFile { Url = "/media/test.pdf" });
150+
151+
var tagHelper = new SelfHostTagHelper(selfHostServiceMock.Object);
152+
tagHelper.HrefAttribute = "https://example.com/test";
153+
tagHelper.Extension = "pdf";
154+
var id = "unique-id";
155+
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
156+
var output = new TagHelperOutput("a", new TagHelperAttributeList(), (useCachedResult, encoder) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent()));
157+
158+
// Act
159+
await tagHelper.ProcessAsync(tagHelperContext, output);
160+
161+
// Assert
162+
Assert.IsTrue(output.Attributes.ContainsName("href") && output.Attributes["href"].Value.ToString().EndsWith(tagHelper.Extension));
163+
}
164+
}
165+
}

Our.Umbraco.TagHelpers/Configuration/OurUmbracoTagHelpersConfiguration.cs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ namespace Our.Umbraco.TagHelpers.Configuration
55
public class OurUmbracoTagHelpersConfiguration
66
{
77
public InlineSvgTagHelperConfiguration OurSVG { get; set; } = new InlineSvgTagHelperConfiguration();
8-
public ImgTagHelperConfiguration OurImg { get; set; } = new ImgTagHelperConfiguration();
8+
public ImgTagHelperConfiguration OurImg { get; set; } = new ImgTagHelperConfiguration();
9+
10+
public SelfHostTagHelperConfiguration OurSelfHost { get; set; } = new SelfHostTagHelperConfiguration();
911
}
1012

1113
public class InlineSvgTagHelperConfiguration
@@ -14,33 +16,33 @@ public class InlineSvgTagHelperConfiguration
1416
public bool Cache { get; set; } = false;
1517
public int CacheMinutes { get; set; } = 180;
1618
}
17-
18-
public class ImgTagHelperConfiguration
19+
20+
public class ImgTagHelperConfiguration
1921
{
2022
/// <summary>
2123
/// Define the typical responsive breakpoints (S,M,L,XL,XXL) in which your website uses during screen resize
2224
/// </summary>
2325
public MediaQuerySizes MediaQueries { get; set; } = new MediaQuerySizes();
24-
26+
2527
/// <summary>
2628
/// If true, let the browser handle image lazy loading, otherwise disable to use a 3rd party JavaScript based library
2729
/// </summary>
2830
public bool UseNativeLazyLoading { get; set; } = true;
29-
31+
3032
/// <summary>
3133
/// Applicable if UseNativeLazyLoading is false
3234
/// </summary>
3335
public string LazyLoadCssClass { get; set; } = "lazyload";
34-
36+
3537
/// <summary>
3638
/// Applicable if UseNativeLazyLoading is false
3739
/// </summary>
3840
public ImagePlaceholderType LazyLoadPlaceholder { get; set; } = ImagePlaceholderType.SVG;
39-
41+
4042
/// <summary>
4143
/// Applicable if UseNativeLazyLoading is false & LazyLoadPlaceholder is LowQualityImage
4244
/// </summary>
43-
public int LazyLoadPlaceholderLowQualityImageQuality { get; set; } = 5;
45+
public int LazyLoadPlaceholderLowQualityImageQuality { get; set; } = 5;
4446
public bool ApplyAspectRatio { get; set; } = false;
4547
public bool MobileFirst { get; set; } = true;
4648

@@ -57,4 +59,9 @@ public class MediaQuerySizes
5759
public int ExtraLarge { get; set; } = 1200;
5860
public int ExtraExtraLarge { get; set; } = 1400;
5961
}
62+
63+
public class SelfHostTagHelperConfiguration
64+
{
65+
public string RootFolder { get; set; } = "~/assets";
66+
}
6067
}

Our.Umbraco.TagHelpers/Extensions/WebHostEnvironmentExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
namespace Our.Umbraco.TagHelpers.Extensions
77
{
88
[Obsolete("This should be removed, when the package gets upgraded past Umbraco 10")]
9-
internal static class WebHostEnvironmentExtensions
9+
public static class WebHostEnvironmentExtensions
1010
{
1111

1212
/// <summary>

Our.Umbraco.TagHelpers/Models/SelfHostedFile.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
{
33
public class SelfHostedFile
44
{
5-
public string? ExternalUrl { get; internal set; }
6-
public string? FileName { get; internal set; }
7-
public string? FolderPath { get; internal set; }
8-
public string? Url { get; internal set; }
5+
public string? ExternalUrl { get; set; }
6+
public string? FileName { get; set; }
7+
public string? FolderPath { get; set; }
8+
public string? Url { get; set; }
99

1010
public override string? ToString()
1111
{

Our.Umbraco.TagHelpers/SelfHostTagHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public override async Task ProcessAsync(TagHelperContext context, TagHelperOutpu
4444
output.Attributes.SetAttribute("href", selfHostedFile.Url);
4545
}
4646

47-
output.Attributes.Remove(new TagHelperAttribute("umb-self-host"));
47+
output.Attributes.Remove(new TagHelperAttribute("our-self-host"));
4848
output.Attributes.Remove(new TagHelperAttribute("folder"));
4949
output.Attributes.Remove(new TagHelperAttribute("ext"));
5050
}

Our.Umbraco.TagHelpers/Services/SelfHostService.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.AspNetCore.Hosting;
2-
using Microsoft.Extensions.Configuration;
2+
using Microsoft.Extensions.Options;
3+
using Our.Umbraco.TagHelpers.Configuration;
34
using Our.Umbraco.TagHelpers.Extensions;
45
using Our.Umbraco.TagHelpers.Models;
56
using System;
@@ -18,19 +19,19 @@ public class SelfHostService : ISelfHostService
1819
private readonly IProfilingLogger _logger;
1920
private readonly IAppPolicyCache _runtimeCache;
2021
private readonly IWebHostEnvironment _hostingEnvironment;
21-
private readonly IConfiguration _config;
22+
private readonly OurUmbracoTagHelpersConfiguration _globalSettings;
2223

2324
public SelfHostService(
2425
IProfilingLogger logger,
2526
IAppPolicyCache appPolicyCache,
2627
IWebHostEnvironment hostingEnvironment,
27-
IConfiguration config
28+
IOptions<OurUmbracoTagHelpersConfiguration> globalSettings
2829
)
2930
{
3031
_logger = logger;
3132
_runtimeCache = appPolicyCache;
3233
_hostingEnvironment = hostingEnvironment;
33-
_config = config;
34+
_globalSettings = globalSettings.Value;
3435
}
3536

3637
public async Task<SelfHostedFile> SelfHostFile(string url, string? subfolder = null, string? fileExtension = null)
@@ -54,9 +55,9 @@ public async Task<SelfHostedFile> SelfHostFile(string url, string? subfolder = n
5455
});
5556
}
5657

57-
private string GetFolderPath(Uri uri, string? subfolder = null)
58+
public string GetFolderPath(Uri uri, string? subfolder = null)
5859
{
59-
var folderPath = _config["Our.Umbraco.TagHelpers.SelfHost.RootFolder"].IfNullOrWhiteSpace("~/assets"); ;
60+
var folderPath = _globalSettings.OurSelfHost.RootFolder;
6061

6162
if (subfolder.IsNullOrWhiteSpace() == false) folderPath += subfolder.EnsureStartsWith("/");
6263

@@ -65,7 +66,7 @@ private string GetFolderPath(Uri uri, string? subfolder = null)
6566
return folderPath;
6667
}
6768

68-
private string GetRemoteFolderPath(Uri uri)
69+
public string GetRemoteFolderPath(Uri uri)
6970
{
7071
var segments = uri?.Segments;
7172

@@ -90,7 +91,7 @@ private async Task<string> GetSelfHostedUrl(SelfHostedFile file)
9091
var localPath = _hostingEnvironment.MapPathWebRoot(file.FolderPath);
9192
var localFilePath = _hostingEnvironment.MapPathWebRoot(filePath);
9293

93-
if (!File.Exists(localFilePath))
94+
if (!File.Exists(localFilePath) && file.ExternalUrl is not null)
9495
{
9596
using (_logger.TraceDuration<ISelfHostService>($"Start downloading SelfHostedFile: {file.ExternalUrl} to {localFilePath}", $"Finished downloading SelfHostedFile: {file.ExternalUrl} to {localFilePath}"))
9697
{

0 commit comments

Comments
 (0)