mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-02 03:57:38 +08:00
fix(module: select): arrow down click does not auto close (#1977)
* fix(module:select): arrow down click does not auto close * test case added
This commit is contained in:
parent
45b47d49b6
commit
5c2f48f718
@ -431,6 +431,7 @@ namespace AntDesign.Internal
|
|||||||
|
|
||||||
protected virtual async Task OnTriggerClick()
|
protected virtual async Task OnTriggerClick()
|
||||||
{
|
{
|
||||||
|
_mouseInTrigger = true;
|
||||||
if (IsContainTrigger(TriggerType.Click))
|
if (IsContainTrigger(TriggerType.Click))
|
||||||
{
|
{
|
||||||
if (_overlay.IsPopup())
|
if (_overlay.IsPopup())
|
||||||
@ -446,6 +447,7 @@ namespace AntDesign.Internal
|
|||||||
{
|
{
|
||||||
await Hide();
|
await Hide();
|
||||||
}
|
}
|
||||||
|
_mouseInTrigger = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual async Task OnTriggerContextmenu(MouseEventArgs args)
|
protected virtual async Task OnTriggerContextmenu(MouseEventArgs args)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<TargetFrameworks>netcoreapp3.1;net5</TargetFrameworks>
|
<TargetFrameworks>netcoreapp3.1;net5</TargetFrameworks>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
|
<LangVersion>9.0</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using AntDesign.JsInterop;
|
||||||
using Bunit;
|
using Bunit;
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
namespace AntDesign.Tests
|
namespace AntDesign.Tests
|
||||||
{
|
{
|
||||||
@ -11,12 +13,14 @@ namespace AntDesign.Tests
|
|||||||
public TestContext Context => this;
|
public TestContext Context => this;
|
||||||
public NavigationManager NavigationManager => Services.GetRequiredService<NavigationManager>();
|
public NavigationManager NavigationManager => Services.GetRequiredService<NavigationManager>();
|
||||||
|
|
||||||
public AntDesignTestBase()
|
public Mock<IDomEventListener> MockedDomEventListener { get; set; } = new Mock<IDomEventListener>();
|
||||||
|
|
||||||
|
public AntDesignTestBase(bool useMoq = false)
|
||||||
{
|
{
|
||||||
Services.AddAntDesign();
|
Services.AddAntDesign();
|
||||||
|
|
||||||
//Needed for Tests using Overlay
|
//Needed for Tests using Overlay
|
||||||
Services.AddScoped<AntDesign.JsInterop.DomEventService>(sp => new TestDomEventService(Context.JSInterop.JSRuntime));
|
Services.AddScoped<AntDesign.JsInterop.DomEventService>(sp => new TestDomEventService(Context.JSInterop.JSRuntime, MockedDomEventListener));
|
||||||
JSInterop.SetupVoid(JSInteropConstants.OverlayComponentHelper.DeleteOverlayFromContainer, _ => true);
|
JSInterop.SetupVoid(JSInteropConstants.OverlayComponentHelper.DeleteOverlayFromContainer, _ => true);
|
||||||
|
|
||||||
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo("en-US");
|
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo("en-US");
|
||||||
|
@ -9,19 +9,24 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AntDesign.JsInterop;
|
using AntDesign.JsInterop;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Moq;
|
||||||
|
|
||||||
namespace AntDesign.Tests
|
namespace AntDesign.Tests
|
||||||
{
|
{
|
||||||
public class TestDomEventService : AntDesign.JsInterop.DomEventService
|
public class TestDomEventService : AntDesign.JsInterop.DomEventService
|
||||||
{
|
{
|
||||||
public TestDomEventService(IJSRuntime js) : base(js)
|
public Mock<IDomEventListener> MockedDomEventListener { get; set; }
|
||||||
|
public TestDomEventService(IJSRuntime js, Mock<IDomEventListener> mock = null) : base(js)
|
||||||
{
|
{
|
||||||
|
if (mock is not null)
|
||||||
|
{
|
||||||
|
MockedDomEventListener = mock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IDomEventListener CreateDomEventListerner()
|
public override IDomEventListener CreateDomEventListerner()
|
||||||
{
|
{
|
||||||
return new TestDomEventListerner();
|
return MockedDomEventListener?.Object ?? new TestDomEventListerner();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
@using AntDesign.Core.JsInterop.Modules.Components
|
||||||
|
@using System.ComponentModel.DataAnnotations
|
||||||
|
@using System.Text.Json
|
||||||
|
@inherits AntDesignTestBase
|
||||||
|
@code {
|
||||||
|
enum City
|
||||||
|
{
|
||||||
|
[Display(Name = "Shanghai City")]
|
||||||
|
Shanghai,
|
||||||
|
Zhejiang,
|
||||||
|
Beijing,
|
||||||
|
}
|
||||||
|
|
||||||
|
public Select_Render_Tests()
|
||||||
|
{
|
||||||
|
JSInterop.Setup<AntDesign.JsInterop.DomRect>(JSInteropConstants.GetBoundingClientRect, _ => true)
|
||||||
|
.SetResult(new AntDesign.JsInterop.DomRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Render_enum_select()
|
||||||
|
{
|
||||||
|
//Arrange
|
||||||
|
|
||||||
|
var cut = Render<EnumSelect<City>>(
|
||||||
|
@<EnumSelect TEnum="City"></EnumSelect>
|
||||||
|
);
|
||||||
|
var options = cut.FindAll(".ant-select-item-option-content");
|
||||||
|
|
||||||
|
Assert.Equal(3, options.Count);
|
||||||
|
Assert.Equal("Shanghai City", options[0].TextContent.Trim('\n').Trim());
|
||||||
|
Assert.Equal("Zhejiang", options[1].TextContent.Trim());
|
||||||
|
Assert.Equal("Beijing", options[2].TextContent.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact] //covers scenario from issue #1989
|
||||||
|
public async Task Render_select_dropdown_on_arrow_click()
|
||||||
|
{
|
||||||
|
#if !NET6_0_OR_GREATER
|
||||||
|
JSInterop.SetupVoid(JSInteropConstants.Focus, _ => true).SetVoidResult();;
|
||||||
|
#endif
|
||||||
|
JSInterop.Setup<OverlayPosition>(JSInteropConstants.OverlayComponentHelper.AddOverlayToContainer, _ => true)
|
||||||
|
.SetResult(new OverlayPosition() { Top = 0, Left = 0, ZIndex = 5000, Placement = Placement.BottomLeft });
|
||||||
|
|
||||||
|
var mock = base.MockedDomEventListener;
|
||||||
|
Action<JsonElement>? onMouseUpCallback = default;
|
||||||
|
mock.Setup(s => s.AddShared<JsonElement>("document", "mouseup", It.IsAny<Action<JsonElement>>(), It.IsAny<bool>()))
|
||||||
|
.Callback((object dom, string eventName, Action<JsonElement> callback, bool preventDefault) =>
|
||||||
|
{
|
||||||
|
if (callback.Target is AntDesign.Internal.OverlayTrigger)
|
||||||
|
{
|
||||||
|
onMouseUpCallback = callback;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var plannedInvocation = JSInterop.Setup<string>(JSInteropConstants.AddDomEventListener, _ => true);
|
||||||
|
var cut = Render<EnumSelect<City>>(@<EnumSelect TEnum="City"></EnumSelect>);
|
||||||
|
//Act
|
||||||
|
var arrow = cut.Find("span.ant-select-arrow");
|
||||||
|
onMouseUpCallback.Should().NotBeNull();
|
||||||
|
|
||||||
|
await cut.InvokeAsync(() => arrow.Click());
|
||||||
|
cut.WaitForState(() => !cut.Find("div.ant-select-dropdown").ClassList.Contains("ant-select-dropdown-hidden"));
|
||||||
|
await cut.InvokeAsync(() => onMouseUpCallback?.Invoke(default));
|
||||||
|
//This is probably not the best solution. However this test is awkward - we are testing
|
||||||
|
//for something that should not appear. In failing scenarios it appears after some
|
||||||
|
//time (due to multiple async/await and re-renderings). That actually points to
|
||||||
|
//a probable wrong design in the way the OverlayTrigger & Overlay are functioning.
|
||||||
|
//So here we wait and hope the delay is going be long enough for the component
|
||||||
|
//to finish all its renderings.
|
||||||
|
await Task.Delay(500);
|
||||||
|
//Assert
|
||||||
|
var dropdown = cut.Find("div.ant-select-dropdown");
|
||||||
|
dropdown.ClassList.Should().NotContain("ant-select-dropdown-hidden");
|
||||||
|
}
|
||||||
|
}
|
@ -1,27 +0,0 @@
|
|||||||
@using System.ComponentModel.DataAnnotations
|
|
||||||
@inherits AntDesignTestBase
|
|
||||||
@code {
|
|
||||||
enum City
|
|
||||||
{
|
|
||||||
[Display(Name = "Shanghai City")]
|
|
||||||
Shanghai,
|
|
||||||
Zhejiang,
|
|
||||||
Beijing,
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void Render_enum_select()
|
|
||||||
{
|
|
||||||
//Arrange
|
|
||||||
JSInterop.Setup<AntDesign.JsInterop.DomRect>(JSInteropConstants.GetBoundingClientRect, _ => true)
|
|
||||||
.SetResult(new AntDesign.JsInterop.DomRect());
|
|
||||||
|
|
||||||
var cut = Render<EnumSelect<City>>(@<EnumSelect TEnum="City"></EnumSelect> );
|
|
||||||
var options = cut.FindAll(".ant-select-item-option-content");
|
|
||||||
|
|
||||||
Assert.Equal(3, options.Count);
|
|
||||||
Assert.Equal("Shanghai City", options[0].TextContent.Trim('\n').Trim());
|
|
||||||
Assert.Equal("Zhejiang", options[1].TextContent.Trim());
|
|
||||||
Assert.Equal("Beijing", options[2].TextContent.Trim());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user