Files
pos-system/services/membership-service-net/tests/MembershipService.FunctionalTests/Controllers/AdminLevelsControllerTests.cs

249 lines
7.4 KiB
C#

using System.Net;
using System.Net.Http.Json;
using FluentAssertions;
using MembershipService.API.Application.Commands;
using Xunit;
namespace MembershipService.FunctionalTests.Controllers;
/// <summary>
/// EN: Functional tests for Admin Level endpoints.
/// VI: Functional tests cho Admin Level endpoints.
/// </summary>
[Collection("Sequential")]
public class AdminLevelsControllerTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly CustomWebApplicationFactory _factory;
public AdminLevelsControllerTests(CustomWebApplicationFactory factory)
{
_factory = factory;
}
#region POST /api/v1/levels - Create Level
[Fact]
public async Task CreateLevel_WithAuth_ShouldReturn201()
{
// Arrange
var client = _factory.CreateAuthenticatedClient();
var command = new CreateLevelDefinitionCommand
{
LevelNumber = 10,
Name = "Test Level",
RequiredExp = 5000,
Description = "Test level for functional tests",
BadgeColor = "#FF5733"
};
// Act
var response = await client.PostAsJsonAsync("/api/v1/levels", command);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Created);
var result = await response.Content.ReadFromJsonAsync<CreateLevelDefinitionResult>();
result.Should().NotBeNull();
result!.LevelNumber.Should().Be(10);
result.Name.Should().Be("Test Level");
result.RequiredExp.Should().Be(5000);
}
[Fact]
public async Task CreateLevel_WithoutAuth_ShouldReturn401()
{
// Arrange
var client = _factory.CreateClient(); // No auth
var command = new CreateLevelDefinitionCommand
{
LevelNumber = 11,
Name = "Unauthorized Level",
RequiredExp = 6000
};
// Act
var response = await client.PostAsJsonAsync("/api/v1/levels", command);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task CreateLevel_DuplicateLevelNumber_ShouldReturn409()
{
// Arrange
var client = _factory.CreateAuthenticatedClient();
// First create a level
var firstCommand = new CreateLevelDefinitionCommand
{
LevelNumber = 50, // Use unique number to avoid conflicts with other tests
Name = "First Level",
RequiredExp = 500
};
var firstResponse = await client.PostAsJsonAsync("/api/v1/levels", firstCommand);
firstResponse.StatusCode.Should().Be(HttpStatusCode.Created);
// Now try to create duplicate
var duplicateCommand = new CreateLevelDefinitionCommand
{
LevelNumber = 50, // Same level number - should conflict
Name = "Duplicate",
RequiredExp = 500
};
// Act
var response = await client.PostAsJsonAsync("/api/v1/levels", duplicateCommand);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Conflict);
}
#endregion
#region PUT /api/v1/levels/{id} - Update Level
[Fact]
public async Task UpdateLevel_WithAuth_ShouldReturn200()
{
// Arrange
var client = _factory.CreateAuthenticatedClient();
// First create a level to update
var createCommand = new CreateLevelDefinitionCommand
{
LevelNumber = 60,
Name = "ToUpdate",
RequiredExp = 6000,
Description = "Original description"
};
var createResponse = await client.PostAsJsonAsync("/api/v1/levels", createCommand);
createResponse.StatusCode.Should().Be(HttpStatusCode.Created);
var createdLevel = await createResponse.Content.ReadFromJsonAsync<CreateLevelDefinitionResult>();
var updateCommand = new UpdateLevelDefinitionCommand
{
Id = createdLevel!.Id,
Name = "Updated Level",
Description = "Updated description"
};
// Act
var response = await client.PutAsJsonAsync($"/api/v1/levels/{createdLevel.Id}", updateCommand);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
var result = await response.Content.ReadFromJsonAsync<UpdateLevelDefinitionResult>();
result.Should().NotBeNull();
result!.Name.Should().Be("Updated Level");
result.Description.Should().Be("Updated description");
}
[Fact]
public async Task UpdateLevel_WithoutAuth_ShouldReturn401()
{
// Arrange
var client = _factory.CreateClient(); // No auth
var randomId = Guid.NewGuid();
var command = new UpdateLevelDefinitionCommand
{
Id = randomId,
Name = "Unauthorized Update"
};
// Act
var response = await client.PutAsJsonAsync($"/api/v1/levels/{randomId}", command);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task UpdateLevel_NotFound_ShouldReturn404()
{
// Arrange
var client = _factory.CreateAuthenticatedClient();
var nonExistentId = Guid.NewGuid();
var command = new UpdateLevelDefinitionCommand
{
Id = nonExistentId,
Name = "NonExistent"
};
// Act
var response = await client.PutAsJsonAsync($"/api/v1/levels/{nonExistentId}", command);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
#endregion
#region DELETE /api/v1/levels/{id} - Deactivate Level
[Fact]
public async Task DeactivateLevel_WithAuth_ShouldReturn204()
{
// Arrange
var client = _factory.CreateAuthenticatedClient();
// First create a level to deactivate
var createCommand = new CreateLevelDefinitionCommand
{
LevelNumber = 99,
Name = "ToDeactivate",
RequiredExp = 9999
};
var createResponse = await client.PostAsJsonAsync("/api/v1/levels", createCommand);
var createdLevel = await createResponse.Content.ReadFromJsonAsync<CreateLevelDefinitionResult>();
// Act
var response = await client.DeleteAsync($"/api/v1/levels/{createdLevel!.Id}");
// Assert
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
}
[Fact]
public async Task DeactivateLevel_WithoutAuth_ShouldReturn401()
{
// Arrange
var client = _factory.CreateClient(); // No auth
var randomId = Guid.NewGuid();
// Act
var response = await client.DeleteAsync($"/api/v1/levels/{randomId}");
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task DeactivateLevel_NotFound_ShouldReturn404()
{
// Arrange
var client = _factory.CreateAuthenticatedClient();
var nonExistentId = Guid.NewGuid();
// Act
var response = await client.DeleteAsync($"/api/v1/levels/{nonExistentId}");
// Assert
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
#endregion
#region Helper DTOs
private class LevelDto
{
public Guid Id { get; set; }
public int LevelNumber { get; set; }
public string Name { get; set; } = string.Empty;
}
#endregion
}