From 754b2ca4663f99fb94c5454c939f73ff030ccf51 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Sat, 27 Jun 2026 15:40:30 -0400 Subject: [PATCH] fix(guild_chat): wait_interval as raw int + capture-replay request field name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove StringifiedIntConverter from GuildChatMessagesResponse.WaitInterval so the wire emits a raw JSON number (3) matching prod, not a quoted string ("3"). Update GuildChatPollTests (2 assertions) and GuildCaptureReplayTests (1 assertion + comment) to expect JsonValueKind.Number. Fix last_message_id → start_message_id typo in GuildChatMessages_Member_ReturnsProdShape request body. Co-Authored-By: Claude Sonnet 4.6 --- .../Dtos/GuildChat/GuildChatMessagesResponse.cs | 3 +-- .../Guild/GuildCaptureReplayTests.cs | 17 ++++++----------- .../Integration/Guild/GuildChatPollTests.cs | 13 ++++++++----- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/GuildChat/GuildChatMessagesResponse.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/GuildChat/GuildChatMessagesResponse.cs index bfeabdff..2e5d427a 100644 --- a/SVSim.EmulatedEntrypoint/Models/Dtos/GuildChat/GuildChatMessagesResponse.cs +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/GuildChat/GuildChatMessagesResponse.cs @@ -1,6 +1,5 @@ using MessagePack; using System.Text.Json.Serialization; -using SVSim.EmulatedEntrypoint.Models.Dtos.Common; using SVSim.EmulatedEntrypoint.Models.Dtos.Common.Guild; namespace SVSim.EmulatedEntrypoint.Models.Dtos.GuildChat; @@ -25,7 +24,7 @@ public class GuildChatMessagesResponse public List ChatMessage { get; set; } = new(); /// Server-driven polling interval in seconds. Client uses this for the next poll. - [JsonPropertyName("wait_interval"), Key("wait_interval"), JsonConverter(typeof(StringifiedIntConverter)), + [JsonPropertyName("wait_interval"), Key("wait_interval"), JsonIgnore(Condition = JsonIgnoreCondition.Never)] public int WaitInterval { get; set; } } diff --git a/SVSim.UnitTests/Integration/Guild/GuildCaptureReplayTests.cs b/SVSim.UnitTests/Integration/Guild/GuildCaptureReplayTests.cs index 53cae053..19b73ec5 100644 --- a/SVSim.UnitTests/Integration/Guild/GuildCaptureReplayTests.cs +++ b/SVSim.UnitTests/Integration/Guild/GuildCaptureReplayTests.cs @@ -215,11 +215,11 @@ public class GuildCaptureReplayTests Assert.That(createResp.IsSuccessStatusCode, Is.True, $"guild/create failed: {await createResp.Content.ReadAsStringAsync()}"); - // Poll messages — last_message_id=0 means "give me everything" + // Poll messages — start_message_id=0 means "give me everything" var resp = await client.PostAsync("/guild_chat/messages", JsonContent.Create(new { - last_message_id = 0, + start_message_id = 0, viewer_id = Vid, steam_id = Sid, steam_session_ticket = Stk, })); @@ -236,17 +236,12 @@ public class GuildCaptureReplayTests Assert.That(chatArr.ValueKind, Is.EqualTo(JsonValueKind.Array), "'chat_message' must be a JSON array"); - // wait_interval must be present and parse to a positive integer. - // Prod ships it as a raw JSON number (3); our server uses StringifiedIntConverter - // so it emits a quoted string ("3"). We accept either form here to avoid a - // broader DTO change that would require updating all existing GuildChatPollTests. + // wait_interval must be a raw JSON number matching prod (prod sends 3, not "3"). Assert.That(root.TryGetProperty("wait_interval", out var waitEl), Is.True, "Response must have 'wait_interval' field"); - int waitValue = waitEl.ValueKind == JsonValueKind.Number - ? waitEl.GetInt32() - : int.Parse(waitEl.GetString()!); - Assert.That(waitValue, Is.GreaterThan(0), - "'wait_interval' must be positive"); + Assert.That(waitEl.ValueKind, Is.EqualTo(JsonValueKind.Number), + "'wait_interval' must be a raw JSON number (prod sends 3, not \"3\")"); + Assert.That(waitEl.GetInt32(), Is.GreaterThan(0), "'wait_interval' must be positive"); // maintenance_card_list must be present as array Assert.That(root.TryGetProperty("maintenance_card_list", out var maintArr), Is.True, diff --git a/SVSim.UnitTests/Integration/Guild/GuildChatPollTests.cs b/SVSim.UnitTests/Integration/Guild/GuildChatPollTests.cs index b94ea242..8f6c35c8 100644 --- a/SVSim.UnitTests/Integration/Guild/GuildChatPollTests.cs +++ b/SVSim.UnitTests/Integration/Guild/GuildChatPollTests.cs @@ -330,9 +330,12 @@ public class GuildChatPollTests Assert.That(messages.GetArrayLength(), Is.EqualTo(0), "chat_message must be empty for a viewer not in a guild"); - // wait_interval is stringified; idle default is ChatPollIdleSeconds (10) - int waitInterval = GetStringifiedInt(root, "wait_interval"); - Assert.That(waitInterval, Is.GreaterThan(0), "wait_interval must be positive"); + // wait_interval is a raw JSON number; idle default is ChatPollIdleSeconds (10) + Assert.That(root.TryGetProperty("wait_interval", out var waitEl), Is.True, + "Response must have 'wait_interval' field"); + Assert.That(waitEl.ValueKind, Is.EqualTo(JsonValueKind.Number), + "'wait_interval' must be a raw JSON number (prod sends 3, not \"3\")"); + Assert.That(waitEl.GetInt32(), Is.GreaterThan(0), "wait_interval must be positive"); } // ========================================================================= @@ -354,11 +357,11 @@ public class GuildChatPollTests // Leader gets messages → active interval var activePoll = await PollAsync(leaderClient, startMessageId: 0, direction: 1); - int activeWait = GetStringifiedInt(activePoll, "wait_interval"); + int activeWait = activePoll.GetProperty("wait_interval").GetInt32(); // Lonely viewer not in a guild → idle interval var idlePoll = await PollAsync(lonelyClient, startMessageId: 0, direction: 1); - int idleWait = GetStringifiedInt(idlePoll, "wait_interval"); + int idleWait = idlePoll.GetProperty("wait_interval").GetInt32(); Assert.That(activeWait, Is.LessThan(idleWait), $"Active interval ({activeWait}s) must be less than idle interval ({idleWait}s)");