using System.Security.Claims; using JdeScoping.Api.Controllers; using JdeScoping.Api.Models; using JdeScoping.Core.Interfaces; using JdeScoping.Core.Models; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using NSubstitute; using Shouldly; namespace JdeScoping.Api.Tests.Controllers; public class AuthControllerTests { private readonly IAuthService _authService; private readonly ILogger _logger; private readonly AuthController _controller; public AuthControllerTests() { _authService = Substitute.For(); _logger = Substitute.For>(); _controller = new AuthController(_authService, _logger); } [Fact] public async Task Login_WithValidCredentials_ReturnsUserInfo() { // Arrange var request = new LoginRequest { Username = "testuser", Password = "password123" }; var user = new UserInfo { Dn = "CN=testuser,DC=example,DC=com", Username = "testuser", FirstName = "Test", LastName = "User", EmailAddress = "test@example.com", Title = "Developer" }; _authService.AuthenticateAsync("testuser", "password123", Arg.Any()) .Returns(new AuthResult(true, user, null)); // Setup HttpContext with mock authentication var httpContext = CreateMockHttpContext(); _controller.ControllerContext = new ControllerContext { HttpContext = httpContext }; // Act var result = await _controller.Login(request, CancellationToken.None); // Assert result.Result.ShouldBeOfType(); var okResult = (OkObjectResult)result.Result!; var returnedUser = okResult.Value.ShouldBeOfType(); returnedUser.Username.ShouldBe("testuser"); returnedUser.FirstName.ShouldBe("Test"); } [Fact] public async Task Login_WithInvalidCredentials_Returns401() { // Arrange var request = new LoginRequest { Username = "testuser", Password = "wrongpassword" }; _authService.AuthenticateAsync("testuser", "wrongpassword", Arg.Any()) .Returns(new AuthResult(false, null, "Incorrect username or password")); // Setup HttpContext var httpContext = CreateMockHttpContext(); _controller.ControllerContext = new ControllerContext { HttpContext = httpContext }; // Act var result = await _controller.Login(request, CancellationToken.None); // Assert result.Result.ShouldBeOfType(); } [Fact] public async Task Logout_ClearsAuthentication() { // Arrange var httpContext = CreateAuthenticatedHttpContext("testuser"); _controller.ControllerContext = new ControllerContext { HttpContext = httpContext }; // Act var result = await _controller.Logout(); // Assert result.ShouldBeOfType(); } [Fact] public void GetCurrentUser_WhenAuthenticated_ReturnsUserInfo() { // Arrange var claims = new List { new(ClaimTypes.Name, "testuser"), new(ClaimTypes.GivenName, "Test"), new(ClaimTypes.Surname, "User"), new(ClaimTypes.Email, "test@example.com"), new("title", "Developer"), new("dn", "CN=testuser,DC=example,DC=com") }; var identity = new ClaimsIdentity(claims, "Test"); var principal = new ClaimsPrincipal(identity); var httpContext = new DefaultHttpContext { User = principal }; _controller.ControllerContext = new ControllerContext { HttpContext = httpContext }; // Act var result = _controller.GetCurrentUser(); // Assert result.Result.ShouldBeOfType(); var okResult = (OkObjectResult)result.Result!; var user = okResult.Value.ShouldBeOfType(); user.Username.ShouldBe("testuser"); } [Fact] public void GetCurrentUser_ExtractsAllClaimsCorrectly() { // Arrange var claims = new List { new(ClaimTypes.Name, "jsmith"), new(ClaimTypes.GivenName, "John"), new(ClaimTypes.Surname, "Smith"), new(ClaimTypes.Email, "jsmith@example.com"), new("title", "Senior Engineer"), new("dn", "CN=jsmith,OU=Users,DC=example,DC=com") }; var identity = new ClaimsIdentity(claims, "Test"); var principal = new ClaimsPrincipal(identity); var httpContext = new DefaultHttpContext { User = principal }; _controller.ControllerContext = new ControllerContext { HttpContext = httpContext }; // Act var result = _controller.GetCurrentUser(); // Assert result.Result.ShouldBeOfType(); var okResult = (OkObjectResult)result.Result!; var user = okResult.Value.ShouldBeOfType(); user.Username.ShouldBe("jsmith"); user.FirstName.ShouldBe("John"); user.LastName.ShouldBe("Smith"); user.EmailAddress.ShouldBe("jsmith@example.com"); user.Title.ShouldBe("Senior Engineer"); user.Dn.ShouldBe("CN=jsmith,OU=Users,DC=example,DC=com"); user.DisplayName.ShouldBe("John Smith"); } private static HttpContext CreateMockHttpContext() { var authServiceMock = Substitute.For(); authServiceMock.SignOutAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns(Task.CompletedTask); authServiceMock.SignInAsync(Arg.Any(), Arg.Any(), Arg.Any(), Arg.Any()) .Returns(Task.CompletedTask); var serviceProvider = Substitute.For(); serviceProvider.GetService(typeof(IAuthenticationService)).Returns(authServiceMock); var httpContext = new DefaultHttpContext { RequestServices = serviceProvider }; return httpContext; } private static HttpContext CreateAuthenticatedHttpContext(string username) { var httpContext = CreateMockHttpContext(); var claims = new List { new(ClaimTypes.Name, username), new("dn", $"CN={username},DC=example,DC=com") }; var identity = new ClaimsIdentity(claims, "Test"); httpContext.User = new ClaimsPrincipal(identity); return httpContext; } }