diff --git a/SVSim.UnitTests/Controllers/FreeBattleControllerTests.cs b/SVSim.UnitTests/Controllers/FreeBattleControllerTests.cs new file mode 100644 index 00000000..9603d539 --- /dev/null +++ b/SVSim.UnitTests/Controllers/FreeBattleControllerTests.cs @@ -0,0 +1,65 @@ +using System.Net.Http.Json; +using System.Text.Json; +using NUnit.Framework; +using SVSim.Database.Enums; +using SVSim.UnitTests.Infrastructure; + +namespace SVSim.UnitTests.Controllers; + +[TestFixture] +public class FreeBattleControllerTests +{ + // BaseRequest fields (viewer_id / steam_id / steam_session_ticket) are required by the + // request DTOs — the ApiController's auto-validation rejects bodies missing them. We + // post placeholder values here; the TestAuthHandler injects the real viewer-id via the + // X-Test-Viewer-Id header set by CreateAuthenticatedClient, so these body values are + // ignored by auth. + private static readonly object DoMatchingBody = new + { + deck_no = 1, + need_init = 1, + log = 0, + viewer_id = "0", + steam_id = 0, + steam_session_ticket = "", + }; + + private static object FinishBody(int battleResult, int classId = 3) => new + { + battle_result = battleResult, + is_retire = 0, + recovery_data = "{}", + class_id = classId, + total_turn = 5, + viewer_id = "0", + steam_id = 0, + steam_session_ticket = "", + }; + + private static readonly object EmptyAuthedBody = new + { + viewer_id = "0", + steam_id = 0, + steam_session_ticket = "", + }; + + [Test] + public async Task DoMatching_unlimited_first_poll_returns_3002_RETRY_with_empty_node_server_url() + { + await using var factory = new SVSimTestFactory(); + var viewerId = await factory.SeedViewerAsync(); + await factory.SeedGlobalsAsync(); + await factory.SeedDeckAsync(viewerId, Format.Unlimited, 1); + var client = factory.CreateAuthenticatedClient(viewerId); + + var resp = await client.PostAsJsonAsync("/unlimited_free_battle/do_matching", DoMatchingBody); + + Assert.That(resp.IsSuccessStatusCode, Is.True, $"Expected 2xx, got {resp.StatusCode}"); + var raw = await resp.Content.ReadAsStringAsync(); + using var doc = JsonDocument.Parse(raw); + var data = doc.RootElement; + Assert.That(data.GetProperty("matching_state").GetInt32(), Is.EqualTo(3002)); + Assert.That(data.GetProperty("node_server_url").GetString(), Is.EqualTo(""), + "Empty string, not absent — Phase 2 fix pattern."); + } +}