147 lines
5.2 KiB
C#
147 lines
5.2 KiB
C#
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);
|
||
});
|
||
}
|
||
|
||
/// <summary>
|
||
/// Alphabetical, with Ё counted as Е — see <c>RosterBrowser.NameOrder</c>. Ordinal order would
|
||
/// agree on this sample (no vanilla surname starts with Ё), which is exactly why the rule is
|
||
/// pinned down separately in <c>ReviewFixTests</c>.
|
||
/// </summary>
|
||
[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);
|
||
}
|