Files
GmRelayBot/tests/GmRelay.Bot.Tests/Features/Sessions/CreateSession/Wizard/CreateSessionHandlerSubmitSingleDraftTests.cs
T
Toutsu 956ec01583
PR Checks / test-and-build (pull_request) Successful in 11m58s
fix(bot): publish wizard-created sessions
After the shared create handler persists sessions, create a Telegram topic when needed, send the schedule/signup message, and store thread_id/batch_message_id/topic_created_by_bot for the batch. Add a Testcontainers regression test for the wizard SubmitDraftAsync happy path. Bump version to 3.9.9.
2026-06-09 16:16:36 +03:00

106 lines
4.4 KiB
C#

using GmRelay.Bot.Features.Sessions.CreateSession;
using GmRelay.Shared.Features.Sessions.CreateSession.Wizard;
using GmRelay.Shared.Platform;
using Microsoft.Extensions.Logging.Abstractions;
using Npgsql;
using static GmRelay.Bot.Tests.Features.Sessions.CreateSession.Wizard.WizardTestFakes;
namespace GmRelay.Bot.Tests.Features.Sessions.CreateSession.Wizard;
[Collection(CreateSessionHandlerPostgresCollection.Name)]
public sealed class CreateSessionHandlerSubmitSingleDraftTests(CreateSessionHandlerPostgresFixture fixture)
{
[Fact]
public async Task SubmitDraftAsync_CompleteSinglePayload_PublishesScheduleAndStoresMessageRefs()
{
var connectionString = await fixture.CreateMigratedDatabaseAsync();
await using var dataSource = NpgsqlDataSource.Create(connectionString);
var drafts = new FakeWizardDraftRepository();
var wizardMessenger = new FakeWizardMessenger();
var platformMessenger = new FakePlatformMessenger();
var sut = new CreateSessionHandler(
drafts,
new GmRelay.Shared.Features.Sessions.CreateSession.CreateSessionHandler(dataSource),
wizardMessenger,
NullLogger<CreateSessionHandler>.Instance,
platformMessenger,
dataSource);
var payload = new WizardPayload
{
Type = WizardCreationType.Single,
Title = "Тест публикации",
System = "Dnd5e",
DurationMinutes = 240,
Visibility = WizardVisibility.Public,
Single = new WizardSingleInput
{
ScheduledAt = DateTimeOffset.UtcNow.AddDays(7),
MaxPlayers = null,
},
};
var draft = NewDraft(WizardStepNames.Confirm, payload, ownerId: 111111111);
draft.ChatId = "-1003916537960";
draft.DraftMessageId = "7";
drafts.Seed(draft);
await sut.SubmitDraftAsync(draft, CancellationToken.None);
Assert.Single(platformMessenger.CreatedThreads);
Assert.Equal("Тест публикации", platformMessenger.CreatedThreads[0].Title);
Assert.Single(platformMessenger.SentSchedules);
Assert.Equal("456", platformMessenger.SentSchedules[0].Group.ExternalThreadId);
Assert.Contains(draft.Id, drafts.DeletedIds);
Assert.Contains(wizardMessenger.Edits, edit => edit.Text.Contains("✅ Создано: 1 сессия", StringComparison.Ordinal));
await using var connection = await dataSource.OpenConnectionAsync();
await using var command = new NpgsqlCommand(
"""
SELECT thread_id, batch_message_id, topic_created_by_bot
FROM sessions
ORDER BY created_at DESC
LIMIT 1
""",
connection);
await using var reader = await command.ExecuteReaderAsync();
Assert.True(await reader.ReadAsync());
Assert.Equal(456, reader.GetInt32(0));
Assert.Equal(789, reader.GetInt32(1));
Assert.True(reader.GetBoolean(2));
}
}
internal sealed class FakePlatformMessenger : IPlatformMessenger
{
public List<(PlatformGroup Group, string Title)> CreatedThreads { get; } = new();
public List<PlatformScheduleMessage> SentSchedules { get; } = new();
public Task<PlatformMessageRef> CreateThreadAsync(PlatformGroup group, string title, CancellationToken ct)
{
CreatedThreads.Add((group, title));
return Task.FromResult(new PlatformMessageRef(group.Platform, group.ExternalGroupId, "456", string.Empty));
}
public Task<PlatformMessageRef> SendScheduleAsync(PlatformScheduleMessage message, CancellationToken ct)
{
SentSchedules.Add(message);
return Task.FromResult(new PlatformMessageRef(
message.Group.Platform,
message.Group.ExternalGroupId,
message.Group.ExternalThreadId,
"789"));
}
public Task UpdateScheduleAsync(PlatformScheduleMessage message, CancellationToken ct) => Task.CompletedTask;
public Task SendGroupMessageAsync(PlatformGroup group, string htmlText, CancellationToken ct) => Task.CompletedTask;
public Task SendPrivateMessageAsync(PlatformPrivateMessage message, CancellationToken ct) => Task.CompletedTask;
public Task AnswerInteractionAsync(PlatformInteractionReply reply, CancellationToken ct) => Task.CompletedTask;
public Task SendCalendarFileAsync(PlatformCalendarFile file, CancellationToken ct) => Task.CompletedTask;
}