Forgot unversioned xd
This commit is contained in:
117
SVSim.UnitTests/Controllers/CheckControllerTests.cs
Normal file
117
SVSim.UnitTests/Controllers/CheckControllerTests.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using SVSim.UnitTests.Infrastructure;
|
||||
|
||||
namespace SVSim.UnitTests.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Coverage for <c>/check/*</c> — the first two endpoints the client hits on boot. The
|
||||
/// SpecialTitle smoke is duplicated in RoutingSmokeTests for routing-prefix coverage; this
|
||||
/// test layers shape assertions over the deeper boot-path concern.
|
||||
/// </summary>
|
||||
public class CheckControllerTests
|
||||
{
|
||||
private const string BaseRequestJson =
|
||||
"""{"viewerId":"0","steamId":0,"steamSessionTicket":""}""";
|
||||
|
||||
private const string GameStartRequestJson =
|
||||
"""{"viewerId":"0","steamId":0,"steamSessionTicket":"","appType":0,"campaignData":"","campaignSign":"","campaignUser":0}""";
|
||||
|
||||
[Test]
|
||||
public async Task SpecialTitle_returns_default_title_id()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
using var client = factory.CreateClient();
|
||||
|
||||
var response = await client.PostAsync("/check/special_title",
|
||||
new StringContent(BaseRequestJson, Encoding.UTF8, "application/json"));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK));
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
using var doc = JsonDocument.Parse(body);
|
||||
Assert.That(doc.RootElement.GetProperty("titleImageId").GetString(), Is.EqualTo("0"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GameStart_with_authed_viewer_returns_spec_shape()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
long viewerId = await factory.SeedViewerAsync();
|
||||
using var client = factory.CreateAuthenticatedClient(viewerId);
|
||||
|
||||
var response = await client.PostAsync("/check/game_start",
|
||||
new StringContent(GameStartRequestJson, Encoding.UTF8, "application/json"));
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), body);
|
||||
|
||||
using var doc = JsonDocument.Parse(body);
|
||||
var root = doc.RootElement;
|
||||
|
||||
// now_tutorial_step is a STRING on the wire (prod sends "100"); client calls .ToInt().
|
||||
Assert.That(root.GetProperty("nowTutorialStep").GetString(), Is.EqualTo("100"),
|
||||
"RegisterViewer's seed-config default sets tutorial_state=100 (tutorial complete).");
|
||||
Assert.That(root.GetProperty("tosState").GetInt32(), Is.EqualTo(1));
|
||||
Assert.That(root.GetProperty("policyState").GetInt32(), Is.EqualTo(1));
|
||||
Assert.That(root.GetProperty("korAuthorityState").GetInt32(), Is.EqualTo(0));
|
||||
Assert.That(root.GetProperty("tosId").GetInt32(), Is.EqualTo(1));
|
||||
Assert.That(root.GetProperty("policyId").GetInt32(), Is.EqualTo(1));
|
||||
Assert.That(root.GetProperty("korAuthorityId").GetInt32(), Is.EqualTo(0));
|
||||
|
||||
// Prod-shape fields (not strictly read by GameStartCheckTask.Parse but sent by prod).
|
||||
Assert.That(root.GetProperty("nowViewerId").GetInt64(), Is.GreaterThan(0));
|
||||
Assert.That(root.GetProperty("nowName").GetString(), Is.Not.Empty);
|
||||
Assert.That(root.GetProperty("nowRank").ValueKind, Is.EqualTo(JsonValueKind.Object));
|
||||
|
||||
// Steam connection should round-trip into transition_account_data — all three fields
|
||||
// serialized as strings (matches prod wire shape).
|
||||
var transitions = root.GetProperty("transitionAccountData");
|
||||
Assert.That(transitions.ValueKind, Is.EqualTo(JsonValueKind.Array));
|
||||
Assert.That(transitions.GetArrayLength(), Is.EqualTo(1),
|
||||
"Seeded viewer has exactly one Steam social account connection.");
|
||||
Assert.That(transitions[0].GetProperty("socialAccountType").GetString(),
|
||||
Is.EqualTo(((int)SVSim.Database.Enums.SocialAccountType.Steam).ToString()));
|
||||
Assert.That(transitions[0].GetProperty("socialAccountId").GetString(), Is.Not.Empty);
|
||||
Assert.That(transitions[0].GetProperty("connectedViewerId").GetString(), Is.Not.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GameStart_does_not_expose_unsettable_optional_fields()
|
||||
{
|
||||
// GameStartCheckTask.Parse uses `Keys.Contains("rewrite_viewer_id")` + `.ToInt()` with
|
||||
// no null guard, and same for `account_delete_reservation_status` (presence-only check).
|
||||
// We can't omit nullable properties on the encrypted MessagePack path — the [Key]
|
||||
// formatter writes them as Nil unconditionally. So these keys must not exist on
|
||||
// GameStartResponse at all. If a future change re-adds them, this test breaks the build.
|
||||
using var factory = new SVSimTestFactory();
|
||||
long viewerId = await factory.SeedViewerAsync();
|
||||
using var client = factory.CreateAuthenticatedClient(viewerId);
|
||||
|
||||
var response = await client.PostAsync("/check/game_start",
|
||||
new StringContent(GameStartRequestJson, Encoding.UTF8, "application/json"));
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), body);
|
||||
|
||||
using var doc = JsonDocument.Parse(body);
|
||||
var root = doc.RootElement;
|
||||
Assert.That(root.TryGetProperty("rewriteViewerId", out _), Is.False,
|
||||
"rewrite_viewer_id must NOT be present in the response — client NREs on null .ToInt().");
|
||||
Assert.That(root.TryGetProperty("accountDeleteReservationStatus", out _), Is.False,
|
||||
"account_delete_reservation_status must NOT be present — presence triggers client behavior.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GameStart_with_no_viewer_returns_401()
|
||||
{
|
||||
using var factory = new SVSimTestFactory();
|
||||
using var client = factory.CreateClient();
|
||||
|
||||
var response = await client.PostAsync("/check/game_start",
|
||||
new StringContent(GameStartRequestJson, Encoding.UTF8, "application/json"));
|
||||
|
||||
Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.Unauthorized));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user