Tests: functional profile round-trip through the real main-window controls
Local checkpoint - NOT for public release. Toward Ed's "every control and every function tested" goal: a new self-test applies a profile to the ACTUAL main-window controls (via an internal ApplyThenCaptureForTest seam on the headless form) and reads it straight back, asserting every persisted value survived - volume, mute, send/receive toggles, peer-shaping master, send mode, send-all- applications, and the selected applications. This exercises each control's load AND save logic, not just that it exists (which the accessibility audit already covers). The apply path pops the "set a password to stream" dialog when enabling send with no password (would hang a headless test); the seam sets the existing suppressStreamingPasswordGate around the apply, same gate the app uses internally. Gate 25/25. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
499e9644d7
commit
a52f08c188
@@ -8172,6 +8172,21 @@ public sealed class MainForm : Form
|
|||||||
return profile;
|
return profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Test-only: push a profile INTO the real controls and read it straight back OUT, so a
|
||||||
|
/// self-test can prove every persisted control both loads and saves correctly. Headless forms only
|
||||||
|
/// (a real form would try to reconnect peers etc.); pass a profile with no peers.</summary>
|
||||||
|
internal Profile ApplyThenCaptureForTest(Profile input)
|
||||||
|
{
|
||||||
|
pendingProfile = input;
|
||||||
|
settings.ApplyProfile(input);
|
||||||
|
// Suppress the interactive "set a password to stream" gate that a real user apply would show —
|
||||||
|
// it would pop a modal dialog and hang the headless test. We only care about control round-trip.
|
||||||
|
suppressStreamingPasswordGate = true;
|
||||||
|
try { ApplyPendingProfileToControls(); }
|
||||||
|
finally { suppressStreamingPasswordGate = false; }
|
||||||
|
return BuildCurrentProfile(input.Title);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>Common save body — gathers all current state into a Profile and writes it.
|
/// <summary>Common save body — gathers all current state into a Profile and writes it.
|
||||||
/// On success, becomes the active profile (sets currentProfileTitle, updates window
|
/// On success, becomes the active profile (sets currentProfileTitle, updates window
|
||||||
/// title, refreshes button visibility, and shows a confirmation popup).</summary>
|
/// title, refreshes button visibility, and shows a confirmation popup).</summary>
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ internal static class SelfTest
|
|||||||
RunStep(results, "Bundled resources present", ResourcesPresent);
|
RunStep(results, "Bundled resources present", ResourcesPresent);
|
||||||
RunStep(results, "Dialog accessibility (names + mnemonics)", AccessibilityAudit);
|
RunStep(results, "Dialog accessibility (names + mnemonics)", AccessibilityAudit);
|
||||||
RunStep(results, "Main window coverage (all tabs + controls)", MainWindowCoverage);
|
RunStep(results, "Main window coverage (all tabs + controls)", MainWindowCoverage);
|
||||||
|
RunStep(results, "Main window profile round-trip (controls load + save)", MainWindowProfileRoundTrip);
|
||||||
|
|
||||||
var failed = results.Count(r => r.Status == "FAIL");
|
var failed = results.Count(r => r.Status == "FAIL");
|
||||||
var skipped = results.Count(r => r.Status == "SKIP");
|
var skipped = results.Count(r => r.Status == "SKIP");
|
||||||
@@ -1050,6 +1051,53 @@ internal static class SelfTest
|
|||||||
finally { try { form.Dispose(); } catch { /* ignore */ } }
|
finally { try { form.Dispose(); } catch { /* ignore */ } }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Functional round-trip through the REAL main-window controls: apply a profile to the
|
||||||
|
/// controls, read it back, and assert every persisted value survived — proving each control's load
|
||||||
|
/// AND save logic, not just that it exists. Uses the headless form with no peers (so nothing tries
|
||||||
|
/// to connect). Device ticks need real hardware ids so they're covered by the profile-store
|
||||||
|
/// round-trip test instead; this covers the hardware-independent controls.</summary>
|
||||||
|
private static string? MainWindowProfileRoundTrip()
|
||||||
|
{
|
||||||
|
MainForm mf;
|
||||||
|
try { mf = new MainForm(null, RemSound.Core.Profile.NewBlank(), null, null, headless: true); }
|
||||||
|
catch (Exception ex) { return Skip($"headless MainForm could not be constructed: {ex.GetType().Name}: {ex.Message}"); }
|
||||||
|
|
||||||
|
using (mf)
|
||||||
|
{
|
||||||
|
var input = new Profile
|
||||||
|
{
|
||||||
|
Title = "roundtrip",
|
||||||
|
Volume = 42,
|
||||||
|
Muted = true,
|
||||||
|
ReceiveAudioOn = true,
|
||||||
|
SendAudioOn = true,
|
||||||
|
EnableAllPeerShaping = true,
|
||||||
|
WasapiSendMode = "applications",
|
||||||
|
SendAllApplications = false,
|
||||||
|
};
|
||||||
|
input.SelectedSendApplications.Add("vlc");
|
||||||
|
input.SelectedSendApplications.Add("firefox");
|
||||||
|
|
||||||
|
var back = mf.ApplyThenCaptureForTest(input);
|
||||||
|
|
||||||
|
Check(back.Volume == 42, $"volume must round-trip through the controls (got {back.Volume})");
|
||||||
|
Check(back.Muted, "mute must round-trip through the controls");
|
||||||
|
Check(back.ReceiveAudioOn && back.SendAudioOn, "send/receive toggles must round-trip");
|
||||||
|
Check(back.EnableAllPeerShaping, "the peer-shaping master switch must round-trip");
|
||||||
|
|
||||||
|
var covered = "volume, mute, send/receive, shaping";
|
||||||
|
if (RemSound.Sender.ProcessLoopbackCapture.IsSupported)
|
||||||
|
{
|
||||||
|
Check(back.WasapiSendMode == "applications", $"send mode must round-trip (got {back.WasapiSendMode})");
|
||||||
|
Check(!back.SendAllApplications, "the send-all-applications toggle must round-trip");
|
||||||
|
Check(back.SelectedSendApplications.Contains("vlc") && back.SelectedSendApplications.Contains("firefox"),
|
||||||
|
"the selected applications must round-trip through the app list");
|
||||||
|
covered += ", send-mode, apps";
|
||||||
|
}
|
||||||
|
return $"round-tripped through the real controls: {covered}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static int CountControls(Control root, Func<Control, bool> predicate)
|
private static int CountControls(Control root, Func<Control, bool> predicate)
|
||||||
{
|
{
|
||||||
var n = 0;
|
var n = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user