From bbdcc36e050f2c123d4a10d0a23f31bb1bb61744 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Mon, 11 May 2026 17:27:29 +0200 Subject: [PATCH] ui/phase-24: declare game.turn.ready as JSON-friendly catalog kind TestBuildClientPushEventCoversCatalog required every catalog kind to encode through a FlatBuffers `preMarshaledEvent`. game.turn.ready intentionally rides on the JSON fallback because its payload is just `{game_id, turn}` and the only consumer (Phase 24 UI handler) parses JSON inline. Make the policy explicit through a jsonFriendlyKinds allow-list so the test still asserts each kind is covered and a future producer that picks the wrong encoding fails loudly. Co-Authored-By: Claude Opus 4.7 --- backend/internal/notification/events_test.go | 30 +++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/backend/internal/notification/events_test.go b/backend/internal/notification/events_test.go index 1b9ae39..e8ab482 100644 --- a/backend/internal/notification/events_test.go +++ b/backend/internal/notification/events_test.go @@ -9,9 +9,25 @@ import ( "github.com/google/uuid" ) +// jsonFriendlyKinds lists catalog kinds whose payload is small and +// stable enough that the gateway-bound encoding stays JSON instead of +// FlatBuffers. The default for new producers is still FB; declaring a +// kind here is a deliberate decision baked into the build target's +// payload contract. +// +// `game.turn.ready` ships `{game_id, turn}` only, the UI parses it +// inline in `routes/games/[id]/+layout.svelte` (Phase 24), and no +// other consumer reads the payload — adopting the FB encoder would +// require a new TS notification stub set and the regen tooling for +// `pkg/schema/fbs/notification.fbs` without buying anything. +var jsonFriendlyKinds = map[string]bool{ + KindGameTurnReady: true, +} + // TestBuildClientPushEventCoversCatalog asserts that every catalog kind -// returns a typed FB event (preMarshaledEvent) and that an unknown kind -// falls through to the JSON safety net. +// is exercised by this test, that FB-typed kinds return a +// `preMarshaledEvent`, and that JSON-friendly kinds (see +// `jsonFriendlyKinds` above) return a `push.JSONEvent`. func TestBuildClientPushEventCoversCatalog(t *testing.T) { t.Parallel() @@ -57,6 +73,10 @@ func TestBuildClientPushEventCoversCatalog(t *testing.T) { "game_id": gameID.String(), "reason": "missing engine version", }}, + {"game turn ready", KindGameTurnReady, map[string]any{ + "game_id": gameID.String(), + "turn": int32(7), + }}, } seenKinds := map[string]bool{} @@ -78,8 +98,10 @@ func TestBuildClientPushEventCoversCatalog(t *testing.T) { if len(bytes) == 0 { t.Fatalf("Marshal returned empty bytes") } - if _, isJSON := event.(push.JSONEvent); isJSON { - t.Fatalf("expected typed FB event for %s, got JSONEvent", tt.kind) + _, isJSON := event.(push.JSONEvent) + wantJSON := jsonFriendlyKinds[tt.kind] + if isJSON != wantJSON { + t.Fatalf("kind %s: JSONEvent=%v, want JSONEvent=%v", tt.kind, isJSON, wantJSON) } }) seenKinds[tt.kind] = true