diff --git a/src/WrapTuneMacOS/MainWindow.axaml.cs b/src/WrapTuneMacOS/MainWindow.axaml.cs index b3681cd..140918a 100644 --- a/src/WrapTuneMacOS/MainWindow.axaml.cs +++ b/src/WrapTuneMacOS/MainWindow.axaml.cs @@ -52,6 +52,7 @@ public MainWindow() ApplyTheme(_theme); WireDragDrop(); WireDerivedFields(); + WireSigningRefresh(); UpdateSigningUi(); UpdateFlowUi(); Opened += (_, _) => StartLaunchUpdateCheck(); @@ -382,6 +383,22 @@ private void WireDerivedFields() TxtOutputFolder.TextChanged += (_, _) => OnPathsChanged(); } + /// Every input reads refreshes the + /// footer as it changes; no debounce — these checks are cheap and local, + /// unlike the path fields' folder-walk. + private void WireSigningRefresh() + { + TextBox[] validated = + [ + TxtPfxPath, TxtSecret, + TxtPkcs11Module, + TxtTsEndpoint, TxtTsAccount, TxtTsProfile, TxtTsToken, + ]; + foreach (var box in validated) + box.TextChanged += (_, _) => UpdateFlowUi(); + ChkSignAllFiles.IsCheckedChanged += (_, _) => UpdateFlowUi(); + } + private void OnPathsChanged() { UpdateFlowUi(); diff --git a/tests/WrapTuneMacOS.App.Tests/SigningRefreshTests.cs b/tests/WrapTuneMacOS.App.Tests/SigningRefreshTests.cs new file mode 100644 index 0000000..a804680 --- /dev/null +++ b/tests/WrapTuneMacOS.App.Tests/SigningRefreshTests.cs @@ -0,0 +1,99 @@ +using Avalonia.Controls; +using Avalonia.Headless.XUnit; +using Avalonia.Threading; + +namespace WrapTuneMacOS.UiTests; + +/// +/// Editing a signing input must refresh the footer validation and the Package +/// button immediately. Before the fix, only the three path fields re-ran +/// UpdateFlowUi, so typing the PFX password left the red "password is required" +/// footer and a disabled Package button until an unrelated event (e.g. flipping +/// the Sign toggle) forced a refresh. +/// +public sealed class SigningRefreshTests : IDisposable +{ + private readonly string _root; + + public SigningRefreshTests() + { + _root = Path.Combine(Path.GetTempPath(), "wraptune-signrefresh-" + Guid.NewGuid().ToString("N")); + // Two source folders so each test's setup file is unambiguous for the + // derived-info auto-detection (which prefers other extensions over .cmd). + Directory.CreateDirectory(Path.Combine(_root, "src-ps1")); + Directory.CreateDirectory(Path.Combine(_root, "src-cmd")); + Directory.CreateDirectory(Path.Combine(_root, "out")); + File.WriteAllText(Path.Combine(_root, "src-ps1", "setup.ps1"), "Write-Host hi"); + File.WriteAllText(Path.Combine(_root, "src-cmd", "setup.cmd"), "@echo off"); + // Signing validation only checks the .pfx exists; content is never read. + File.WriteAllBytes(Path.Combine(_root, "cert.pfx"), [1, 2, 3]); + AppSettings.BaseDirOverride = _root; + new AppSettings().Save(); + } + + [AvaloniaFact] + public void Typing_the_pfx_password_immediately_arms_package() + { + var w = NewStagedWindow("src-ps1", "setup.ps1"); + + w.FindControl("ChkSignPayload")!.IsChecked = true; + w.FindControl("TxtPfxPath")!.Text = Path.Combine(_root, "cert.pfx"); + Pump(); + Assert.False(w.FindControl