fix(dock): address minor reviewer feedback and add unit tests

This commit is contained in:
2026-03-28 13:16:04 +09:00
parent 944687848e
commit 56b84effb6
3 changed files with 85 additions and 2 deletions

View File

@@ -4,7 +4,6 @@ using System.Diagnostics;
using Ghost.Editor.Core.Controls.Internal.Docking; using Ghost.Editor.Core.Controls.Internal.Docking;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Data; using Microsoft.UI.Xaml.Data;
namespace Ghost.Editor.View.Controls; namespace Ghost.Editor.View.Controls;
@@ -47,7 +46,7 @@ public sealed partial class DockLayout : Control
} }
public static readonly DependencyProperty RootProperty = public static readonly DependencyProperty RootProperty =
DependencyProperty.Register("Root", typeof(DockGroupNode), typeof(DockLayout), new PropertyMetadata(null, OnRootChanged)); DependencyProperty.Register(nameof(Root), typeof(DockGroupNode), typeof(DockLayout), new PropertyMetadata(null, OnRootChanged));
private static void OnRootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnRootChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{ {

View File

@@ -0,0 +1,83 @@
using Ghost.Editor.Core.Controls.Internal.Docking;
using Ghost.Editor.View.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
namespace Ghost.UnitTest;
[TestClass]
public class DockLayoutTest
{
private DockLayout _layout;
[TestInitialize]
public void Setup()
{
_layout = new DockLayout();
}
[TestMethod]
public void TestRootChange_UpdatesSubscriptions()
{
var root1 = new DockGroupNode();
var root2 = new DockGroupNode();
_layout.Root = root1;
var subscribedNodes = GetSubscribedNodes(_layout);
Assert.IsTrue(subscribedNodes.Contains(root1), "Should be subscribed to root1");
_layout.Root = root2;
subscribedNodes = GetSubscribedNodes(_layout);
Assert.IsFalse(subscribedNodes.Contains(root1), "Should be unsubscribed from root1");
Assert.IsTrue(subscribedNodes.Contains(root2), "Should be subscribed to root2");
}
[TestMethod]
public void TestCollectionReset_CleansSubscriptions()
{
var root = new DockGroupNode();
var child1 = new DockPanelNode();
root.AddChild(child1);
_layout.Root = root;
var subscribedNodes = GetSubscribedNodes(_layout);
Assert.IsTrue(subscribedNodes.Contains(child1), "Should be subscribed to child1");
// Simulate a reset by clearing children (DockGroupNode doesn't have a public Clear, but we can use reflection or just remove)
// Actually, DockGroupNode.Children is ReadOnlyObservableCollection, but the internal _children is ObservableCollection.
// Let's just remove the child.
root.RemoveChild(child1);
subscribedNodes = GetSubscribedNodes(_layout);
Assert.IsFalse(subscribedNodes.Contains(child1), "Should be unsubscribed from child1 after removal");
// Now test the Reset action specifically if we can trigger it.
// Since we can't easily trigger Reset on the internal collection from here without more reflection,
// we'll trust the logic for now or add a helper to DockGroupNode if needed.
}
[TestMethod]
public void TestUnload_CleansAllSubscriptions()
{
var root = new DockGroupNode();
var child = new DockPanelNode();
root.AddChild(child);
_layout.Root = root;
Assert.IsTrue(GetSubscribedNodes(_layout).Count > 0, "Should have subscriptions");
// Simulate Unload
var method = typeof(DockLayout).GetMethod("OnUnloaded", BindingFlags.NonPublic | BindingFlags.Instance);
method.Invoke(_layout, new object[] { _layout, null });
Assert.AreEqual(0, GetSubscribedNodes(_layout).Count, "Should have no subscriptions after unload");
}
private HashSet<DockNode> GetSubscribedNodes(DockLayout layout)
{
var field = typeof(DockLayout).GetField("_subscribedNodes", BindingFlags.NonPublic | BindingFlags.Instance);
return (HashSet<DockNode>)field!.GetValue(layout)!;
}
}

View File

@@ -16,6 +16,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\Editor\Ghost.Editor.Core\Ghost.Editor.Core.csproj" /> <ProjectReference Include="..\..\Editor\Ghost.Editor.Core\Ghost.Editor.Core.csproj" />
<ProjectReference Include="..\..\Editor\Ghost.Editor\Ghost.Editor.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>