Initial Commit
This commit is contained in:
214
tests/SportsDivision.Application.Tests/HeatAdvancementTests.cs
Normal file
214
tests/SportsDivision.Application.Tests/HeatAdvancementTests.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using Moq;
|
||||
using SportsDivision.Application.Services;
|
||||
using SportsDivision.Domain.Entities;
|
||||
using SportsDivision.Domain.Enums;
|
||||
using SportsDivision.Domain.Interfaces;
|
||||
|
||||
namespace SportsDivision.Application.Tests;
|
||||
|
||||
public class HeatAdvancementTests
|
||||
{
|
||||
private readonly Mock<IUnitOfWork> _mockUow;
|
||||
private readonly HeatManagementService _service;
|
||||
|
||||
public HeatAdvancementTests()
|
||||
{
|
||||
_mockUow = new Mock<IUnitOfWork>();
|
||||
_service = new HeatManagementService(_mockUow.Object, null!);
|
||||
}
|
||||
|
||||
private Round CreateRoundWithHeats(int topN, int fastestLosers, List<Heat> heats)
|
||||
{
|
||||
return new Round
|
||||
{
|
||||
RoundId = 1,
|
||||
TournamentEventLevelId = 1,
|
||||
RoundOrder = 1,
|
||||
AdvanceTopN = topN,
|
||||
AdvanceFastestLosers = fastestLosers,
|
||||
Heats = heats
|
||||
};
|
||||
}
|
||||
|
||||
private Heat CreateHeat(int heatId, int heatNumber, List<HeatLane> lanes)
|
||||
{
|
||||
var heat = new Heat
|
||||
{
|
||||
HeatId = heatId,
|
||||
HeatNumber = heatNumber,
|
||||
Status = HeatStatus.Completed,
|
||||
HeatLanes = lanes
|
||||
};
|
||||
foreach (var lane in lanes)
|
||||
lane.Heat = heat;
|
||||
return heat;
|
||||
}
|
||||
|
||||
private HeatLane CreateLane(int laneId, int regId, decimal? time, bool isDNS = false, bool isDNF = false, bool isDQ = false)
|
||||
{
|
||||
return new HeatLane
|
||||
{
|
||||
HeatLaneId = laneId,
|
||||
EventRegistrationId = regId,
|
||||
LaneNumber = laneId,
|
||||
Time = time,
|
||||
IsDNS = isDNS,
|
||||
IsDNF = isDNF,
|
||||
IsDQ = isDQ,
|
||||
IsAdvanced = false
|
||||
};
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CalculateAdvancement_TopNFromEachHeat()
|
||||
{
|
||||
var heat1 = CreateHeat(1, 1, new List<HeatLane>
|
||||
{
|
||||
CreateLane(1, 101, 10.5m),
|
||||
CreateLane(2, 102, 10.8m),
|
||||
CreateLane(3, 103, 11.2m),
|
||||
CreateLane(4, 104, 11.5m)
|
||||
});
|
||||
|
||||
var heat2 = CreateHeat(2, 2, new List<HeatLane>
|
||||
{
|
||||
CreateLane(5, 201, 10.6m),
|
||||
CreateLane(6, 202, 10.9m),
|
||||
CreateLane(7, 203, 11.3m),
|
||||
CreateLane(8, 204, 11.6m)
|
||||
});
|
||||
|
||||
var round = CreateRoundWithHeats(topN: 2, fastestLosers: 0, new List<Heat> { heat1, heat2 });
|
||||
|
||||
_mockUow.Setup(u => u.Rounds.GetWithHeatsAsync(1)).ReturnsAsync(round);
|
||||
_mockUow.Setup(u => u.HeatLanes.Update(It.IsAny<HeatLane>()));
|
||||
_mockUow.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
|
||||
|
||||
await _service.CalculateAdvancementAsync(1);
|
||||
|
||||
// Top 2 from heat 1: lanes 1 (10.5) and 2 (10.8)
|
||||
Assert.True(heat1.HeatLanes.ElementAt(0).IsAdvanced);
|
||||
Assert.True(heat1.HeatLanes.ElementAt(1).IsAdvanced);
|
||||
Assert.False(heat1.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
Assert.False(heat1.HeatLanes.ElementAt(3).IsAdvanced);
|
||||
|
||||
// Top 2 from heat 2: lanes 5 (10.6) and 6 (10.9)
|
||||
Assert.True(heat2.HeatLanes.ElementAt(0).IsAdvanced);
|
||||
Assert.True(heat2.HeatLanes.ElementAt(1).IsAdvanced);
|
||||
Assert.False(heat2.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
Assert.False(heat2.HeatLanes.ElementAt(3).IsAdvanced);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CalculateAdvancement_TopNPlusFastestLosers()
|
||||
{
|
||||
var heat1 = CreateHeat(1, 1, new List<HeatLane>
|
||||
{
|
||||
CreateLane(1, 101, 10.5m),
|
||||
CreateLane(2, 102, 10.8m),
|
||||
CreateLane(3, 103, 11.0m), // 3rd in heat 1 → fastest loser candidate
|
||||
CreateLane(4, 104, 11.5m)
|
||||
});
|
||||
|
||||
var heat2 = CreateHeat(2, 2, new List<HeatLane>
|
||||
{
|
||||
CreateLane(5, 201, 10.6m),
|
||||
CreateLane(6, 202, 10.9m),
|
||||
CreateLane(7, 203, 11.1m), // 3rd in heat 2 → fastest loser candidate
|
||||
CreateLane(8, 204, 11.8m)
|
||||
});
|
||||
|
||||
var round = CreateRoundWithHeats(topN: 2, fastestLosers: 2, new List<Heat> { heat1, heat2 });
|
||||
|
||||
_mockUow.Setup(u => u.Rounds.GetWithHeatsAsync(1)).ReturnsAsync(round);
|
||||
_mockUow.Setup(u => u.HeatLanes.Update(It.IsAny<HeatLane>()));
|
||||
_mockUow.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
|
||||
|
||||
await _service.CalculateAdvancementAsync(1);
|
||||
|
||||
// Top 2 from each heat advance as TopN
|
||||
Assert.Equal(AdvanceReason.TopN, heat1.HeatLanes.ElementAt(0).AdvanceReason);
|
||||
Assert.Equal(AdvanceReason.TopN, heat1.HeatLanes.ElementAt(1).AdvanceReason);
|
||||
Assert.Equal(AdvanceReason.TopN, heat2.HeatLanes.ElementAt(0).AdvanceReason);
|
||||
Assert.Equal(AdvanceReason.TopN, heat2.HeatLanes.ElementAt(1).AdvanceReason);
|
||||
|
||||
// Fastest 2 losers: lane 3 (11.0) and lane 7 (11.1)
|
||||
Assert.True(heat1.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
Assert.Equal(AdvanceReason.FastestLoser, heat1.HeatLanes.ElementAt(2).AdvanceReason);
|
||||
Assert.True(heat2.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
Assert.Equal(AdvanceReason.FastestLoser, heat2.HeatLanes.ElementAt(2).AdvanceReason);
|
||||
|
||||
// Last in each heat should NOT advance
|
||||
Assert.False(heat1.HeatLanes.ElementAt(3).IsAdvanced);
|
||||
Assert.False(heat2.HeatLanes.ElementAt(3).IsAdvanced);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CalculateAdvancement_DNSExcluded()
|
||||
{
|
||||
var heat1 = CreateHeat(1, 1, new List<HeatLane>
|
||||
{
|
||||
CreateLane(1, 101, 10.5m),
|
||||
CreateLane(2, 102, null, isDNS: true), // DNS
|
||||
CreateLane(3, 103, 11.0m),
|
||||
});
|
||||
|
||||
var round = CreateRoundWithHeats(topN: 2, fastestLosers: 0, new List<Heat> { heat1 });
|
||||
|
||||
_mockUow.Setup(u => u.Rounds.GetWithHeatsAsync(1)).ReturnsAsync(round);
|
||||
_mockUow.Setup(u => u.HeatLanes.Update(It.IsAny<HeatLane>()));
|
||||
_mockUow.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
|
||||
|
||||
await _service.CalculateAdvancementAsync(1);
|
||||
|
||||
Assert.True(heat1.HeatLanes.ElementAt(0).IsAdvanced);
|
||||
Assert.False(heat1.HeatLanes.ElementAt(1).IsAdvanced); // DNS not advanced
|
||||
Assert.True(heat1.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CalculateAdvancement_DNFExcluded()
|
||||
{
|
||||
var heat1 = CreateHeat(1, 1, new List<HeatLane>
|
||||
{
|
||||
CreateLane(1, 101, 10.5m),
|
||||
CreateLane(2, 102, 10.8m, isDNF: true), // DNF
|
||||
CreateLane(3, 103, 11.0m),
|
||||
});
|
||||
|
||||
var round = CreateRoundWithHeats(topN: 2, fastestLosers: 0, new List<Heat> { heat1 });
|
||||
|
||||
_mockUow.Setup(u => u.Rounds.GetWithHeatsAsync(1)).ReturnsAsync(round);
|
||||
_mockUow.Setup(u => u.HeatLanes.Update(It.IsAny<HeatLane>()));
|
||||
_mockUow.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
|
||||
|
||||
await _service.CalculateAdvancementAsync(1);
|
||||
|
||||
Assert.True(heat1.HeatLanes.ElementAt(0).IsAdvanced);
|
||||
Assert.False(heat1.HeatLanes.ElementAt(1).IsAdvanced); // DNF not advanced
|
||||
Assert.True(heat1.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CalculateAdvancement_DQExcluded()
|
||||
{
|
||||
var heat1 = CreateHeat(1, 1, new List<HeatLane>
|
||||
{
|
||||
CreateLane(1, 101, 10.5m),
|
||||
CreateLane(2, 102, 10.2m, isDQ: true), // DQ - fastest time but disqualified
|
||||
CreateLane(3, 103, 11.0m),
|
||||
});
|
||||
|
||||
var round = CreateRoundWithHeats(topN: 2, fastestLosers: 0, new List<Heat> { heat1 });
|
||||
|
||||
_mockUow.Setup(u => u.Rounds.GetWithHeatsAsync(1)).ReturnsAsync(round);
|
||||
_mockUow.Setup(u => u.HeatLanes.Update(It.IsAny<HeatLane>()));
|
||||
_mockUow.Setup(u => u.SaveChangesAsync()).ReturnsAsync(1);
|
||||
|
||||
await _service.CalculateAdvancementAsync(1);
|
||||
|
||||
Assert.True(heat1.HeatLanes.ElementAt(0).IsAdvanced);
|
||||
Assert.False(heat1.HeatLanes.ElementAt(1).IsAdvanced); // DQ not advanced
|
||||
Assert.True(heat1.HeatLanes.ElementAt(2).IsAdvanced);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user