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);
}
}