From c13c878de5fadedd8cb797cf051b16b8b9e6beb3 Mon Sep 17 00:00:00 2001 From: Daniel Widgren Date: Fri, 1 May 2026 23:36:48 +0200 Subject: [PATCH] feat(tests): add protocol dispatch test against canonical fixtures Per-SDK protocol dispatch unit test: feeds every canonical server-emitted message envelope through AsobiRealtime.HandleMessage and asserts the matching SDK event fires. Vendors the 32-fixture corpus from asobi/priv/protocol/fixtures into Tests/Runtime/Resources/Fixtures. Audit findings against the canonical corpus turned up six dispatch cases that were silently falling through to the generic OnMatchEvent / OnWorldEvent buckets, plus session.heartbeat with no surfaced event. Added explicit handlers and events: match.finished -> OnMatchFinished match.matchmaker_expired -> OnMatchmakerExpired match.matchmaker_failed -> OnMatchmakerFailed world.finished -> OnWorldFinished world.list -> OnWorldList world.phase_changed -> OnWorldPhaseChanged session.heartbeat -> OnHeartbeat The defensive matchmaker.matched alias is kept as a fall-through to OnMatchmakerMatched with a TODO-deprecate note; removing without a deprecation cycle would break consumers that listened for it during the historical drift period. The alias is pinned by a dedicated test. Made HandleMessage internal and added a parameterless test-only ctor to allow exercising dispatch without a live WebSocket. Asobi.Tests already references Asobi via its asmdef; InternalsVisibleTo is wired through a new Runtime/AssemblyInfo.cs. The test also asserts the bidirectional invariant: every fixture has an Expected mapping and every Expected entry has a fixture, so future drift in either direction fails CI. --- Runtime/AssemblyInfo.cs | 3 + Runtime/AssemblyInfo.cs.meta | 11 ++ Runtime/WebSocket/AsobiRealtime.cs | 35 +++- Tests/Runtime/DispatchTests.cs | 180 ++++++++++++++++++ Tests/Runtime/DispatchTests.cs.meta | 11 ++ Tests/Runtime/README.md | 10 +- Tests/Runtime/Resources.meta | 8 + Tests/Runtime/Resources/Fixtures.meta | 8 + .../Resources/Fixtures/chat.joined.json | 1 + .../Runtime/Resources/Fixtures/chat.left.json | 1 + .../Resources/Fixtures/chat.message.json | 1 + .../Resources/Fixtures/dm.message.json | 1 + Tests/Runtime/Resources/Fixtures/dm.sent.json | 1 + Tests/Runtime/Resources/Fixtures/error.json | 1 + .../Resources/Fixtures/match.finished.json | 1 + .../Resources/Fixtures/match.joined.json | 1 + .../Resources/Fixtures/match.left.json | 1 + .../Resources/Fixtures/match.matched.json | 1 + .../Fixtures/match.matchmaker_expired.json | 1 + .../Fixtures/match.matchmaker_failed.json | 1 + .../Resources/Fixtures/match.state.json | 1 + .../Resources/Fixtures/match.vote_result.json | 1 + .../Resources/Fixtures/match.vote_start.json | 1 + .../Resources/Fixtures/match.vote_tally.json | 1 + .../Resources/Fixtures/match.vote_vetoed.json | 1 + .../Resources/Fixtures/matchmaker.queued.json | 1 + .../Fixtures/matchmaker.removed.json | 1 + .../Resources/Fixtures/notification.new.json | 1 + .../Resources/Fixtures/presence.updated.json | 1 + .../Resources/Fixtures/session.connected.json | 1 + .../Resources/Fixtures/session.heartbeat.json | 1 + .../Resources/Fixtures/vote.cast_ok.json | 1 + .../Resources/Fixtures/vote.veto_ok.json | 1 + .../Resources/Fixtures/world.finished.json | 1 + .../Resources/Fixtures/world.joined.json | 1 + .../Resources/Fixtures/world.left.json | 1 + .../Resources/Fixtures/world.list.json | 1 + .../Fixtures/world.phase_changed.json | 1 + .../Resources/Fixtures/world.terrain.json | 1 + .../Resources/Fixtures/world.tick.json | 1 + 40 files changed, 296 insertions(+), 2 deletions(-) create mode 100644 Runtime/AssemblyInfo.cs create mode 100644 Runtime/AssemblyInfo.cs.meta create mode 100644 Tests/Runtime/DispatchTests.cs create mode 100644 Tests/Runtime/DispatchTests.cs.meta create mode 100644 Tests/Runtime/Resources.meta create mode 100644 Tests/Runtime/Resources/Fixtures.meta create mode 100644 Tests/Runtime/Resources/Fixtures/chat.joined.json create mode 100644 Tests/Runtime/Resources/Fixtures/chat.left.json create mode 100644 Tests/Runtime/Resources/Fixtures/chat.message.json create mode 100644 Tests/Runtime/Resources/Fixtures/dm.message.json create mode 100644 Tests/Runtime/Resources/Fixtures/dm.sent.json create mode 100644 Tests/Runtime/Resources/Fixtures/error.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.finished.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.joined.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.left.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.matched.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.matchmaker_expired.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.matchmaker_failed.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.state.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.vote_result.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.vote_start.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.vote_tally.json create mode 100644 Tests/Runtime/Resources/Fixtures/match.vote_vetoed.json create mode 100644 Tests/Runtime/Resources/Fixtures/matchmaker.queued.json create mode 100644 Tests/Runtime/Resources/Fixtures/matchmaker.removed.json create mode 100644 Tests/Runtime/Resources/Fixtures/notification.new.json create mode 100644 Tests/Runtime/Resources/Fixtures/presence.updated.json create mode 100644 Tests/Runtime/Resources/Fixtures/session.connected.json create mode 100644 Tests/Runtime/Resources/Fixtures/session.heartbeat.json create mode 100644 Tests/Runtime/Resources/Fixtures/vote.cast_ok.json create mode 100644 Tests/Runtime/Resources/Fixtures/vote.veto_ok.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.finished.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.joined.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.left.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.list.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.phase_changed.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.terrain.json create mode 100644 Tests/Runtime/Resources/Fixtures/world.tick.json diff --git a/Runtime/AssemblyInfo.cs b/Runtime/AssemblyInfo.cs new file mode 100644 index 0000000..b17b883 --- /dev/null +++ b/Runtime/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Asobi.Tests")] diff --git a/Runtime/AssemblyInfo.cs.meta b/Runtime/AssemblyInfo.cs.meta new file mode 100644 index 0000000..26b5cc9 --- /dev/null +++ b/Runtime/AssemblyInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 173241c20e37404a92f273bc8ffb5c0f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Runtime/WebSocket/AsobiRealtime.cs b/Runtime/WebSocket/AsobiRealtime.cs index c3f85ab..a6d98a8 100644 --- a/Runtime/WebSocket/AsobiRealtime.cs +++ b/Runtime/WebSocket/AsobiRealtime.cs @@ -46,9 +46,20 @@ public class AsobiRealtime : IDisposable public event Action OnVoteCastOk; public event Action OnVoteVetoOk; public event Action OnError; + public event Action OnHeartbeat; + public event Action OnMatchFinished; + public event Action OnMatchmakerExpired; + public event Action OnMatchmakerFailed; + public event Action OnWorldFinished; + public event Action OnWorldList; + public event Action OnWorldPhaseChanged; internal AsobiRealtime(AsobiClient client) => _client = client; + // Test-only: construct without a client/WebSocket so dispatch logic + // can be exercised in isolation. + internal AsobiRealtime() { } + public async Task ConnectAsync() { if (IsConnected) return; @@ -275,7 +286,7 @@ async Task ReceiveLoop() } } - void HandleMessage(string raw) + internal void HandleMessage(string raw) { var msg = JsonUtility.FromJson(raw); if (msg == null) return; @@ -304,10 +315,22 @@ void HandleMessage(string raw) case "notification.new": OnNotification?.Invoke(raw); break; + // TODO deprecate: server only emits "match.matched". The + // "matchmaker.matched" alias is kept defensively against + // historical drift; remove in a future major version. case "matchmaker.matched": case "match.matched": OnMatchmakerMatched?.Invoke(raw); break; + case "match.finished": + OnMatchFinished?.Invoke(raw); + break; + case "match.matchmaker_expired": + OnMatchmakerExpired?.Invoke(raw); + break; + case "match.matchmaker_failed": + OnMatchmakerFailed?.Invoke(raw); + break; case "match.vote_start": OnVoteStart?.Invoke(raw); break; @@ -326,12 +349,21 @@ void HandleMessage(string raw) case "world.terrain": OnWorldTerrain?.Invoke(raw); break; + case "world.list": + OnWorldList?.Invoke(raw); + break; case "world.joined": OnWorldJoined?.Invoke(raw); break; case "world.left": OnWorldLeft?.Invoke(raw); break; + case "world.phase_changed": + OnWorldPhaseChanged?.Invoke(raw); + break; + case "world.finished": + OnWorldFinished?.Invoke(raw); + break; case "match.joined": OnMatchJoined?.Invoke(raw); break; @@ -366,6 +398,7 @@ void HandleMessage(string raw) OnPresenceUpdated?.Invoke(raw); break; case "session.heartbeat": + OnHeartbeat?.Invoke(raw); break; case "error": OnError?.Invoke(raw); diff --git a/Tests/Runtime/DispatchTests.cs b/Tests/Runtime/DispatchTests.cs new file mode 100644 index 0000000..7572051 --- /dev/null +++ b/Tests/Runtime/DispatchTests.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using UnityEngine; + +namespace Asobi.Tests +{ + /// + /// Per-SDK protocol dispatch unit test. + /// + /// Feeds every canonical server-emitted message envelope through the + /// SDK's WebSocket message handler and asserts the right SDK event + /// fires. Catches doc-vs-server drift (silent failures) before any + /// user reports a missed callback. + /// + /// Fixtures live under Tests/Runtime/Resources/Fixtures/*.json and are + /// vendored from asobi/priv/protocol/fixtures (the canonical corpus). + /// + public class DispatchTests + { + // Maps server wire `type` -> the event name on AsobiRealtime that + // should fire for that fixture. Must stay in sync with the asobi + // protocol fixture corpus and the dispatch switch in + // AsobiRealtime.HandleMessage. + static readonly Dictionary Expected = new() + { + { "error", nameof(AsobiRealtime.OnError) }, + { "session.connected", nameof(AsobiRealtime.OnConnected) }, + { "session.heartbeat", nameof(AsobiRealtime.OnHeartbeat) }, + { "match.state", nameof(AsobiRealtime.OnMatchState) }, + { "match.matched", nameof(AsobiRealtime.OnMatchmakerMatched) }, + { "match.joined", nameof(AsobiRealtime.OnMatchJoined) }, + { "match.left", nameof(AsobiRealtime.OnMatchLeft) }, + { "match.finished", nameof(AsobiRealtime.OnMatchFinished) }, + { "match.matchmaker_expired", nameof(AsobiRealtime.OnMatchmakerExpired) }, + { "match.matchmaker_failed", nameof(AsobiRealtime.OnMatchmakerFailed) }, + { "match.vote_start", nameof(AsobiRealtime.OnVoteStart) }, + { "match.vote_tally", nameof(AsobiRealtime.OnVoteTally) }, + { "match.vote_result", nameof(AsobiRealtime.OnVoteResult) }, + { "match.vote_vetoed", nameof(AsobiRealtime.OnVoteVetoed) }, + { "matchmaker.queued", nameof(AsobiRealtime.OnMatchmakerQueued) }, + { "matchmaker.removed", nameof(AsobiRealtime.OnMatchmakerRemoved) }, + { "chat.joined", nameof(AsobiRealtime.OnChatJoined) }, + { "chat.left", nameof(AsobiRealtime.OnChatLeft) }, + { "chat.message", nameof(AsobiRealtime.OnChatMessage) }, + { "dm.sent", nameof(AsobiRealtime.OnDmSent) }, + { "dm.message", nameof(AsobiRealtime.OnDmMessage) }, + { "presence.updated", nameof(AsobiRealtime.OnPresenceUpdated) }, + { "notification.new", nameof(AsobiRealtime.OnNotification) }, + { "vote.cast_ok", nameof(AsobiRealtime.OnVoteCastOk) }, + { "vote.veto_ok", nameof(AsobiRealtime.OnVoteVetoOk) }, + { "world.tick", nameof(AsobiRealtime.OnWorldTick) }, + { "world.terrain", nameof(AsobiRealtime.OnWorldTerrain) }, + { "world.list", nameof(AsobiRealtime.OnWorldList) }, + { "world.joined", nameof(AsobiRealtime.OnWorldJoined) }, + { "world.left", nameof(AsobiRealtime.OnWorldLeft) }, + { "world.phase_changed", nameof(AsobiRealtime.OnWorldPhaseChanged) }, + { "world.finished", nameof(AsobiRealtime.OnWorldFinished) }, + }; + + static IEnumerable FixtureCases() + { + foreach (var kv in Expected) + { + yield return new TestCaseData(kv.Key, kv.Value).SetName($"Dispatches_{kv.Key}"); + } + } + + [Test, TestCaseSource(nameof(FixtureCases))] + public void DispatchesFixtureToExpectedEvent(string wireType, string eventName) + { + var raw = LoadFixture(wireType); + Assert.That(raw, Is.Not.Null.And.Not.Empty, + $"fixture for '{wireType}' missing under Resources/Fixtures/"); + + var realtime = new AsobiRealtime(); + var fired = false; + Subscribe(realtime, eventName, () => fired = true); + + realtime.HandleMessage(raw); + + Assert.That(fired, Is.True, + $"'{wireType}' did not fire {eventName}"); + } + + [Test] + public void EveryFixtureHasExpectedMapping() + { + var fixtures = Resources.LoadAll("Fixtures"); + Assert.That(fixtures.Length, Is.GreaterThan(0), + "no fixtures loaded from Resources/Fixtures/"); + + var unmapped = fixtures + .Select(f => f.name) + .Where(name => !Expected.ContainsKey(name)) + .ToList(); + + Assert.That(unmapped, Is.Empty, + "fixtures with no Expected mapping (add a dispatch case + entry): " + + string.Join(", ", unmapped)); + } + + [Test] + public void EveryExpectedHasFixture() + { + var fixtureNames = Resources.LoadAll("Fixtures") + .Select(f => f.name) + .ToHashSet(); + + var stale = Expected.Keys + .Where(t => !fixtureNames.Contains(t)) + .ToList(); + + Assert.That(stale, Is.Empty, + "Expected entries with no fixture (stale or missing fixture): " + + string.Join(", ", stale)); + } + + [Test] + public void MatchmakerMatchedAliasesMatchMatched() + { + // Server only emits "match.matched"; "matchmaker.matched" is a + // historical alias kept defensively. This test pins that alias + // until it's removed in a future major. + var raw = "{\"type\":\"matchmaker.matched\",\"payload\":{\"match_id\":\"m1\"}}"; + + var realtime = new AsobiRealtime(); + var fired = false; + realtime.OnMatchmakerMatched += _ => fired = true; + realtime.HandleMessage(raw); + + Assert.That(fired, Is.True, + "matchmaker.matched alias should still dispatch to OnMatchmakerMatched"); + } + + // ---- helpers ---- + + static Dictionary _fixtureCache; + + static string LoadFixture(string wireType) + { + if (_fixtureCache == null) + { + _fixtureCache = Resources.LoadAll("Fixtures") + .ToDictionary(t => t.name, t => t.text); + } + return _fixtureCache.TryGetValue(wireType, out var raw) ? raw : null; + } + + static void Subscribe(AsobiRealtime realtime, string eventName, Action onFire) + { + // Reflectively attach a handler to the named event so the test + // stays data-driven. Supports the two delegate shapes used by + // AsobiRealtime: Action and Action. + var ev = typeof(AsobiRealtime).GetEvent(eventName); + Assert.That(ev, Is.Not.Null, $"AsobiRealtime has no event named {eventName}"); + + var handlerType = ev.EventHandlerType; + + Delegate handler; + if (handlerType == typeof(Action)) + { + handler = onFire; + } + else if (handlerType == typeof(Action)) + { + Action wrapped = _ => onFire(); + handler = wrapped; + } + else + { + throw new InvalidOperationException( + $"event {eventName} has unsupported delegate type {handlerType}"); + } + + ev.AddEventHandler(realtime, handler); + } + } +} diff --git a/Tests/Runtime/DispatchTests.cs.meta b/Tests/Runtime/DispatchTests.cs.meta new file mode 100644 index 0000000..9bfc076 --- /dev/null +++ b/Tests/Runtime/DispatchTests.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 834d7e72a9e042d3954745166c9c5a1a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime/README.md b/Tests/Runtime/README.md index 2837423..370e511 100644 --- a/Tests/Runtime/README.md +++ b/Tests/Runtime/README.md @@ -1,4 +1,12 @@ -# Unity smoke test +# Unity tests + +## DispatchTests + +`DispatchTests.cs` is a pure-unit dispatch test. Feeds every canonical server-emitted message envelope (vendored under `Resources/Fixtures/` from `asobi/priv/protocol/fixtures`) through `AsobiRealtime.HandleMessage` and asserts the matching event fires. Catches doc-vs-server drift before any user reports a silent failure. + +It runs in PlayMode (where the `Tests/Runtime` asmdef lives) but uses `[Test]` (not `[UnityTest]`) and does not require a backend or a scene. + +## SmokeTest `SmokeTest.cs` exercises the 3 canonical scenarios (auth + WS, matchmaker → match.matched, input → state) against [asobi-test-harness](https://github.com/widgrensit/asobi-test-harness). It's a Unity Test Framework `UnityTest`. diff --git a/Tests/Runtime/Resources.meta b/Tests/Runtime/Resources.meta new file mode 100644 index 0000000..611ce0a --- /dev/null +++ b/Tests/Runtime/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 54b0d817939243468b45c028f72f0f10 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime/Resources/Fixtures.meta b/Tests/Runtime/Resources/Fixtures.meta new file mode 100644 index 0000000..f27ff4d --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8f0819f3494749e1b4153d4256a38741 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Tests/Runtime/Resources/Fixtures/chat.joined.json b/Tests/Runtime/Resources/Fixtures/chat.joined.json new file mode 100644 index 0000000..b3a1f77 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/chat.joined.json @@ -0,0 +1 @@ +{"type":"chat.joined","cid":"7","payload":{"channel_id":"01j8x000000000000000000005"}} diff --git a/Tests/Runtime/Resources/Fixtures/chat.left.json b/Tests/Runtime/Resources/Fixtures/chat.left.json new file mode 100644 index 0000000..ef05147 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/chat.left.json @@ -0,0 +1 @@ +{"type":"chat.left","cid":"8","payload":{"channel_id":"01j8x000000000000000000005"}} diff --git a/Tests/Runtime/Resources/Fixtures/chat.message.json b/Tests/Runtime/Resources/Fixtures/chat.message.json new file mode 100644 index 0000000..edb07b5 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/chat.message.json @@ -0,0 +1 @@ +{"type":"chat.message","payload":{"channel_id":"01j8x000000000000000000005","sender_id":"01j8x000000000000000000000","content":"hello","ts":1730000000000}} diff --git a/Tests/Runtime/Resources/Fixtures/dm.message.json b/Tests/Runtime/Resources/Fixtures/dm.message.json new file mode 100644 index 0000000..7217128 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/dm.message.json @@ -0,0 +1 @@ +{"type":"dm.message","payload":{"sender_id":"01j8x000000000000000000002","content":"hi","ts":1730000000000}} diff --git a/Tests/Runtime/Resources/Fixtures/dm.sent.json b/Tests/Runtime/Resources/Fixtures/dm.sent.json new file mode 100644 index 0000000..84071d2 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/dm.sent.json @@ -0,0 +1 @@ +{"type":"dm.sent","cid":"9","payload":{"recipient_id":"01j8x000000000000000000002","ts":1730000000000}} diff --git a/Tests/Runtime/Resources/Fixtures/error.json b/Tests/Runtime/Resources/Fixtures/error.json new file mode 100644 index 0000000..aa8b5cf --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/error.json @@ -0,0 +1 @@ +{"type":"error","payload":{"reason":"invalid_message"}} diff --git a/Tests/Runtime/Resources/Fixtures/match.finished.json b/Tests/Runtime/Resources/Fixtures/match.finished.json new file mode 100644 index 0000000..15ad8dd --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.finished.json @@ -0,0 +1 @@ +{"type":"match.finished","payload":{"match_id":"01j8x000000000000000000001","result":{"winner":"01j8x000000000000000000000"}}} diff --git a/Tests/Runtime/Resources/Fixtures/match.joined.json b/Tests/Runtime/Resources/Fixtures/match.joined.json new file mode 100644 index 0000000..a9b7755 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.joined.json @@ -0,0 +1 @@ +{"type":"match.joined","cid":"3","payload":{"match_id":"01j8x000000000000000000001","mode":"demo","players":["01j8x000000000000000000000"]}} diff --git a/Tests/Runtime/Resources/Fixtures/match.left.json b/Tests/Runtime/Resources/Fixtures/match.left.json new file mode 100644 index 0000000..9466845 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.left.json @@ -0,0 +1 @@ +{"type":"match.left","cid":"4","payload":{"success":true}} diff --git a/Tests/Runtime/Resources/Fixtures/match.matched.json b/Tests/Runtime/Resources/Fixtures/match.matched.json new file mode 100644 index 0000000..6750684 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.matched.json @@ -0,0 +1 @@ +{"type":"match.matched","payload":{"match_id":"01j8x000000000000000000001","mode":"demo","players":["01j8x000000000000000000000","01j8x000000000000000000002"]}} diff --git a/Tests/Runtime/Resources/Fixtures/match.matchmaker_expired.json b/Tests/Runtime/Resources/Fixtures/match.matchmaker_expired.json new file mode 100644 index 0000000..4e25f23 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.matchmaker_expired.json @@ -0,0 +1 @@ +{"type":"match.matchmaker_expired","payload":{"ticket_id":"01j8x000000000000000000003"}} diff --git a/Tests/Runtime/Resources/Fixtures/match.matchmaker_failed.json b/Tests/Runtime/Resources/Fixtures/match.matchmaker_failed.json new file mode 100644 index 0000000..4ba71c7 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.matchmaker_failed.json @@ -0,0 +1 @@ +{"type":"match.matchmaker_failed","payload":{"reason":"no_game_module"}} diff --git a/Tests/Runtime/Resources/Fixtures/match.state.json b/Tests/Runtime/Resources/Fixtures/match.state.json new file mode 100644 index 0000000..b7fd103 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.state.json @@ -0,0 +1 @@ +{"type":"match.state","payload":{"tick":7,"players":{"01j8x000000000000000000000":{"x":120,"y":80}}}} diff --git a/Tests/Runtime/Resources/Fixtures/match.vote_result.json b/Tests/Runtime/Resources/Fixtures/match.vote_result.json new file mode 100644 index 0000000..11281a6 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.vote_result.json @@ -0,0 +1 @@ +{"type":"match.vote_result","payload":{"vote_id":"01j8x000000000000000000004","winner":"a"}} diff --git a/Tests/Runtime/Resources/Fixtures/match.vote_start.json b/Tests/Runtime/Resources/Fixtures/match.vote_start.json new file mode 100644 index 0000000..869bb72 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.vote_start.json @@ -0,0 +1 @@ +{"type":"match.vote_start","payload":{"vote_id":"01j8x000000000000000000004","template":"map_pick","options":[{"id":"a","label":"Arena"}]}} diff --git a/Tests/Runtime/Resources/Fixtures/match.vote_tally.json b/Tests/Runtime/Resources/Fixtures/match.vote_tally.json new file mode 100644 index 0000000..a7c5be7 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.vote_tally.json @@ -0,0 +1 @@ +{"type":"match.vote_tally","payload":{"vote_id":"01j8x000000000000000000004","tally":{"a":1}}} diff --git a/Tests/Runtime/Resources/Fixtures/match.vote_vetoed.json b/Tests/Runtime/Resources/Fixtures/match.vote_vetoed.json new file mode 100644 index 0000000..f7806ff --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/match.vote_vetoed.json @@ -0,0 +1 @@ +{"type":"match.vote_vetoed","payload":{"vote_id":"01j8x000000000000000000004"}} diff --git a/Tests/Runtime/Resources/Fixtures/matchmaker.queued.json b/Tests/Runtime/Resources/Fixtures/matchmaker.queued.json new file mode 100644 index 0000000..a96541c --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/matchmaker.queued.json @@ -0,0 +1 @@ +{"type":"matchmaker.queued","cid":"5","payload":{"ticket_id":"01j8x000000000000000000003","status":"pending"}} diff --git a/Tests/Runtime/Resources/Fixtures/matchmaker.removed.json b/Tests/Runtime/Resources/Fixtures/matchmaker.removed.json new file mode 100644 index 0000000..49f9d93 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/matchmaker.removed.json @@ -0,0 +1 @@ +{"type":"matchmaker.removed","cid":"6","payload":{"success":true}} diff --git a/Tests/Runtime/Resources/Fixtures/notification.new.json b/Tests/Runtime/Resources/Fixtures/notification.new.json new file mode 100644 index 0000000..61b2231 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/notification.new.json @@ -0,0 +1 @@ +{"type":"notification.new","payload":{"id":"01j8x000000000000000000006","kind":"friend_request","from":"01j8x000000000000000000002"}} diff --git a/Tests/Runtime/Resources/Fixtures/presence.updated.json b/Tests/Runtime/Resources/Fixtures/presence.updated.json new file mode 100644 index 0000000..7dc9050 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/presence.updated.json @@ -0,0 +1 @@ +{"type":"presence.updated","cid":"10","payload":{"status":"online"}} diff --git a/Tests/Runtime/Resources/Fixtures/session.connected.json b/Tests/Runtime/Resources/Fixtures/session.connected.json new file mode 100644 index 0000000..be8aa9c --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/session.connected.json @@ -0,0 +1 @@ +{"type":"session.connected","cid":"1","payload":{"player_id":"01j8x000000000000000000000"}} diff --git a/Tests/Runtime/Resources/Fixtures/session.heartbeat.json b/Tests/Runtime/Resources/Fixtures/session.heartbeat.json new file mode 100644 index 0000000..b82222d --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/session.heartbeat.json @@ -0,0 +1 @@ +{"type":"session.heartbeat","cid":"2","payload":{"ts":1730000000000}} diff --git a/Tests/Runtime/Resources/Fixtures/vote.cast_ok.json b/Tests/Runtime/Resources/Fixtures/vote.cast_ok.json new file mode 100644 index 0000000..60fb68a --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/vote.cast_ok.json @@ -0,0 +1 @@ +{"type":"vote.cast_ok","cid":"11","payload":{"success":true}} diff --git a/Tests/Runtime/Resources/Fixtures/vote.veto_ok.json b/Tests/Runtime/Resources/Fixtures/vote.veto_ok.json new file mode 100644 index 0000000..4321de6 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/vote.veto_ok.json @@ -0,0 +1 @@ +{"type":"vote.veto_ok","cid":"12","payload":{"success":true}} diff --git a/Tests/Runtime/Resources/Fixtures/world.finished.json b/Tests/Runtime/Resources/Fixtures/world.finished.json new file mode 100644 index 0000000..5458593 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.finished.json @@ -0,0 +1 @@ +{"type":"world.finished","payload":{"world_id":"01j8x000000000000000000007","result":{"winner":"01j8x000000000000000000000"}}} diff --git a/Tests/Runtime/Resources/Fixtures/world.joined.json b/Tests/Runtime/Resources/Fixtures/world.joined.json new file mode 100644 index 0000000..7017bf4 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.joined.json @@ -0,0 +1 @@ +{"type":"world.joined","cid":"14","payload":{"world_id":"01j8x000000000000000000007","mode":"village"}} diff --git a/Tests/Runtime/Resources/Fixtures/world.left.json b/Tests/Runtime/Resources/Fixtures/world.left.json new file mode 100644 index 0000000..e717961 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.left.json @@ -0,0 +1 @@ +{"type":"world.left","cid":"15","payload":{"success":true}} diff --git a/Tests/Runtime/Resources/Fixtures/world.list.json b/Tests/Runtime/Resources/Fixtures/world.list.json new file mode 100644 index 0000000..f064e87 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.list.json @@ -0,0 +1 @@ +{"type":"world.list","cid":"13","payload":{"worlds":[{"id":"01j8x000000000000000000007","mode":"village","capacity":16,"size":3}]}} diff --git a/Tests/Runtime/Resources/Fixtures/world.phase_changed.json b/Tests/Runtime/Resources/Fixtures/world.phase_changed.json new file mode 100644 index 0000000..4e7b738 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.phase_changed.json @@ -0,0 +1 @@ +{"type":"world.phase_changed","payload":{"phase":"event","started_at":1730000000000}} diff --git a/Tests/Runtime/Resources/Fixtures/world.terrain.json b/Tests/Runtime/Resources/Fixtures/world.terrain.json new file mode 100644 index 0000000..1903a91 --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.terrain.json @@ -0,0 +1 @@ +{"type":"world.terrain","payload":{"coords":[0,0],"data":""}} diff --git a/Tests/Runtime/Resources/Fixtures/world.tick.json b/Tests/Runtime/Resources/Fixtures/world.tick.json new file mode 100644 index 0000000..3778eca --- /dev/null +++ b/Tests/Runtime/Resources/Fixtures/world.tick.json @@ -0,0 +1 @@ +{"type":"world.tick","payload":{"tick":42,"updates":[{"id":"01j8x000000000000000000000","op":"a","x":120,"y":80}]}}