using FluentAssertions; using InboxIntel.Application.Abstractions; using InboxIntel.Application.Search; using InboxIntel.Domain.Entities; using InboxIntel.Infrastructure.Persistence; using InboxIntel.Infrastructure.Search; using Microsoft.EntityFrameworkCore; using Xunit; namespace InboxIntel.IntegrationTests; /// /// SearchService now relevance-ranks (ts_rank_cd via RankCoverDensity) when a free-text /// query is present, falling back to date order otherwise. The ranked path requires a /// live PostgreSQL instance to exercise (EF's InMemory provider cannot translate /// websearch_to_tsquery/RankCoverDensity) — this project deliberately avoids a hard /// Postgres/Testcontainers dependency for tests (see AuthEndpointsTests.TestAppFactory), /// so ranking correctness itself is verified manually/in staging, not here. What IS /// covered: the date-order fallback, which is plain LINQ and must not regress. /// public class SearchRankingTests { private sealed class FakeCurrentUser : ICurrentUser { public Guid UserId { get; set; } public bool IsAuthenticated => UserId != Guid.Empty; } [Fact] public async Task No_query_falls_back_to_date_descending_order() { var user = Guid.NewGuid(); var opts = new DbContextOptionsBuilder() .UseInMemoryDatabase(nameof(No_query_falls_back_to_date_descending_order)).Options; using (var seed = new AppDbContext(opts, new FakeCurrentUser())) { var sender = new Sender { UserId = user, Address = "sender@example.com", DisplayName = "Sender" }; seed.Senders.Add(sender); var baseline = DateTimeOffset.UtcNow; seed.Emails.Add(new Email { UserId = user, GmailMessageId = "oldest", SentAtUtc = baseline.AddDays(-2), Sender = sender }); seed.Emails.Add(new Email { UserId = user, GmailMessageId = "newest", SentAtUtc = baseline, Sender = sender }); seed.Emails.Add(new Email { UserId = user, GmailMessageId = "middle", SentAtUtc = baseline.AddDays(-1), Sender = sender }); await seed.SaveChangesAsync(); } using var ctx = new AppDbContext(opts, new FakeCurrentUser { UserId = user }); var request = GmailQueryParser.Parse(null, page: 1, pageSize: 50); var result = await new SearchService(ctx).SearchAsync(user, request); result.Items.Select(i => i.GmailMessageId).Should().ContainInOrder("newest", "middle", "oldest"); } }