using Core.Entities; using Core.Validation; using Core.Validation.Rules.StudentRankingRules; using Tests.Builders; namespace Tests.Validation.Rules; [TestFixture] public class StudentRankingRulesTests { [SetUp] public void SetUp() { BuilderExtensions.ResetAllBuilders(); } #region NoRegionalEventRule Tests [Test] public void NoRegionalEventRule_StudentHasRegionalEvent_ReturnsNull() { // Arrange var config = new ValidationConfiguration { RequireRegionalEvent = true, RequireOnSiteActivity = false, RequireIndividualEvent = false }; var rule = new NoRegionalEventRule(); var flight = EventDefinitionBuilder.Individual("Flight").AsRegionalEvent().Build(); var student = StudentBuilder.Default() .WithRanking(flight, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Null, "Student with regional event should not trigger warning"); } [Test] public void NoRegionalEventRule_StudentLacksRegionalEvent_ReturnsWarning() { // Arrange var config = new ValidationConfiguration { RequireRegionalEvent = true, NoRegionalEventSeverity = ValidationSeverity.Warning }; var rule = new NoRegionalEventRule(); var coding = EventDefinitionBuilder.Individual("Coding").Build(); // Not regional var student = StudentBuilder.Default() .WithRanking(coding, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Not.Null); Assert.That(warning!.Code, Is.EqualTo("NO_REGIONAL_EVENT")); Assert.That(warning.Message, Is.EqualTo("No Regional Event")); Assert.That(warning.Severity, Is.EqualTo(ValidationSeverity.Warning)); Assert.That(warning.IconIdentifier, Is.EqualTo("RegionalEvent")); } [Test] public void NoRegionalEventRule_RequirementDisabled_ReturnsNull() { // Arrange var config = new ValidationConfiguration { RequireRegionalEvent = false }; var rule = new NoRegionalEventRule(); var coding = EventDefinitionBuilder.Individual("Coding").Build(); var student = StudentBuilder.Default() .WithRanking(coding, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Null, "Warning should not be returned when requirement is disabled"); } [Test] public void NoRegionalEventRule_AppliesTo_CorrectContexts() { // Arrange var rule = new NoRegionalEventRule(); // Act & Assert Assert.That(rule.AppliesTo(ValidationContext.StudentRanking), Is.True); Assert.That(rule.AppliesTo(ValidationContext.StudentRegistration), Is.True); Assert.That(rule.AppliesTo(ValidationContext.StudentAssignment), Is.False); Assert.That(rule.AppliesTo(ValidationContext.Team), Is.False); } #endregion #region NoOnSiteActivityRule Tests [Test] public void NoOnSiteActivityRule_StudentHasOnSiteActivity_ReturnsNull() { // Arrange var config = new ValidationConfiguration { RequireOnSiteActivity = true, RequireRegionalEvent = false, RequireIndividualEvent = false }; var rule = new NoOnSiteActivityRule(); var speech = EventDefinitionBuilder.Individual("Speech").AsOnSite().Build(); var student = StudentBuilder.Default() .WithRanking(speech, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Null); } [Test] public void NoOnSiteActivityRule_StudentLacksOnSiteActivity_ReturnsWarning() { // Arrange var config = new ValidationConfiguration { RequireOnSiteActivity = true, NoOnSiteActivitySeverity = ValidationSeverity.Error }; var rule = new NoOnSiteActivityRule(); var flight = EventDefinitionBuilder.Individual("Flight").Build(); // Not on-site var student = StudentBuilder.Default() .WithRanking(flight, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Not.Null); Assert.That(warning!.Code, Is.EqualTo("NO_ONSITE_ACTIVITY")); Assert.That(warning.Severity, Is.EqualTo(ValidationSeverity.Error)); } #endregion #region NoIndividualEventRule Tests [Test] public void NoIndividualEventRule_StudentHasIndividualEvent_ReturnsNull() { // Arrange var config = new ValidationConfiguration { RequireIndividualEvent = true, RequireRegionalEvent = false, RequireOnSiteActivity = false }; var rule = new NoIndividualEventRule(); var flight = EventDefinitionBuilder.Individual("Flight").Build(); var student = StudentBuilder.Default() .WithRanking(flight, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Null); } [Test] public void NoIndividualEventRule_StudentOnlyHasTeamEvents_ReturnsWarning() { // Arrange var config = new ValidationConfiguration { RequireIndividualEvent = true, NoIndividualEventSeverity = ValidationSeverity.Warning }; var rule = new NoIndividualEventRule(); var robotics = EventDefinitionBuilder.Team("Robotics", 2, 5).Build(); var student = StudentBuilder.Default() .WithRanking(robotics, 1) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Not.Null); Assert.That(warning!.Code, Is.EqualTo("NO_INDIVIDUAL_EVENT")); Assert.That(warning.Message, Is.EqualTo("No Individual Event")); } #endregion #region TooManyRegionalEventsRule Tests [Test] public void TooManyRegionalEventsRule_WithinLimit_ReturnsNull() { // Arrange var config = new ValidationConfiguration { MaxRegionalEvents = 3 }; var rule = new TooManyRegionalEventsRule(); var flight = EventDefinitionBuilder.Individual("Flight").AsRegionalEvent().Build(); var coding = EventDefinitionBuilder.Individual("Coding").AsRegionalEvent().Build(); var student = StudentBuilder.Default() .WithRanking(flight, 1) .WithRanking(coding, 2) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Null); } [Test] public void TooManyRegionalEventsRule_ExceedsLimit_ReturnsWarning() { // Arrange var config = new ValidationConfiguration { MaxRegionalEvents = 2, TooManyRegionalEventsSeverity = ValidationSeverity.Warning }; var rule = new TooManyRegionalEventsRule(); var flight = EventDefinitionBuilder.Individual("Flight").AsRegionalEvent().Build(); var coding = EventDefinitionBuilder.Individual("Coding").AsRegionalEvent().Build(); var essays = EventDefinitionBuilder.Individual("Essays").AsRegionalEvent().Build(); var student = StudentBuilder.Default() .WithRanking(flight, 1) .WithRanking(coding, 2) .WithRanking(essays, 3) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Not.Null); Assert.That(warning!.Code, Is.EqualTo("TOO_MANY_REGIONAL_EVENTS")); Assert.That(warning.Message, Does.Contain("3 regional events")); Assert.That(warning.Message, Does.Contain("max recommended: 2")); Assert.That(warning.IconIdentifier, Is.EqualTo("RegionalEvent")); } [Test] public void TooManyRegionalEventsRule_ContainsMetadata() { // Arrange var config = new ValidationConfiguration { MaxRegionalEvents = 1 }; var rule = new TooManyRegionalEventsRule(); var flight = EventDefinitionBuilder.Individual("Flight").AsRegionalEvent().Build(); var coding = EventDefinitionBuilder.Individual("Coding").AsRegionalEvent().Build(); var student = StudentBuilder.Default() .WithName("Alice", "Anderson") .WithRanking(flight, 1) .WithRanking(coding, 2) .Build(); // Act var warning = rule.Validate(student, config); // Assert Assert.That(warning, Is.Not.Null); Assert.That(warning!.Metadata, Contains.Key("RegionalEventCount")); Assert.That(warning.Metadata, Contains.Key("MaxRegionalEvents")); Assert.That(warning.Metadata["RegionalEventCount"], Is.EqualTo(2)); Assert.That(warning.Metadata["MaxRegionalEvents"], Is.EqualTo(1)); } #endregion }