@
R1: Umbau auf Multi-Projekt-Struktur (Vorbild PolytraderSharp) Kurskorrektur: Vorbild ist PolytraderSharp (C#), nicht die veraltete Python-Version. Reiner Strukturumbau, Verhalten unveraendert. - src/IBKRTrader.Core (classlib): Core-Code + UI-Contract (ModuleFormBase, WindowManager) - src/IBKRTrader.Modules.CongressTrading (classlib, referenziert nur Core) - Root: IBKRTrader.App (WinExe) referenziert Core + Modul - tests/IBKRTrader.Tests: Referenzen auf Core + Modul - Neue .slnx; ungenutztes HtmlAgilityPack entfernt - docs/ARCHITECTURE.md: korrigierter Ziel-Stand + R-Phasenplan - Build + 38/38 Tests gruen; App startet Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
using FluentAssertions;
|
||||
using IBKRTrader.UI;
|
||||
|
||||
namespace IBKRTrader.Tests.UI;
|
||||
|
||||
[Trait("cat", "unit")]
|
||||
public class WindowManagerTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Testbare Variante: unterdrückt echte Show-/Focus-Aufrufe (kein Message-Loop),
|
||||
/// zählt aber die Focus-Aufrufe.
|
||||
/// </summary>
|
||||
private sealed class TestWindowManager : WindowManager
|
||||
{
|
||||
public int FocusCount;
|
||||
protected override void Present(Form form) { /* kein Show im Test */ }
|
||||
protected override void Focus(Form form) => FocusCount++;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OpenOrFocus_NewKey_InvokesFactory_AndTracks()
|
||||
{
|
||||
var wm = new TestWindowManager();
|
||||
var created = 0;
|
||||
|
||||
using var form = wm.OpenOrFocus("CT", () => { created++; return new Form(); });
|
||||
|
||||
created.Should().Be(1);
|
||||
wm.IsOpen("CT").Should().BeTrue();
|
||||
wm.OpenCount.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OpenOrFocus_SameKey_FocusesExisting_DoesNotRecreate()
|
||||
{
|
||||
var wm = new TestWindowManager();
|
||||
var created = 0;
|
||||
|
||||
using var first = wm.OpenOrFocus("CT", () => { created++; return new Form(); });
|
||||
var second = wm.OpenOrFocus("CT", () => { created++; return new Form(); });
|
||||
|
||||
created.Should().Be(1);
|
||||
wm.FocusCount.Should().Be(1);
|
||||
second.Should().BeSameAs(first);
|
||||
wm.OpenCount.Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OpenOrFocus_DifferentKeys_TracksSeparately()
|
||||
{
|
||||
var wm = new TestWindowManager();
|
||||
|
||||
using var a = wm.OpenOrFocus("A", () => new Form());
|
||||
using var b = wm.OpenOrFocus("B", () => new Form());
|
||||
|
||||
wm.OpenCount.Should().Be(2);
|
||||
wm.IsOpen("A").Should().BeTrue();
|
||||
wm.IsOpen("B").Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OpenOrFocus_AfterDisposed_RecreatesWindow()
|
||||
{
|
||||
var wm = new TestWindowManager();
|
||||
var created = 0;
|
||||
|
||||
var first = wm.OpenOrFocus("CT", () => { created++; return new Form(); });
|
||||
first.Dispose();
|
||||
|
||||
wm.IsOpen("CT").Should().BeFalse();
|
||||
|
||||
using var second = wm.OpenOrFocus("CT", () => { created++; return new Form(); });
|
||||
|
||||
created.Should().Be(2);
|
||||
second.Should().NotBeSameAs(first);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CloseAll_RemovesAllWindows()
|
||||
{
|
||||
var wm = new TestWindowManager();
|
||||
wm.OpenOrFocus("A", () => new Form());
|
||||
wm.OpenOrFocus("B", () => new Form());
|
||||
|
||||
wm.CloseAll();
|
||||
|
||||
wm.OpenCount.Should().Be(0);
|
||||
wm.IsOpen("A").Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OpenOrFocus_BlankKey_Throws()
|
||||
{
|
||||
var wm = new TestWindowManager();
|
||||
|
||||
var act = () => wm.OpenOrFocus(" ", () => new Form());
|
||||
|
||||
act.Should().Throw<ArgumentException>();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user