76 lines
4.1 KiB
C#
76 lines
4.1 KiB
C#
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);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|