using System.Text; using Core.Entities; using Core.Models; using Core.Parsers; using Tests.Builders; namespace Tests.Parsers; [TestFixture] public class StudentEventRankingParser_Tests { private Student _aria = null!; private EventDefinition _videoGame = null!; private EventDefinition _coding = null!; private EventDefinition _jss = null!; private EventDefinition _digitalPhoto = null!; private EventDefinition _biotech = null!; private EventDefinition _inventions = null!; private EventDefinition _techBowl = null!; private EventDefinition _techDesign = null!; private List _students = null!; private List _events = null!; [SetUp] public void SetUp() { BuilderExtensions.ResetAllBuilders(); _aria = StudentBuilder.Create("Aria", "Chittenden").Build(); _videoGame = EventDefinitionBuilder.Team("Video Game Design", 2, 6).WithShortName("Video Game").Build(); _coding = EventDefinitionBuilder.Team("Coding", 2, 2).WithShortName("Coding").Build(); _jss = EventDefinitionBuilder.Team("Junior Solar Sprint", 2, 4).WithShortName("JSS").Build(); _digitalPhoto = EventDefinitionBuilder.Individual("Digital Photography").WithShortName("Digital Photo").Build(); _biotech = EventDefinitionBuilder.Team("Biotechnology", 2, 6).WithShortName("Biotech").Build(); _inventions = EventDefinitionBuilder.Team("Inventions & Innovations", 3, 6).WithShortName("I&I").Build(); _techBowl = EventDefinitionBuilder.Team("Tech Bowl", 3, 3).WithShortName("Tech Bowl").Build(); _techDesign = EventDefinitionBuilder.Team("Technical Design", 2, 2).WithShortName("Tech Design").Build(); _students = [_aria]; _events = [_videoGame, _coding, _jss, _digitalPhoto, _biotech, _inventions, _techBowl, _techDesign]; } [Test] public void Parse_LastCommaFirst_MatchesStudent() { var result = ParseCsv(""" Student Name,1 "Chittenden, Aria",Coding """, _students, _events); Assert.That(result.IsSuccess, Is.True); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.Student, Is.SameAs(_aria)); Assert.That(result.Matches[0].Ranking.EventDefinition, Is.SameAs(_coding)); Assert.That(result.Matches[0].Ranking.Rank, Is.EqualTo(1)); } [Test] public void Parse_FirstLast_MatchesStudent() { var result = ParseCsv(""" Student Name,1 Aria Chittenden,Coding """, _students, _events); Assert.That(result.IsSuccess, Is.True); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.Student, Is.SameAs(_aria)); } [Test] public void Parse_NicknamePlusLastName_MatchesStudent() { var jo = StudentBuilder.Create("Josiah", "Brown").WithNickname("Jo").Build(); var result = ParseCsv(""" Student Name,1 Jo Brown,Coding """, [jo], _events); Assert.That(result.IsSuccess, Is.True); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.Student, Is.SameAs(jo)); } [Test] public void Parse_ShortName_MatchesEvent() { var result = ParseCsv(""" Student Name,1,2,3 Aria Chittenden,Video Game,JSS,I&I """, _students, _events); Assert.That(result.Issues, Is.Empty); Assert.That(result.Matches, Has.Count.EqualTo(3)); Assert.That(result.Matches.Select(m => m.Ranking.EventDefinition), Is.EqualTo(new[] { _videoGame, _jss, _inventions })); } [Test] public void Parse_NearMissFullName_MatchesEvent() { var result = ParseCsv(""" Student Name,1 Aria Chittenden,Digital Photo """, _students, _events); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.EventDefinition, Is.SameAs(_digitalPhoto)); Assert.That(result.Matches[0].EventScore, Is.GreaterThanOrEqualTo(StudentEventRankingParser.EventMatchThreshold)); } [Test] public void Parse_BiotechShortName_MatchesBiotechnology() { var result = ParseCsv(""" Student Name,1 Aria Chittenden,Biotech """, _students, _events); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.EventDefinition, Is.SameAs(_biotech)); } [Test] public void Parse_UnmatchedStudent_IsReported() { var result = ParseCsv(""" Student Name,1 Nobody Here,Coding """, _students, _events); Assert.That(result.Matches, Is.Empty); Assert.That(result.Issues, Has.Count.EqualTo(1)); Assert.That(result.Issues[0].IssueType, Is.EqualTo(StudentEventRankingIssueType.UnmatchedStudent)); Assert.That(result.Issues[0].RawStudentName, Is.EqualTo("Nobody Here")); } [Test] public void Parse_SolarRacer_MatchesJuniorSolarSprint() { var result = ParseCsv(""" Student Name,1 Aria Chittenden,Solar Racer """, _students, _events); Assert.That(result.Issues, Is.Empty); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.EventDefinition, Is.SameAs(_jss)); } [TestCase("Solar Racer", "Junior Solar Sprint")] [TestCase("Solar Race", "Junior Solar Sprint")] [TestCase("Challenging Tech", "Challenging Technology Issues")] [TestCase("Digital Photo", "Digital Photography")] [TestCase("Forensics", "Forensic Technology")] [TestCase("Micro Controller", "Microcontroller Design")] [TestCase("Med Tech", "Medical Technology")] [TestCase("Innovations & Inventions", "Inventions & Innovations")] [TestCase("Inventions and Innovations", "Inventions & Innovations")] [TestCase("Systems Control Tech", "System Control Technology")] [TestCase("Systems Control Technology", "System Control Technology")] [TestCase("Structural Eng", "Structural Engineering")] [TestCase("Drone Challenge", "Drone Challenge (UAV)")] [TestCase("Robotics", "TSA Robotics")] [TestCase("Audio Podcast", "Audio Podcasting")] public void Parse_KnownAlias_MatchesOfficialEvent(string alias, string officialName) { var events = TestEntityHandler.GetEvents().ToList(); events.AddRange( [ EventDefinitionBuilder.Team("Drone Challenge (UAV)", 2, 6).WithShortName("Drone").Build(), EventDefinitionBuilder.Team("TSA Robotics", 2, 6).WithShortName("Robotics").Build(), EventDefinitionBuilder.Team("Audio Podcasting", 2, 6).WithShortName("Podcasting").Build() ]); var result = ParseCsv($""" Student Name,1 Aria Chittenden,{alias} """, _students, events); Assert.That(result.Issues, Is.Empty, $"Expected '{alias}' to match '{officialName}'"); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Matches[0].Ranking.EventDefinition.Name, Is.EqualTo(officialName)); } [Test] public void Parse_UnmatchedEvent_IsReported() { var result = ParseCsv(""" Student Name,1 Aria Chittenden,Underwater Basket Weaving """, _students, _events); Assert.That(result.Matches, Is.Empty); Assert.That(result.Issues, Has.Count.EqualTo(1)); Assert.That(result.Issues[0].IssueType, Is.EqualTo(StudentEventRankingIssueType.UnmatchedEvent)); Assert.That(result.Issues[0].RawEventName, Is.EqualTo("Underwater Basket Weaving")); } [Test] public void Parse_AmbiguousEvent_IsReported() { var result = ParseCsv(""" Student Name,1 Aria Chittenden,Tech """, _students, _events); Assert.That(result.Matches, Is.Empty); Assert.That(result.Issues, Has.Count.EqualTo(1)); Assert.That(result.Issues[0].IssueType, Is.EqualTo(StudentEventRankingIssueType.AmbiguousEvent)); } [Test] public void Parse_RankColumnsBeyondSix_AreRead() { var result = ParseCsv(""" Student Name,1,2,3,4,5,6,7 Aria Chittenden,Coding,,,,,,JSS """, _students, _events); Assert.That(result.Matches, Has.Count.EqualTo(2)); Assert.That(result.Matches.Select(m => m.Ranking.Rank), Is.EqualTo(new[] { 1, 7 })); Assert.That(result.Matches[1].Ranking.EventDefinition, Is.SameAs(_jss)); } [Test] public void Parse_DuplicateEvent_IsReported() { var result = ParseCsv(""" Student Name,1,2 Aria Chittenden,Coding,Coding """, _students, _events); Assert.That(result.Matches, Has.Count.EqualTo(1)); Assert.That(result.Issues, Has.Count.EqualTo(1)); Assert.That(result.Issues[0].IssueType, Is.EqualTo(StudentEventRankingIssueType.DuplicateEvent)); } [Test] public void Parse_MissingStudentNameHeader_IsError() { var result = ParseCsv(""" Name,1 Aria Chittenden,Coding """, _students, _events); Assert.That(result.IsSuccess, Is.False); Assert.That(result.Errors, Is.Not.Empty); } [Test] public void Parse_2024RankingsFile_MatchesKnownStudentsAndEvents() { var events = TestEntityHandler.GetEvents(); var students = TestEntityHandler.GetStudents(events); var rankings = TestEntityHandler.GetStudentEventRankings(students, events); Assert.That(students, Has.Length.EqualTo(29)); Assert.That(rankings, Is.Not.Empty); Assert.That(rankings.Select(r => r.Student.FirstNameLastName).Distinct().Count(), Is.EqualTo(29)); Assert.That(rankings.All(r => r.EventDefinition is not null), Is.True); Assert.That(rankings.All(r => r.Rank is >= 1 and <= 10), Is.True); Assert.That(rankings.Count(r => r.Student.FirstName == "First26"), Is.EqualTo(7)); } private static StudentEventRankingParseResult ParseCsv( string csv, ICollection students, ICollection events) { using var reader = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(csv))); using var parser = new StudentEventRankingParser(reader); return parser.Parse(students, events); } }