From 170aea44083227bf79b58625412199978f44ad7f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 29 Aug 2026 19:11:40 +0200 Subject: [PATCH] Wait for the click target instead of counting frames Right_Clicking_A_Second_Row_Moves_The_Context_Highlight_To_It timed out on the Windows CI agent waiting for the second context menu to open. A closed popup's light-dismiss overlay keeps answering hit tests until the scene is rendered again, and a press that lands on it raises no ContextRequested at all, so the menu never opens. The test pumped a fixed four frames after dismissing the first menu to get past that, which is a guess about how long the overlay survives: enough on a fast machine, not on a loaded agent. Hit testing the point is the same question the context-request handler asks, so waiting for it to reach the row is the actual precondition for the click, whatever number of frames that takes. The failure could not be reproduced locally - removing the frames entirely still passes here - so this fixes the documented mechanism rather than a reproduction, and a timeout now reports which of the two conditions was not met. Assisted-by: Claude:claude-opus-5[1m]:Claude Code --- .../ContextMenus/DecompileInNewViewTests.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs b/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs index d1ca446d8..562c3f1f8 100644 --- a/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs +++ b/ILSpy.Tests/ContextMenus/DecompileInNewViewTests.cs @@ -257,6 +257,15 @@ public class DecompileInNewViewTests var row = Row(node); var clickX = System.Math.Min(row.Bounds.Width, grid.Bounds.Width) / 2; var pt = row.TranslatePoint(new Point(clickX, row.Bounds.Height / 2), window); + // A popup's light-dismiss overlay keeps answering hit tests for as long as the frame + // that still shows it, and it swallows a press without raising ContextRequested - so + // nothing becomes the context target. Hit testing the point is the same question the + // context-request handler asks, so waiting for it to reach the row is exactly the + // precondition for this click, however many frames the overlay takes to disappear. + await Waiters.WaitForAsync( + () => window.InputHitTest(pt!.Value) is Visual hit + && ReferenceEquals(hit.FindAncestorOfType(includeSelf: true), row), + description: "the row to answer hit tests at the point about to be right-clicked"); HeadlessWindowExtensions.MouseDown(window, pt!.Value, MouseButton.Right); HeadlessWindowExtensions.MouseUp(window, pt.Value, MouseButton.Right); // The highlight is scoped to the popup - set while the menu is being requested, dropped @@ -269,13 +278,6 @@ public class DecompileInNewViewTests { window.KeyPress(Key.Escape, RawInputModifiers.None, PhysicalKey.Escape, keySymbol: null); await Waiters.WaitForAsync(() => !menu.IsOpen, description: "the context menu to close"); - // IsOpen flips the moment the popup is torn down, but the frame that still shows its - // light-dismiss overlay is what answers hit tests until the scene is rendered again. - // Right-clicking into that frame delivers press and release to the vanishing overlay - // instead of the row: no ContextRequested is raised at all, so nothing becomes the - // context target and the next assertion sees a row with no classes on it. - for (int i = 0; i < 4; i++) - Waiters.PumpUI(); } await RightClick(nodeB);