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