542f15f2d6
PR Checks / test-and-build (pull_request) Successful in 13m48s
- Extract CreateSessionHandler, ListSessionsHandler, DeleteSessionHandler, ExportCalendarHandler, HandleRescheduleTimeInputHandler, HandleRescheduleVoteHandler to GmRelay.Shared - Add IPlatformMessenger methods: SendScheduleAsync, UpdateScheduleAsync, SendGroupMessageAsync with actions, CreateThreadAsync, DeleteThreadAsync - Rewrite Telegram Bot wrappers as thin adapters delegating to shared handlers - Rewrite DiscordRescheduleVoteHandler to use shared HandleRescheduleVoteHandler - Update UpdateRouter with explicit type aliases for ambiguous handler names - Add contract and source-inspection tests for extracted handlers - Bump version 3.1.1 → 3.2.0 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
121 lines
4.4 KiB
C#
121 lines
4.4 KiB
C#
using BotHandler = GmRelay.Bot.Features.Sessions.RescheduleSession.HandleRescheduleTimeInputHandler;
|
||
using GmRelay.Shared.Features.Sessions.RescheduleSession;
|
||
|
||
namespace GmRelay.Bot.Tests.Features.Sessions.RescheduleSession;
|
||
|
||
public sealed class HandleRescheduleTimeInputHandlerTests
|
||
{
|
||
[Fact]
|
||
public void TryParseVotingInput_ShouldAcceptTwoOptionsAndDeadline()
|
||
{
|
||
var now = new DateTimeOffset(2026, 4, 24, 8, 0, 0, TimeSpan.Zero);
|
||
|
||
var ok = RescheduleVotingInput.TryParse(
|
||
"""
|
||
25.04.2026 19:30
|
||
26.04.2026 18:00
|
||
Дедлайн: 25.04.2026 12:00
|
||
""",
|
||
now,
|
||
out var input,
|
||
out var error);
|
||
|
||
Assert.True(ok, error);
|
||
Assert.Equal(2, input.Options.Count);
|
||
Assert.Equal(new DateTimeOffset(2026, 4, 25, 16, 30, 0, TimeSpan.Zero), input.Options[0]);
|
||
Assert.Equal(new DateTimeOffset(2026, 4, 26, 15, 0, 0, TimeSpan.Zero), input.Options[1]);
|
||
Assert.Equal(new DateTimeOffset(2026, 4, 25, 9, 0, 0, TimeSpan.Zero), input.Deadline);
|
||
}
|
||
|
||
[Fact]
|
||
public void TryParseVotingInput_ShouldRejectSingleOption()
|
||
{
|
||
var now = new DateTimeOffset(2026, 4, 24, 8, 0, 0, TimeSpan.Zero);
|
||
|
||
var ok = RescheduleVotingInput.TryParse(
|
||
"""
|
||
25.04.2026 19:30
|
||
Дедлайн: 25.04.2026 12:00
|
||
""",
|
||
now,
|
||
out _,
|
||
out var error);
|
||
|
||
Assert.False(ok);
|
||
Assert.Equal("Укажите от 2 до 3 вариантов времени.", error);
|
||
}
|
||
|
||
[Fact]
|
||
public void BuildVotingMessage_ShouldShowOptionsDeadlineVotesAndPendingParticipants()
|
||
{
|
||
var firstOptionId = Guid.NewGuid();
|
||
var secondOptionId = Guid.NewGuid();
|
||
var aliceId = Guid.NewGuid();
|
||
var bobId = Guid.NewGuid();
|
||
var charlieId = Guid.NewGuid();
|
||
var currentTime = new DateTime(2026, 4, 25, 16, 30, 0, DateTimeKind.Utc);
|
||
var deadline = new DateTimeOffset(2026, 4, 25, 9, 0, 0, TimeSpan.Zero);
|
||
var options = new List<RescheduleOptionDto>
|
||
{
|
||
new(firstOptionId, 1, new DateTimeOffset(2026, 4, 26, 16, 0, 0, TimeSpan.Zero)),
|
||
new(secondOptionId, 2, new DateTimeOffset(2026, 4, 27, 17, 0, 0, TimeSpan.Zero))
|
||
};
|
||
var participants = new List<VoteParticipantDto>
|
||
{
|
||
new(aliceId, "Alice", "alice"),
|
||
new(bobId, "Bob", null),
|
||
new(charlieId, "Charlie", null)
|
||
};
|
||
var votes = new List<RescheduleOptionVoteDto>
|
||
{
|
||
new(firstOptionId, aliceId, "Alice", "alice"),
|
||
new(secondOptionId, bobId, "Bob", null)
|
||
};
|
||
|
||
var text = BotHandler.BuildVotingMessage(
|
||
"Shadowrun",
|
||
currentTime,
|
||
deadline,
|
||
options,
|
||
participants,
|
||
votes);
|
||
|
||
Assert.Contains("Shadowrun", text);
|
||
Assert.Contains("Дедлайн: <b>25 апреля 2026, 12:00</b> (МСК)", text);
|
||
Assert.Contains("1. <b>26 апреля 2026, 19:00</b> (МСК) — 1 голос", text);
|
||
Assert.Contains("@alice", text);
|
||
Assert.Contains("2. <b>27 апреля 2026, 20:00</b> (МСК) — 1 голос", text);
|
||
Assert.Contains("Bob", text);
|
||
Assert.Contains("Не проголосовали: Charlie", text);
|
||
Assert.Contains("Голосов: 2/3", text);
|
||
}
|
||
|
||
[Fact]
|
||
public void BuildVotingKeyboard_ShouldCreateOneButtonPerOption()
|
||
{
|
||
var firstOptionId = Guid.NewGuid();
|
||
var secondOptionId = Guid.NewGuid();
|
||
var options = new List<RescheduleOptionDto>
|
||
{
|
||
new(firstOptionId, 1, new DateTimeOffset(2026, 4, 26, 16, 0, 0, TimeSpan.Zero)),
|
||
new(secondOptionId, 2, new DateTimeOffset(2026, 4, 27, 17, 0, 0, TimeSpan.Zero))
|
||
};
|
||
|
||
var keyboard = BotHandler.BuildVotingKeyboard(options);
|
||
var buttons = keyboard.InlineKeyboard.SelectMany(row => row).ToList();
|
||
|
||
Assert.Collection(
|
||
buttons,
|
||
button =>
|
||
{
|
||
Assert.Equal("1. 26.04 19:00", button.Text);
|
||
Assert.Equal($"reschedule_vote:{firstOptionId}", button.CallbackData);
|
||
},
|
||
button =>
|
||
{
|
||
Assert.Equal("2. 27.04 20:00", button.Text);
|
||
Assert.Equal($"reschedule_vote:{secondOptionId}", button.CallbackData);
|
||
});
|
||
}
|
||
}
|