mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
Five fixtures covered the "Use nested namespace structure" setting, four of them running the same toggle at a different layer: the model shape, the same toggle awaited live, and the same toggle again asserting it reached the SharpTreeView's rows. Each paid its own boot for a scenario that is one story end to end, and together they were the second-largest block of time in the suite after the process-list scroll loops. One test now walks the whole path once, carrying every assertion the four had, including the nesting depth only the first checked. The comparison view's model-is-bound test is dropped: the test after it renders rows out of that model, which cannot happen unless it is bound, and it opened two fixture assemblies to prove it. The expander hitbox test asserted the toggle measures 13x16 and its glyph 9x9, then clicked 14px down to prove the area below the glyph is live. The click proves the geometry; the measurements only restate it, and would fail on a font-metric change that broke nothing. Its layout-settling loop slept 200ms unconditionally, which is a race that usually wins - it now waits for the condition it needs. Assisted-by: Claude:claude-opus-5:Claude Codepull/3980/head
5 changed files with 75 additions and 287 deletions
@ -1,95 +0,0 @@
@@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System.Collections; |
||||
using System.Linq; |
||||
using System.Threading.Tasks; |
||||
|
||||
using Avalonia.Headless.NUnit; |
||||
|
||||
using AwesomeAssertions; |
||||
|
||||
using ICSharpCode.ILSpyX.TreeView; |
||||
|
||||
using ICSharpCode.ILSpy; |
||||
using ICSharpCode.ILSpy.AppEnv; |
||||
using ICSharpCode.ILSpy.AssemblyTree; |
||||
using ICSharpCode.ILSpy.TreeNodes; |
||||
|
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.ILSpy.Tests; |
||||
|
||||
[TestFixture] |
||||
public class UseNestedNamespaceNodesGridVerification |
||||
{ |
||||
[AvaloniaTest] |
||||
public async Task Toggling_UseNestedNamespaceNodes_Reshapes_The_Visible_Tree_In_Place() |
||||
{ |
||||
// Toggling UseNestedNamespaceNodes rebuilds each loaded assembly's namespace subtree.
|
||||
// SharpTreeView's flattener observes node.Children mutations live, so the rebuilt shape
|
||||
// surfaces in the visible row list without any model re-bind (the ProDataGrid snapshot
|
||||
// problem that used to need a HierarchicalModel rebind is gone). This pins that the
|
||||
// flat-mode -> nested-mode switch is reflected in the SharpTreeView's ItemsSource.
|
||||
|
||||
var settings = AppComposition.Current.GetExport<SettingsService>().DisplaySettings; |
||||
settings.UseNestedNamespaceNodes = false; |
||||
|
||||
var (window, vm) = await TestHarness.BootAsync(3); |
||||
var pane = await window.WaitForComponent<AssemblyListPane>(); |
||||
var grid = await pane.WaitForComponent<ICSharpCode.ILSpy.Controls.TreeView.SharpTreeView>(); |
||||
|
||||
// Expand an assembly so its namespace children become visible rows.
|
||||
var assemblyNode = vm.AssemblyTreeModel.FindNode<AssemblyTreeNode>("System.Linq"); |
||||
assemblyNode.IsExpanded = true; |
||||
await Waiters.WaitForAsync(() => assemblyNode.Children.OfType<NamespaceTreeNode>().Any()); |
||||
TestCapture.Step("system-linq-expanded-flat"); |
||||
|
||||
var flat = (IList)grid.ItemsSource!; |
||||
bool VisibleNamespace(string name) => flat.Cast<SharpTreeNode>() |
||||
.OfType<NamespaceTreeNode>() |
||||
.Any(n => string.Equals(n.Text?.ToString(), name, System.StringComparison.Ordinal)); |
||||
|
||||
// In flat mode the full dotted namespace is a single visible row.
|
||||
await Waiters.WaitForAsync(() => VisibleNamespace("System.Collections.Generic"), |
||||
description: "flat mode shows the dotted namespace as one row"); |
||||
|
||||
try |
||||
{ |
||||
settings.UseNestedNamespaceNodes = true; |
||||
assemblyNode.IsExpanded = true; |
||||
TestCapture.Step("nested-namespaces-rebuilt"); |
||||
|
||||
// In nested mode the leaf segment ("Generic") becomes its own row nested under
|
||||
// "System" -> "Collections"; the live flattener must surface that without a re-bind.
|
||||
await Waiters.WaitForAsync( |
||||
() => assemblyNode.Children.OfType<NamespaceTreeNode>() |
||||
.Any(n => string.Equals(n.Text?.ToString(), "System", System.StringComparison.Ordinal)), |
||||
System.TimeSpan.FromSeconds(5), |
||||
"toggling UseNestedNamespaceNodes must rebuild the namespace subtree into nested nodes"); |
||||
|
||||
VisibleNamespace("System").Should().BeTrue( |
||||
"the rebuilt nested 'System' namespace node must appear in the SharpTreeView's visible rows " |
||||
+ "without any model re-bind (the live flattener observes the child mutations directly)"); |
||||
} |
||||
finally |
||||
{ |
||||
settings.UseNestedNamespaceNodes = false; |
||||
} |
||||
} |
||||
} |
||||
@ -1,78 +0,0 @@
@@ -1,78 +0,0 @@
|
||||
// Copyright (c) 2026 AlphaSierraPapa for the SharpDevelop Team
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System.Linq; |
||||
using System.Threading.Tasks; |
||||
|
||||
using Avalonia.Headless.NUnit; |
||||
|
||||
using AwesomeAssertions; |
||||
|
||||
using ICSharpCode.ILSpy; |
||||
using ICSharpCode.ILSpy.AppEnv; |
||||
using ICSharpCode.ILSpy.TreeNodes; |
||||
|
||||
using NUnit.Framework; |
||||
|
||||
namespace ICSharpCode.ILSpy.Tests; |
||||
|
||||
[TestFixture] |
||||
public class UseNestedNamespaceNodesLiveTests |
||||
{ |
||||
[AvaloniaTest] |
||||
public async Task Toggling_UseNestedNamespaceNodes_Live_Refreshes_The_Tree_Shape() |
||||
{ |
||||
// Drives the live-reactivity path: toggle the Display-Settings flag and observe
|
||||
// that the AssemblyTreeNode's namespace children switch between flat and nested
|
||||
// layouts without a manual rebuild.
|
||||
var settings = AppComposition.Current.GetExport<SettingsService>().DisplaySettings; |
||||
settings.UseNestedNamespaceNodes = false; |
||||
|
||||
var (_, vm) = await TestHarness.BootAsync(3); |
||||
|
||||
try |
||||
{ |
||||
var assemblyNode = vm.AssemblyTreeModel.FindNode<AssemblyTreeNode>("System.Linq"); |
||||
assemblyNode.EnsureLazyChildren(); |
||||
|
||||
var flatNamespaces = assemblyNode.Children.OfType<NamespaceTreeNode>() |
||||
.Select(n => n.Name).ToList(); |
||||
flatNamespaces.Should().Contain("System.Linq", |
||||
"baseline: flat mode lists 'System.Linq' as a top-level sibling"); |
||||
|
||||
// Toggle the live setting — should fan out through MessageBus<SettingsChangedEventArgs>
|
||||
// to AssemblyTreeModel.OnSettingsChanged and rebuild the namespace subtrees.
|
||||
settings.UseNestedNamespaceNodes = true; |
||||
|
||||
await Waiters.WaitForAsync(() => |
||||
assemblyNode.Children.OfType<NamespaceTreeNode>().Any(n => n.Name == "System"), |
||||
System.TimeSpan.FromSeconds(5)); |
||||
|
||||
var nestedNames = assemblyNode.Children.OfType<NamespaceTreeNode>() |
||||
.Select(n => n.Name).ToList(); |
||||
nestedNames.Should().Contain("System", |
||||
"after live toggle: nested mode must surface 'System' as top-level"); |
||||
nestedNames.Should().NotContain("System.Linq", |
||||
"after live toggle: the flat 'System.Linq' sibling must disappear"); |
||||
} |
||||
finally |
||||
{ |
||||
settings.UseNestedNamespaceNodes = false; |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue