using FluentAssertions; using IBKRTrader.Core.Capital; using IBKRTrader.Core.Modularity; using IBKRTrader.Modules.Accounting; using IBKRTrader.Modules.CongressTrading; using IBKRTrader.Modules.OptionsWheel; using IBKRTrader.Modules.Supervisor; namespace IBKRTrader.Tests.Modules.OptionsWheel; /// /// Der Modulvertrag des OptionsWheels und die Buchzuordnung. /// [Trait("cat", "unit")] public class OptionsWheelModuleTests { private static IModule[] AllModules() => [ new CongressTradingModule(), new OptionsWheelModule(), new AccountingModule(), new SupervisorModule() ]; private static string BookNameOf(IModule m) => m.DbPrefix.TrimEnd('_').ToUpperInvariant(); [Fact] public void Module_UsesItsOwnTablePrefix() { var module = new OptionsWheelModule(); module.Name.Should().Be("OptionsWheel"); module.DbPrefix.Should().Be("ow_"); } [Fact] public void Module_CarriesNoUiCode() { // RegisterUi bleibt leer, sonst muesste das Modul Avalonia referenzieren und waere nicht // mehr kopflos lauffaehig. Das Fenster registriert die Shell zentral. var act = () => new OptionsWheelModule().RegisterUi(null!, null!); act.Should().NotThrow(); } [Fact] public void Module_NamesItsMissingPrerequisites_InsteadOfSilentlyDoingNothing() { // Der Handelsbetrieb haengt an #299 und #294. Ein aktiviertes Modul, das nichts tut und // nicht sagt warum, kostet den Betreiber eine Stunde Fehlersuche. var blocker = new OptionsWheelModule().GetActivationBlocker(null!); blocker.Should().NotBeNull(); blocker.Should().Contain("#299").And.Contain("#294"); } [Fact] public void EveryModuleMapsToItsOwnBook() { // Zwei Module, die auf denselben Buchnamen fallen, teilten sich unbemerkt ein Cap und eine // Buchfuehrung. var names = AllModules().Select(BookNameOf).ToList(); names.Should().OnlyHaveUniqueItems(); names.Should().Contain("OW"); } [Fact] public void NoModuleClaimsAReservedBookName() { foreach (var name in AllModules().Select(BookNameOf)) BookId.IsReserved(name).Should().BeFalse($"'{name}' darf kein reservierter Name sein"); } [Fact] public void TheDiagnosticsBookIsSeparateFromEveryModule() { // Eine Prueforder darf nicht in der Buchfuehrung eines Strategiemoduls landen: sie // verfaelschte dessen Auslastung und dessen GuV, und zwar dauerhaft. AllModules().Select(BookNameOf).Should().NotContain(BookId.Diagnostics.Value); } }