using Moq; using SportsDivision.Application.Services; using SportsDivision.Domain.Entities; using SportsDivision.Domain.Enums; using SportsDivision.Domain.Interfaces; namespace SportsDivision.Application.Tests; public class RegistrationEligibilityTests { private readonly Mock _mockUow; private readonly RegistrationService _service; public RegistrationEligibilityTests() { _mockUow = new Mock(); _service = new RegistrationService(_mockUow.Object, null!); } private void SetupTournamentEventLevel(TournamentEventLevel tel) { _mockUow.Setup(u => u.TournamentEventLevels.GetWithRegistrationsAsync(It.IsAny())) .ReturnsAsync(tel); } private void SetupStudent(Student student) { _mockUow.Setup(u => u.Students.GetByIdAsync(student.StudentId)) .ReturnsAsync(student); } private void SetupSchool(School school) { _mockUow.Setup(u => u.Schools.GetByIdAsync(school.SchoolId)) .ReturnsAsync(school); } private void SetupNotAlreadyRegistered() { _mockUow.Setup(u => u.EventRegistrations.IsStudentRegisteredAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(false); } private void SetupAlreadyRegistered() { _mockUow.Setup(u => u.EventRegistrations.IsStudentRegisteredAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(true); } private TournamentEventLevel CreateTel(Sex sex = Sex.Male, SchoolLevel schoolLevel = SchoolLevel.Secondary, int? maxAge = null, bool isAgeBased = false, bool ageWaived = false) { return new TournamentEventLevel { TournamentEventLevelId = 1, EventLevel = new EventLevel { Sex = sex, SchoolLevel = schoolLevel, MaxAge = maxAge, IsAgeBased = isAgeBased }, AgeRestrictionWaived = ageWaived, Tournament = new Tournament { StartDate = new DateOnly(2024, 6, 1) }, Registrations = new List() }; } private Student CreateStudent(Sex sex = Sex.Male, int schoolId = 1, DateOnly? dob = null) { return new Student { StudentId = 1, FirstName = "Test", LastName = "Student", Sex = sex, SchoolId = schoolId, DateOfBirth = dob ?? new DateOnly(2010, 1, 1) }; } private School CreateSchool(SchoolLevel level = SchoolLevel.Secondary) { return new School { SchoolId = 1, Name = "Test School", SchoolLevel = level, ZoneId = 1 }; } [Fact] public async Task CheckEligibility_EligibleStudent_ReturnsTrue() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary); var student = CreateStudent(Sex.Male); var school = CreateSchool(SchoolLevel.Secondary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); SetupNotAlreadyRegistered(); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.True(isEligible); Assert.Null(reason); } [Fact] public async Task CheckEligibility_SexMismatch_ReturnsFalse() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary); var student = CreateStudent(Sex.Female); SetupTournamentEventLevel(tel); SetupStudent(student); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.False(isEligible); Assert.Contains("sex", reason!, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task CheckEligibility_SecondaryStudentInPrimaryEvent_ReturnsFalse() { var tel = CreateTel(Sex.Male, SchoolLevel.Primary); var student = CreateStudent(Sex.Male); var school = CreateSchool(SchoolLevel.Secondary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.False(isEligible); Assert.Contains("level", reason!, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task CheckEligibility_PrimaryStudentInSecondaryEvent_CompeteUp_ReturnsTrue() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary); var student = CreateStudent(Sex.Male); var school = CreateSchool(SchoolLevel.Primary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); SetupNotAlreadyRegistered(); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.True(isEligible); } [Fact] public async Task CheckEligibility_AgeExceedsMax_ReturnsFalse() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary, maxAge: 13, isAgeBased: true); // Student born 2010-01-01, tournament June 2024 → age 14 var student = CreateStudent(Sex.Male, dob: new DateOnly(2010, 1, 1)); var school = CreateSchool(SchoolLevel.Secondary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.False(isEligible); Assert.Contains("age", reason!, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task CheckEligibility_AgeWithinLimit_ReturnsTrue() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary, maxAge: 15, isAgeBased: true); // Student born 2010-01-01, tournament June 2024 → age 14 var student = CreateStudent(Sex.Male, dob: new DateOnly(2010, 1, 1)); var school = CreateSchool(SchoolLevel.Secondary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); SetupNotAlreadyRegistered(); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.True(isEligible); } [Fact] public async Task CheckEligibility_AgeExceedsButWaived_ReturnsTrue() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary, maxAge: 13, isAgeBased: true, ageWaived: true); // Student age 14, max is 13, but waived var student = CreateStudent(Sex.Male, dob: new DateOnly(2010, 1, 1)); var school = CreateSchool(SchoolLevel.Secondary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); SetupNotAlreadyRegistered(); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.True(isEligible); } [Fact] public async Task CheckEligibility_AlreadyRegistered_ReturnsFalse() { var tel = CreateTel(Sex.Male, SchoolLevel.Secondary); var student = CreateStudent(Sex.Male); var school = CreateSchool(SchoolLevel.Secondary); SetupTournamentEventLevel(tel); SetupStudent(student); SetupSchool(school); SetupAlreadyRegistered(); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 1); Assert.False(isEligible); Assert.Contains("already registered", reason!, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task CheckEligibility_TelNotFound_ReturnsFalse() { _mockUow.Setup(u => u.TournamentEventLevels.GetWithRegistrationsAsync(It.IsAny())) .ReturnsAsync((TournamentEventLevel?)null); var (isEligible, reason) = await _service.CheckEligibilityAsync(999, 1); Assert.False(isEligible); Assert.Contains("not found", reason!, StringComparison.OrdinalIgnoreCase); } [Fact] public async Task CheckEligibility_StudentNotFound_ReturnsFalse() { var tel = CreateTel(); SetupTournamentEventLevel(tel); _mockUow.Setup(u => u.Students.GetByIdAsync(It.IsAny())) .ReturnsAsync((Student?)null); var (isEligible, reason) = await _service.CheckEligibilityAsync(1, 999); Assert.False(isEligible); Assert.Contains("not found", reason!, StringComparison.OrdinalIgnoreCase); } }