namespace HSchool.People.Tests; public class RosterBrowserTests { [Fact] public void FilterByRoleAndYear_KeepsOnlyThosePupils() { var roster = Fixtures.Generate(Fixtures.Classrooms(4)); var page = RosterBrowser.Apply( roster, Fixtures.AsOf, Query(role: PersonRoles.Student, year: 1, pageSize: RosterBrowser.MaxPageSize)); Assert.NotEmpty(page.People); Assert.Equal(page.People.Count, page.Total); Assert.All(page.People, person => { Assert.True(person.IsStudent); var schoolClass = roster.Classes.Single(candidate => candidate.Id == person.ClassId); Assert.Equal(1, schoolClass.Year); }); } /// /// Alphabetical, with Ё counted as Е — see RosterBrowser.NameOrder. Ordinal order would /// agree on this sample (no vanilla surname starts with Ё), which is exactly why the rule is /// pinned down separately in ReviewFixTests. /// [Fact] public void SortBySurname_IsAlphabetical() { var roster = Fixtures.Generate(Fixtures.Classrooms(4)); var page = RosterBrowser.Apply(roster, Fixtures.AsOf, Query(pageSize: 20)); var surnames = page.People.Select(person => person.Name.Surname).ToArray(); var expected = surnames .OrderBy(name => name.Replace('Ё', 'Е').Replace('ё', 'е'), StringComparer.Ordinal) .ToArray(); Assert.Equal(expected, surnames); } [Fact] public void PagePastTheEnd_IsEmptyButKeepsTheTotal() { var roster = Fixtures.Generate(Fixtures.Classrooms(2)); var first = RosterBrowser.Apply(roster, Fixtures.AsOf, Query(page: 1, pageSize: 10)); var past = RosterBrowser.Apply(roster, Fixtures.AsOf, Query(page: 999, pageSize: 10)); Assert.True(first.Total > 10); Assert.Equal(10, first.People.Count); Assert.Equal(first.Total, past.Total); Assert.Empty(past.People); } [Fact] public void ParentFilter_ReturnsOnlyParents() { var roster = Fixtures.Generate(Fixtures.VanillaMap()); var page = RosterBrowser.Apply( roster, Fixtures.AsOf, Query(role: PersonRoles.Parent, pageSize: RosterBrowser.MaxPageSize)); Assert.NotEmpty(page.People); Assert.All(page.People, person => Assert.True(person.IsParent)); } [Fact] public void FilterBySex_KeepsOnlyThatSex() { var roster = Fixtures.Generate(Fixtures.Classrooms(4)); var page = RosterBrowser.Apply( roster, Fixtures.AsOf, Query(female: true, pageSize: RosterBrowser.MaxPageSize)); Assert.NotEmpty(page.People); Assert.True(page.Total < roster.People.Count); Assert.All(page.People, person => Assert.True(person.Female)); } [Fact] public void FilterByLetter_KeepsOnlyThatClassLetter() { var roster = Fixtures.Generate(Fixtures.Classrooms(4)); var letter = roster.Classes[0].Letter; var page = RosterBrowser.Apply( roster, Fixtures.AsOf, Query(letter: letter, pageSize: RosterBrowser.MaxPageSize)); var classes = roster.Classes.ToDictionary(schoolClass => schoolClass.Id, StringComparer.Ordinal); Assert.NotEmpty(page.People); Assert.All(page.People, person => Assert.Equal(letter, person.ClassId is { } classId ? classes[classId].Letter : null)); } [Fact] public void FilterByAgeRange_KeepsAgesInside() { var roster = Fixtures.Generate(Fixtures.Classrooms(4)); var pupil = roster.People.First(person => person.IsStudent); var age = pupil.AgeOn(Fixtures.AsOf); var page = RosterBrowser.Apply( roster, Fixtures.AsOf, Query(ageMin: age, ageMax: age, pageSize: RosterBrowser.MaxPageSize)); Assert.Contains(page.People, person => person.Id == pupil.Id); Assert.All(page.People, person => Assert.Equal(age, person.AgeOn(Fixtures.AsOf))); } [Fact] public void FilterByPosition_KeepsThatJob() { var roster = Fixtures.Generate(Fixtures.Classrooms(4)); var parent = roster.People.First(person => person.IsParent); roster = roster with { People = roster.People .Select(person => person.Id.Equals(parent.Id, StringComparison.Ordinal) ? person with { IsStaff = true, Position = "Librarian" } : person) .ToArray(), }; var page = RosterBrowser.Apply( roster, Fixtures.AsOf, Query(position: "Librarian", pageSize: RosterBrowser.MaxPageSize)); Assert.Equal(parent.Id, Assert.Single(page.People).Id); } private static RosterQuery Query( string? role = null, int? year = null, string? letter = null, string? position = null, bool? female = null, int? ageMin = null, int? ageMax = null, int page = 1, int pageSize = RosterBrowser.DefaultPageSize) => new(role, year, letter, position, female, ageMin, ageMax, PersonSort.Surname, Descending: false, page, pageSize); }