neon-sprawl/server/NeonSprawl.Server.Tests/Game/PositionState/MoveCommandApiTests.cs

109 lines
3.9 KiB
C#

using System.Net;
using System.Net.Http.Json;
using System.Text;
using NeonSprawl.Server.Game.PositionState;
using Xunit;
namespace NeonSprawl.Server.Tests.Game.PositionState;
/// <summary>
/// NS-16: integration tests for <c>POST /game/players/{{id}}/move</c> on <see cref="NeonSprawl.Server.Game.PositionState.PositionStateApi"/>.
/// Isolated host per test (fresh in-memory store).
/// </summary>
public class MoveCommandApiTests
{
[Fact]
public async Task PostMove_ShouldPersistTargetAndIncrementSequence_WhenDevPlayerPostsValidMove()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
var cmd = new MoveCommandRequest
{
SchemaVersion = MoveCommandRequest.CurrentSchemaVersion,
Target = new PositionVector { X = 1.5, Y = -0.5, Z = 2.25 },
};
// Act
var beforeMove = await client.GetFromJsonAsync<PositionStateResponse>("/game/players/dev-local-1/position");
var postResponse = await client.PostAsJsonAsync("/game/players/dev-local-1/move", cmd);
var postBody = await postResponse.Content.ReadFromJsonAsync<PositionStateResponse>();
var afterMove = await client.GetFromJsonAsync<PositionStateResponse>("/game/players/dev-local-1/position");
// Assert
Assert.NotNull(beforeMove);
var seq0 = beforeMove!.Sequence;
Assert.Equal(HttpStatusCode.OK, postResponse.StatusCode);
Assert.NotNull(postBody);
Assert.Equal(PositionStateResponse.CurrentSchemaVersion, postBody!.SchemaVersion);
Assert.Equal("dev-local-1", postBody.PlayerId);
Assert.Equal(seq0 + 1, postBody.Sequence);
Assert.Equal(1.5, postBody.Position.X);
Assert.Equal(-0.5, postBody.Position.Y);
Assert.Equal(2.25, postBody.Position.Z);
Assert.NotNull(afterMove);
Assert.Equal(postBody.Position.X, afterMove!.Position.X);
Assert.Equal(postBody.Position.Y, afterMove.Position.Y);
Assert.Equal(postBody.Position.Z, afterMove.Position.Z);
Assert.Equal(postBody.Sequence, afterMove.Sequence);
}
[Fact]
public async Task PostMove_ShouldReturnNotFound_WhenPlayerIsUnknown()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
var cmd = new MoveCommandRequest
{
SchemaVersion = MoveCommandRequest.CurrentSchemaVersion,
Target = new PositionVector { X = 0, Y = 0, Z = 0 },
};
// Act
var response = await client.PostAsJsonAsync("/game/players/unknown-player/move", cmd);
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task PostMove_ShouldReturnBadRequest_WhenSchemaVersionIsWrong()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
var cmd = new MoveCommandRequest
{
SchemaVersion = 999,
Target = new PositionVector { X = 0, Y = 0, Z = 0 },
};
// Act
var response = await client.PostAsJsonAsync("/game/players/dev-local-1/move", cmd);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Fact]
public async Task PostMove_ShouldReturnBadRequest_WhenTargetIsMissing()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
var content = new StringContent(
"{\"schemaVersion\":1}",
Encoding.UTF8,
"application/json");
// Act
var response = await client.PostAsync("/game/players/dev-local-1/move", content);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
}