using System.Net; using System.Net.Http.Json; using System.Net.Http.Headers; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.Extensions.DependencyInjection; using Microsoft.AspNetCore.Identity; using Xunit; using IamService.API.Application.Common; using IamService.Domain.AggregatesModel.UserAggregate; namespace IamService.FunctionalTests.Controllers; /// /// EN: Functional tests for UsersController endpoints. /// VI: Functional tests cho các endpoints của UsersController. /// public class UsersControllerTests : IClassFixture { private readonly HttpClient _client; private readonly CustomWebApplicationFactory _factory; public UsersControllerTests(CustomWebApplicationFactory factory) { _factory = factory; _client = factory.CreateClient(new WebApplicationFactoryClientOptions { AllowAutoRedirect = false }); } private async Task GetAccessTokenAsync() { // Register and login a user var email = $"user_{Guid.NewGuid()}@example.com"; var password = "Password123!"; await _client.PostAsJsonAsync("/api/v1/auth/register", new { Email = email, Password = password, FirstName = "Test", LastName = "User" }); // Activate user using var scope = _factory.Services.CreateScope(); var userManager = scope.ServiceProvider.GetRequiredService>(); var user = await userManager.FindByEmailAsync(email); if (user != null) { user.Activate(); await userManager.UpdateAsync(user); } // Get token var tokenRequest = new FormUrlEncodedContent(new Dictionary { ["grant_type"] = "password", ["username"] = email, ["password"] = password, ["scope"] = "openid profile email offline_access" }); var response = await _client.PostAsync("/connect/token", tokenRequest); var result = await response.Content.ReadFromJsonAsync(); return result?.access_token ?? throw new Exception("Failed to get token"); } [Fact] public async Task GetUsers_WithoutAuth_ShouldReturn401() { // Act var response = await _client.GetAsync("/api/v1/users"); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } [Fact] public async Task GetUsers_WithAuth_ShouldReturn200() { // Arrange var token = await GetAccessTokenAsync(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); // Act var response = await _client.GetAsync("/api/v1/users"); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); } [Fact] public async Task GetMe_WithAuth_ShouldReturnCurrentUser() { // Arrange var token = await GetAccessTokenAsync(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); // Act var response = await _client.GetAsync("/api/v1/users/me"); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); var result = await response.Content.ReadFromJsonAsync>(); Assert.NotNull(result); Assert.True(result.Success); Assert.NotNull(result.Data); Assert.NotEmpty(result.Data.Id); } [Fact] public async Task GetMe_WithoutAuth_ShouldReturn401() { // Act var response = await _client.GetAsync("/api/v1/users/me"); // Assert Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); } [Fact] public async Task GetUserById_WithValidId_ShouldReturnUser() { // Arrange var email = $"getbyid_{Guid.NewGuid()}@example.com"; var password = "Password123!"; // Register user var registerResponse = await _client.PostAsJsonAsync("/api/v1/auth/register", new { Email = email, Password = password, FirstName = "GetById", LastName = "Test" }); var registerResult = await registerResponse.Content.ReadFromJsonAsync>(); var userId = registerResult?.Data?.UserId; // Get auth token var token = await GetAccessTokenAsync(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); // Act var response = await _client.GetAsync($"/api/v1/users/{userId}"); // Assert Assert.Equal(HttpStatusCode.OK, response.StatusCode); } [Fact] public async Task GetUserById_WithInvalidId_ShouldReturn404() { // Arrange var token = await GetAccessTokenAsync(); _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var randomId = Guid.NewGuid(); // Act var response = await _client.GetAsync($"/api/v1/users/{randomId}"); // Assert Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } private record TokenResponse(string access_token, string token_type, int expires_in); private record RegisterResult(Guid UserId, string Email); }