208 lines
8.0 KiB
C#
208 lines
8.0 KiB
C#
using System.Net.Http.Json;
|
|
|
|
namespace HSchool.AppHost.Tests;
|
|
|
|
[Collection(AppHostCollection.Name)]
|
|
public class PeopleApiTests(AppHostFixture fixture)
|
|
{
|
|
private static readonly DateTime Start = new(2012, 4, 3, 6, 0, 0, DateTimeKind.Utc);
|
|
|
|
[Fact]
|
|
public async Task List_FiltersByRoleAndYear()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
await SchoolApiTests.ResetAsync(client);
|
|
var school = await SchoolApiTests.CreateAsync(client, "Люди фильтр", Start);
|
|
|
|
var page = await GetPeopleAsync(client, school.Id, "role=student&year=5&pageSize=100");
|
|
|
|
Assert.NotEmpty(page.People);
|
|
Assert.Equal(page.People.Count, page.Total);
|
|
Assert.All(page.People, person =>
|
|
{
|
|
Assert.Contains("student", person.Roles);
|
|
Assert.Equal(5, person.ClassYear);
|
|
});
|
|
Assert.Contains(5, page.Filters.Years);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_SortsBySurname()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
await SchoolApiTests.ResetAsync(client);
|
|
var school = await SchoolApiTests.CreateAsync(client, "Люди сорт", Start);
|
|
|
|
var page = await GetPeopleAsync(client, school.Id, "sort=surname&pageSize=20");
|
|
var surnames = page.People.Select(person => person.Surname).ToArray();
|
|
Assert.Equal(surnames.OrderBy(name => name, StringComparer.Ordinal), surnames);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_PageBounds()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
await SchoolApiTests.ResetAsync(client);
|
|
var school = await SchoolApiTests.CreateAsync(client, "Люди страницы", Start);
|
|
|
|
var first = await GetPeopleAsync(client, school.Id, "page=1&pageSize=10");
|
|
Assert.True(first.Total > 10);
|
|
Assert.Equal(10, first.People.Count);
|
|
Assert.Equal(1, first.Page);
|
|
Assert.Equal(10, first.PageSize);
|
|
|
|
var past = await GetPeopleAsync(client, school.Id, "page=999&pageSize=10");
|
|
Assert.Equal(first.Total, past.Total);
|
|
Assert.Empty(past.People);
|
|
|
|
using var zero = await client.GetAsync($"/api/schools/{school.Id}/people?page=0", TestContext.Current.CancellationToken);
|
|
Assert.Equal(HttpStatusCode.BadRequest, zero.StatusCode);
|
|
Assert.Equal("invalid-query", await ProblemCodeAsync(zero));
|
|
|
|
using var huge = await client.GetAsync($"/api/schools/{school.Id}/people?pageSize=101", TestContext.Current.CancellationToken);
|
|
Assert.Equal(HttpStatusCode.BadRequest, huge.StatusCode);
|
|
Assert.Equal("invalid-query", await ProblemCodeAsync(huge));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_HasPupilsAndParentsButNoStaff()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
await SchoolApiTests.ResetAsync(client);
|
|
var school = await SchoolApiTests.CreateAsync(client, "Пустой штат", Start);
|
|
|
|
var students = await GetPeopleAsync(client, school.Id, "role=student&pageSize=10");
|
|
var parents = await GetPeopleAsync(client, school.Id, "role=parent&pageSize=10");
|
|
var staff = await GetPeopleAsync(client, school.Id, "role=staff&pageSize=10");
|
|
|
|
Assert.NotEmpty(students.People);
|
|
Assert.NotEmpty(parents.People);
|
|
Assert.Equal(0, staff.Total);
|
|
Assert.Empty(staff.People);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_UnknownSchool_IsNotFound()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
|
|
using var response = await client.GetAsync("/api/schools/999999/people", TestContext.Current.CancellationToken);
|
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
|
Assert.Equal("unknown-school", await ProblemCodeAsync(response));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Card_UnknownPerson_IsNotFound()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
await SchoolApiTests.ResetAsync(client);
|
|
var school = await SchoolApiTests.CreateAsync(client, "Люди карточка", Start);
|
|
|
|
using var response = await client.GetAsync(
|
|
$"/api/schools/{school.Id}/people/nobody",
|
|
TestContext.Current.CancellationToken);
|
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
|
Assert.Equal("unknown-person", await ProblemCodeAsync(response));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Card_IncludesFamilyAndLiveNeeds()
|
|
{
|
|
using var client = fixture.App.CreateHttpClient("server");
|
|
await SchoolApiTests.ResetAsync(client);
|
|
var school = await SchoolApiTests.CreateAsync(client, "Люди семья", Start);
|
|
|
|
var page = await GetPeopleAsync(client, school.Id, "role=student&year=5&pageSize=10");
|
|
var pupil = page.People[0];
|
|
|
|
var card = await client.GetFromJsonAsync<PersonCardResponse>(
|
|
$"/api/schools/{school.Id}/people/{Uri.EscapeDataString(pupil.Id)}?lang=ru",
|
|
TestContext.Current.CancellationToken);
|
|
Assert.NotNull(card);
|
|
Assert.Equal(pupil.Id, card.Id);
|
|
Assert.Equal(2, card.Family.Parents.Count);
|
|
Assert.Contains(card.Needs, need => need.Id == "Sleep" && need.Value == 1f);
|
|
Assert.NotEmpty(card.Body);
|
|
Assert.NotEmpty(card.Skills);
|
|
|
|
var mother = card.Family.Parents.Single(parent => parent.Female);
|
|
var motherCard = await client.GetFromJsonAsync<PersonCardResponse>(
|
|
$"/api/schools/{school.Id}/people/{Uri.EscapeDataString(mother.Id)}?lang=ru",
|
|
TestContext.Current.CancellationToken);
|
|
Assert.NotNull(motherCard);
|
|
Assert.Contains(motherCard.Family.Children, child => child.Id == pupil.Id);
|
|
}
|
|
|
|
private static async Task<PeopleListResponse> GetPeopleAsync(HttpClient client, int schoolId, string query)
|
|
{
|
|
var page = await client.GetFromJsonAsync<PeopleListResponse>(
|
|
$"/api/schools/{schoolId}/people?{query}",
|
|
TestContext.Current.CancellationToken);
|
|
Assert.NotNull(page);
|
|
return page;
|
|
}
|
|
|
|
private static async Task<string?> ProblemCodeAsync(HttpResponseMessage response)
|
|
{
|
|
var problem = await response.Content.ReadFromJsonAsync<ProblemResponse>(TestContext.Current.CancellationToken);
|
|
return problem?.Code;
|
|
}
|
|
|
|
private sealed record ProblemResponse(string? Code);
|
|
|
|
private sealed record PeopleListResponse(
|
|
int Total,
|
|
int Page,
|
|
int PageSize,
|
|
IReadOnlyList<PersonListItemResponse> People,
|
|
PeopleFilterOptionsResponse Filters);
|
|
|
|
private sealed record PeopleFilterOptionsResponse(
|
|
IReadOnlyList<int> Years,
|
|
IReadOnlyList<string> Letters,
|
|
IReadOnlyList<DefLabelResponse> Positions);
|
|
|
|
private sealed record DefLabelResponse(string DefName, string Label);
|
|
|
|
private sealed record PersonListItemResponse(
|
|
string Id,
|
|
string FullName,
|
|
string Surname,
|
|
string Given,
|
|
string Patronymic,
|
|
bool Female,
|
|
int Age,
|
|
IReadOnlyList<string> Roles,
|
|
int? ClassYear,
|
|
string? ClassLetter,
|
|
string? Position,
|
|
string? PositionLabel);
|
|
|
|
private sealed record PersonCardResponse(
|
|
string Id,
|
|
string FullName,
|
|
bool Female,
|
|
int Age,
|
|
DateTime BirthDate,
|
|
IReadOnlyList<string> Roles,
|
|
int? ClassYear,
|
|
string? ClassLetter,
|
|
IReadOnlyList<LabeledStatResponse> Body,
|
|
IReadOnlyList<LabeledStatResponse> Skills,
|
|
IReadOnlyList<DefLabelResponse> Traits,
|
|
IReadOnlyList<NeedStatResponse> Needs,
|
|
PersonFamilyResponse Family);
|
|
|
|
private sealed record LabeledStatResponse(string Id, string Label, string Value);
|
|
|
|
private sealed record NeedStatResponse(string Id, string Label, float Value);
|
|
|
|
private sealed record PersonFamilyResponse(
|
|
IReadOnlyList<PersonRelResponse> Parents,
|
|
IReadOnlyList<PersonRelResponse> Children,
|
|
IReadOnlyList<PersonRelResponse> Siblings,
|
|
IReadOnlyList<PersonRelResponse> Partners);
|
|
|
|
private sealed record PersonRelResponse(string Id, string FullName, bool Female);
|
|
}
|