270 lines
7.6 KiB
C#
270 lines
7.6 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using FluentAssertions;
|
|
using MembershipService.API.Application.Commands;
|
|
using MembershipService.API.Application.Queries;
|
|
using Xunit;
|
|
|
|
namespace MembershipService.FunctionalTests.Controllers;
|
|
|
|
/// <summary>
|
|
/// EN: Comprehensive functional tests for MembersController.
|
|
/// VI: Functional tests toàn diện cho MembersController.
|
|
/// </summary>
|
|
public class MembersControllerTests : IClassFixture<CustomWebApplicationFactory>
|
|
{
|
|
private readonly CustomWebApplicationFactory _factory;
|
|
|
|
public MembersControllerTests(CustomWebApplicationFactory factory)
|
|
{
|
|
_factory = factory;
|
|
}
|
|
|
|
#region GET /api/v1/members
|
|
|
|
[Fact]
|
|
public async Task GetMembers_WithoutAuth_ShouldReturnUnauthorized()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync("/api/v1/members?page=1&pageSize=10");
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetMembers_WithAuth_ShouldReturnOk()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateAuthenticatedClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync("/api/v1/members?page=1&pageSize=10");
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GET /api/v1/members/{id}
|
|
|
|
[Fact]
|
|
public async Task GetMemberById_WithoutAuth_ShouldReturnUnauthorized()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync($"/api/v1/members/{Guid.NewGuid()}");
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetMemberById_NonExistent_ShouldReturnNotFound()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateAuthenticatedClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync($"/api/v1/members/{Guid.NewGuid()}");
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region POST /api/v1/members
|
|
|
|
[Fact]
|
|
public async Task CreateMember_WithoutAuth_ShouldReturnUnauthorized()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateClient();
|
|
var command = new CreateMemberCommand
|
|
{
|
|
UserId = Guid.NewGuid(),
|
|
CountryCode = "VN"
|
|
};
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync("/api/v1/members", command);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CreateMember_ValidRequest_ShouldReturnCreated()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateAuthenticatedClient();
|
|
var userId = Guid.NewGuid();
|
|
var command = new CreateMemberCommand
|
|
{
|
|
UserId = userId,
|
|
CountryCode = "VN"
|
|
};
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync("/api/v1/members", command);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
|
|
|
var result = await response.Content.ReadFromJsonAsync<CreateMemberResult>();
|
|
result.Should().NotBeNull();
|
|
result!.MemberId.Should().Be(userId);
|
|
result.CurrentLevel.Should().Be(1);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CreateMember_DuplicateUserId_ShouldReturnConflict()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateAuthenticatedClient();
|
|
var userId = Guid.NewGuid();
|
|
var command = new CreateMemberCommand
|
|
{
|
|
UserId = userId,
|
|
CountryCode = "VN"
|
|
};
|
|
|
|
// Create first member
|
|
await client.PostAsJsonAsync("/api/v1/members", command);
|
|
|
|
// Act - Try to create again
|
|
var response = await client.PostAsJsonAsync("/api/v1/members", command);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Conflict);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CreateMember_WithGender_ShouldSetGender()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateAuthenticatedClient();
|
|
var command = new CreateMemberCommand
|
|
{
|
|
UserId = Guid.NewGuid(),
|
|
CountryCode = "VN",
|
|
Gender = "Female"
|
|
};
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync("/api/v1/members", command);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Full Member Workflow
|
|
|
|
[Fact]
|
|
public async Task FullMemberWorkflow_CreateGetUpdate_ShouldSucceed()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateAuthenticatedClient();
|
|
var userId = Guid.NewGuid();
|
|
|
|
// Step 1: Create member
|
|
var createCommand = new CreateMemberCommand
|
|
{
|
|
UserId = userId,
|
|
CountryCode = "VN",
|
|
Gender = "Male"
|
|
};
|
|
var createResponse = await client.PostAsJsonAsync("/api/v1/members", createCommand);
|
|
createResponse.StatusCode.Should().Be(HttpStatusCode.Created);
|
|
|
|
// Step 2: Get member
|
|
var getResponse = await client.GetAsync($"/api/v1/members/{userId}");
|
|
getResponse.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
|
|
var member = await getResponse.Content.ReadFromJsonAsync<MemberDto>();
|
|
member.Should().NotBeNull();
|
|
member!.Id.Should().Be(userId);
|
|
member.CountryCode.Should().Be("VN");
|
|
member.Gender.Should().Be("Male");
|
|
member.CurrentLevel.Should().Be(1);
|
|
member.CurrentExp.Should().Be(0);
|
|
|
|
// Step 3: Update profile
|
|
var updateCommand = new UpdateMemberProfileCommand
|
|
{
|
|
MemberId = userId,
|
|
Gender = "Female",
|
|
CountryCode = "US",
|
|
Preferences = "{\"theme\": \"dark\"}"
|
|
};
|
|
var updateResponse = await client.PutAsJsonAsync($"/api/v1/members/{userId}", updateCommand);
|
|
updateResponse.StatusCode.Should().Be(HttpStatusCode.OK);
|
|
|
|
// Step 4: Verify update
|
|
var verifyResponse = await client.GetAsync($"/api/v1/members/{userId}");
|
|
var updatedMember = await verifyResponse.Content.ReadFromJsonAsync<MemberDto>();
|
|
updatedMember!.Gender.Should().Be("Female");
|
|
updatedMember.CountryCode.Should().Be("US");
|
|
updatedMember.Preferences.Should().Contain("dark");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Experience Endpoints
|
|
|
|
[Fact]
|
|
public async Task AddExperience_WithoutAuth_ShouldReturnUnauthorized()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateClient();
|
|
var command = new AddExperienceCommand
|
|
{
|
|
Points = 50,
|
|
SourceId = 1
|
|
};
|
|
|
|
// Act
|
|
var response = await client.PostAsJsonAsync($"/api/v1/members/{Guid.NewGuid()}/experience", command);
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetProgress_WithoutAuth_ShouldReturnUnauthorized()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync($"/api/v1/members/{Guid.NewGuid()}/progress");
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetExperienceHistory_WithoutAuth_ShouldReturnUnauthorized()
|
|
{
|
|
// Arrange
|
|
var client = _factory.CreateClient();
|
|
|
|
// Act
|
|
var response = await client.GetAsync($"/api/v1/members/{Guid.NewGuid()}/experience");
|
|
|
|
// Assert
|
|
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
|
}
|
|
|
|
#endregion
|
|
}
|