Files
GmRelayBot/tests/GmRelay.Bot.Tests/Discord/Wizard/DiscordWizardSubmitterBuildCommandTests.cs
T
Toutsu 9709d09b15
PR Checks / test-and-build (pull_request) Successful in 30m45s
feat(discord): make /newsession identical to Telegram wizard
- Remove legacy DiscordNewSessionCommand/Handler and their tests.
- Rename /newsession-wizard to /newsession.
- Add shared pool capacity step before Format/Location.
- Render Format and Location in Discord wizard; Location uses a modal.
- Propagate Format, JoinLink and LocationAddress in BuildCommand.
- Publish created sessions through existing IPlatformMessenger pipeline.
- Update README, version bump to 3.11.1, sync compose/deploy/NavMenu.
2026-06-15 17:49:53 +03:00

199 lines
6.0 KiB
C#

using GmRelay.DiscordBot.Features.Sessions.Wizard;
using GmRelay.Shared.Features.Sessions.CreateSession.Wizard;
using Xunit;
namespace GmRelay.Bot.Tests.Discord.Wizard;
/// <summary>
/// Regression coverage for <see cref="DiscordWizardSubmitter"/>'s
/// <c>BuildCommand</c>: when the wizard payload carries no player limit
/// (user picked «♾ Без лимита» on the Capacity step), the resulting
/// <c>CreateSessionCommand.MaxPlayers</c> must be <c>null</c> — never
/// <c>0</c>. <c>0</c> would violate the DB CHECK
/// <c>ck_sessions_max_players</c> in V006 and the contract that
/// <c>null</c> means "no limit".
/// </summary>
public sealed class DiscordWizardSubmitterBuildCommandTests
{
[Fact]
public void BuildCommand_WhenSingleMaxPlayersIsNull_PropagatesNull()
{
var draft = new WizardDraft
{
Id = Guid.NewGuid(),
ChatId = "42",
OwnerId = "100",
Step = "confirm",
};
var payload = new WizardPayload
{
Type = WizardCreationType.Single,
Title = "T",
System = "Dnd5e",
DurationMinutes = 240,
Visibility = WizardVisibility.Public,
Single = new WizardSingleInput
{
ScheduledAt = DateTimeOffset.UtcNow.AddDays(1),
MaxPlayers = null,
},
};
var cmd = DiscordWizardSubmitter.BuildCommand(
draft,
payload,
new[] { payload.Single!.ScheduledAt!.Value },
payload.Single.MaxPlayers,
isOneShot: true);
Assert.Null(cmd.MaxPlayers);
}
[Fact]
public void BuildCommand_WhenSingleMaxPlayersIsSet_PropagatesValue()
{
var draft = new WizardDraft
{
Id = Guid.NewGuid(),
ChatId = "42",
OwnerId = "100",
Step = "confirm",
};
var payload = new WizardPayload
{
Type = WizardCreationType.Single,
Title = "T",
System = "Dnd5e",
DurationMinutes = 240,
Visibility = WizardVisibility.Public,
Single = new WizardSingleInput
{
ScheduledAt = DateTimeOffset.UtcNow.AddDays(1),
MaxPlayers = 5,
},
};
var cmd = DiscordWizardSubmitter.BuildCommand(
draft,
payload,
new[] { payload.Single!.ScheduledAt!.Value },
payload.Single.MaxPlayers,
isOneShot: true);
Assert.Equal(5, cmd.MaxPlayers);
}
[Fact]
public void BuildCommand_WhenFormatIsOnline_PropagatesFormatAndJoinLink()
{
var draft = new WizardDraft
{
Id = Guid.NewGuid(),
ChatId = "42",
OwnerId = "100",
Step = "confirm",
};
var payload = new WizardPayload
{
Type = WizardCreationType.Single,
Title = "T",
System = "Dnd5e",
DurationMinutes = 240,
Visibility = WizardVisibility.Public,
Format = WizardSessionFormat.Online,
JoinLink = "https://vtt.example/game",
Single = new WizardSingleInput
{
ScheduledAt = DateTimeOffset.UtcNow.AddDays(1),
MaxPlayers = 5,
},
};
var cmd = DiscordWizardSubmitter.BuildCommand(
draft,
payload,
new[] { payload.Single!.ScheduledAt!.Value },
payload.Single.MaxPlayers,
isOneShot: true);
Assert.Equal("Online", cmd.Format);
Assert.Equal("https://vtt.example/game", cmd.Link);
Assert.Null(cmd.LocationAddress);
}
[Fact]
public void BuildCommand_WhenFormatIsOffline_PropagatesFormatAndAddress()
{
var draft = new WizardDraft
{
Id = Guid.NewGuid(),
ChatId = "42",
OwnerId = "100",
Step = "confirm",
};
var payload = new WizardPayload
{
Type = WizardCreationType.Single,
Title = "T",
System = "Dnd5e",
DurationMinutes = 240,
Visibility = WizardVisibility.Public,
Format = WizardSessionFormat.Offline,
LocationAddress = "Москва, ул. Кубиков, 12",
Single = new WizardSingleInput
{
ScheduledAt = DateTimeOffset.UtcNow.AddDays(1),
MaxPlayers = 5,
},
};
var cmd = DiscordWizardSubmitter.BuildCommand(
draft,
payload,
new[] { payload.Single!.ScheduledAt!.Value },
payload.Single.MaxPlayers,
isOneShot: true);
Assert.Equal("Offline", cmd.Format);
Assert.Equal("Москва, ул. Кубиков, 12", cmd.LocationAddress);
Assert.Equal(string.Empty, cmd.Link);
}
[Fact]
public void BuildCommand_WhenPoolMaxPlayersIsSet_PropagatesValueToMaxPlayers()
{
var draft = new WizardDraft
{
Id = Guid.NewGuid(),
ChatId = "42",
OwnerId = "100",
Step = "confirm",
};
var slotTime = DateTimeOffset.UtcNow.AddDays(1);
var payload = new WizardPayload
{
Type = WizardCreationType.Pool,
Title = "Pool",
System = "Dnd5e",
DurationMinutes = 240,
Visibility = WizardVisibility.Public,
Format = WizardSessionFormat.Online,
JoinLink = "https://vtt.example/game",
Pool = new WizardPoolInput
{
MaxPlayers = 12,
Slots = { new WizardSlotInput { ScheduledAt = slotTime, MaxPlayers = 8 } },
},
};
var cmd = DiscordWizardSubmitter.BuildCommand(
draft,
payload,
new[] { slotTime },
payload.Pool.MaxPlayers,
isOneShot: false);
Assert.Equal(12, cmd.MaxPlayers);
}
}