Files
Elternbeirat/Elternbeirat.Web.Tests/PocketBaseClientTests.cs
T

121 lines
4.3 KiB
C#

using Elternbeirat.PocketBase;
namespace Elternbeirat.Web.Tests;
/// <summary>
/// Tests the <see cref="PocketBaseClient"/> against a throwaway PocketBase container
/// with a known seed (see <see cref="PocketBaseFixture"/>). Because the data is fixed,
/// the tests assert on exact values, and they need no network to the live instance.
/// </summary>
[Collection(PocketBaseTestGroup.Name)]
public sealed class PocketBaseClientTests(PocketBaseFixture pocketBase)
{
[Fact]
public async Task Events_load_sorted_by_start()
{
var client = pocketBase.CreateClient();
var events = await client.GetEventsAsync();
// Three seeded events, earliest start first.
events.Select(@event => @event.Title).ShouldBe(["Projekttage", "Infoabend Klasse 5", "Elternbeiratssitzung", "Herbstbasar"]);
}
[Fact]
public async Task Event_utc_is_converted_to_berlin_wall_clock()
{
var client = pocketBase.CreateClient();
var events = await client.GetEventsAsync();
// The meeting is seeded as 17:30Z. October is summer time (UTC+2), so the
// converter turns it into 19:30 Berlin wall-clock -- the time an editor
// entered in the admin form.
var meeting = events.FirstOrDefault(e =>
e.Title.Contains("Elternbeiratssitzung", StringComparison.Ordinal));
meeting.ShouldNotBeNull();
meeting.Start.Hour.ShouldBe(19);
meeting.Start.Minute.ShouldBe(30);
meeting.Start.Kind.ShouldBe(DateTimeKind.Unspecified);
}
[Fact]
public async Task Event_without_end_maps_to_null()
{
var client = pocketBase.CreateClient();
var events = await client.GetEventsAsync();
var meeting = events.Single(@event => @event.Title == "Elternbeiratssitzung");
var basar = events.Single(@event => @event.Title == "Herbstbasar");
meeting.End.ShouldBeNull(); // no end seeded
basar.End.ShouldNotBeNull(); // end seeded
}
[Fact]
public async Task Posts_load_newest_first()
{
var client = pocketBase.CreateClient();
var posts = await client.GetPostsAsync();
// Sorted by -date: March before January.
posts.Select(post => post.Title).ShouldBe(["Neuer Vorstand", "Neue Sporthalle"]);
}
[Fact]
public async Task Post_date_is_the_berlin_calendar_day()
{
var client = pocketBase.CreateClient();
var posts = await client.GetPostsAsync();
// The post is seeded as 2026-03-01 23:30Z, which is 2 March 00:30 in Berlin.
// The date is the Berlin day the editor picked (2 March), not the raw UTC
// day (1 March) -- the time zone is applied before the day is taken.
var post = posts.Single(p => p.Title == "Neuer Vorstand");
post.Date.ShouldBe(new DateOnly(2026, 3, 2));
}
[Fact]
public async Task Pages_exclude_non_public_records()
{
var client = pocketBase.CreateClient();
var pages = await client.GetPagesAsync();
// The draft (public=false) must be filtered out, the public ones present.
pages.ShouldNotContain(page => page.Slug == "draft");
pages.ShouldContain(page => page.Slug == "home");
pages.ShouldContain(page => page.Slug == "contact");
}
[Fact]
public async Task Page_embed_is_read_as_list()
{
var client = pocketBase.CreateClient();
var pages = await client.GetPagesAsync();
var home = pages.Single(p => p.Slug == "home");
home.Embed.ShouldBe(["posts", "events"], ignoreOrder: true);
// Home sits in the header like every other page (location is required); it
// is the single source of the home nav link.
home.Location.ShouldBe("header");
}
[Fact]
public async Task Faqs_load_from_instance()
{
var client = pocketBase.CreateClient();
var faqs = await client.GetFaqsAsync();
// The topic relation is expanded, so each entry carries its topic. The two
// seeded topics are ordered (Mensa order 1 before Schließfächer order 2), and
// GetFaqsAsync sorts by topic.order, so the groups come back in that order.
faqs.Select(faq => faq.Topic?.Title).ShouldBe(["Mensa und Mittagessen", "Schließfächer"]);
faqs.ShouldAllBe(faq => !string.IsNullOrWhiteSpace(faq.Question));
}
}