using GmRelay.Bot.Features.Sessions.CreateSession; namespace GmRelay.Bot.Tests.Features.Sessions.CreateSession; public sealed class NewSessionCommandParserTests { [Fact] public void Parse_ShouldExtractTitleLinkAndUpcomingTimes() { var nowUtc = new DateTimeOffset(2026, 4, 23, 12, 0, 0, TimeSpan.Zero); var text = """ /newsession Название: Curse of Strahd Время: 24.04.2026 19:30 Время: 01.05.2026 20:00 Мест: 4 Ссылка: https://example.test/room """; var result = NewSessionCommandParser.Parse(text, nowUtc); Assert.True(result.IsValid); Assert.Equal("Curse of Strahd", result.Title); Assert.Equal("https://example.test/room", result.Link); Assert.Equal(4, result.MaxPlayers); Assert.Equal( [ new DateTimeOffset(2026, 4, 24, 16, 30, 0, TimeSpan.Zero), new DateTimeOffset(2026, 5, 1, 17, 0, 0, TimeSpan.Zero) ], result.ScheduledTimes); Assert.Empty(result.PastTimeInputs); Assert.Empty(result.InvalidTimeInputs); } [Fact] public void Parse_ShouldExpandRecurringSchedule_WhenRepeatCountAndIntervalProvided() { var nowUtc = new DateTimeOffset(2026, 4, 23, 12, 0, 0, TimeSpan.Zero); var text = """ /newsession Название: Kingmaker Время: 30.04.2026 19:30 Игр: 4 Интервал: 14 Ссылка: https://example.test/kingmaker """; var result = NewSessionCommandParser.Parse(text, nowUtc); Assert.True(result.IsValid); Assert.Equal( [ new DateTimeOffset(2026, 4, 30, 16, 30, 0, TimeSpan.Zero), new DateTimeOffset(2026, 5, 14, 16, 30, 0, TimeSpan.Zero), new DateTimeOffset(2026, 5, 28, 16, 30, 0, TimeSpan.Zero), new DateTimeOffset(2026, 6, 11, 16, 30, 0, TimeSpan.Zero) ], result.ScheduledTimes); } [Fact] public void Parse_ShouldCollectPastAndInvalidTimes() { var nowUtc = new DateTimeOffset(2026, 4, 23, 12, 0, 0, TimeSpan.Zero); var text = """ Название: Delta Green Время: 20.04.2026 19:30 Время: 31.04.2026 19:30 Время: 25.04.2026 18:00 Ссылка: https://example.test/dg """; var result = NewSessionCommandParser.Parse(text, nowUtc); Assert.True(result.IsValid); Assert.Single(result.ScheduledTimes); Assert.Equal(["20.04.2026 19:30"], result.PastTimeInputs); Assert.Equal(["31.04.2026 19:30"], result.InvalidTimeInputs); } [Fact] public void Parse_ShouldBeInvalid_WhenRequiredFieldsMissing() { var text = """ /newsession Название: Blades in the Dark Время: 25.04.2026 19:30 """; var result = NewSessionCommandParser.Parse(text, DateTimeOffset.UtcNow); Assert.False(result.IsValid); Assert.Null(result.Link); } [Fact] public void Parse_ShouldCollectInvalidSeatLimit() { var text = """ /newsession Название: Blades in the Dark Время: 25.04.2026 19:30 Мест: 0 Ссылка: https://example.test/blades """; var result = NewSessionCommandParser.Parse(text, DateTimeOffset.UtcNow); Assert.False(result.IsValid); Assert.Null(result.MaxPlayers); Assert.Equal(["0"], result.InvalidSeatLimitInputs); } }