neon-sprawl/server/NeonSprawl.Server.Tests/Game/Quests/QuestAcceptApiTests.cs

201 lines
8.0 KiB
C#

using System.Net;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using NeonSprawl.Server.Game.Quests;
using NeonSprawl.Server.Tests;
using Xunit;
namespace NeonSprawl.Server.Tests.Game.Quests;
public sealed class QuestAcceptApiTests
{
private const string PlayerId = "dev-local-1";
private const string GatherQuestId = PrototypeE7M1QuestCatalogRules.GatherIntroQuestId;
private const string RefineQuestId = PrototypeE7M1QuestCatalogRules.RefineIntroQuestId;
[Fact]
public async Task PostQuestAccept_ShouldReturnNotFound_WhenPlayerUnknown()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
// Act
var response = await client.PostAsync(
$"/game/players/missing-player/quests/{GatherQuestId}/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task PostQuestAccept_ShouldReturnNotFound_WhenPlayerIdIsWhitespaceOnly()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
// Act
var response = await client.PostAsync(
$"/game/players/%20/quests/{GatherQuestId}/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task PostQuestAccept_ShouldReturnAcceptedTrue_WhenGatherIntroNotStarted()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
// Act
var response = await client.PostAsync(
$"/game/players/{PlayerId}/quests/{GatherQuestId}/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<QuestAcceptResponse>();
Assert.NotNull(body);
Assert.Equal(QuestAcceptResponse.CurrentSchemaVersion, body!.SchemaVersion);
Assert.True(body.Accepted);
Assert.Null(body.ReasonCode);
Assert.NotNull(body.Quest);
Assert.Equal(GatherQuestId, body.Quest!.QuestId);
Assert.Equal(QuestProgressApi.StatusActive, body.Quest.Status);
Assert.Equal(0, body.Quest.CurrentStepIndex);
Assert.Empty(body.Quest.ObjectiveCounters);
Assert.Null(body.Quest.CompletedAt);
var getResponse = await client.GetAsync($"/game/players/{PlayerId}/quest-progress");
Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode);
var progress = await getResponse.Content.ReadFromJsonAsync<QuestProgressListResponse>();
Assert.NotNull(progress);
var row = Assert.Single(progress!.Quests, static r => r.QuestId == GatherQuestId);
Assert.Equal(QuestProgressApi.StatusActive, row.Status);
}
[Fact]
public async Task PostQuestAccept_ShouldReturnAcceptedTrue_WhenRequestBodyOmitted()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
// Act
var response = await client.PostAsync(
$"/game/players/{PlayerId}/quests/{GatherQuestId}/accept",
content: null);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<QuestAcceptResponse>();
Assert.NotNull(body);
Assert.True(body!.Accepted);
Assert.Equal(GatherQuestId, body.Quest!.QuestId);
}
[Fact]
public async Task PostQuestAccept_ShouldReturnBadRequest_WhenSchemaVersionInvalid()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
using var content = new StringContent(
JsonSerializer.Serialize(new { schemaVersion = 99 }),
Encoding.UTF8,
"application/json");
// Act
var response = await client.PostAsync(
$"/game/players/{PlayerId}/quests/{GatherQuestId}/accept",
content);
// Assert
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
}
[Fact]
public async Task PostQuestAccept_ShouldDenyPrerequisiteIncomplete_WhenRefineIntroBeforeGatherComplete()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
// Act
var response = await client.PostAsync(
$"/game/players/{PlayerId}/quests/{RefineQuestId}/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<QuestAcceptResponse>();
Assert.NotNull(body);
Assert.False(body!.Accepted);
Assert.Equal(QuestStateReasonCodes.PrerequisiteIncomplete, body.ReasonCode);
Assert.Null(body.Quest);
var getResponse = await client.GetAsync($"/game/players/{PlayerId}/quest-progress");
var progress = await getResponse.Content.ReadFromJsonAsync<QuestProgressListResponse>();
Assert.NotNull(progress);
var row = Assert.Single(progress!.Quests, static r => r.QuestId == RefineQuestId);
Assert.Equal(QuestProgressApi.StatusNotStarted, row.Status);
}
[Fact]
public async Task PostQuestAccept_ShouldDenyAlreadyActive_WhenQuestAlreadyAccepted()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
var first = await client.PostAsync(
$"/game/players/{PlayerId}/quests/{GatherQuestId}/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
Assert.Equal(HttpStatusCode.OK, first.StatusCode);
var firstBody = await first.Content.ReadFromJsonAsync<QuestAcceptResponse>();
Assert.NotNull(firstBody);
Assert.True(firstBody!.Accepted);
// Act
var response = await client.PostAsync(
$"/game/players/{PlayerId}/quests/{GatherQuestId}/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<QuestAcceptResponse>();
Assert.NotNull(body);
Assert.False(body!.Accepted);
Assert.Equal(QuestStateReasonCodes.AlreadyActive, body.ReasonCode);
Assert.NotNull(body.Quest);
Assert.Equal(QuestProgressApi.StatusActive, body.Quest!.Status);
Assert.Equal(firstBody.Quest!.CurrentStepIndex, body.Quest.CurrentStepIndex);
}
[Fact]
public async Task PostQuestAccept_ShouldDenyUnknownQuest_WhenQuestIdNotInCatalog()
{
// Arrange
await using var factory = new InMemoryWebApplicationFactory();
var client = factory.CreateClient();
// Act
var response = await client.PostAsync(
$"/game/players/{PlayerId}/quests/prototype_quest_missing/accept",
JsonContent.Create(new QuestAcceptRequest { SchemaVersion = QuestAcceptRequest.CurrentSchemaVersion }));
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadFromJsonAsync<QuestAcceptResponse>();
Assert.NotNull(body);
Assert.False(body!.Accepted);
Assert.Equal(QuestStateReasonCodes.UnknownQuest, body.ReasonCode);
Assert.Null(body.Quest);
}
}