using FluentAssertions; using IBKRTrader.Core.Logging; using IBKRTrader.Modules.CongressTrading.Scraper; namespace IBKRTrader.Tests.Modules; [Trait("cat", "unit")] public class CapitolTradesScraperTests { private static string LoadFixture() { var path = Path.Combine(AppContext.BaseDirectory, "Fixtures", "ct_raw.html"); File.Exists(path).Should().BeTrue($"Fixture fehlt: {path}"); return File.ReadAllText(path); } [Fact] public void ParseTradesFromHtml_ExtractsTradesFromRscStream() { var scraper = new CapitolTradesScraper(new LoggingService()); var (trades, memberIds) = scraper.ParseTradesFromHtml(LoadFixture()); trades.Should().NotBeEmpty("die Fixture enthält einen RSC-Datenstrom mit Trades"); memberIds.Should().NotBeEmpty(); var first = trades[0]; first.TradeId.Should().NotBeNullOrWhiteSpace(); first.TradeType.Should().NotBeNullOrWhiteSpace(); } [Fact] public void ParseTradesFromHtml_MapsMemberSnapshotConsistently() { var scraper = new CapitolTradesScraper(new LoggingService()); var (trades, memberIds) = scraper.ParseTradesFromHtml(LoadFixture()); // Jeder Member-Snapshot muss eine BioId haben, die auch im MemberBioIds-Set liegt. foreach (var trade in trades.Where(t => t.MemberSnapshot is not null)) { trade.MemberSnapshot!.BioId.Should().NotBeNullOrWhiteSpace(); memberIds.Should().Contain(trade.MemberBioId); } } [Fact] public void ParseTradesFromHtml_EmptyHtml_ReturnsNoTrades() { var scraper = new CapitolTradesScraper(new LoggingService()); var (trades, memberIds) = scraper.ParseTradesFromHtml("nichts"); trades.Should().BeEmpty(); memberIds.Should().BeEmpty(); } }