Two issues caught during v1 smoke at the mulligan / first-turn boundary:
1) BuildSwapResponse ignored the player's idxList and echoed the same
3-card hand back. The client diffs the new self[] against the Deal
to compute "drawn cards" — empty diff against the same hand throws
"Card swap failed: AbandonCards[X]/DrawCards[]". Replace swapped
idxs with fresh deck idxs (initial hand was 1/2/3, deck has 4..30
still available). Same hand must flow into Ready since the client
diffs again there. Move the hand computation into a new helper
ComputeHandAfterSwap and have ComputeResponses thread it through
both BuildSwapResponse and BuildReady.
2) The client doesn't transition to the "Opponent's turn…" display
on its own after sending TurnEnd — it waits for the server to push
an opponent TurnStart (per prod TK2 capture line 14). Without it
the UI just sits on the end-of-turn frame. Add a TurnEnd handler
that pushes a minimal TurnStart{spin} and transitions to a new
OpponentTurn phase, which IS the documented v1 stopping point.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
101 lines
3.6 KiB
C#
101 lines
3.6 KiB
C#
using NUnit.Framework;
|
|
using SVSim.BattleNode.Lifecycle;
|
|
using SVSim.BattleNode.Protocol;
|
|
|
|
namespace SVSim.UnitTests.BattleNode.Lifecycle;
|
|
|
|
[TestFixture]
|
|
public class ScriptedLifecycleTests
|
|
{
|
|
[Test]
|
|
public void BuildMatched_PutsOppoIdInSelfInfoEqualToTheRealOpponentVid()
|
|
{
|
|
var env = ScriptedLifecycle.BuildMatched(playerViewerId: 906243102, opponentViewerId: 847666884, battleId: "b");
|
|
|
|
Assert.That(env.Uri, Is.EqualTo(NetworkBattleUri.Matched));
|
|
var selfInfo = (Dictionary<string, object?>)env.Body["selfInfo"]!;
|
|
Assert.That(selfInfo["oppoId"], Is.EqualTo(847666884L));
|
|
var oppoInfo = (Dictionary<string, object?>)env.Body["oppoInfo"]!;
|
|
Assert.That(oppoInfo["oppoId"], Is.EqualTo(906243102L));
|
|
|
|
// Bid travels in the envelope, not the Body — protect against the Task 5 reserved-keys regression.
|
|
Assert.That(env.Bid, Is.EqualTo("b"));
|
|
Assert.That(env.Body.ContainsKey("bid"), Is.False);
|
|
}
|
|
|
|
[Test]
|
|
public void BuildMatched_ContainsThirtyCardSelfDeck()
|
|
{
|
|
var env = ScriptedLifecycle.BuildMatched(1, 2, "b");
|
|
var deck = (List<object?>)env.Body["selfDeck"]!;
|
|
Assert.That(deck.Count, Is.EqualTo(30));
|
|
}
|
|
|
|
[Test]
|
|
public void BuildBattleStart_HasTurnStateZeroAndBattleTypeEleven()
|
|
{
|
|
var env = ScriptedLifecycle.BuildBattleStart(playerViewerId: 1);
|
|
Assert.That(env.Body["turnState"], Is.EqualTo(0));
|
|
Assert.That(env.Body["battleType"], Is.EqualTo(11));
|
|
}
|
|
|
|
[Test]
|
|
public void BuildDeal_HasThreeSelfAndThreeOppoEntries()
|
|
{
|
|
var env = ScriptedLifecycle.BuildDeal();
|
|
var self = (List<object?>)env.Body["self"]!;
|
|
var oppo = (List<object?>)env.Body["oppo"]!;
|
|
Assert.That(self.Count, Is.EqualTo(3));
|
|
Assert.That(oppo.Count, Is.EqualTo(3));
|
|
}
|
|
|
|
[Test]
|
|
public void ComputeHandAfterSwap_NoSwap_ReturnsInitialHand()
|
|
{
|
|
var hand = ScriptedLifecycle.ComputeHandAfterSwap(Array.Empty<long>());
|
|
Assert.That(hand, Is.EqualTo(new long[] { 1, 2, 3 }));
|
|
}
|
|
|
|
[Test]
|
|
public void ComputeHandAfterSwap_SwapMiddleCard_ReplacesWithFreshDeckIdx()
|
|
{
|
|
var hand = ScriptedLifecycle.ComputeHandAfterSwap(new long[] { 2 });
|
|
// pos 0 keeps idx 1; pos 1 (was idx 2) gets next deck idx (4); pos 2 keeps idx 3.
|
|
Assert.That(hand, Is.EqualTo(new long[] { 1, 4, 3 }));
|
|
}
|
|
|
|
[Test]
|
|
public void ComputeHandAfterSwap_SwapAll_ReplacesAllWithFreshDeckIdxs()
|
|
{
|
|
var hand = ScriptedLifecycle.ComputeHandAfterSwap(new long[] { 1, 2, 3 });
|
|
Assert.That(hand, Is.EqualTo(new long[] { 4, 5, 6 }));
|
|
}
|
|
|
|
[Test]
|
|
public void BuildSwapResponse_RendersGivenHandAsPositions()
|
|
{
|
|
var env = ScriptedLifecycle.BuildSwapResponse(new long[] { 1, 4, 3 });
|
|
var self = (List<object?>)env.Body["self"]!;
|
|
Assert.That(self.Count, Is.EqualTo(3));
|
|
Assert.That(((Dictionary<string, object?>)self[1]!)["idx"], Is.EqualTo(4));
|
|
}
|
|
|
|
[Test]
|
|
public void BuildReady_IncludesIdxChangeSeedAndSpin_AndUsesGivenHand()
|
|
{
|
|
var env = ScriptedLifecycle.BuildReady(new long[] { 1, 4, 3 });
|
|
Assert.That(env.Body.ContainsKey("idxChangeSeed"), Is.True);
|
|
Assert.That(env.Body.ContainsKey("spin"), Is.True);
|
|
var self = (List<object?>)env.Body["self"]!;
|
|
Assert.That(((Dictionary<string, object?>)self[1]!)["idx"], Is.EqualTo(4));
|
|
}
|
|
|
|
[Test]
|
|
public void BuildOpponentTurnStart_HasUriTurnStartAndSpin()
|
|
{
|
|
var env = ScriptedLifecycle.BuildOpponentTurnStart();
|
|
Assert.That(env.Uri, Is.EqualTo(NetworkBattleUri.TurnStart));
|
|
Assert.That(env.Body.ContainsKey("spin"), Is.True);
|
|
}
|
|
}
|