183 lines
6.5 KiB
C#
183 lines
6.5 KiB
C#
using System.Linq;
|
|
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using NeonSprawl.Server.Game.Items;
|
|
using Xunit;
|
|
|
|
namespace NeonSprawl.Server.Tests.Game.Items;
|
|
|
|
/// <summary>Regression tests for <c>GET</c>/<c>POST …/inventory</c> (NEO-55).</summary>
|
|
public sealed class PlayerInventoryApiTests
|
|
{
|
|
private static PlayerInventoryMutationRequest Mutation(
|
|
string mutationKind,
|
|
string itemId,
|
|
int quantity,
|
|
int schemaVersion = PlayerInventoryMutationRequest.CurrentSchemaVersion) =>
|
|
new()
|
|
{
|
|
SchemaVersion = schemaVersion,
|
|
MutationKind = mutationKind,
|
|
ItemId = itemId,
|
|
Quantity = quantity,
|
|
};
|
|
|
|
[Fact]
|
|
public async Task GetInventory_ShouldReturnNotFound_WhenPlayerUnknown()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync("/game/players/missing-player/inventory");
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetInventory_ShouldReturnSchemaV1_WithEmptyFixedSlotArrays()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync("/game/players/dev-local-1/inventory");
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
var body = await response.Content.ReadFromJsonAsync<PlayerInventorySnapshotResponse>();
|
|
Assert.NotNull(body);
|
|
Assert.Equal(PlayerInventorySnapshotResponse.CurrentSchemaVersion, body!.SchemaVersion);
|
|
Assert.Equal("dev-local-1", body.PlayerId);
|
|
Assert.Equal(PlayerInventorySnapshot.BagSlotCount, body.BagSlots.Count);
|
|
Assert.Single(body.EquipmentSlots);
|
|
Assert.All(body.BagSlots, static slot =>
|
|
{
|
|
Assert.Null(slot.ItemId);
|
|
Assert.Equal(0, slot.Quantity);
|
|
});
|
|
Assert.All(body.EquipmentSlots, static slot =>
|
|
{
|
|
Assert.Null(slot.ItemId);
|
|
Assert.Equal(0, slot.Quantity);
|
|
});
|
|
Assert.Equal(Enumerable.Range(0, PlayerInventorySnapshot.BagSlotCount), body.BagSlots.Select(static s => s.SlotIndex));
|
|
Assert.Equal(0, body.EquipmentSlots[0].SlotIndex);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostInventory_ShouldReturnBadRequest_WhenSchemaVersionMismatch()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
var request = Mutation("add", "scrap_metal_bulk", quantity: 1, schemaVersion: 99);
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync("/game/players/dev-local-1/inventory", request);
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostInventory_ShouldReturnBadRequest_WhenMutationKindUnknown()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
var request = Mutation("consume", "scrap_metal_bulk", quantity: 1);
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync("/game/players/dev-local-1/inventory", request);
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostInventory_ShouldReturnNotFound_WhenPlayerUnknown()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync(
|
|
"/game/players/missing-player/inventory",
|
|
Mutation("add", "scrap_metal_bulk", quantity: 1));
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostInventory_ShouldApplyAdd_WithUpdatedSnapshot()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync(
|
|
"/game/players/dev-local-1/inventory",
|
|
Mutation("add", "scrap_metal_bulk", quantity: 10));
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
var body = await response.Content.ReadFromJsonAsync<PlayerInventoryMutationResponse>();
|
|
Assert.NotNull(body);
|
|
Assert.True(body!.Applied);
|
|
Assert.Null(body.ReasonCode);
|
|
Assert.Equal("dev-local-1", body.Inventory.PlayerId);
|
|
var occupied = body.Inventory.BagSlots.Where(static s => s.Quantity > 0).ToList();
|
|
Assert.Single(occupied);
|
|
Assert.Equal("scrap_metal_bulk", occupied[0].ItemId);
|
|
Assert.Equal(10, occupied[0].Quantity);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostInventory_ShouldDenyUnknownItem_WithInvalidItem_AndLeaveInventoryEmpty()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync(
|
|
"/game/players/dev-local-1/inventory",
|
|
Mutation("add", "not-a-prototype-item", quantity: 1));
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
var body = await response.Content.ReadFromJsonAsync<PlayerInventoryMutationResponse>();
|
|
Assert.NotNull(body);
|
|
Assert.False(body!.Applied);
|
|
Assert.Equal(PlayerInventoryReasonCodes.InvalidItem, body.ReasonCode);
|
|
Assert.All(body.Inventory.BagSlots, static slot => Assert.Equal(0, slot.Quantity));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PostInventory_ShouldDenyRemove_WithInsufficientQuantity()
|
|
{
|
|
// Arrange
|
|
await using var factory = new InMemoryWebApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync(
|
|
"/game/players/dev-local-1/inventory",
|
|
Mutation("remove", "scrap_metal_bulk", quantity: 1));
|
|
|
|
// Assert
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
var body = await response.Content.ReadFromJsonAsync<PlayerInventoryMutationResponse>();
|
|
Assert.NotNull(body);
|
|
Assert.False(body!.Applied);
|
|
Assert.Equal(PlayerInventoryReasonCodes.InsufficientQuantity, body.ReasonCode);
|
|
}
|
|
}
|