mirror of https://github.com/abpframework/abp.git
5 changed files with 455 additions and 9 deletions
@ -0,0 +1,204 @@ |
|||||
|
using System.Globalization; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Http; |
||||
|
using Microsoft.AspNetCore.RequestLocalization; |
||||
|
using Microsoft.AspNetCore.Routing; |
||||
|
using Shouldly; |
||||
|
using MsOptions = Microsoft.Extensions.Options.Options; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.UI.Navigation; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Localization; |
||||
|
|
||||
|
public class AbpCultureMenuItemUrlProvider_Tests |
||||
|
{ |
||||
|
[Fact] |
||||
|
public async Task Should_Not_Modify_Urls_When_RouteBasedCulture_Is_Disabled() |
||||
|
{ |
||||
|
var provider = CreateProvider(useRouteBasedCulture: false, cultureName: "zh-Hans"); |
||||
|
var menu = CreateMenuWithItems("/home", "/about"); |
||||
|
|
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
|
||||
|
menu.Items[0].Url.ShouldBe("/home"); |
||||
|
menu.Items[1].Url.ShouldBe("/about"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Prepend_Culture_Prefix_When_Route_Has_Culture() |
||||
|
{ |
||||
|
var provider = CreateProvider(useRouteBasedCulture: true, cultureName: "zh-Hans"); |
||||
|
var menu = CreateMenuWithItems("/home", "/about"); |
||||
|
|
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
|
||||
|
menu.Items[0].Url.ShouldBe("/zh-Hans/home"); |
||||
|
menu.Items[1].Url.ShouldBe("/zh-Hans/about"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Not_Add_Prefix_When_No_Culture_Route_Value() |
||||
|
{ |
||||
|
// MVC request with no {culture} route value (e.g. user visits /About directly)
|
||||
|
var provider = CreateProvider(useRouteBasedCulture: true, cultureName: null); |
||||
|
var menu = CreateMenuWithItems("/home", "/about"); |
||||
|
|
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
|
||||
|
menu.Items[0].Url.ShouldBe("/home"); |
||||
|
menu.Items[1].Url.ShouldBe("/about"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Use_CurrentUICulture_Fallback_When_No_HttpContext() |
||||
|
{ |
||||
|
// Simulates Blazor interactive circuit: no HttpContext, but CurrentUICulture is set
|
||||
|
var provider = CreateProviderWithoutHttpContext( |
||||
|
useRouteBasedCulture: true, |
||||
|
knownLanguages: new[] { "en", "zh-Hans", "tr" }); |
||||
|
|
||||
|
var menu = CreateMenuWithItems("/home", "/about"); |
||||
|
|
||||
|
var previousCulture = CultureInfo.CurrentUICulture; |
||||
|
try |
||||
|
{ |
||||
|
CultureInfo.CurrentUICulture = new CultureInfo("zh-Hans"); |
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
CultureInfo.CurrentUICulture = previousCulture; |
||||
|
} |
||||
|
|
||||
|
menu.Items[0].Url.ShouldBe("/zh-Hans/home"); |
||||
|
menu.Items[1].Url.ShouldBe("/zh-Hans/about"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Not_Modify_Urls_When_No_HttpContext_And_Unknown_Culture() |
||||
|
{ |
||||
|
// Blazor interactive circuit with a culture that is not in the known languages list
|
||||
|
var provider = CreateProviderWithoutHttpContext( |
||||
|
useRouteBasedCulture: true, |
||||
|
knownLanguages: new[] { "en", "tr" }); |
||||
|
|
||||
|
var menu = CreateMenuWithItems("/home", "/about"); |
||||
|
|
||||
|
var previousCulture = CultureInfo.CurrentUICulture; |
||||
|
try |
||||
|
{ |
||||
|
CultureInfo.CurrentUICulture = new CultureInfo("fr"); |
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
CultureInfo.CurrentUICulture = previousCulture; |
||||
|
} |
||||
|
|
||||
|
menu.Items[0].Url.ShouldBe("/home"); |
||||
|
menu.Items[1].Url.ShouldBe("/about"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Prepend_Prefix_Recursively_For_Nested_Items() |
||||
|
{ |
||||
|
var provider = CreateProvider(useRouteBasedCulture: true, cultureName: "tr"); |
||||
|
|
||||
|
var menu = new ApplicationMenu("TestMenu"); |
||||
|
var parent = new ApplicationMenuItem("Parent", "Parent", url: "/parent"); |
||||
|
var child = new ApplicationMenuItem("Child", "Child", url: "/child"); |
||||
|
var grandChild = new ApplicationMenuItem("GrandChild", "GrandChild", url: "/grandchild"); |
||||
|
child.AddItem(grandChild); |
||||
|
parent.AddItem(child); |
||||
|
menu.AddItem(parent); |
||||
|
|
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
|
||||
|
parent.Url.ShouldBe("/tr/parent"); |
||||
|
child.Url.ShouldBe("/tr/child"); |
||||
|
grandChild.Url.ShouldBe("/tr/grandchild"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Not_Modify_External_Urls() |
||||
|
{ |
||||
|
var provider = CreateProvider(useRouteBasedCulture: true, cultureName: "zh-Hans"); |
||||
|
|
||||
|
var menu = new ApplicationMenu("TestMenu"); |
||||
|
menu.AddItem(new ApplicationMenuItem("External", "External", url: "https://example.com/page")); |
||||
|
menu.AddItem(new ApplicationMenuItem("Relative", "Relative", url: "page")); |
||||
|
menu.AddItem(new ApplicationMenuItem("Local", "Local", url: "/local")); |
||||
|
|
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
|
||||
|
// External and relative URLs should not be modified
|
||||
|
menu.Items[0].Url.ShouldBe("https://example.com/page"); |
||||
|
menu.Items[1].Url.ShouldBe("page"); |
||||
|
// Local URL should be prefixed
|
||||
|
menu.Items[2].Url.ShouldBe("/zh-Hans/local"); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public async Task Should_Not_Throw_When_Url_Is_Null() |
||||
|
{ |
||||
|
var provider = CreateProvider(useRouteBasedCulture: true, cultureName: "tr"); |
||||
|
|
||||
|
var menu = new ApplicationMenu("TestMenu"); |
||||
|
menu.AddItem(new ApplicationMenuItem("NoUrl", "No URL", url: null)); |
||||
|
menu.AddItem(new ApplicationMenuItem("WithUrl", "With URL", url: "/page")); |
||||
|
|
||||
|
await provider.HandleAsync(new MenuItemUrlProviderContext(menu)); |
||||
|
|
||||
|
// Null URL should remain null
|
||||
|
menu.Items[0].Url.ShouldBeNull(); |
||||
|
// Normal URL should be prefixed
|
||||
|
menu.Items[1].Url.ShouldBe("/tr/page"); |
||||
|
} |
||||
|
|
||||
|
private static AbpCultureMenuItemUrlProvider CreateProvider( |
||||
|
bool useRouteBasedCulture, |
||||
|
string? cultureName) |
||||
|
{ |
||||
|
var httpContext = new DefaultHttpContext(); |
||||
|
if (cultureName != null) |
||||
|
{ |
||||
|
httpContext.Request.RouteValues["culture"] = cultureName; |
||||
|
} |
||||
|
|
||||
|
var httpContextAccessor = new HttpContextAccessor { HttpContext = httpContext }; |
||||
|
var localizationOptions = MsOptions.Create( |
||||
|
new AbpRequestLocalizationOptions { UseRouteBasedCulture = useRouteBasedCulture }); |
||||
|
var abpLocalizationOptions = MsOptions.Create(new AbpLocalizationOptions()); |
||||
|
|
||||
|
return new AbpCultureMenuItemUrlProvider( |
||||
|
httpContextAccessor, localizationOptions, abpLocalizationOptions); |
||||
|
} |
||||
|
|
||||
|
private static AbpCultureMenuItemUrlProvider CreateProviderWithoutHttpContext( |
||||
|
bool useRouteBasedCulture, |
||||
|
string[] knownLanguages) |
||||
|
{ |
||||
|
var httpContextAccessor = new HttpContextAccessor { HttpContext = null }; |
||||
|
var localizationOptions = MsOptions.Create( |
||||
|
new AbpRequestLocalizationOptions { UseRouteBasedCulture = useRouteBasedCulture }); |
||||
|
var abpLocOptions = new AbpLocalizationOptions(); |
||||
|
foreach (var lang in knownLanguages) |
||||
|
{ |
||||
|
abpLocOptions.Languages.Add(new LanguageInfo(lang)); |
||||
|
} |
||||
|
|
||||
|
return new AbpCultureMenuItemUrlProvider( |
||||
|
httpContextAccessor, localizationOptions, MsOptions.Create(abpLocOptions)); |
||||
|
} |
||||
|
|
||||
|
private static ApplicationMenu CreateMenuWithItems(params string[] urls) |
||||
|
{ |
||||
|
var menu = new ApplicationMenu("TestMenu"); |
||||
|
for (var i = 0; i < urls.Length; i++) |
||||
|
{ |
||||
|
menu.AddItem(new ApplicationMenuItem($"Item{i}", $"Item {i}", url: urls[i])); |
||||
|
} |
||||
|
return menu; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue