test(core/slice-1): full portal+logout event-sequence ordering + no-duplicate-fire coverage
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f1b59f3a64
commit
c3d6eccf51
1 changed files with 111 additions and 0 deletions
|
|
@ -341,4 +341,115 @@ public sealed class TeleportAnimSequencerTests
|
|||
Assert.Equal(TeleportAnimState.TunnelContinue, seq.State);
|
||||
Assert.True(snap2.ShowPleaseWait);
|
||||
}
|
||||
|
||||
// --- Task 1.5: Full portal event sequence and logout event sequence ---
|
||||
|
||||
// Helper: run the sequencer to completion collecting ordered events.
|
||||
private static List<TeleportAnimEvent> RunToOff(
|
||||
TeleportEntryKind kind, bool worldReadyAfterFirstTunnel = true, float step = 0.05f)
|
||||
{
|
||||
var seq = new TeleportAnimSequencer();
|
||||
var allEvts = new List<TeleportAnimEvent>();
|
||||
seq.Begin(kind);
|
||||
|
||||
int safetyNet = 5000;
|
||||
while (seq.IsActive && --safetyNet > 0)
|
||||
{
|
||||
// Simulate world becoming ready on first Tick inside Tunnel
|
||||
bool ready = worldReadyAfterFirstTunnel && seq.State == TeleportAnimState.Tunnel;
|
||||
var (_, evts) = seq.Tick(step, worldReady: ready);
|
||||
allEvts.AddRange(evts);
|
||||
}
|
||||
return allEvts;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Portal_FullSequence_EventsInOrder()
|
||||
{
|
||||
var evts = RunToOff(TeleportEntryKind.Portal);
|
||||
|
||||
// Required events in order: PlayEnterSound, Place, PlayExitSound, FireLoginComplete.
|
||||
// EnterTunnel is optional but must come before Place if present.
|
||||
int enterIdx = evts.IndexOf(TeleportAnimEvent.PlayEnterSound);
|
||||
int placeIdx = evts.IndexOf(TeleportAnimEvent.Place);
|
||||
int exitIdx = evts.IndexOf(TeleportAnimEvent.PlayExitSound);
|
||||
int loginIdx = evts.IndexOf(TeleportAnimEvent.FireLoginComplete);
|
||||
|
||||
Assert.True(enterIdx >= 0, "PlayEnterSound must fire");
|
||||
Assert.True(placeIdx >= 0, "Place must fire");
|
||||
Assert.True(exitIdx >= 0, "PlayExitSound must fire");
|
||||
Assert.True(loginIdx >= 0, "FireLoginComplete must fire");
|
||||
|
||||
Assert.True(enterIdx < placeIdx, "PlayEnterSound must precede Place");
|
||||
Assert.True(placeIdx < exitIdx, "Place must precede PlayExitSound");
|
||||
Assert.True(exitIdx < loginIdx, "PlayExitSound must precede FireLoginComplete");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Logout_FullSequence_EventsInOrder_WithEnterTunnelAfterFades()
|
||||
{
|
||||
var evts = RunToOff(TeleportEntryKind.Logout);
|
||||
|
||||
int enterIdx = evts.IndexOf(TeleportAnimEvent.PlayEnterSound);
|
||||
int tunnelIdx = evts.IndexOf(TeleportAnimEvent.EnterTunnel);
|
||||
int placeIdx = evts.IndexOf(TeleportAnimEvent.Place);
|
||||
int exitIdx = evts.IndexOf(TeleportAnimEvent.PlayExitSound);
|
||||
int loginIdx = evts.IndexOf(TeleportAnimEvent.FireLoginComplete);
|
||||
|
||||
Assert.True(enterIdx >= 0, "PlayEnterSound must fire");
|
||||
Assert.True(tunnelIdx >= 0, "EnterTunnel must fire (Logout path goes through WorldFadeOut->TunnelFadeIn->Tunnel)");
|
||||
Assert.True(placeIdx >= 0, "Place must fire");
|
||||
Assert.True(exitIdx >= 0, "PlayExitSound must fire");
|
||||
Assert.True(loginIdx >= 0, "FireLoginComplete must fire");
|
||||
|
||||
Assert.True(enterIdx < tunnelIdx, "PlayEnterSound must precede EnterTunnel");
|
||||
Assert.True(tunnelIdx < placeIdx, "EnterTunnel must precede Place");
|
||||
Assert.True(placeIdx < exitIdx, "Place must precede PlayExitSound");
|
||||
Assert.True(exitIdx < loginIdx, "PlayExitSound must precede FireLoginComplete");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Portal_NoEventsFiredTwice()
|
||||
{
|
||||
var evts = RunToOff(TeleportEntryKind.Portal);
|
||||
Assert.Equal(1, evts.Count(e => e == TeleportAnimEvent.PlayEnterSound));
|
||||
Assert.Equal(1, evts.Count(e => e == TeleportAnimEvent.Place));
|
||||
Assert.Equal(1, evts.Count(e => e == TeleportAnimEvent.PlayExitSound));
|
||||
Assert.Equal(1, evts.Count(e => e == TeleportAnimEvent.FireLoginComplete));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Death_BehavesIdenticallyToPortal_FullSequence()
|
||||
{
|
||||
var portalEvts = RunToOff(TeleportEntryKind.Portal);
|
||||
var deathEvts = RunToOff(TeleportEntryKind.Death);
|
||||
// Same event sequence (both enter at Tunnel)
|
||||
Assert.Equal(portalEvts, deathEvts);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_BehavesIdenticallyToPortal_FullSequence()
|
||||
{
|
||||
var portalEvts = RunToOff(TeleportEntryKind.Portal);
|
||||
var loginEvts = RunToOff(TeleportEntryKind.Login);
|
||||
Assert.Equal(portalEvts, loginEvts);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AfterOff_IsActiveIsFalse_AndStateIsOff()
|
||||
{
|
||||
RunToOff(TeleportEntryKind.Portal);
|
||||
var seq = new TeleportAnimSequencer();
|
||||
seq.Begin(TeleportEntryKind.Portal);
|
||||
|
||||
// Drain to Off
|
||||
for (int i = 0; i < 5000 && seq.IsActive; i++)
|
||||
{
|
||||
bool ready = seq.State == TeleportAnimState.Tunnel;
|
||||
seq.Tick(0.05f, worldReady: ready);
|
||||
}
|
||||
|
||||
Assert.False(seq.IsActive);
|
||||
Assert.Equal(TeleportAnimState.Off, seq.State);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue