From 595faf16b8805acb1fffd90b3db9534864201654 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Thu, 7 May 2026 11:34:43 +0200 Subject: [PATCH] WaitForComponent helper + scrub boilerplate comments Replaces the brittle root.GetVisualDescendants().OfType().Single() / .First() pattern with a new WaitForComponent() extension that polls until the requested control is in the visual tree, then returns it. Avalonia.Headless tests routinely queried the visual tree before lazily-templated panes (DataGrid, dock content) had materialised, surfacing as intermittent 'Sequence contains no elements' failures across the suite. Assisted-by: Claude:claude-opus-4-7:Claude Code --- .../AssemblyTreeContextMenuTests.cs | 3 -- ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs | 46 +------------------ .../RemoveAssemblyContextMenuTests.cs | 7 +-- .../Commands/CommandLineArgumentsTests.cs | 3 -- ILSpy.Tests/Commands/HelpCommandTests.cs | 21 +-------- .../ContextMenus/DecompileInNewViewTests.cs | 6 --- ILSpy.Tests/Editor/DecompilerViewTests.cs | 39 +--------------- ILSpy.Tests/MainWindow/MainMenuTests.cs | 2 +- ILSpy.Tests/MainWindow/MainWindowTests.cs | 6 +-- .../BrowseBackForwardCommandTests.cs | 8 +--- ILSpy.Tests/Navigation/NavigationTests.cs | 23 ---------- .../Options/ApiVisibilityFilterTests.cs | 8 ++-- 12 files changed, 13 insertions(+), 159 deletions(-) diff --git a/ILSpy.Tests/AssemblyList/AssemblyTreeContextMenuTests.cs b/ILSpy.Tests/AssemblyList/AssemblyTreeContextMenuTests.cs index d872ef279..ad2a598c1 100644 --- a/ILSpy.Tests/AssemblyList/AssemblyTreeContextMenuTests.cs +++ b/ILSpy.Tests/AssemblyList/AssemblyTreeContextMenuTests.cs @@ -52,7 +52,6 @@ public class AssemblyTreeContextMenuTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); // Assert — TreeGrid carries a ContextMenu. (The menu may be empty if no entries are @@ -75,11 +74,9 @@ public class AssemblyTreeContextMenuTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); var pane = await window.WaitForComponent(); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); - // select assemblyNode vm.AssemblyTreeModel.SelectNode(assemblyNode); TextViewContext? executionContext = null; diff --git a/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs b/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs index a79a9c76c..da9955c26 100644 --- a/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs +++ b/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs @@ -61,7 +61,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); // Act — pick CoreLib (always ships localised error-message tables), expand it. @@ -89,7 +88,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); // Act — locate the realised DataGrid inside the AssemblyListPane. @@ -112,7 +110,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( @@ -153,7 +150,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var tempDir = Path.Combine(Path.GetTempPath(), "ILSpy.Tests", System.Guid.NewGuid().ToString("N")); @@ -174,7 +170,6 @@ public class AssemblyTreeTests var openCommand = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._Open)) .CreateExport().Value; - // execute openCommand openCommand.Execute(zipPath); await Waiters.WaitForAsync(() => @@ -212,7 +207,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLibName = typeof(object).Assembly.GetName().Name!; @@ -247,7 +241,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -279,7 +272,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -312,7 +304,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -349,7 +340,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -375,7 +365,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -405,7 +394,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -459,7 +447,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLibDir = System.IO.Path.GetDirectoryName(typeof(object).Assembly.Location)!; @@ -473,7 +460,6 @@ public class AssemblyTreeTests var openCommand = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._Open)) .CreateExport().Value; - // execute openCommand openCommand.Execute(mscorlibPath); await Waiters.WaitForAsync(() => @@ -523,7 +509,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -561,7 +546,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); @@ -602,7 +586,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var newAsmPath = typeof(System.Net.Http.HttpClient).Assembly.Location; @@ -610,7 +593,6 @@ public class AssemblyTreeTests var openCommand = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._Open)) .CreateExport().Value; - // execute openCommand openCommand.Execute(newAsmPath); await Waiters.WaitForAsync(() => @@ -634,7 +616,6 @@ public class AssemblyTreeTests var methodNode = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "CancelPendingRequests"); - // select methodNode vm.AssemblyTreeModel.SelectNode(methodNode); await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -667,7 +648,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var newAsmPath = typeof(System.Net.Http.HttpClient).Assembly.Location; @@ -675,7 +655,6 @@ public class AssemblyTreeTests var openCommand = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._Open)) .CreateExport().Value; - // execute openCommand openCommand.Execute(newAsmPath); await Waiters.WaitForAsync(() => @@ -693,7 +672,6 @@ public class AssemblyTreeTests var methodNode = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "CancelPendingRequests"); - // select methodNode vm.AssemblyTreeModel.SelectNode(methodNode); await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -734,7 +712,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var newAsmPath = typeof(System.Net.Http.HttpClient).Assembly.Location; @@ -745,7 +722,6 @@ public class AssemblyTreeTests var openCommand = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._Open)) .CreateExport().Value; - // execute openCommand openCommand.Execute(newAsmPath); await Waiters.WaitForAsync(() => @@ -777,7 +753,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var enumerable = vm.AssemblyTreeModel.FindNode( @@ -787,23 +762,18 @@ public class AssemblyTreeTests var ns = (NamespaceTreeNode)enumerable.Parent!; ns.EnsureLazyChildren(); ns.IsExpanded = true; - // expand ns var asm = (AssemblyTreeNode)ns.Parent!; - // expand asm asm.IsExpanded = true; foreach (var child in ns.Children.OfType()) { child.EnsureLazyChildren(); child.IsExpanded = true; - // expand child } var pane = await window.WaitForComponent(); var grid = await pane.WaitForComponent(); - // select enumerable vm.AssemblyTreeModel.SelectNode(enumerable); - // wait for the predicate await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, enumerable)); for (int i = 0; i < 8; i++) { @@ -812,7 +782,7 @@ public class AssemblyTreeTests } grid.UpdateLayout(); - var scrollViewer = grid.GetVisualDescendants().OfType().Single(); + var scrollViewer = await grid.WaitForComponent(); (scrollViewer.Extent.Height - scrollViewer.Viewport.Height).Should().BeGreaterThan(50, "the grid must have something to scroll for this test to be meaningful"); scrollViewer.Offset = new Vector(scrollViewer.Offset.X, 50); @@ -863,11 +833,9 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var probe = new SaveProbeNode(); - // select probe vm.AssemblyTreeModel.SelectNode(probe); // Act — fire the Save Code main-menu command. @@ -875,7 +843,6 @@ public class AssemblyTreeTests var saveCmd = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._SaveCode)) .CreateExport().Value; - // execute saveCmd saveCmd.Execute(null); // Assert — probe's Save() ran. @@ -905,7 +872,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( @@ -914,7 +880,6 @@ public class AssemblyTreeTests typeNode.IsExpanded = true; var method = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "AsEnumerable"); - // select method vm.AssemblyTreeModel.SelectNode(method); await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -959,15 +924,12 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var sacrificialName = typeof(System.Linq.Enumerable).Assembly.GetName().Name!; var survivorName = typeof(object).Assembly.GetName().Name!; var sacrificialNode = vm.AssemblyTreeModel.FindNode(sacrificialName); - // select sacrificialNode vm.AssemblyTreeModel.SelectNode(sacrificialNode); - // wait for the predicate await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, sacrificialNode)); var pane = await window.WaitForComponent(); @@ -1013,7 +975,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); vm.AssemblyTreeModel.AssemblyList!.Count.Should().BeGreaterThan(0); @@ -1023,11 +984,9 @@ public class AssemblyTreeTests .Single(c => c.Metadata.Header == nameof(Resources.ClearAssemblyList)) .CreateExport().Value; clearCmd.CanExecute(null).Should().BeTrue("non-empty list must enable Clear"); - // execute clearCmd clearCmd.Execute(null); // Assert — the list goes to zero entries. - // wait for the predicate await Waiters.WaitForAsync(() => vm.AssemblyTreeModel.AssemblyList!.Count == 0); vm.AssemblyTreeModel.AssemblyList!.Count.Should().Be(0); } @@ -1044,7 +1003,6 @@ public class AssemblyTreeTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var brokenPath = System.IO.Path.Combine( @@ -1060,7 +1018,6 @@ public class AssemblyTreeTests var broken = vm.AssemblyTreeModel.AssemblyList!.GetAssemblies() .First(a => string.Equals(a.FileName, brokenPath, System.StringComparison.OrdinalIgnoreCase)); // GetLoadResultAsync rethrows the load failure; HasLoadError is the safe probe. - // wait for the predicate await Waiters.WaitForAsync(() => broken.HasLoadError); var validBefore = vm.AssemblyTreeModel.AssemblyList!.GetAssemblies() @@ -1075,7 +1032,6 @@ public class AssemblyTreeTests .Single(c => c.Metadata.Header == nameof(Resources._RemoveAssembliesWithLoadErrors)) .CreateExport().Value; cmd.CanExecute(null).Should().BeTrue("a broken entry must enable the command"); - // execute cmd cmd.Execute(null); await Waiters.WaitForAsync(() => diff --git a/ILSpy.Tests/AssemblyList/RemoveAssemblyContextMenuTests.cs b/ILSpy.Tests/AssemblyList/RemoveAssemblyContextMenuTests.cs index 8b3332c3f..8ccf3f3b0 100644 --- a/ILSpy.Tests/AssemblyList/RemoveAssemblyContextMenuTests.cs +++ b/ILSpy.Tests/AssemblyList/RemoveAssemblyContextMenuTests.cs @@ -71,7 +71,6 @@ public class RemoveAssemblyContextMenuTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var registry = AppComposition.Current.GetExport(); var removeEntry = registry.Entries @@ -110,7 +109,6 @@ public class RemoveAssemblyContextMenuTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var registry = AppComposition.Current.GetExport(); var removeEntry = registry.Entries @@ -145,14 +143,11 @@ public class RemoveAssemblyContextMenuTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); - // wait for the predicate await Waiters.WaitForAsync( () => window.GetVisualDescendants().OfType().Any()); - var pane = window.GetVisualDescendants().OfType().Single(); + var pane = await window.WaitForComponent(); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); - // select assemblyNode vm.AssemblyTreeModel.SelectNode(assemblyNode); var registry = AppComposition.Current.GetExport(); diff --git a/ILSpy.Tests/Commands/CommandLineArgumentsTests.cs b/ILSpy.Tests/Commands/CommandLineArgumentsTests.cs index f12f9f811..c537942f1 100644 --- a/ILSpy.Tests/Commands/CommandLineArgumentsTests.cs +++ b/ILSpy.Tests/Commands/CommandLineArgumentsTests.cs @@ -46,7 +46,6 @@ public class CommandLineArgumentsTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); var languageService = AppComposition.Current.GetExport(); languageService.CurrentLanguage.Name.Should().NotBe("IL", "baseline must differ from the value we'll assert"); @@ -72,7 +71,6 @@ public class CommandLineArgumentsTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var args = CommandLineArguments.Create(new[] { "--navigateto", "T:System.Linq.Enumerable" }); @@ -98,7 +96,6 @@ public class CommandLineArgumentsTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); // clear selection vm.AssemblyTreeModel.SelectedItems.Clear(); diff --git a/ILSpy.Tests/Commands/HelpCommandTests.cs b/ILSpy.Tests/Commands/HelpCommandTests.cs index a0bf07eab..3be9341f3 100644 --- a/ILSpy.Tests/Commands/HelpCommandTests.cs +++ b/ILSpy.Tests/Commands/HelpCommandTests.cs @@ -55,7 +55,6 @@ public class HelpCommandTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); var registry = AppComposition.Current.GetExport(); @@ -68,7 +67,6 @@ public class HelpCommandTests // Act — fire the About command. aboutCmd.Execute(null); - // execute aboutCmd // Assert — a new DecompilerTabPageModel landed in the document dock, titled "About", // containing the version line and the MIT License mention from the embedded blurb. @@ -95,7 +93,6 @@ public class HelpCommandTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); var registry = AppComposition.Current.GetExport(); @@ -103,9 +100,7 @@ public class HelpCommandTests .Single(c => c.Metadata.Header == nameof(Resources._About)) .CreateExport().Value; var documents = ((ILSpyDockFactory)vm.DockWorkspace.Factory).Documents!; - // execute aboutCmd aboutCmd.Execute(null); - // wait for the predicate await Waiters.WaitForAsync( () => documents.ActiveDockable is DecompilerTabPageModel { Text.Length: > 0 }); var aboutTab = (DecompilerTabPageModel)documents.ActiveDockable!; @@ -160,20 +155,16 @@ public class HelpCommandTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); var node = vm.AssemblyTreeModel.FindNode("System.Linq"); - // select node vm.AssemblyTreeModel.SelectNode(node); - // wait for decompile to finish await vm.DockWorkspace.WaitForDecompiledTextAsync(); - // wait for the predicate await Waiters.WaitForAsync( () => window.GetVisualDescendants().OfType().Any()); // Act — locate the editor inside the realised DecompilerTextView. - var view = window.GetVisualDescendants().OfType().First(); - var editor = view.GetVisualDescendants().OfType().Single(); + var view = await window.WaitForComponent(); + var editor = await view.WaitForComponent(); // Assert — the editor's hyperlink-click option is off. editor.Options.RequireControlModifierForHyperlinkClick.Should().BeFalse( @@ -193,18 +184,14 @@ public class HelpCommandTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var method = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "AsEnumerable"); - // select method vm.AssemblyTreeModel.SelectNode(method); - // wait for decompile to finish await vm.DockWorkspace.WaitForDecompiledTextAsync(); var decompilerTab = vm.DockWorkspace.ActiveDecompilerTab!; var methodText = decompilerTab.Text; @@ -219,9 +206,7 @@ public class HelpCommandTests .Single(c => c.Metadata.Header == nameof(Resources._About)) .CreateExport().Value; var documents = ((ILSpyDockFactory)vm.DockWorkspace.Factory).Documents!; - // execute aboutCmd aboutCmd.Execute(null); - // wait for the predicate await Waiters.WaitForAsync( () => documents.ActiveDockable is DecompilerTabPageModel { IsStaticContent: true }); var aboutTab = (DecompilerTabPageModel)documents.ActiveDockable!; @@ -238,7 +223,6 @@ public class HelpCommandTests vm.DockWorkspace.NavigateBackCommand.CanExecute(null).Should().BeTrue(); // execute vm.DockWorkspace.NavigateBackCommand vm.DockWorkspace.NavigateBackCommand.Execute(null); - // wait for the predicate await Waiters.WaitForAsync( () => ReferenceEquals(documents.ActiveDockable, decompilerTab)); @@ -253,7 +237,6 @@ public class HelpCommandTests vm.DockWorkspace.NavigateForwardCommand.CanExecute(null).Should().BeTrue(); // execute vm.DockWorkspace.NavigateForwardCommand vm.DockWorkspace.NavigateForwardCommand.Execute(null); - // wait for the predicate await Waiters.WaitForAsync( () => ReferenceEquals(documents.ActiveDockable, aboutTab)); diff --git a/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs b/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs index eb441db0e..6040f866d 100644 --- a/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs +++ b/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs @@ -67,7 +67,6 @@ public class DecompileInNewViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); var registry = AppComposition.Current.GetExport(); var entry = registry.Entries @@ -96,19 +95,15 @@ public class DecompileInNewViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var firstMethod = typeNode.Children.OfType() .Single(m => m.MethodDefinition.Name == "AsEnumerable"); var secondMethod = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "Empty"); - // select firstMethod vm.AssemblyTreeModel.SelectNode(firstMethod); - // wait for decompile to finish var firstTab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); var registry = AppComposition.Current.GetExport(); @@ -128,7 +123,6 @@ public class DecompileInNewViewTests // shows AsEnumerable. await Waiters.WaitForAsync( () => (documents.VisibleDockables?.Count ?? 0) > initialCount); - // wait for decompile to finish var newTab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); ReferenceEquals(newTab, firstTab).Should().BeFalse( "a fresh decompiler tab must be created instead of reusing the existing one"); diff --git a/ILSpy.Tests/Editor/DecompilerViewTests.cs b/ILSpy.Tests/Editor/DecompilerViewTests.cs index 6c5c3fd07..178364bd4 100644 --- a/ILSpy.Tests/Editor/DecompilerViewTests.cs +++ b/ILSpy.Tests/Editor/DecompilerViewTests.cs @@ -53,21 +53,17 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var methodNode = typeNode.Children.OfType() .Single(m => m.MethodDefinition.Name == "AsEnumerable"); methodNode.MethodDefinition.IsExtensionMethod.Should().BeTrue(); // Act — select the method node and wait for the decompile. - // select methodNode vm.AssemblyTreeModel.SelectNode(methodNode); - // wait for decompile to finish var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); // Assert — signature + body fragments are present and the row centred in the tree. @@ -89,16 +85,13 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); - // expand assemblyNode assemblyNode.IsExpanded = true; var refFolder = assemblyNode.Children.OfType().Single(); // Act — select the References folder and wait for its decompile output. - // select refFolder vm.AssemblyTreeModel.SelectNode(refFolder); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -120,7 +113,6 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLib = typeof(object).Assembly.GetName().Name!; @@ -128,7 +120,6 @@ public class DecompilerViewTests coreLib, "System", "System.Version"); // Act — select the type node, wait for the decompile. - // select typeNode vm.AssemblyTreeModel.SelectNode(typeNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -148,19 +139,16 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLib = typeof(object).Assembly.GetName().Name!; var typeNode = vm.AssemblyTreeModel.FindNode( coreLib, "System", "System.Version"); - // expand typeNode typeNode.IsExpanded = true; var propertyNode = typeNode.Children.OfType() .Single(p => p.PropertyDefinition.Name == "Major"); // Act — select the property, wait for the decompile. - // select propertyNode vm.AssemblyTreeModel.SelectNode(propertyNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -178,19 +166,16 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLib = typeof(object).Assembly.GetName().Name!; var typeNode = vm.AssemblyTreeModel.FindNode( coreLib, "System", "System.Math"); - // expand typeNode typeNode.IsExpanded = true; var fieldNode = typeNode.Children.OfType() .Single(f => f.FieldDefinition.Name == "PI"); // Act — select the field, wait for the decompile. - // select fieldNode vm.AssemblyTreeModel.SelectNode(fieldNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -208,19 +193,16 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLib = typeof(object).Assembly.GetName().Name!; var typeNode = vm.AssemblyTreeModel.FindNode( coreLib, "System", "System.AppDomain"); - // expand typeNode typeNode.IsExpanded = true; var eventNode = typeNode.Children.OfType() .Single(e => e.EventDefinition.Name == "ProcessExit"); // Act — select the event, wait for the decompile. - // select eventNode vm.AssemblyTreeModel.SelectNode(eventNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -238,7 +220,6 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var coreLib = typeof(object).Assembly.GetName().Name!; @@ -246,7 +227,6 @@ public class DecompilerViewTests coreLib, "System.Runtime.Versioning"); // Act — select the namespace, wait for the decompile. - // select namespaceNode vm.AssemblyTreeModel.SelectNode(namespaceNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -266,7 +246,6 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); // Act 1 — fire OpenCommand on a new path. OpenCommand selects the new node before its @@ -276,7 +255,6 @@ public class DecompilerViewTests var openCommand = registry.Commands .Single(c => c.Metadata.Header == nameof(Resources._Open)) .CreateExport().Value; - // execute openCommand openCommand.Execute(newAsmPath); await Waiters.WaitForAsync(() => @@ -290,7 +268,6 @@ public class DecompilerViewTests // Assert — once Text is rich, the tab title catches up. Sanity-check the form is rich // (otherwise the test isn't exercising the late-update path). - // wait for the predicate await Waiters.WaitForAsync(() => string.Equals(tab.Title, node.Text?.ToString(), System.StringComparison.Ordinal)); node.Text!.ToString().Should().NotBe(node.LoadedAssembly.ShortName, "the rich form (with version + tfm) must be available, otherwise the test isn't exercising the late-update path"); @@ -309,11 +286,9 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var firstNode = vm.AssemblyTreeModel.FindNode("System.Linq"); - // select firstNode vm.AssemblyTreeModel.SelectNode(firstNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -324,7 +299,6 @@ public class DecompilerViewTests // Act — kick off a second decompile and observe Title/Text changes throughout. var coreLib = typeof(object).Assembly.GetName().Name!; var second = vm.AssemblyTreeModel.FindNode(coreLib, "System", "System.Version"); - // select second vm.AssemblyTreeModel.SelectNode(second); await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -359,12 +333,10 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var asEnumerable = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "AsEnumerable"); @@ -392,12 +364,10 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var asEnumerable = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "AsEnumerable"); @@ -409,7 +379,6 @@ public class DecompilerViewTests vm.AssemblyTreeModel.SelectedItems.Add(asEnumerable); vm.AssemblyTreeModel.SelectedItems.Add(empty); - // wait for decompile to finish var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); // Assert — both names AND a body-fragment from one of them confirm both bodies @@ -429,16 +398,13 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); // Act — select the assembly node, wait for the decompile. - // select assemblyNode vm.AssemblyTreeModel.SelectNode(assemblyNode); - // wait for decompile to finish var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); // Assert — every documented header line and at least one assembly attribute land. @@ -462,11 +428,9 @@ public class DecompilerViewTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var assemblyNode = vm.AssemblyTreeModel.FindNode("System.Linq"); - // select assemblyNode vm.AssemblyTreeModel.SelectNode(assemblyNode); var tab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -475,10 +439,9 @@ public class DecompilerViewTests var xml = "\n \n text\n \n \n \n"; var bytes = System.Text.Encoding.UTF8.GetBytes(xml); tab.CurrentNode = new XmlResourceEntryNode("test.xml", () => new System.IO.MemoryStream(bytes)); - // wait for the predicate await Waiters.WaitForAsync(() => tab.SyntaxExtension == ".xml" && tab.Text.Contains("")); - var view = window.GetVisualDescendants().OfType().Single(); + var view = await window.WaitForComponent(); // Drain the layout so ApplyDocument's PropertyChanged handler has executed. for (int i = 0; i < 5; i++) { diff --git a/ILSpy.Tests/MainWindow/MainMenuTests.cs b/ILSpy.Tests/MainWindow/MainMenuTests.cs index 3295d850f..54f623d7c 100644 --- a/ILSpy.Tests/MainWindow/MainMenuTests.cs +++ b/ILSpy.Tests/MainWindow/MainMenuTests.cs @@ -64,7 +64,7 @@ public class MainMenuTests var window = AppComposition.Current.GetExport(); window.Show(); - var menu = window.GetVisualDescendants().OfType().First(); + var menu = await window.WaitForComponent(); await Waiters.WaitForAsync(() => menu.Items.OfType().Any(m => (string?)m.Tag == nameof(Resources._File)) && menu.Items.OfType().Single(m => (string?)m.Tag == nameof(Resources._File)) diff --git a/ILSpy.Tests/MainWindow/MainWindowTests.cs b/ILSpy.Tests/MainWindow/MainWindowTests.cs index b79130667..d7212bdfb 100644 --- a/ILSpy.Tests/MainWindow/MainWindowTests.cs +++ b/ILSpy.Tests/MainWindow/MainWindowTests.cs @@ -66,9 +66,8 @@ public class MainWindowTests var window = AppComposition.Current.GetExport(); window.Show(); - // wait for the predicate await Waiters.WaitForAsync(() => window.GetVisualDescendants().OfType().Any()); - var pane = window.GetVisualDescendants().OfType().Single(); + var pane = await window.WaitForComponent(); // Assert — visible with positive width and height. pane.IsVisible.Should().BeTrue(); @@ -137,7 +136,6 @@ public class MainWindowTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var service = AppComposition.Current.GetExport(); @@ -147,9 +145,7 @@ public class MainWindowTests // Act — trigger a decompile. var node = vm.AssemblyTreeModel.FindNode("System.Linq"); - // select node vm.AssemblyTreeModel.SelectNode(node); - // wait for decompile to finish await vm.DockWorkspace.WaitForDecompiledTextAsync(); service.StateChanged -= Observe; diff --git a/ILSpy.Tests/Navigation/BrowseBackForwardCommandTests.cs b/ILSpy.Tests/Navigation/BrowseBackForwardCommandTests.cs index 9b758c7d1..bc8230fb9 100644 --- a/ILSpy.Tests/Navigation/BrowseBackForwardCommandTests.cs +++ b/ILSpy.Tests/Navigation/BrowseBackForwardCommandTests.cs @@ -82,12 +82,10 @@ public class BrowseBackForwardCommandTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var firstMethod = typeNode.Children.OfType() .Single(m => m.MethodDefinition.Name == "AsEnumerable"); @@ -95,7 +93,7 @@ public class BrowseBackForwardCommandTests .First(m => m.MethodDefinition.Name == "Empty"); // Locate the View > Back menu item. - var menu = window.GetVisualDescendants().OfType().First(); + var menu = await window.WaitForComponent(); var viewMenu = menu.Items.OfType() .Single(m => (string?)m.Tag == nameof(Resources._View)); // expand the View menu so its child items are realised. @@ -109,11 +107,9 @@ public class BrowseBackForwardCommandTests "with no navigation history, BrowseBack must report CanExecute=false"); // Build history: select two methods with a delay so they record as separate entries. - // select firstMethod vm.AssemblyTreeModel.SelectNode(firstMethod); await vm.DockWorkspace.WaitForDecompiledTextAsync(); await Task.Delay(600); - // select secondMethod vm.AssemblyTreeModel.SelectNode(secondMethod); await vm.DockWorkspace.WaitForDecompiledTextAsync(); @@ -136,7 +132,7 @@ public class BrowseBackForwardCommandTests // Arrange — boot, locate the View menu, wait for both nav items to materialise. var window = AppComposition.Current.GetExport(); window.Show(); - var menu = window.GetVisualDescendants().OfType().First(); + var menu = await window.WaitForComponent(); var viewMenu = menu.Items.OfType() .Single(m => (string?)m.Tag == nameof(Resources._View)); viewMenu.Open(); diff --git a/ILSpy.Tests/Navigation/NavigationTests.cs b/ILSpy.Tests/Navigation/NavigationTests.cs index e0e15474d..a9b0c38ab 100644 --- a/ILSpy.Tests/Navigation/NavigationTests.cs +++ b/ILSpy.Tests/Navigation/NavigationTests.cs @@ -49,12 +49,10 @@ public class NavigationTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var firstMethod = typeNode.Children.OfType() .Single(m => m.MethodDefinition.Name == "AsEnumerable"); @@ -62,10 +60,7 @@ public class NavigationTests .First(m => m.MethodDefinition.Name == "Empty"); // Act 1 — select AsEnumerable, wait for it to decompile. - // select firstMethod - // select firstMethod vm.AssemblyTreeModel.SelectNode(firstMethod); - // wait for decompile to finish var firstTab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); firstTab.Text.Should().Contain("AsEnumerable"); @@ -74,12 +69,8 @@ public class NavigationTests await Task.Delay(600); // Act 2 — select Empty, wait for its decompile. - // select secondMethod - // select secondMethod vm.AssemblyTreeModel.SelectNode(secondMethod); - // wait for the predicate await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, secondMethod)); - // wait for decompile to finish var secondTab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); secondTab.Text.Should().Contain("Empty"); @@ -90,9 +81,7 @@ public class NavigationTests // Assert — selection restores to AsEnumerable, the document re-decompiles to its body, // and the row is centred back into view. - // wait for the predicate await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, firstMethod)); - // wait for decompile to finish var restoredTab = await vm.DockWorkspace.WaitForDecompiledTextAsync(); restoredTab.Text.Should().Contain("AsEnumerable"); restoredTab.Text.Should().Contain("return source"); @@ -112,12 +101,10 @@ public class NavigationTests var window = AppComposition.Current.GetExport(); window.Show(); var vm = (MainWindowViewModel)window.DataContext!; - // wait for assemblies to load await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 3); var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); - // expand typeNode typeNode.IsExpanded = true; var methodA = typeNode.Children.OfType() .First(m => m.MethodDefinition.Name == "AsEnumerable"); @@ -128,19 +115,13 @@ public class NavigationTests // Act 1 — three distinct selections with >0.6s gaps so each lands as its own entry on // the back stack (NavigationHistory collapses sub-0.5s rapid succession into one entry). - // select methodA vm.AssemblyTreeModel.SelectNode(methodA); - // wait for decompile to finish await vm.DockWorkspace.WaitForDecompiledTextAsync(); await Task.Delay(600); - // select methodB vm.AssemblyTreeModel.SelectNode(methodB); - // wait for decompile to finish await vm.DockWorkspace.WaitForDecompiledTextAsync(); await Task.Delay(600); - // select methodC vm.AssemblyTreeModel.SelectNode(methodC); - // wait for decompile to finish await vm.DockWorkspace.WaitForDecompiledTextAsync(); // Act 2 — open the Back SplitButton's flyout. The Opening handler populates the menu @@ -150,8 +131,6 @@ public class NavigationTests var flyout = (MenuFlyout)backSplit.Flyout!; // open flyout on backSplit flyout.ShowAt(backSplit); - // wait for the predicate - // wait for the predicate await Waiters.WaitForAsync(() => flyout.Items.OfType().Count() >= 2); // Assert 1 — newest-first ordering: index 0 is the immediate previous selection @@ -166,8 +145,6 @@ public class NavigationTests // Act 3 — multi-step jump: clicking methodA pops two entries off the back stack in one go. items[1].Command!.Execute(items[1].CommandParameter); - // wait for the predicate - // wait for the predicate await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, methodA)); // Assert 2 — the two displaced entries (methodC, methodB) are now on the forward stack, diff --git a/ILSpy.Tests/Options/ApiVisibilityFilterTests.cs b/ILSpy.Tests/Options/ApiVisibilityFilterTests.cs index c689b825d..821de8824 100644 --- a/ILSpy.Tests/Options/ApiVisibilityFilterTests.cs +++ b/ILSpy.Tests/Options/ApiVisibilityFilterTests.cs @@ -177,8 +177,8 @@ public class ApiVisibilityFilterTests await vm.AssemblyTreeModel.WaitForAssembliesAsync(minimumCount: 1); await Waiters.WaitForAsync( () => window.GetVisualDescendants().OfType().Any()); - var pane = window.GetVisualDescendants().OfType().Single(); - var grid = pane.GetVisualDescendants().OfType().Single(); + var pane = await window.WaitForComponent(); + var grid = await pane.WaitForComponent(); // Force any pending DataContext propagation so the initial HierarchicalModel is set. var settings = AppComposition.Current.GetExport().SessionSettings.LanguageSettings; @@ -220,8 +220,8 @@ public class ApiVisibilityFilterTests var nonPublicMethod = stringType.Children.OfType().First(m => !m.IsPublicAPI); await Waiters.WaitForAsync(() => window.GetVisualDescendants().OfType().Any()); - var pane = window.GetVisualDescendants().OfType().Single(); - var grid = pane.GetVisualDescendants().OfType().Single(); + var pane = await window.WaitForComponent(); + var grid = await pane.WaitForComponent(); // Selecting each node scrolls it into view; that's how the row's TextBlock realises. vm.AssemblyTreeModel.SelectNode(publicMethod);