diff --git a/ILSpy.Tests/Analyzers/AnalyzerTreeKeyboardTests.cs b/ILSpy.Tests/Analyzers/AnalyzerTreeKeyboardTests.cs index 7b34d4ed4..7cc914db1 100644 --- a/ILSpy.Tests/Analyzers/AnalyzerTreeKeyboardTests.cs +++ b/ILSpy.Tests/Analyzers/AnalyzerTreeKeyboardTests.cs @@ -154,12 +154,7 @@ public class AnalyzerTreeKeyboardTests var typeNode = vm.AssemblyTreeModel.FindNode( "System.Linq", "System.Linq", "System.Linq.Enumerable"); vm.AssemblyTreeModel.SelectNode(typeNode); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - tree.UpdateLayout(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); tree.Focus(); Dispatcher.UIThread.RunJobs(); diff --git a/ILSpy.Tests/AssemblyList/AssemblyTreeExpanderHitboxTests.cs b/ILSpy.Tests/AssemblyList/AssemblyTreeExpanderHitboxTests.cs index 90df93d69..fa3f855e4 100644 --- a/ILSpy.Tests/AssemblyList/AssemblyTreeExpanderHitboxTests.cs +++ b/ILSpy.Tests/AssemblyList/AssemblyTreeExpanderHitboxTests.cs @@ -81,10 +81,7 @@ public class AssemblyTreeExpanderHitboxTests // outside the centred glyph at ~y=3.5..12.5) collapses the node. This proves the grown // area is genuinely hittable, not just larger in layout. assemblyNode.IsExpanded.Should().BeTrue("precondition: node is expanded before the click"); - var hitPoint = expander.TranslatePoint(new Point(expander.Bounds.Width / 2, 14), window); - hitPoint.Should().NotBeNull(); - HeadlessWindowExtensions.MouseDown(window, hitPoint!.Value, MouseButton.Left); - HeadlessWindowExtensions.MouseUp(window, hitPoint.Value, MouseButton.Left); + await window.ClickAsync(() => expander, pointInTarget: e => new Point(e.Bounds.Width / 2, 14)); TestCapture.Step("clicked-enlarged-expander-area"); await Waiters.WaitForAsync(() => !assemblyNode.IsExpanded, diff --git a/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs b/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs index 7c8daeb90..0dac02119 100644 --- a/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs +++ b/ILSpy.Tests/AssemblyList/AssemblyTreeTests.cs @@ -634,11 +634,7 @@ public class AssemblyTreeTests vm.AssemblyTreeModel.SelectNode(enumerable); await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, enumerable)); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); grid.UpdateLayout(); var scrollViewer = await grid.WaitForComponent(); @@ -665,19 +661,13 @@ public class AssemblyTreeTests var offsetBefore = scrollViewer.Offset.Y; // Act — real pointer click. Setting SelectedItem programmatically would fire DataGrid's - // internal ScrollIntoView too, which a real user click does not. - var rowCentre = candidateRow!.TranslatePoint( - new Point(candidateRow.Bounds.Width / 2, candidateRow.Bounds.Height / 2), - window)!.Value; - global::Avalonia.Headless.HeadlessWindowExtensions.MouseDown(window, rowCentre, global::Avalonia.Input.MouseButton.Left); - global::Avalonia.Headless.HeadlessWindowExtensions.MouseUp(window, rowCentre, global::Avalonia.Input.MouseButton.Left); + // internal ScrollIntoView too, which a real user click does not. Tree rows stretch to + // content width, so clamp X to the visible grid viewport. + await window.ClickAsync(() => candidateRow, + pointInTarget: r => new Point(System.Math.Min(r.Bounds.Width, grid.Bounds.Width) / 2, r.Bounds.Height / 2)); TestCapture.Step("visible-row-clicked"); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); // Assert — viewport offset is unchanged (within 1px tolerance for layout jitter). scrollViewer.Offset.Y.Should().BeApproximately(offsetBefore, 1.0, @@ -711,11 +701,7 @@ public class AssemblyTreeTests vm.AssemblyTreeModel.SelectNode(enumerable); await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, enumerable)); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); grid.UpdateLayout(); var scrollViewer = await grid.WaitForComponent(); @@ -742,11 +728,7 @@ public class AssemblyTreeTests // Act — model-driven selection (the open-in-new-tab path), NOT a mouse click. vm.AssemblyTreeModel.SelectNode(candidateNode); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); scrollViewer.Offset.Y.Should().BeApproximately(offsetBefore, 1.0, "selecting an already-visible row via the model (e.g. Decompile to new tab) must not move the viewport"); @@ -780,11 +762,7 @@ public class AssemblyTreeTests // Select + reveal the type, then let it settle on screen. vm.AssemblyTreeModel.SelectNode(enumerable); await Waiters.WaitForAsync(() => ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, enumerable)); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); grid.UpdateLayout(); (scrollViewer.Extent.Height - scrollViewer.Viewport.Height).Should().BeGreaterThan(50, @@ -795,11 +773,7 @@ public class AssemblyTreeTests // rows above the selection and pushing it off-screen. var coreLib = vm.AssemblyTreeModel.FindNode(typeof(object).Assembly.GetName().Name!); coreLib.IsExpanded = true; - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); grid.UpdateLayout(); // Assert: the app did not chase the selection. The expand reveals the opened node's children; @@ -1774,14 +1748,9 @@ public class AssemblyTreeTests Assert.That(targetNode, Is.Not.Null, "the clicked row must wrap a tree node"); // Tree rows stretch to content width (with horizontal scroll), so a row can be wider than // the grid viewport. Click within the visible viewport, not at the (off-screen) row centre. - var clickX = System.Math.Min(targetRow.Bounds.Width, grid.Bounds.Width) / 2; - var rowCentre = targetRow.TranslatePoint( - new Point(clickX, targetRow.Bounds.Height / 2), window)!.Value; - HeadlessWindowExtensions.MouseDown(window, rowCentre, MouseButton.Left); - HeadlessWindowExtensions.MouseUp(window, rowCentre, MouseButton.Left); - Dispatcher.UIThread.RunJobs(); - await Task.Delay(50); - Dispatcher.UIThread.RunJobs(); + await window.ClickAsync(() => targetRow, + pointInTarget: r => new Point(System.Math.Min(r.Bounds.Width, grid.Bounds.Width) / 2, r.Bounds.Height / 2)); + await Waiters.WaitForIdleAsync(); TestCapture.Step("plain-click-collapsed-selection"); // Assert — selection collapsed to exactly the clicked row, in both grid and model. @@ -1822,11 +1791,7 @@ public class AssemblyTreeTests // Act -- run Load Dependencies on the System.Net.Http node. await vm.AssemblyTreeModel.LoadDependenciesAsync(new SharpTreeNode[] { httpNode }); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); // Assert -- references were resolved AND survive in the list as auto-loaded entries. var added = vm.AssemblyTreeModel.AssemblyList!.GetAssemblies() diff --git a/ILSpy.Tests/Bookmarks/BookmarkContextMenuTests.cs b/ILSpy.Tests/Bookmarks/BookmarkContextMenuTests.cs index 1acc4430f..23429a3fb 100644 --- a/ILSpy.Tests/Bookmarks/BookmarkContextMenuTests.cs +++ b/ILSpy.Tests/Bookmarks/BookmarkContextMenuTests.cs @@ -54,11 +54,7 @@ public class BookmarkContextMenuTests await vm.DockWorkspace.WaitForDecompiledTextAsync(); var view = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); var bookmarkableLines = Enumerable.Range(1, view.Editor.Document.LineCount) .Where(view.CanToggleBookmarkAtLine) @@ -94,11 +90,7 @@ public class BookmarkContextMenuTests await vm.DockWorkspace.WaitForDecompiledTextAsync(); var view = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); int line = Enumerable.Range(1, view.Editor.Document.LineCount) .First(view.CanToggleBookmarkAtLine); diff --git a/ILSpy.Tests/Bookmarks/BookmarkGutterTests.cs b/ILSpy.Tests/Bookmarks/BookmarkGutterTests.cs index d73f845bc..64f2dedb6 100644 --- a/ILSpy.Tests/Bookmarks/BookmarkGutterTests.cs +++ b/ILSpy.Tests/Bookmarks/BookmarkGutterTests.cs @@ -57,11 +57,7 @@ public class BookmarkGutterTests await vm.DockWorkspace.WaitForDecompiledTextAsync(); var view = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); window.UpdateLayout(); var margin = view.Editor.TextArea.LeftMargins.OfType().Single(); @@ -107,11 +103,7 @@ public class BookmarkGutterTests await vm.DockWorkspace.WaitForDecompiledTextAsync(); var view = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); window.UpdateLayout(); var margin = view.Editor.TextArea.LeftMargins.OfType().Single(); @@ -150,11 +142,7 @@ public class BookmarkGutterTests await vm.DockWorkspace.WaitForDecompiledTextAsync(); var view = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); window.UpdateLayout(); var margin = view.Editor.TextArea.LeftMargins.OfType().Single(); @@ -231,11 +219,7 @@ public class BookmarkGutterTests vm.AssemblyTreeModel.SelectNode(node); await vm.DockWorkspace.WaitForDecompiledTextAsync(); var shown = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); return shown; } diff --git a/ILSpy.Tests/Bookmarks/BookmarkNavigationViewTests.cs b/ILSpy.Tests/Bookmarks/BookmarkNavigationViewTests.cs index 52e147f18..74dc304ad 100644 --- a/ILSpy.Tests/Bookmarks/BookmarkNavigationViewTests.cs +++ b/ILSpy.Tests/Bookmarks/BookmarkNavigationViewTests.cs @@ -59,11 +59,7 @@ public class BookmarkNavigationViewTests await vm.DockWorkspace.WaitForDecompiledTextAsync(); var view = await window.WaitForComponent(); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); int bookmarkLine = Enumerable.Range(1, view.Editor.Document.LineCount) .Where(view.CanToggleBookmarkAtLine) @@ -232,10 +228,6 @@ public class BookmarkNavigationViewTests static async Task PumpLayoutAsync() { - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); } } diff --git a/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs b/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs index 1072bb5a9..dd2cbaa50 100644 --- a/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs +++ b/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs @@ -181,12 +181,7 @@ public class DecompileInNewViewTests vm.AssemblyTreeModel.SelectNode(nodeA); // Let the top-level rows realise and layout settle. - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); var rowB = grid.GetVisualDescendants().OfType() .FirstOrDefault(r => RowNodeEquals(r, nodeB)); @@ -200,16 +195,9 @@ public class DecompileInNewViewTests // Right-click the centre of B's row (clear of the far-left expander glyph). Tree rows // stretch to content width, so clamp X to the visible grid viewport. - var clickX = System.Math.Min(rowB!.Bounds.Width, grid.Bounds.Width) / 2; - var point = rowB.TranslatePoint(new Point(clickX, rowB.Bounds.Height / 2), window); - point.Should().NotBeNull(); - HeadlessWindowExtensions.MouseDown(window, point!.Value, MouseButton.Right); - HeadlessWindowExtensions.MouseUp(window, point.Value, MouseButton.Right); - for (int i = 0; i < 4; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(20); - } + await window.ClickAsync(() => rowB, MouseButton.Right, + pointInTarget: r => new Point(System.Math.Min(r.Bounds.Width, grid.Bounds.Width) / 2, r.Bounds.Height / 2)); + await Waiters.WaitForIdleAsync(); ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, nodeA).Should().BeTrue( "right-clicking an unselected row must not change the selection (Thunderbird-style context target)"); @@ -239,12 +227,7 @@ public class DecompileInNewViewTests var nodeC = assemblies[2]; vm.AssemblyTreeModel.SelectNode(nodeA); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); ICSharpCode.ILSpy.Controls.TreeView.SharpTreeViewItem Row(SharpTreeNode node) => grid.GetVisualDescendants() .OfType() @@ -252,43 +235,16 @@ public class DecompileInNewViewTests var menu = grid.ContextMenu!; - Point? ClickPoint(SharpTreeNode node) - { - var row = grid.GetVisualDescendants() - .OfType() - .FirstOrDefault(r => RowNodeEquals(r, node)); - if (row == null) - return null; - var clickX = System.Math.Min(row.Bounds.Width, grid.Bounds.Width) / 2; - return row.TranslatePoint(new Point(clickX, row.Bounds.Height / 2), window); - } - async Task RightClick(SharpTreeNode node) { - // A press only becomes a context request for the row when the hit test at the press - // point answers with that row - the same question OnTreeContextRequested asks - and it - // takes an unknown number of frames for that to hold: a closed popup's light-dismiss - // overlay keeps answering hit tests until the scene is rendered again, and assemblies - // still loading in the background reshuffle the rows, which re-realises containers and - // shifts them. So the row container and the point are resolved afresh on every poll and - // the hit is matched by node, not by container identity. - Point? pt = null; - Visual? lastHit = null; - try - { - await Waiters.WaitForAsync( - () => (pt = ClickPoint(node)) is { } p - && (lastHit = window.InputHitTest(p) as Visual) is { } hit - && hit.FindAncestorOfType(includeSelf: true) is { } hitRow - && RowNodeEquals(hitRow, node), - description: "the row to answer hit tests at the point about to be right-clicked"); - } - catch (System.TimeoutException ex) - { - throw new System.TimeoutException($"{ex.Message} (point: {pt?.ToString() ?? "row not realised"}, hit: {lastHit?.GetType().Name ?? "nothing"})", ex); - } - HeadlessWindowExtensions.MouseDown(window, pt!.Value, MouseButton.Right); - HeadlessWindowExtensions.MouseUp(window, pt.Value, MouseButton.Right); + // Tree rows stretch to content width, so clamp X to the visible grid viewport. + await window.ClickAsync( + () => grid.GetVisualDescendants() + .OfType() + .FirstOrDefault(r => RowNodeEquals(r, node)), + MouseButton.Right, + pointInTarget: row => new Point(System.Math.Min(row.Bounds.Width, grid.Bounds.Width) / 2, row.Bounds.Height / 2), + description: $"the row for {node}"); // The highlight is scoped to the popup - set while the menu is being requested, dropped // again when it closes - so the popup is the point at which the gesture is finished and // the row's classes are worth reading. @@ -328,27 +284,15 @@ public class DecompileInNewViewTests var nodeA = vm.AssemblyTreeModel.FindNode("System.Linq"); var nodeB = vm.AssemblyTreeModel.FindNode(TreeNavigation.CoreLibName); vm.AssemblyTreeModel.SelectNode(nodeA); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); var rowB = grid.GetVisualDescendants().OfType() .First(r => RowNodeEquals(r, nodeB)); int tabsBefore = vm.DockWorkspace.Documents!.VisibleDockables!.OfType().Count(); - var clickX = System.Math.Min(rowB.Bounds.Width, grid.Bounds.Width) / 2; - var point = rowB.TranslatePoint(new Point(clickX, rowB.Bounds.Height / 2), window)!.Value; - HeadlessWindowExtensions.MouseDown(window, point, MouseButton.Middle); - HeadlessWindowExtensions.MouseUp(window, point, MouseButton.Middle); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(20); - } + await window.ClickAsync(() => rowB, MouseButton.Middle, + pointInTarget: r => new Point(System.Math.Min(r.Bounds.Width, grid.Bounds.Width) / 2, r.Bounds.Height / 2)); + await Waiters.WaitForIdleAsync(); vm.DockWorkspace.Documents!.VisibleDockables!.OfType().Count() .Should().BeGreaterThan(tabsBefore, "middle-clicking a row must open it in a new document tab"); @@ -376,23 +320,13 @@ public class DecompileInNewViewTests vm.AssemblyTreeModel.SelectNode(nodeA); await vm.DockWorkspace.WaitForDecompiledTextAsync(); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); var registry = AppComposition.Current.GetExport(); var menu = pane.BuildContextMenuForCurrentState(registry.Entries, rightClickedNode: nodeB); menu!.ClickItem(Resources.DecompileToNewPanel); await vm.DockWorkspace.WaitForDecompiledTextAsync(); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); // The model selection follows the new active tab... ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, nodeB).Should().BeTrue( @@ -428,12 +362,7 @@ public class DecompileInNewViewTests vm.AssemblyTreeModel.SelectedItems.Add(nodeA); vm.AssemblyTreeModel.SelectedItems.Add(nodeB); await vm.DockWorkspace.WaitForDecompiledTextAsync(); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); vm.AssemblyTreeModel.SelectedItems.Count.Should().Be(2, "precondition: a multi-selection is held"); // Open C in a new tab -> activates it -> the tree must follow to C. @@ -441,12 +370,7 @@ public class DecompileInNewViewTests var menu = pane.BuildContextMenuForCurrentState(registry.Entries, rightClickedNode: nodeC); menu!.ClickItem(Resources.DecompileToNewPanel); await vm.DockWorkspace.WaitForDecompiledTextAsync(); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); ReferenceEquals(vm.AssemblyTreeModel.SelectedItem, nodeC).Should().BeTrue( "the tree model selection must follow the newly-activated single-node tab"); @@ -494,12 +418,7 @@ public class DecompileInNewViewTests // 3) Re-activate the multi-node tab. vm.DockWorkspace.Factory.SetActiveDockable(multiTab); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); // 4) The tree selection must contain BOTH original nodes again -- in the model... vm.AssemblyTreeModel.SelectedItems.Should().Contain(nodeA) diff --git a/ILSpy.Tests/ContextMenus/KeyboardContextMenuFocusTests.cs b/ILSpy.Tests/ContextMenus/KeyboardContextMenuFocusTests.cs index 87e735994..78f2cd82c 100644 --- a/ILSpy.Tests/ContextMenus/KeyboardContextMenuFocusTests.cs +++ b/ILSpy.Tests/ContextMenus/KeyboardContextMenuFocusTests.cs @@ -60,12 +60,7 @@ public class KeyboardContextMenuFocusTests var node = vm.AssemblyTreeModel.Root!.Children.OfType().First(); vm.AssemblyTreeModel.SelectNode(node); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - grid.UpdateLayout(); - await Task.Delay(25); - } + await Waiters.WaitForIdleAsync(); var row = grid.GetVisualDescendants() .OfType().First(); @@ -77,21 +72,13 @@ public class KeyboardContextMenuFocusTests // Keyboard invocation raises ContextRequested with no pointer position (the Shift+F10 / Apps path). row.RaiseEvent(new ContextRequestedEventArgs()); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); grid.ContextMenu!.IsOpen.Should().BeTrue("the keyboard gesture must open the tree context menu"); row.Classes.Should().Contain("contextTarget", "a keyboard-invoked menu must show the transient target highlight on the selected row, like the mouse path"); window.KeyPress(Key.Escape, RawInputModifiers.None, PhysicalKey.Escape, keySymbol: null); - for (int i = 0; i < 6; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); (focusManager.GetFocusedElement() == row).Should().BeTrue( "closing a keyboard-invoked context menu must return focus to the row, not strand it"); diff --git a/ILSpy.Tests/ContextMenus/ReferenceScopeAndNewTabTests.cs b/ILSpy.Tests/ContextMenus/ReferenceScopeAndNewTabTests.cs index cc571ad23..51eb162b3 100644 --- a/ILSpy.Tests/ContextMenus/ReferenceScopeAndNewTabTests.cs +++ b/ILSpy.Tests/ContextMenus/ReferenceScopeAndNewTabTests.cs @@ -64,11 +64,7 @@ public class ReferenceScopeAndNewTabTests int before = vm.DockWorkspace.Documents!.VisibleDockables!.OfType().Count(); entry.Execute(RefContext(entity)); - for (int i = 0; i < 8; i++) - { - Dispatcher.UIThread.RunJobs(); - await Task.Delay(20); - } + await Waiters.WaitForIdleAsync(); vm.DockWorkspace.Documents!.VisibleDockables!.OfType().Count() .Should().BeGreaterThan(before, "Decompile to new tab on a code reference must open a new document tab"); diff --git a/ILSpy.Tests/Controls/OmnibarSettingTests.cs b/ILSpy.Tests/Controls/OmnibarSettingTests.cs index 61c8d9d67..1c7601393 100644 --- a/ILSpy.Tests/Controls/OmnibarSettingTests.cs +++ b/ILSpy.Tests/Controls/OmnibarSettingTests.cs @@ -51,17 +51,11 @@ public class OmnibarSettingTests "System.Linq", "System.Linq", "System.Linq.Enumerable"); vm.AssemblyTreeModel.SelectedItem = typeNode; Omnibar? omnibar = null; - for (int i = 0; i < 200; i++) - { - Dispatcher.UIThread.RunJobs(); - omnibar = window.GetVisualDescendants().OfType() + await Waiters.WaitForAsync(() => (omnibar = window.GetVisualDescendants().OfType() .Where(v => v.IsEffectivelyVisible) .SelectMany(v => v.GetVisualDescendants().OfType()) - .FirstOrDefault(); - if (omnibar != null) - break; - await Task.Delay(20); - } + .FirstOrDefault()) != null, + description: "a visible decompiler text view hosting the omnibar"); Assert.That(omnibar, Is.Not.Null, "selecting a node realizes a decompiler text view hosting the omnibar"); Assert.That(omnibar!.IsVisible, Is.False, diff --git a/ILSpy.Tests/Docking/DocumentTabStripModeTests.cs b/ILSpy.Tests/Docking/DocumentTabStripModeTests.cs index cf2b52792..72db830cb 100644 --- a/ILSpy.Tests/Docking/DocumentTabStripModeTests.cs +++ b/ILSpy.Tests/Docking/DocumentTabStripModeTests.cs @@ -65,15 +65,7 @@ public class DocumentTabStripModeTests return (window, strip); } - static async Task Pump(MainWindow window) - { - for (int i = 0; i < 12; i++) - { - Dispatcher.UIThread.RunJobs(); - window.UpdateLayout(); - await Task.Delay(20); - } - } + static Task Pump(MainWindow window) => Waiters.WaitForIdleAsync(); static Button? Dropdown(DocumentTabStrip strip) => strip.GetVisualDescendants().OfType