feat(discord): make /newsession identical to Telegram wizard
PR Checks / test-and-build (pull_request) Successful in 30m45s

- 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.
This commit is contained in:
2026-06-15 17:49:53 +03:00
parent a391c51761
commit 9709d09b15
23 changed files with 362 additions and 560 deletions
@@ -46,7 +46,7 @@ public sealed class GameCreationWizardStepTransitionsTests
}
[Fact]
public async Task PoolSystemDuration_PreselectedButton_AdvancesToFormat()
public async Task PoolSystemDuration_PreselectedButton_AdvancesToCapacity()
{
var wizard = BuildWizard(out var drafts, out _);
var payload = new WizardPayload
@@ -60,7 +60,7 @@ public sealed class GameCreationWizardStepTransitionsTests
var data = WizardCallbackData.Choice(WizardStepNames.PoolSystemDuration, "Dnd5e:240");
await wizard.HandleInteractionAsync(CallbackInteraction(data, ownerId: draft.OwnerId), draft, CancellationToken.None);
Assert.Equal(WizardStepNames.Format, draft.Step);
Assert.Equal(WizardStepNames.Capacity, draft.Step);
using var doc = JsonDocument.Parse(draft.PayloadJson);
var root = doc.RootElement;
Assert.True(root.TryGetProperty("system", out var sys));
@@ -69,6 +69,53 @@ public sealed class GameCreationWizardStepTransitionsTests
Assert.Equal(240, dur.GetInt32());
}
[Fact]
public async Task PoolCapacity_Text_AdvancesToFormat_AndSetsMaxPlayers()
{
var wizard = BuildWizard(out var drafts, out _);
var payload = new WizardPayload
{
Type = WizardCreationType.Pool,
Title = "Pool",
System = "Dnd5e",
DurationMinutes = 240,
};
var draft = NewDraft(WizardStepNames.Capacity, payload);
drafts.Seed(draft);
await wizard.HandleInteractionAsync(TextInteraction("10", ownerId: draft.OwnerId), draft, CancellationToken.None);
Assert.Equal(WizardStepNames.Format, draft.Step);
using var doc = JsonDocument.Parse(draft.PayloadJson);
var root = doc.RootElement;
Assert.True(root.TryGetProperty("pool", out var pool));
Assert.True(pool.TryGetProperty("maxPlayers", out var maxPlayers));
Assert.Equal(10, maxPlayers.GetInt32());
}
[Theory]
[InlineData("waitlist:on")]
[InlineData("waitlist:off")]
public async Task Capacity_WithMaxPlayersAndWaitlist_AdvancesToFormat(string waitlistChoice)
{
var wizard = BuildWizard(out var drafts, out _);
var payload = new WizardPayload
{
Type = WizardCreationType.Single,
Title = "T",
System = "Dnd5e",
DurationMinutes = 240,
Single = new WizardSingleInput { ScheduledAt = DateTimeOffset.UtcNow.AddDays(1), MaxPlayers = 5 },
};
var draft = NewDraft(WizardStepNames.Capacity, payload);
drafts.Seed(draft);
var data = WizardCallbackData.Choice(WizardStepNames.Capacity, waitlistChoice);
await wizard.HandleInteractionAsync(CallbackInteraction(data, ownerId: draft.OwnerId), draft, CancellationToken.None);
Assert.Equal(WizardStepNames.Format, draft.Step);
}
[Fact]
public async Task NoLimitCapacityButton_AdvancesToVisibility_AndLeavesMaxPlayersNull()
{