using FluentAssertions; using Marathon.Application.UseCases; using Marathon.Domain.Backtesting; using Marathon.Domain.ValueObjects; using Marathon.UI.Services; namespace Marathon.UI.Tests.Services; /// /// Tests the pure projection — per-row hit /// rate and the single best-by-ROI flag — without the (sealed) use case. /// public sealed class StrategyComparisonServiceTests { private static BacktestResult Result(int bets, int wins, int losses, decimal net, decimal? roi, decimal maxDd = 0m) => new( StartingBankroll: 1000m, FinalBankroll: 1000m + net, NetProfit: net, RoiPercent: roi, TotalStaked: 0m, TotalReturned: 0m, MaxDrawdown: maxDd, MaxDrawdownPercent: null, BetsPlaced: bets, Wins: wins, Losses: losses, Skipped: 0, SkippedByThreshold: 0, SkippedByDataQuality: 0, SkippedByBankroll: 0, MaxWinStreak: 0, MaxLossStreak: 0, Trace: Array.Empty(), EventTitles: new Dictionary()); private static StrategyComparison Comp(string name, BacktestResult result) => new(Guid.NewGuid(), name, result); [Fact] public void BuildVm_Empty_When_NoComparisons() { StrategyComparisonService.BuildVm(Array.Empty()) .Should().Be(StrategyComparisonVm.Empty); } [Fact] public void BuildVm_MarksHighestRoiBest_AndComputesHitRate() { var comps = new[] { Comp("Flat", Result(bets: 10, wins: 6, losses: 4, net: 20m, roi: 5m)), Comp("Kelly", Result(bets: 10, wins: 7, losses: 3, net: 50m, roi: 12m)), Comp("Percent", Result(bets: 10, wins: 5, losses: 5, net: -10m, roi: -3m)), }; var vm = StrategyComparisonService.BuildVm(comps); vm.Rows.Should().HaveCount(3); vm.Rows.Count(r => r.IsBest).Should().Be(1); vm.Rows.Single(r => r.IsBest).Name.Should().Be("Kelly"); vm.Rows.Single(r => r.Name == "Flat").HitRatePercent.Should().Be(60m); // 6/10 } [Fact] public void BuildVm_NoBetsPreset_NotBest_AndNullHitRate() { var vm = StrategyComparisonService.BuildVm(new[] { Comp("Idle", Result(bets: 0, wins: 0, losses: 0, net: 0m, roi: null)), }); vm.Rows.Should().ContainSingle(); vm.Rows[0].IsBest.Should().BeFalse(); vm.Rows[0].HitRatePercent.Should().BeNull(); } [Fact] public void BuildVm_Ties_ProduceSingleBest() { var comps = new[] { Comp("A", Result(10, 6, 4, 20m, 5m)), Comp("B", Result(10, 6, 4, 20m, 5m)), }; StrategyComparisonService.BuildVm(comps).Rows.Count(r => r.IsBest).Should().Be(1); } }