using System; using System.Linq; using PolyTrader.Modules.CopyTrading.Persistence.Ef; using PolyTrader.Tests.TestSupport; using PolyTraderSharp.Models; using Xunit; namespace PolyTrader.Tests { public class RepositoryEdgeCaseTests { private static EfTrackedTraderRepository TraderRepo() => new(new InMemoryContextFactory(o => new CopyTradingDbContext(o))); private static EfMasterTraderHistoryRepository HistoryRepo() => new(new InMemoryContextFactory(o => new CopyTradingDbContext(o))); [Fact] public void GetAll_on_empty_repo_returns_empty_not_null() { var repo = TraderRepo(); var all = repo.GetAll(); Assert.NotNull(all); Assert.Empty(all); } [Fact] public void Update_alias_behaves_like_upsert_for_existing() { var repo = TraderRepo(); repo.Upsert(new TrackedTrader { Id = 1, DisplayName = "A" }); repo.Update(new TrackedTrader { Id = 1, DisplayName = "B" }); Assert.Equal("B", Assert.Single(repo.GetAll()).DisplayName); } [Fact] public void Two_factories_are_isolated_from_each_other() { var a = TraderRepo(); var b = TraderRepo(); a.Upsert(new TrackedTrader { Id = 1 }); Assert.Single(a.GetAll()); Assert.Empty(b.GetAll()); } [Fact] public void History_Exists_is_inclusive_on_window_boundaries() { var repo = HistoryRepo(); var t = new DateTime(2026, 7, 1, 12, 0, 0, DateTimeKind.Utc); repo.Insert(new MasterTraderHistoryRecord { TraderId = 1, TokenId = "tok", ClosedAt = t }); // Fenster endet exakt auf dem Zeitpunkt (untere Grenze) Assert.True(repo.Exists(1, "tok", t, t.AddSeconds(2))); // Fenster beginnt exakt auf dem Zeitpunkt (obere Grenze) Assert.True(repo.Exists(1, "tok", t.AddSeconds(-2), t)); } [Fact] public void GetByTraderSince_is_inclusive_on_cutoff() { var repo = HistoryRepo(); var cutoff = new DateTime(2026, 7, 1, 0, 0, 0, DateTimeKind.Utc); repo.Insert(new MasterTraderHistoryRecord { TraderId = 1, ClosedAt = cutoff }); // genau am Cutoff -> drin repo.Insert(new MasterTraderHistoryRecord { TraderId = 1, ClosedAt = cutoff.AddTicks(-1) }); // knapp davor -> raus Assert.Single(repo.GetByTraderSince(1, cutoff)); } } }