mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-20 07:39:09 +08:00
210 lines
6.9 KiB
C#
210 lines
6.9 KiB
C#
using System.Reflection;
|
|
using AtomUI.Controls.Data;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Threading;
|
|
using Avalonia.VisualTree;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using AtomUIWindow = AtomUI.Desktop.Controls.Window;
|
|
|
|
namespace AtomUI.Desktop.Controls.Tests.Transfer;
|
|
|
|
public class TransferPinnedOpenTests
|
|
{
|
|
static TransferPinnedOpenTests()
|
|
{
|
|
AvaloniaTestApp.EnsureInitialized();
|
|
}
|
|
|
|
[Fact]
|
|
public void Pinned_Transfer_Opens_One_Source_Dropdown_And_Rejects_Normal_Hide()
|
|
{
|
|
var transfer = CreateTransfer();
|
|
var window = CreateWindow(transfer);
|
|
|
|
try
|
|
{
|
|
window.Show();
|
|
Dispatcher.UIThread.RunJobs();
|
|
var dropdowns = GetDropdowns(transfer);
|
|
var source = dropdowns.Single(dropdown => dropdown.ViewType == TransferViewType.Source);
|
|
var target = dropdowns.Single(dropdown => dropdown.ViewType == TransferViewType.Target);
|
|
|
|
SetPopupPinnedOpen(transfer, true);
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
GetPopupPinnedOpen(source).ShouldBeTrue();
|
|
GetPopupPinnedOpen(target).ShouldBeFalse();
|
|
var flyout = source.Flyout.ShouldBeOfType<MenuFlyout>();
|
|
flyout.IsPopupPinnedOpen.ShouldBeTrue();
|
|
flyout.IsOpen.ShouldBeTrue();
|
|
flyout.Popup.ShouldBeOfType<Popup>().IsPopupPinnedOpen.ShouldBeTrue();
|
|
|
|
flyout.Hide();
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
flyout.IsOpen.ShouldBeTrue();
|
|
flyout.Popup.IsOpen.ShouldBeTrue();
|
|
}
|
|
finally
|
|
{
|
|
SetPopupPinnedOpenIfAvailable(transfer, false);
|
|
window.Close();
|
|
Dispatcher.UIThread.RunJobs();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Pinned_Transfer_Detach_Closes_Old_And_Reattach_Reopens_Source_Dropdown()
|
|
{
|
|
var transfer = CreateTransfer();
|
|
var window = CreateWindow(transfer);
|
|
|
|
try
|
|
{
|
|
window.Show();
|
|
Dispatcher.UIThread.RunJobs();
|
|
var source = GetSourceDropdown(transfer);
|
|
SetPopupPinnedOpen(transfer, true);
|
|
Dispatcher.UIThread.RunJobs();
|
|
var oldFlyout = source.Flyout.ShouldBeOfType<MenuFlyout>();
|
|
oldFlyout.IsOpen.ShouldBeTrue();
|
|
|
|
window.Content = new Border();
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
GetPopupPinnedOpen(source).ShouldBeFalse();
|
|
oldFlyout.IsPopupPinnedOpen.ShouldBeFalse();
|
|
oldFlyout.IsOpen.ShouldBeFalse();
|
|
oldFlyout.Popup.IsOpen.ShouldBeFalse();
|
|
|
|
window.Content = transfer;
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
var reattachedSource = GetSourceDropdown(transfer);
|
|
GetPopupPinnedOpen(reattachedSource).ShouldBeTrue();
|
|
var newFlyout = reattachedSource.Flyout.ShouldBeOfType<MenuFlyout>();
|
|
newFlyout.ShouldNotBeSameAs(oldFlyout);
|
|
newFlyout.IsOpen.ShouldBeTrue();
|
|
}
|
|
finally
|
|
{
|
|
SetPopupPinnedOpenIfAvailable(transfer, false);
|
|
window.Close();
|
|
Dispatcher.UIThread.RunJobs();
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Transfer_Registers_A_Dropdown_Only_While_A_Pin_Request_Is_Active()
|
|
{
|
|
var transfer = CreateTransfer();
|
|
var window = CreateWindow(transfer);
|
|
|
|
try
|
|
{
|
|
window.Show();
|
|
Dispatcher.UIThread.RunJobs();
|
|
GetPrivateField<TransferSelectDropdown?>(transfer, "_pinnedOpenDropdown").ShouldBeNull();
|
|
|
|
SetPopupPinnedOpen(transfer, true);
|
|
Dispatcher.UIThread.RunJobs();
|
|
var source = GetSourceDropdown(transfer);
|
|
GetPrivateField<TransferSelectDropdown?>(transfer, "_pinnedOpenDropdown").ShouldBeSameAs(source);
|
|
var flyout = source.Flyout.ShouldBeOfType<MenuFlyout>();
|
|
flyout.IsOpen.ShouldBeTrue();
|
|
|
|
SetPopupPinnedOpen(transfer, false);
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
GetPrivateField<TransferSelectDropdown?>(transfer, "_pinnedOpenDropdown").ShouldBeNull();
|
|
flyout.IsPopupPinnedOpen.ShouldBeFalse();
|
|
flyout.IsOpen.ShouldBeTrue();
|
|
}
|
|
finally
|
|
{
|
|
SetPopupPinnedOpenIfAvailable(transfer, false);
|
|
window.Close();
|
|
Dispatcher.UIThread.RunJobs();
|
|
}
|
|
}
|
|
|
|
private static ListTransfer CreateTransfer()
|
|
{
|
|
return new ListTransfer
|
|
{
|
|
Width = 520,
|
|
Height = 260,
|
|
IsMotionEnabled = false,
|
|
ItemsSource =
|
|
[
|
|
new ListItemData { ItemKey = "first", Content = "First" },
|
|
new ListItemData { ItemKey = "second", Content = "Second" }
|
|
]
|
|
};
|
|
}
|
|
|
|
private static AtomUIWindow CreateWindow(Control content)
|
|
{
|
|
return new AtomUIWindow
|
|
{
|
|
Width = 640,
|
|
Height = 360,
|
|
Content = content
|
|
};
|
|
}
|
|
|
|
private static TransferSelectDropdown[] GetDropdowns(AbstractTransfer transfer)
|
|
{
|
|
return transfer.GetVisualDescendants()
|
|
.OfType<TransferSelectDropdown>()
|
|
.ToArray();
|
|
}
|
|
|
|
private static TransferSelectDropdown GetSourceDropdown(AbstractTransfer transfer)
|
|
{
|
|
return GetDropdowns(transfer)
|
|
.Single(dropdown => dropdown.ViewType == TransferViewType.Source);
|
|
}
|
|
|
|
private static void SetPopupPinnedOpen(object target, bool value)
|
|
{
|
|
var property = target.GetType().GetProperty(
|
|
"IsPopupPinnedOpen",
|
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
|
property.ShouldNotBeNull($"{target.GetType().Name} must own the internal popup pin contract.")
|
|
.SetValue(target, value);
|
|
}
|
|
|
|
private static void SetPopupPinnedOpenIfAvailable(object target, bool value)
|
|
{
|
|
target.GetType()
|
|
.GetProperty("IsPopupPinnedOpen", BindingFlags.Instance | BindingFlags.NonPublic)?
|
|
.SetValue(target, value);
|
|
}
|
|
|
|
private static bool GetPopupPinnedOpen(object target)
|
|
{
|
|
var property = target.GetType().GetProperty(
|
|
"IsPopupPinnedOpen",
|
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
|
return property.ShouldNotBeNull($"{target.GetType().Name} must expose the internal popup pin adapter.")
|
|
.GetValue(target)
|
|
.ShouldBeOfType<bool>();
|
|
}
|
|
|
|
private static T GetPrivateField<T>(object target, string fieldName)
|
|
{
|
|
for (var type = target.GetType(); type != null; type = type.BaseType)
|
|
{
|
|
var field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
|
|
if (field != null)
|
|
{
|
|
return (T)field.GetValue(target)!;
|
|
}
|
|
}
|
|
|
|
throw new MissingFieldException(target.GetType().FullName, fieldName);
|
|
}
|
|
}
|