From fbf8f1d46dce386a60ccff8b9686313c100201f7 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Tue, 11 Aug 2026 21:09:11 +0200 Subject: [PATCH 01/11] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20package=20?= =?UTF-8?q?dependencies=20to=20latest=20versions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Directory.Packages.props | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 490f661a..c9ad7fc1 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,6 +1,7 @@ true + true @@ -22,33 +23,33 @@ - + - - - - - + + + + + - + - - - - - - + + + + + + - - - - - - + + + + + + From ead6473ac065ac95ad0d9117870945d98ea349ad Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Tue, 11 Aug 2026 21:09:20 +0200 Subject: [PATCH 02/11] =?UTF-8?q?=E2=9C=A8=20add=20automatic=20base=20url?= =?UTF-8?q?=20resolution=20to=20tag=20helpers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppTagHelperOptions.cs | 4 ++ .../CacheBustingTagHelper.cs | 33 ++++++++++++++- .../CdnTagHelperOptions.cs | 4 ++ .../ImageTagHelper.cs | 5 +-- .../LinkTagHelper.cs | 5 +-- .../ScriptTagHelper.cs | 5 +-- .../TagHelperBaseUrlMode.cs | 15 +++++++ .../TagHelperOptions.cs | 40 +++++++++++++++---- 8 files changed, 94 insertions(+), 17 deletions(-) create mode 100644 src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs index 022c4987..4131c1f4 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/AppTagHelperOptions.cs @@ -19,6 +19,10 @@ public class AppTagHelperOptions : TagHelperOptions /// /// /// + /// + /// + /// + /// /// /// null /// diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs index 946d5527..d7d42a66 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/CacheBustingTagHelper.cs @@ -1,6 +1,10 @@ -using Cuemon.AspNetCore.Configuration; +using System; +using System.Globalization; +using Cuemon.AspNetCore.Configuration; using Cuemon.Configuration; using Microsoft.AspNetCore.Razor.TagHelpers; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.Extensions.Options; namespace Cuemon.AspNetCore.Razor.TagHelpers; @@ -34,9 +38,36 @@ protected CacheBustingTagHelper(IOptions setup, ICacheBusting cacheBus /// true if an object implementing the interface is specified; otherwise, false. protected bool UseCacheBusting => CacheBusting != null; + /// + /// Gets or sets the current view context. + /// + /// The current view context. + [HtmlAttributeNotBound] + [ViewContext] + public ViewContext ViewContext { get; set; } + /// /// Gets the configured options of this instance. /// /// The configured options of this instance. public TOptions Options { get; } + + /// + /// Resolves the fully qualified URL of the specified static resource. + /// + /// The relative path of the static resource. + /// The fully qualified URL of the specified static resource. + protected string ResolveUrl(string path) + { + var baseUrl = Options.GetFormattedBaseUrl(ViewContext?.HttpContext?.Request); + var resolvedPath = NormalizePath(path, !string.IsNullOrWhiteSpace(baseUrl)); + return string.Concat(baseUrl, UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{resolvedPath}?v={CacheBusting.Version}") : resolvedPath); + } + + private static string NormalizePath(string path, bool normalize) + { + if (!normalize || string.IsNullOrWhiteSpace(path)) { return path; } + if (path.StartsWith("~/", StringComparison.Ordinal)) { path = path.Substring(2); } + return path.TrimStart('/'); + } } diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs index ca8aaa8d..e737b590 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/CdnTagHelperOptions.cs @@ -19,6 +19,10 @@ public class CdnTagHelperOptions : TagHelperOptions /// /// /// + /// + /// + /// + /// /// /// null /// diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs index 54847a27..8732c980 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/ImageTagHelper.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon.AspNetCore.Configuration; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Options; @@ -62,7 +61,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.TagName = "img"; if (!string.IsNullOrWhiteSpace(Id)) { output.Attributes.Add("id", Id); } if (!string.IsNullOrWhiteSpace(Class)) { output.Attributes.Add("class", Class); } - output.Attributes.Add("src", string.Concat(Options.GetFormattedBaseUrl(), UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{Src}?v={CacheBusting.Version}") : Src)); + output.Attributes.Add("src", ResolveUrl(Src)); if (!string.IsNullOrWhiteSpace(Alt)) { output.Attributes.Add("alt", Alt); } if (!string.IsNullOrWhiteSpace(Title)) { output.Attributes.Add("title", Title); } return Task.CompletedTask; diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs index 6afff710..9c85b21c 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/LinkTagHelper.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon.AspNetCore.Configuration; using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Razor.TagHelpers; @@ -52,7 +51,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.TagMode = TagMode.StartTagOnly; output.TagName = "link"; output.Attributes.Add("rel", Rel); - output.Attributes.Add("href", string.Concat(Options.GetFormattedBaseUrl(), UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{Href}?v={CacheBusting.Version}") : Href)); + output.Attributes.Add("href", ResolveUrl(Href)); if (!string.IsNullOrWhiteSpace(Type)) { output.Attributes.Add("type", new HtmlString(Type)); } return Task.CompletedTask; } diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs index 3308bbd8..8ed03af9 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/ScriptTagHelper.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Threading.Tasks; +using System.Threading.Tasks; using Cuemon.AspNetCore.Configuration; using Microsoft.AspNetCore.Razor.TagHelpers; using Microsoft.Extensions.Options; @@ -43,7 +42,7 @@ public override Task ProcessAsync(TagHelperContext context, TagHelperOutput outp output.TagMode = TagMode.StartTagAndEndTag; output.TagName = "script"; output.Attributes.Add("type", "text/javascript"); - output.Attributes.Add("src", string.Concat(Options.GetFormattedBaseUrl(), UseCacheBusting ? string.Create(CultureInfo.InvariantCulture, $"{Src}?v={CacheBusting.Version}") : Src)); + output.Attributes.Add("src", ResolveUrl(Src)); if (Defer) { output.Attributes.Add("defer", "defer"); } return Task.CompletedTask; } diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs new file mode 100644 index 00000000..55c777ca --- /dev/null +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperBaseUrlMode.cs @@ -0,0 +1,15 @@ +namespace Cuemon.AspNetCore.Razor.TagHelpers; +/// +/// Specifies how the base URL of a static resource is resolved. +/// +public enum TagHelperBaseUrlMode +{ + /// + /// Specifies that the base URL is resolved exclusively from the configured values of and . + /// + Configured, + /// + /// Specifies that the base URL is resolved from the configured value of when available; otherwise from the current HTTP request. + /// + Automatic +} diff --git a/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs index 37fbe684..e7e1364d 100644 --- a/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs +++ b/src/Cuemon.AspNetCore.Razor.TagHelpers/TagHelperOptions.cs @@ -1,6 +1,7 @@ using System.Globalization; using Cuemon.Configuration; using Cuemon.Text; +using Microsoft.AspNetCore.Http; namespace Cuemon.AspNetCore.Razor.TagHelpers; /// @@ -9,10 +10,10 @@ namespace Cuemon.AspNetCore.Razor.TagHelpers; public abstract class TagHelperOptions : IParameterObject { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// - /// The following table shows the initial property values for an instance of . + /// The following table shows the initial property values for an instance of . /// /// /// Property @@ -23,6 +24,10 @@ public abstract class TagHelperOptions : IParameterObject /// /// /// + /// + /// + /// + /// /// /// null /// @@ -30,6 +35,7 @@ public abstract class TagHelperOptions : IParameterObject /// protected TagHelperOptions() { + BaseUrlMode = TagHelperBaseUrlMode.Configured; Scheme = ProtocolUriScheme.Relative; } @@ -39,6 +45,12 @@ protected TagHelperOptions() /// The of these options. public ProtocolUriScheme Scheme { get; set; } + /// + /// Gets or sets the base URL resolution mode of these options. + /// + /// The base URL resolution mode of these options. + public TagHelperBaseUrlMode BaseUrlMode { get; set; } + /// /// Gets or sets the base URL of these options. /// @@ -51,20 +63,34 @@ protected TagHelperOptions() /// The base URL of this instance, formatted according to the defined . public string GetFormattedBaseUrl() { - var baseUrlIsNullOrEmpty = string.IsNullOrWhiteSpace(BaseUrl); + if (string.IsNullOrWhiteSpace(BaseUrl)) { return ""; } var baseUrlWithForwardingSlash = new Stem(BaseUrl).AttachSuffix("/"); switch (Scheme) { case ProtocolUriScheme.None: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"{baseUrlWithForwardingSlash}"); case ProtocolUriScheme.Http: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Http).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Http).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); case ProtocolUriScheme.Https: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Https).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"{nameof(UriScheme.Https).ToLowerInvariant()}://{baseUrlWithForwardingSlash}"); case ProtocolUriScheme.Relative: - return baseUrlIsNullOrEmpty ? "" : string.Create(CultureInfo.InvariantCulture, $"//{baseUrlWithForwardingSlash}"); + return string.Create(CultureInfo.InvariantCulture, $"//{baseUrlWithForwardingSlash}"); default: return ""; } } + + /// + /// Gets the base URL of this instance, resolved from the configured values of this instance or the specified . + /// + /// The current HTTP request that may provide the effective scheme, host and application base path when is and is not configured. + /// The base URL of this instance, resolved from the configured values of this instance or the specified . + public string GetFormattedBaseUrl(HttpRequest request) + { + if (BaseUrlMode == TagHelperBaseUrlMode.Automatic && string.IsNullOrWhiteSpace(BaseUrl) && request != null) + { + return string.Create(CultureInfo.InvariantCulture, $"{request.Scheme}://{request.Host.ToUriComponent()}{request.PathBase.ToUriComponent()}/"); + } + return GetFormattedBaseUrl(); + } } From fb0c47b34a89dd8bc8b540dceac8fdfa8a02aeb5 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Tue, 11 Aug 2026 21:09:28 +0200 Subject: [PATCH 03/11] =?UTF-8?q?=E2=9C=85=20add=20tests=20for=20automatic?= =?UTF-8?q?=20base=20url=20resolution?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AppImageTagHelperTest.cs | 78 +++-------- .../AppLinkTagHelperTest.cs | 131 ++++++++++-------- .../AppScriptTagHelperTest.cs | 105 +++++++------- .../Pages/AppImageTagHelper.cshtml | 6 +- .../Pages/AppLinkTagHelper.cshtml | 40 +++++- .../Pages/AppScriptTagHelper.cshtml | 6 +- .../TagHelperTestFactory.cs | 44 ++++++ 7 files changed, 238 insertions(+), 172 deletions(-) create mode 100644 test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/TagHelperTestFactory.cs diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs index 966bb069..083aa606 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppImageTagHelperTest.cs @@ -1,11 +1,6 @@ -using System.Threading.Tasks; -using Cuemon.AspNetCore.Razor.TagHelpers.Assets; -using Cuemon.Extensions.AspNetCore.Configuration; +using System; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; -using Codebelt.Extensions.Xunit.Hosting.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Cuemon.AspNetCore.Razor.TagHelpers; @@ -18,65 +13,34 @@ public AppImageTagHelperTest(ITestOutputHelper output) : base(output) [Fact] public async Task Page_RenderImageTagForAppRole() { - using (var filter = WebHostTestFactory.Create(services => - { - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) - { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppImageTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + var body = await TagHelperTestFactory.GetBodyAsync("/AppImageTagHelper"); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } [Fact] public async Task Page_RenderImageTagForAppRole_WithCacheBusting() { - using (var filter = WebHostTestFactory.Create(services => - { - services.AddCacheBusting(); - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) + var body = await TagHelperTestFactory.GetBodyAsync("/AppImageTagHelper", useCacheBusting: true); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderImageTagForAppRole_UsingCurrentRequestOrigin() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppImageTagHelper?path=/images/logo.svg", o => { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppImageTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + }, baseAddress: new Uri("https://localhost:7241")); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } } diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs index 4bd1b9e7..95083304 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/AppLinkTagHelperTest.cs @@ -1,11 +1,6 @@ -using System.Threading.Tasks; -using Cuemon.AspNetCore.Razor.TagHelpers.Assets; -using Cuemon.Extensions.AspNetCore.Configuration; +using System; +using System.Threading.Tasks; using Codebelt.Extensions.Xunit; -using Codebelt.Extensions.Xunit.Hosting.AspNetCore; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.TestHost; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Cuemon.AspNetCore.Razor.TagHelpers; @@ -18,65 +13,89 @@ public AppLinkTagHelperTest(ITestOutputHelper output) : base(output) [Fact] public async Task Page_RenderLinkTagForAppRole() { - using (var filter = WebHostTestFactory.Create(services => - { - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) - { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppLinkTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper"); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } [Fact] public async Task Page_RenderLinkTagForAppRole_WithCacheBusting() { - using (var filter = WebHostTestFactory.Create(services => + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper", useCacheBusting: true); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_WithoutConfiguredBaseUrl() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=stylesheet&path=/css/site.css", o => o.BaseUrl = null); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_UsingCurrentRequestOrigin() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=stylesheet&path=css/site.css", o => { - services.AddCacheBusting(); - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + o.Scheme = ProtocolUriScheme.Http; + }, baseAddress: new Uri("https://localhost:7241")); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_UsingExplicitBaseUrlWhenAutomaticModeIsEnabled() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=stylesheet&path=/css/site.css", o => { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppLinkTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = "assets.example.com"; + o.Scheme = ProtocolUriScheme.Https; + }, baseAddress: new Uri("http://localhost:7241")); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderLinkTagForAppRole_PreservesFontPreloadAttributes() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppLinkTagHelper?variant=preload"); + + TestOutput.WriteLine(body); + + Assert.Contains(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Contains(@" - { - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) - { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppScriptTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper"); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } [Fact] public async Task Page_RenderScriptTagForAppRole_WithCacheBusting() { - using (var filter = WebHostTestFactory.Create(services => + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper", useCacheBusting: true); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderScriptTagForAppRole_UsingCurrentRequestOrigin() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper", o => { - services.AddCacheBusting(); - services.AddRazorPages(); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Https; - o.BaseUrl = "nblcdn.net"; - }); - services.Configure(o => - { - o.Scheme = ProtocolUriScheme.Relative; - o.BaseUrl = "static.cuemon.net"; - }); - }, app => - { - app.UseRouting(); - app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); - })) + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + }, baseAddress: new Uri("https://localhost:7241")); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderScriptTagForAppRole_UsingCurrentRequestOriginAndPathBase_WithCacheBusting() + { + var body = await TagHelperTestFactory.GetBodyAsync("/myapp/AppScriptTagHelper?path=~/js/site.js", o => + { + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = null; + }, useCacheBusting: true, baseAddress: new Uri("https://example.com"), pathBase: "/myapp"); + + TestOutput.WriteLine(body); + + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); + } + + [Fact] + public async Task Page_RenderScriptTagForAppRole_UsingLocalHttpExternalOriginWhenConfigured() + { + var body = await TagHelperTestFactory.GetBodyAsync("/AppScriptTagHelper?path=~/js/site.js", o => { - var client = filter.Host.GetTestClient(); - var result = await client.GetAsync("/AppScriptTagHelper"); - var body = await result.Content.ReadAsStringAsync(); + o.BaseUrlMode = TagHelperBaseUrlMode.Automatic; + o.BaseUrl = "localhost:8080"; + o.Scheme = ProtocolUriScheme.Http; + }, baseAddress: new Uri("https://localhost:7241")); - TestOutput.WriteLine(body); + TestOutput.WriteLine(body); - Assert.Equal(@"", body, ignoreLineEndingDifferences: true); - } + Assert.Equal(@"", body, ignoreLineEndingDifferences: true); } } diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml index a5699d18..6a711394 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppImageTagHelper.cshtml @@ -1,2 +1,6 @@ @page - \ No newline at end of file +@{ + var src = Request.Query["path"].ToString(); + if (string.IsNullOrWhiteSpace(src)) { src = "cuemon-logo.svg"; } +} + \ No newline at end of file diff --git a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml index 6bd541af..74308e07 100644 --- a/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml +++ b/test/Cuemon.AspNetCore.Razor.TagHelpers.Tests/Pages/AppLinkTagHelper.cshtml @@ -1,2 +1,40 @@ @page -