Promote returning students, assign officers, and clear last season's data after an automatic SQLite backup, with Docker volume path docs fixed for /app/Data. Co-authored-by: Cursor <cursoragent@cursor.com>
231 lines
8.2 KiB
C#
231 lines
8.2 KiB
C#
using Core.Entities;
|
|
using Core.Models;
|
|
using Core.YearTransition;
|
|
using NUnit.Framework;
|
|
using Tests.Builders;
|
|
|
|
namespace Tests.YearTransition;
|
|
|
|
[TestFixture]
|
|
public class GraduatingGradeResolver_Tests
|
|
{
|
|
[Test]
|
|
public void FromSchoolLevel_MiddleSchool_Returns8()
|
|
{
|
|
Assert.That(GraduatingGradeResolver.FromSchoolLevel(SchoolLevel.MiddleSchool), Is.EqualTo(8));
|
|
}
|
|
|
|
[Test]
|
|
public void FromSchoolLevel_HighSchool_Returns12()
|
|
{
|
|
Assert.That(GraduatingGradeResolver.FromSchoolLevel(SchoolLevel.HighSchool), Is.EqualTo(12));
|
|
}
|
|
|
|
[Test]
|
|
public void FromSchoolLevel_Null_ReturnsNull()
|
|
{
|
|
Assert.That(GraduatingGradeResolver.FromSchoolLevel(null), Is.Null);
|
|
}
|
|
}
|
|
|
|
[TestFixture]
|
|
public class YearTransitionPlanner_Tests
|
|
{
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
StudentBuilder.ResetIdCounter();
|
|
}
|
|
|
|
[Test]
|
|
public void SuggestReturning_BelowGraduatingGrade_IsTrue()
|
|
{
|
|
var student = StudentBuilder.Create("Ann", "Lee").WithGrade(7).Build();
|
|
Assert.That(YearTransitionPlanner.SuggestReturning(student, graduatingGrade: 8), Is.True);
|
|
}
|
|
|
|
[Test]
|
|
public void SuggestReturning_AtGraduatingGrade_IsFalse()
|
|
{
|
|
var student = StudentBuilder.Create("Ann", "Lee").WithGrade(8).Build();
|
|
Assert.That(YearTransitionPlanner.SuggestReturning(student, graduatingGrade: 8), Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public void Build_PromotesReturningStudents_MiddleSchool()
|
|
{
|
|
var returning = StudentBuilder.Create("Ann", "Lee").WithGrade(6).WithTsaYear(1).Build();
|
|
var graduating = StudentBuilder.Create("Bob", "Smith").WithGrade(8).WithTsaYear(3).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [returning, graduating],
|
|
ReturningStudentIds = new HashSet<int> { returning.Id },
|
|
GraduatingGrade = 8,
|
|
TargetCompetitionYear = "2027"
|
|
});
|
|
|
|
Assert.That(plan.ReturningCount, Is.EqualTo(1));
|
|
Assert.That(plan.RemovalCount, Is.EqualTo(1));
|
|
Assert.That(plan.Promotions[0].NewGrade, Is.EqualTo(7));
|
|
Assert.That(plan.Promotions[0].NewTsaYear, Is.EqualTo(2));
|
|
Assert.That(plan.StudentsToRemove[0].Id, Is.EqualTo(graduating.Id));
|
|
}
|
|
|
|
[Test]
|
|
public void Build_CapsGradeAtGraduatingGrade_HighSchool()
|
|
{
|
|
var senior = StudentBuilder.Create("Chris", "Young").WithGrade(12).WithTsaYear(4).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [senior],
|
|
ReturningStudentIds = new HashSet<int> { senior.Id },
|
|
GraduatingGrade = 12,
|
|
TargetCompetitionYear = "2027"
|
|
});
|
|
|
|
Assert.That(plan.Promotions[0].NewGrade, Is.EqualTo(12));
|
|
Assert.That(plan.Promotions[0].NewTsaYear, Is.EqualTo(5));
|
|
Assert.That(plan.Warnings, Has.Some.Contain("graduating grade"));
|
|
}
|
|
|
|
[Test]
|
|
public void Build_CapsGradeAtEight_WhenMiddleSchoolReturnerAtGraduatingGrade()
|
|
{
|
|
var eighth = StudentBuilder.Create("Dana", "Nguyen").WithGrade(8).WithTsaYear(2).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [eighth],
|
|
ReturningStudentIds = new HashSet<int> { eighth.Id },
|
|
GraduatingGrade = 8,
|
|
TargetCompetitionYear = "2027"
|
|
});
|
|
|
|
Assert.That(plan.Promotions[0].NewGrade, Is.EqualTo(8));
|
|
Assert.That(plan.Warnings, Has.Some.Contain("graduating grade"));
|
|
}
|
|
|
|
[Test]
|
|
public void Build_AssignsOfficersAndClearsOthers()
|
|
{
|
|
var president = StudentBuilder.Create("Eve", "Adams").WithGrade(7).AsPresident().Build();
|
|
var vp = StudentBuilder.Create("Frank", "Baker").WithGrade(6).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [president, vp],
|
|
ReturningStudentIds = new HashSet<int> { president.Id, vp.Id },
|
|
GraduatingGrade = 8,
|
|
TargetCompetitionYear = "2027",
|
|
OfficerAssignments = new Dictionary<OfficerRole, int?>
|
|
{
|
|
[OfficerRole.President] = vp.Id,
|
|
[OfficerRole.VicePresident] = president.Id
|
|
}
|
|
});
|
|
|
|
var eve = plan.Promotions.Single(p => p.Student.Id == president.Id);
|
|
var frank = plan.Promotions.Single(p => p.Student.Id == vp.Id);
|
|
|
|
Assert.That(eve.PreviousOfficerRole, Is.EqualTo(OfficerRole.President));
|
|
Assert.That(eve.NewOfficerRole, Is.EqualTo(OfficerRole.VicePresident));
|
|
Assert.That(frank.NewOfficerRole, Is.EqualTo(OfficerRole.President));
|
|
|
|
var presidentChange = plan.OfficerChanges.Single(c => c.Role == OfficerRole.President);
|
|
Assert.That(presidentChange.PreviousOfficer!.Id, Is.EqualTo(president.Id));
|
|
Assert.That(presidentChange.NewOfficer!.Id, Is.EqualTo(vp.Id));
|
|
}
|
|
|
|
[Test]
|
|
public void Build_WarnsWhenOfficerAssignedToNonReturningStudent()
|
|
{
|
|
var returning = StudentBuilder.Create("Gina", "Cole").WithGrade(6).Build();
|
|
var leaving = StudentBuilder.Create("Hank", "Diaz").WithGrade(8).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [returning, leaving],
|
|
ReturningStudentIds = new HashSet<int> { returning.Id },
|
|
GraduatingGrade = 8,
|
|
TargetCompetitionYear = "2027",
|
|
OfficerAssignments = new Dictionary<OfficerRole, int?>
|
|
{
|
|
[OfficerRole.President] = leaving.Id
|
|
}
|
|
});
|
|
|
|
Assert.That(plan.Warnings, Has.Some.Contain("not marked returning"));
|
|
Assert.That(plan.Promotions[0].NewOfficerRole, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void Build_WarnsWhenSameStudentHasTwoOffices()
|
|
{
|
|
var student = StudentBuilder.Create("Ivy", "Evans").WithGrade(7).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [student],
|
|
ReturningStudentIds = new HashSet<int> { student.Id },
|
|
GraduatingGrade = 8,
|
|
TargetCompetitionYear = "2027",
|
|
OfficerAssignments = new Dictionary<OfficerRole, int?>
|
|
{
|
|
[OfficerRole.President] = student.Id,
|
|
[OfficerRole.Treasurer] = student.Id
|
|
}
|
|
});
|
|
|
|
Assert.That(plan.Warnings, Has.Some.Contain("more than one officer role"));
|
|
Assert.That(plan.Promotions[0].NewOfficerRole, Is.Null);
|
|
}
|
|
|
|
[Test]
|
|
public void MatchPastedNames_MatchesLastCommaFirstAndFirstLast()
|
|
{
|
|
var a = StudentBuilder.Create("Ann", "Lee").WithGrade(6).Build();
|
|
var b = StudentBuilder.Create("Bob", "Smith").WithGrade(7).Build();
|
|
|
|
var result = YearTransitionPlanner.MatchPastedNames(
|
|
[a, b],
|
|
["Lee, Ann", "Bob Smith", "Nobody Here"]);
|
|
|
|
Assert.That(result.MatchedStudentIds, Is.EquivalentTo(new[] { a.Id, b.Id }));
|
|
Assert.That(result.UnmatchedNames, Is.EquivalentTo(new[] { "Nobody Here" }));
|
|
}
|
|
|
|
[Test]
|
|
public void MatchPastedNames_AmbiguousWhenDuplicateNames()
|
|
{
|
|
var a = StudentBuilder.Create("Ann", "Lee").WithGrade(6).Build();
|
|
var b = StudentBuilder.Create("Ann", "Lee").WithGrade(7).Build();
|
|
|
|
var result = YearTransitionPlanner.MatchPastedNames([a, b], ["Ann Lee"]);
|
|
|
|
Assert.That(result.AmbiguousNames, Is.EquivalentTo(new[] { "Ann Lee" }));
|
|
Assert.That(result.MatchedStudentIds, Is.EquivalentTo(new[] { a.Id, b.Id }));
|
|
}
|
|
|
|
[Test]
|
|
public void Build_IncludesUnmatchedAndAmbiguousFromPaste()
|
|
{
|
|
var a = StudentBuilder.Create("Ann", "Lee").WithGrade(6).Build();
|
|
var b = StudentBuilder.Create("Ann", "Lee").WithGrade(7).Build();
|
|
|
|
var plan = YearTransitionPlanner.Build(new YearTransitionRequest
|
|
{
|
|
Students = [a, b],
|
|
ReturningStudentIds = new HashSet<int> { a.Id },
|
|
GraduatingGrade = 8,
|
|
TargetCompetitionYear = "2027",
|
|
PastedNames = ["Ann Lee", "Zed Zulu"]
|
|
});
|
|
|
|
Assert.That(plan.AmbiguousPastedNames, Has.Member("Ann Lee"));
|
|
Assert.That(plan.UnmatchedPastedNames, Has.Member("Zed Zulu"));
|
|
Assert.That(plan.Warnings, Has.Some.Contain("matched more than one"));
|
|
}
|
|
}
|