using System.Text.Json.Nodes; using decePubClient.E2E.Support; using Microsoft.Playwright; namespace decePubClient.E2E.Actions { // Notifications as groups: two likes of one post are one card naming both, the tab's badge counts what is unread, and // reading the tab moves the marker so PrivaPub counts nothing unread public sealed class NotificationTests(Browser browser) { [Fact] public async Task Two_likes_of_one_post_are_one_card_and_reading_them_clears_the_badge() { var personas = Pasture.Personas(); Assert.SkipWhen(personas.Count < 3, "the town has fewer than three personas"); var (author, first, second) = (personas[0], personas[1], personas[2]); var post = (await PersonaApi.Call(author, "/api/v1/statuses", HttpMethod.Post, new JsonObject { ["status"] = $"like me {Guid.NewGuid():N}"[..16], ["visibility"] = "public" }))!; var id = post["id"]!.GetValue(); await using var session = await SignIn.As(browser, author); var page = session.Page; try { await PersonaApi.Call(first, $"/api/v1/statuses/{id}/favourite", HttpMethod.Post); await PersonaApi.Call(second, $"/api/v1/statuses/{id}/favourite", HttpMethod.Post); await Results.Cell("client.render.notification-group", "privapub", author.UserName, async () => { await page.GotoAsync($"{Pasture.Site}/"); await page.EvaluateAsync("() => localStorage.removeItem('FeedFilter')"); await page.GotoAsync($"{Pasture.Site}/"); await page.Locator("[data-unread]").WaitForAsync(new() { Timeout = 30000 }); await page.GetByRole(AriaRole.Tab).Filter(new() { Has = page.Locator(".ion-md-notifications") }).ClickAsync(); var card = page.Locator($"article[data-uri='{post["uri"]!.GetValue()}']").Filter(new() { Has = page.Locator("[data-notification='favourite']") }); await card.WaitForAsync(new() { Timeout = 30000 }); await Assertions.Expect(card.Locator("[data-notification='favourite']")).ToHaveAttributeAsync("data-count", "2"); await Assertions.Expect(card).ToContainTextAsync($"{second.Name} and {first.Name} favourited your post"); Assert.True(await Pasture.Eventually(async () => (await PersonaApi.Call(author, "/api/v2/notifications/unread_count"))!["count"]!.GetValue() == 0, 15), "reading the tab left notifications unread"); await Assertions.Expect(page.Locator("[data-unread]")).ToHaveCountAsync(0); await session.AssertGuards(); }, page); } finally { await PersonaApi.Call(author, $"/api/v1/statuses/{id}", HttpMethod.Delete); } } } }