014b5edd31
PR Checks / test-and-build (pull_request) Successful in 15m52s
Add format and location steps to the Telegram /newsession wizard, persist offline addresses in sessions.location_address, and render online links/offline addresses in schedule messages. Bump version to 3.10.0.
162 lines
4.9 KiB
C#
162 lines
4.9 KiB
C#
using GmRelay.Bot.Features.Sessions.CreateSession;
|
|
using GmRelay.Shared.Features.Sessions.CreateSession.Wizard;
|
|
using Xunit;
|
|
|
|
namespace GmRelay.Bot.Tests.Features.Sessions.CreateSession.Wizard;
|
|
|
|
/// <summary>
|
|
/// Regression coverage for <see cref="CreateSessionHandler.BuildCommand"/>:
|
|
/// when the wizard payload carries no player limit (e.g. 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 constraint
|
|
/// (<c>ck_sessions_max_players</c> in V006) by inserting <c>0</c> instead of
|
|
/// <c>NULL</c>, which is the wire-level representation of "no limit".
|
|
/// </summary>
|
|
public sealed class CreateSessionHandlerBuildCommandTests
|
|
{
|
|
[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 = CreateSessionHandler.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 = CreateSessionHandler.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 = 4,
|
|
},
|
|
};
|
|
|
|
var cmd = CreateSessionHandler.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 = 4,
|
|
},
|
|
};
|
|
|
|
var cmd = CreateSessionHandler.BuildCommand(
|
|
draft,
|
|
payload,
|
|
new[] { payload.Single!.ScheduledAt!.Value },
|
|
payload.Single.MaxPlayers,
|
|
isOneShot: true);
|
|
|
|
Assert.Equal("Offline", cmd.Format);
|
|
Assert.Equal(string.Empty, cmd.Link);
|
|
Assert.Equal("Москва, ул. Кубиков, 12", cmd.LocationAddress);
|
|
}
|
|
}
|