Files

63 lines
3.4 KiB
C#
Raw Permalink Normal View History

using System.Net.Http.Headers;
using System.Text;
using System.Text.Json.Nodes;
using decePubClient.E2E.Support;
using Microsoft.Playwright;
namespace decePubClient.E2E.Actions
{
// An article in a feed shows its title, its excerpt and a Read button, and its whole text once asked: a WriteFreely
// blog the persona follows publishes one (SocialPub's peers/writefreely.sh keeps the blog's token).
public sealed class ArticleTests(Browser browser)
{
[Fact]
public async Task An_article_is_folded_in_the_feed_and_read_on_demand()
{
var tokenFile = Path.Combine(Pasture.Root, ".state", "writefreely", "wfuser.token");
Assert.SkipUnless(File.Exists(tokenFile), "no WriteFreely blog: run tools/pasture/run.sh add writefreely");
var persona = Pasture.Personas().First();
var blog = (await PersonaApi.Call(persona, "/api/v2/search?q=wfuser%40writefreely.test&resolve=true&type=accounts"))?["accounts"]?.AsArray().FirstOrDefault();
Assert.SkipWhen(blog is null, "PrivaPub cannot resolve the WriteFreely blog");
var blogId = blog!["id"]!.GetValue<string>();
await PersonaApi.Call(persona, $"/api/v1/accounts/{blogId}/follow", HttpMethod.Post);
Assert.True(await Pasture.Eventually(async () =>
(await PersonaApi.Call(persona, $"/api/v1/accounts/relationships?id[]={blogId}"))![0]!["following"]!.GetValue<bool>(), 45), "the blog never accepted");
var title = $"An article to fold {Guid.NewGuid():N}"[..30];
var ending = $"the last words {Guid.NewGuid():N}"[..24];
var body = string.Join(" ", Enumerable.Repeat("A long paragraph that a feed should not show whole.", 12)) + " " + ending;
using var http = Pasture.Http();
using var publish = new HttpRequestMessage(HttpMethod.Post, "https://writefreely.test/api/collections/wfuser/posts")
{
Content = new StringContent(new JsonObject { ["title"] = title, ["body"] = body }.ToJsonString(), Encoding.UTF8, "application/json")
};
publish.Headers.Authorization = new AuthenticationHeaderValue("Token", File.ReadAllText(tokenFile).Trim());
(await http.SendAsync(publish)).EnsureSuccessStatusCode();
JsonNode article = null;
Assert.True(await Pasture.Eventually(async () =>
(article = (await PersonaApi.Call(persona, "/api/v1/timelines/home?limit=40"))!.AsArray()
.FirstOrDefault(s => s!["privapub"]?["title"]?.GetValue<string>() == title)) is not null, 60), "the article never reached the persona");
await using var session = await SignIn.As(browser, persona);
var page = session.Page;
await Results.Cell("client.render.article", "writefreely", persona.UserName, async () =>
{
await page.GotoAsync($"{Pasture.Site}/");
await page.EvaluateAsync("() => localStorage.removeItem('FeedFilter')");
await page.GotoAsync($"{Pasture.Site}/");
var card = page.Locator($"article[data-uri='{article!["uri"]!.GetValue<string>()}']").First;
await card.WaitForAsync(new() { Timeout = 30000 });
await Assertions.Expect(card).ToContainTextAsync(title);
await Assertions.Expect(card.Locator("[data-article]")).ToBeVisibleAsync();
await Assertions.Expect(card).Not.ToContainTextAsync(ending);
await card.Locator("[data-article-open]").ClickAsync();
await Assertions.Expect(card).ToContainTextAsync(ending, new() { Timeout = 5000 });
await session.AssertGuards();
}, page);
await PersonaApi.Call(persona, $"/api/v1/accounts/{blogId}/unfollow", HttpMethod.Post);
}
}
}