using System.Text.Json.Nodes; using decePubClient.E2E.Support; using Microsoft.Playwright; namespace decePubClient.E2E.Actions { // A persona pins its own post from the card, finds it above its posts on its profile, and unpins it. PrivaPub tells // the persona's followers with Add and Remove; SocialPub's tools/pasture/scenarios/pins.sh checks that side. public sealed class PinTests(Browser browser) { [Fact] public async Task A_persona_pins_its_post_from_the_card_and_its_profile_shows_it_first() { var persona = Pasture.Personas().First(); var text = $"pin me {Guid.NewGuid():N}"[..20]; var post = (await PersonaApi.Call(persona, "/api/v1/statuses", HttpMethod.Post, new JsonObject { ["status"] = text, ["visibility"] = "public" }))!; var id = post["id"]!.GetValue(); var me = (await PersonaApi.Call(persona, "/api/v1/accounts/verify_credentials"))!["id"]!.GetValue(); async Task Pinned() => (await PersonaApi.Call(persona, $"/api/v1/accounts/{me}/statuses?pinned=true"))!.AsArray().Any(s => s!["id"]!.GetValue() == id); await using var session = await SignIn.As(browser, persona); var page = session.Page; try { await Results.Cell("client.action.pin", "privapub", persona.UserName, async () => { await page.GotoAsync($"{Pasture.Site}/account/{me}"); var card = page.Locator($"article[data-uri='{post["uri"]!.GetValue()}']").First; await card.WaitForAsync(new() { Timeout = 30000 }); await card.Locator("footer [title='Other'] > [role=button]").ClickAsync(); await card.Locator("button[data-pin]").ClickAsync(); Assert.True(await Pasture.Eventually(Pinned, 15), "the pin never reached PrivaPub"); await page.ReloadAsync(); var pinnedCard = page.Locator($"[data-pinned] article[data-uri='{post["uri"]!.GetValue()}']"); await pinnedCard.WaitForAsync(new() { Timeout = 30000 }); Assert.Equal(1, await page.Locator($"article[data-uri='{post["uri"]!.GetValue()}']").CountAsync()); await pinnedCard.Locator("footer [title='Other'] > [role=button]").ClickAsync(); await Assertions.Expect(pinnedCard.Locator("button[data-pin]")).ToContainTextAsync("Unpin", new() { Timeout = 5000 }); await pinnedCard.Locator("button[data-pin]").ClickAsync(); Assert.True(await Pasture.Eventually(async () => !await Pinned(), 15), "the unpin never reached PrivaPub"); await session.AssertGuards(); }, page); } finally { await PersonaApi.Call(persona, $"/api/v1/statuses/{id}", HttpMethod.Delete); } } } }