From 91aef95b1b6f7fe66cfb1fbd59d0f67272b3b990 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 6 Oct 2026 16:52:52 -0400 Subject: [PATCH] fix(tests): acknowledge native BOM dialog without assuming button id Fix DuplicateRows_CreateNestsButtonImportsOneDrawingWithCombinedQuantity timeout from Windows run 37526243901. Native trace on DesktopPC showed the sole OK button uses control ID 2, not IDOK 1. Preserve real dialog text and nest assertions; find the sole button and stop polling only after successful posting. All 392 WinForms and 49 FrontEnd tests pass in an interactive Windows session. --- .../Forms/BomImportFormTests.cs | 19 ++++++++++++------- docs/windows-acceptance.md | 9 +++++++-- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/OpenNest.WinForms.Tests/Forms/BomImportFormTests.cs b/OpenNest.WinForms.Tests/Forms/BomImportFormTests.cs index 6a7b71c..b1817b4 100644 --- a/OpenNest.WinForms.Tests/Forms/BomImportFormTests.cs +++ b/OpenNest.WinForms.Tests/Forms/BomImportFormTests.cs @@ -117,7 +117,15 @@ public class BomImportFormTests if (className.ToString() != "#32770") return true; + // An OK-only native MessageBox can assign its button the + // IDCANCEL id (2), not IDOK (1). Find its sole real button + // instead of assuming an id, and keep polling until ready. + var ok = FindWindowEx(window, IntPtr.Zero, "Button", null); + if (ok == IntPtr.Zero || FindWindowEx(window, ok, "Button", null) != IntPtr.Zero) + return true; + dialogTitle = WindowText(window); + dialogText = ""; var text = FindWindowEx(window, IntPtr.Zero, "Static", null); while (text != IntPtr.Zero) { @@ -126,10 +134,10 @@ public class BomImportFormTests dialogText += value; text = FindWindowEx(window, text, "Static", null); } - var ok = GetDlgItem(window, 1); - okPosted = ok != IntPtr.Zero && PostMessage(ok, 0x00F5, IntPtr.Zero, IntPtr.Zero); - dismiss.Stop(); - return false; + okPosted = PostMessage(ok, 0x00F5, IntPtr.Zero, IntPtr.Zero); + if (okPosted) + dismiss.Stop(); + return !okPosted; }, IntPtr.Zero); if (DateTime.UtcNow >= deadline && !okPosted) throw new TimeoutException("The Create Nests result dialog could not be acknowledged."); @@ -199,9 +207,6 @@ public class BomImportFormTests [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr FindWindowEx(IntPtr parent, IntPtr after, string className, string? title); - [DllImport("user32.dll")] - private static extern IntPtr GetDlgItem(IntPtr dialog, int id); - [DllImport("user32.dll", CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool PostMessage(IntPtr window, uint message, IntPtr wParam, IntPtr lParam); diff --git a/docs/windows-acceptance.md b/docs/windows-acceptance.md index 7379406..a6016d3 100644 --- a/docs/windows-acceptance.md +++ b/docs/windows-acceptance.md @@ -51,8 +51,13 @@ run when updating an individual task. ## Repeat locally on Windows Use a clean, committed checkout, .NET 8 and Python 3. Run from the repository root -in PowerShell. Always use a new results directory so stale TRX files cannot stand -in for a failed build. Do not reuse downloaded CI results as a new local run. +in PowerShell in a logged-in Windows desktop session: an OpenSSH/service session +(session 0) cannot show the real native completion dialogs these tests exercise. +A remote interactive-session launch should use an explicitly approved temporary +scheduled task, without saved passwords, and remove that task after completion. +Test windows may appear briefly; do not manually acknowledge them during a run. +Always use a new results directory so stale TRX files cannot stand in for a failed +build. Do not reuse downloaded CI results as a new local run. ```powershell $results = Join-Path 'TestResults' ([guid]::NewGuid().ToString())