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

82 lines
3.6 KiB
C#
Raw Normal View History

using System.IO.Compression;
using decePubClient.E2E.Support;
using Microsoft.Playwright;
namespace decePubClient.E2E.Actions
{
// A persona's archive from Settings (owner decision 2026-10-07): one town persona's archive made and downloaded through
// its link, then imported into another, whose profile shows the posts while nobody was told; the copies are taken away
// again after, so the town stays as seeded
public sealed class PersonaArchiveTests(Browser browser)
{
static async Task<ILocator> Open(IPage page)
{
await page.GotoAsync($"{Pasture.Site}/settings");
var header = page.Locator(".collapse-title", new() { HasText = "Data import/export" }).First;
await header.ClickAsync();
var panel = header.Locator("xpath=..").Locator("[data-archive]");
await panel.WaitForAsync(new() { Timeout = 30000 });
return panel;
}
[Fact]
public async Task An_archive_is_downloaded_and_imported_into_another_persona()
{
var personas = Pasture.Personas();
var (source, target) = (personas[0], personas[1]);
var file = Path.Combine(Path.GetTempPath(), $"decepub-archive-{Guid.NewGuid():N}.zip");
try
{
await using (var session = await SignIn.As(browser, source))
{
var page = session.Page;
await Results.Cell("client.action.archive-export", "privapub", source.UserName, async () =>
{
var panel = await Open(page);
await panel.Locator("[data-archive-make]").ClickAsync();
var get = panel.Locator("[data-archive-get-link]");
await get.WaitForAsync(new() { Timeout = 120000 });
await get.ClickAsync();
var link = panel.Locator("[data-archive-link]");
var download = await page.RunAndWaitForDownloadAsync(() => link.ClickAsync(), new() { Timeout = 120000 });
await download.SaveAsAsync(file);
using var archive = ZipFile.OpenRead(file);
Assert.Contains(archive.Entries, e => e.FullName == "outbox.json");
Assert.Contains(archive.Entries, e => e.FullName == "actor.json");
Assert.DoesNotContain(archive.Entries, e => e.FullName.Contains(source.Root, StringComparison.Ordinal));
await session.AssertGuards();
}, page);
}
await using (var session = await SignIn.As(browser, target))
{
var page = session.Page;
await Results.Cell("client.action.archive-import", "privapub", target.UserName, async () =>
{
var panel = await Open(page);
await panel.Locator("input[data-archive-file]").SetInputFilesAsync(file);
foreach (var part in new[] { "follows", "blocks", "mutes", "domainblocks", "lists", "bookmarks", "filters", "tags", "pins" })
await panel.Locator($"[data-archive-part='{part}'] input, input[data-archive-part='{part}']").First.UncheckAsync();
await panel.Locator("[data-archive-import-start]").ClickAsync();
var report = panel.Locator("[data-archive-report][data-archive-state='done']");
await report.WaitForAsync(new() { Timeout = 300000 });
await Assertions.Expect(report.Locator("[data-archive-count='posts']")).ToBeVisibleAsync();
var copies = (await PersonaApi.Call(target, $"/api/v1/accounts/{target.LocalId}/statuses?limit=40"))!.AsArray();
Assert.NotEmpty(copies);
await session.AssertGuards();
}, page);
}
}
finally
{
File.Delete(file);
// the copies go, as if never imported: the town stays as seeded
await Pasture.Mongo($"const copies = db.Post.find({{GroupUserId:'{target.LocalId}', ImportedFromURI:{{$exists:true, $ne:null}}}}, {{_id:1}}).toArray().map(p => p._id); "
+ "db.MediaAttachment.deleteMany({PostId:{$in:copies.map(id => id.toString())}}); db.Post.deleteMany({_id:{$in:copies}})");
}
}
}
}