Files
decePubClient/tests/e2e/Actions/NotificationPolicyTests.cs
T

76 lines
4.1 KiB
C#
Raw Normal View History

using System.Text.Json.Nodes;
using decePubClient.E2E.Support;
using Microsoft.Playwright;
namespace decePubClient.E2E.Actions
{
// The persona's notification policy from Settings: people it does not follow are filtered, a like from one waits in a
// request the Notifications tab leads to, and letting the request in brings the notification back; the policy is put back to accepting everything, and
// the stranger's permission is taken away again
public sealed class NotificationPolicyTests(Browser browser)
{
[Fact]
public async Task A_strangers_like_waits_in_a_request_the_persona_lets_in()
{
var personas = Pasture.Personas();
var author = personas[0];
// (a persona of the town the author does not follow)
var stranger = default(Pasture.Persona);
foreach (var candidate in personas.Skip(1))
if ((await PersonaApi.Call(author, $"/api/v1/accounts/relationships?id[]={candidate.LocalId}"))![0]!["following"]!.GetValue<bool>() == false)
{
stranger = candidate;
break;
}
Assert.SkipWhen(stranger is null, "the town's first persona follows every other");
var strangerAcct = (await PersonaApi.Call(stranger!, "/api/v1/accounts/verify_credentials"))!["acct"]!.GetValue<string>();
var post = (await PersonaApi.Call(author, "/api/v1/statuses", HttpMethod.Post,
new JsonObject { ["status"] = $"like me, stranger {Guid.NewGuid():N}"[..30], ["visibility"] = "public" }))!;
var id = post["id"]!.GetValue<string>();
await using var session = await SignIn.As(browser, author);
var page = session.Page;
try
{
await Results.Cell("client.action.notification-policy", "privapub", author.UserName, async () =>
{
await page.GotoAsync($"{Pasture.Site}/settings");
var header = page.Locator(".collapse-title", new() { HasText = "Notifications" }).First;
await header.ClickAsync();
var panel = page.Locator("[data-notification-policy]");
await panel.WaitForAsync(new() { Timeout = 30000 });
await panel.Locator("[data-policy='for_not_following']").SelectOptionAsync("filter");
await panel.Locator("[data-policy-save]").ClickAsync();
Assert.True(await Pasture.Eventually(async () =>
(await PersonaApi.Call(author, "/api/v2/notifications/policy"))!["for_not_following"]!.GetValue<string>() == "filter", 15), "the policy was never saved");
await PersonaApi.Call(stranger!, $"/api/v1/statuses/{id}/favourite", HttpMethod.Post);
Assert.DoesNotContain((await PersonaApi.Call(author, "/api/v1/notifications?types[]=favourite"))!.AsArray(),
n => n!["account"]!["acct"]!.GetValue<string>() == strangerAcct && n["status"]?["id"]?.GetValue<string>() == id);
// the Notifications tab says requests are waiting, and leads to them
await page.GotoAsync($"{Pasture.Site}/");
await page.EvaluateAsync("() => localStorage.removeItem('FeedFilter')");
await page.GotoAsync($"{Pasture.Site}/");
await page.GetByRole(AriaRole.Tab).Filter(new() { Has = page.Locator(".ion-md-notifications") }).ClickAsync();
await page.Locator("[data-filtered-requests]").ClickAsync(new() { Timeout = 30000 });
var request = page.Locator($"[data-notification-requests] [data-request='{strangerAcct}']");
await request.WaitForAsync(new() { Timeout = 30000 });
await request.Locator("[data-request-accept]").ClickAsync();
await Assertions.Expect(request).ToHaveCountAsync(0, new() { Timeout = 15000 });
Assert.Contains((await PersonaApi.Call(author, "/api/v1/notifications?types[]=favourite"))!.AsArray(),
n => n!["account"]!["acct"]!.GetValue<string>() == strangerAcct && n["status"]?["id"]?.GetValue<string>() == id);
await session.AssertGuards();
}, page);
}
finally
{
await PersonaApi.Call(author, "/api/v2/notifications/policy", HttpMethod.Patch, new JsonObject { ["for_not_following"] = "accept" });
// (letting a request in lets its account in for good, which no API takes back)
await Pasture.Mongo($"db.NotificationPermission.deleteMany({{AvatarId: '{author.LocalId}', FromActorURI: '{stranger!.ActorUri}'}})");
await PersonaApi.Call(author, $"/api/v1/statuses/{id}", HttpMethod.Delete);
}
}
}
}