using MongoDB.Entities; using PrivaPub.ClientModels.Post; using PrivaPub.Domain.Privacy; using PrivaPub.Federation.Outbox; using PrivaPub.Models.Jobs; using PrivaPub.Models.Post; using PrivaPub.Tests.Support; using System.Text.Json; namespace PrivaPub.Tests.Domain { [Trait("Category", "Integration")] public sealed class NearbyTests : IAsyncLifetime { Harness _harness; public async ValueTask InitializeAsync() { Assert.SkipUnless(MongoFixture.Enabled, MongoFixture.Skip); _harness = await Harness.Start(); } public async ValueTask DisposeAsync() { if (_harness != default) await _harness.DisposeAsync(); } [Fact] public async Task A_located_post_reaches_only_those_within_its_radius_and_never_leaves_the_server() { var token = TestContext.Current.CancellationToken; var latitude = 10 + Random.Shared.NextDouble() * 50; var longitude = 10 + Random.Shared.NextDouble() * 50; var (aliceRoot, alice) = await _harness.Persona("alice"); var (bobRoot, bob) = await _harness.Persona("bob"); var (carolRoot, carol) = await _harness.Persona("carol"); var follower = new RemoteActor(_harness.Peer, "follower"); await _harness.FollowedBy(alice, follower); var created = await _harness.Posts.InsertPost(aliceRoot, new InsertPostForm { AvatarId = alice.Id, Text = "free bread at the bakery", Latitude = latitude, Longitude = longitude, RangeKm = 5 }, token); var post = await DB.Default.Find().OneAsync(((ViewPost)created.Data).Id, token); var three = (List)(await _harness.Posts.Nearby(bobRoot, bob.Id, latitude + 0.027, longitude, token)).Data; var eight = (List)(await _harness.Posts.Nearby(carolRoot, carol.Id, latitude + 0.072, longitude, token)).Data; Assert.Equal(PostVisibility.LocalGeo, post.Visibility); Assert.Equal(Math.Round(latitude, 2), post.Geo.Coordinates[1]); Assert.Contains(three, p => p.Id == post.ID); Assert.InRange(three.First(p => p.Id == post.ID).DistanceKm.Value, 2.0, 4.0); Assert.DoesNotContain(eight, p => p.Id == post.ID); Assert.False(await VisibilityPolicy.CanSee(post, bob.Id, token)); var outgoing = (await DB.Default.Find().Match(j => j.Kind == JobKind.Deliver).ExecuteAsync(token)) .Select(j => JsonSerializer.Deserialize(j.Payload)) .Where(p => p.Body.Contains(post.ID)); Assert.Empty(outgoing); } [Fact] public async Task A_located_post_cannot_be_direct_or_in_a_group() { var (root, alice) = await _harness.Persona("alice"); var result = await _harness.Statuses.Publish(alice, new PrivaPub.Domain.Statuses.StatusDraft { Text = "x", Latitude = 45, Longitude = 7, Visibility = PostVisibility.Direct }, TestContext.Current.CancellationToken); Assert.False(result.Ok); } } }