using FluentAssertions; using Marathon.Infrastructure.Scraping.Parsers; using Microsoft.Extensions.Logging.Abstractions; namespace Marathon.Infrastructure.Tests.Scraping; public sealed class UpcomingEventsParserTests { private static readonly string FixturePath = Path.Combine( AppContext.BaseDirectory, "Fixtures", "marathonbet", "listing-sample.html"); private readonly UpcomingEventsParser _sut; public UpcomingEventsParserTests() { var serverTimeProvider = new ServerTimeProvider( NullLogger.Instance); _sut = new UpcomingEventsParser( serverTimeProvider, NullLogger.Instance); } [Fact] public async Task ParseAsync_SampleListing_ReturnsThreeEvents() { var html = await File.ReadAllTextAsync(FixturePath); var events = await _sut.ParseAsync(html); events.Should().HaveCount(3); } [Fact] public async Task ParseAsync_SampleListing_FootballEventHasCorrectSport() { var html = await File.ReadAllTextAsync(FixturePath); var events = await _sut.ParseAsync(html); var football = events.Single(e => e.Id.Value == "26456117"); football.Sport.Value.Should().Be(11); // Football canonical ID } [Fact] public async Task ParseAsync_SampleListing_BasketballEventHasCorrectSport() { var html = await File.ReadAllTextAsync(FixturePath); var events = await _sut.ParseAsync(html); var basketball = events.Single(e => e.Id.Value == "26769028"); basketball.Sport.Value.Should().Be(6); // Basketball canonical ID } [Fact] public async Task ParseAsync_SampleListing_EventNamesAreSplit() { var html = await File.ReadAllTextAsync(FixturePath); var events = await _sut.ParseAsync(html); var football = events.Single(e => e.Id.Value == "26456117"); football.Side1Name.Should().Be("Арсенал"); football.Side2Name.Should().Be("Атлетико Мадрид"); } [Fact] public async Task ParseAsync_SampleListing_ScheduledAtIsMoscowOffset() { var html = await File.ReadAllTextAsync(FixturePath); var events = await _sut.ParseAsync(html); foreach (var evt in events) { evt.ScheduledAt.Offset.Should().Be(TimeSpan.FromHours(3), "all events must be in Moscow time (UTC+3)"); } } [Fact] public async Task ParseAsync_SampleListing_FootballEventLeagueExtracted() { var html = await File.ReadAllTextAsync(FixturePath); var events = await _sut.ParseAsync(html); var football = events.Single(e => e.Id.Value == "26456117"); football.LeagueId.Should().Contain("UEFA"); } [Fact] public async Task ParseAsync_EmptyHtml_ReturnsEmptyList() { const string html = ""; var events = await _sut.ParseAsync(html); events.Should().BeEmpty(); } }