From bff947d1e80b5267ada4f6fd27cf9eb27907dc33 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Tue, 6 Jan 2026 11:39:09 -0500 Subject: [PATCH] test: add AuthApiClientIntegrationTests Add 5 integration tests for AuthApiClient: - GetPublicKeyAsync_ReturnsValidPublicKey - LoginAsync_WithValidCredentials_ReturnsSuccess - GetCurrentUserAsync_AfterLogin_ReturnsUserInfo - GetCurrentUserAsync_WithoutAuth_ReturnsUnauthorized - LogoutAsync_AfterLogin_InvalidatesSession Tests use RSA encryption pattern for login credentials and verify auth cookie behavior across requests. --- .../AuthApiClientIntegrationTests.cs | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs diff --git a/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs new file mode 100644 index 0000000..eb1928d --- /dev/null +++ b/NEW/tests/JdeScoping.Api.IntegrationTests/ClientIntegration/AuthApiClientIntegrationTests.cs @@ -0,0 +1,111 @@ +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using JdeScoping.Client.Services; +using JdeScoping.Core.Models.Auth; +using Microsoft.AspNetCore.Mvc.Testing; +using Shouldly; + +namespace JdeScoping.Api.IntegrationTests.ClientIntegration; + +public class AuthApiClientIntegrationTests : ClientIntegrationTestBase +{ + public AuthApiClientIntegrationTests(TestWebApplicationFactory factory) : base(factory) { } + + [Fact] + public async Task GetPublicKeyAsync_ReturnsValidPublicKey() + { + // Act + var result = await AuthClient.GetPublicKeyAsync(); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Value.PublicKeyPem.ShouldStartWith("-----BEGIN PUBLIC KEY-----"); + } + + [Fact] + public async Task LoginAsync_WithValidCredentials_ReturnsSuccess() + { + // Arrange - get public key and encrypt credentials + var publicKeyResult = await AuthClient.GetPublicKeyAsync(); + publicKeyResult.IsSuccess.ShouldBeTrue(); + + var loginModel = new LoginModel { Username = "testuser", Password = "testpass" }; + var json = JsonSerializer.Serialize(loginModel); + var plaintext = Encoding.UTF8.GetBytes(json); + + using var rsa = RSA.Create(); + rsa.ImportFromPem(publicKeyResult.Value.PublicKeyPem); + var ciphertext = rsa.Encrypt(plaintext, RSAEncryptionPadding.OaepSHA256); + + var encryptedRequest = new EncryptedLoginRequest(Convert.ToBase64String(ciphertext)); + + // Act + var result = await AuthClient.LoginAsync(encryptedRequest); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Value.Success.ShouldBeTrue(); + result.Value.User.ShouldNotBeNull(); + result.Value.User.Username.ShouldBe("testuser"); + } + + [Fact] + public async Task GetCurrentUserAsync_AfterLogin_ReturnsUserInfo() + { + // Arrange + await LoginAsync(); + + // Act + var result = await AuthClient.GetCurrentUserAsync(); + + // Assert + result.IsSuccess.ShouldBeTrue(); + result.Value.Username.ShouldBe("testuser"); + } + + [Fact] + public async Task GetCurrentUserAsync_WithoutAuth_ReturnsUnauthorized() + { + // Arrange - use fresh client without cookies + var freshClient = new AuthApiClient(CreateFreshClient()); + + // Act + var result = await freshClient.GetCurrentUserAsync(); + + // Assert + result.IsUnauthorized.ShouldBeTrue(); + } + + [Fact] + public async Task LogoutAsync_AfterLogin_InvalidatesSession() + { + // Arrange - create fresh client for this test to avoid affecting other tests + var client = Factory.CreateClient(new WebApplicationFactoryClientOptions + { + HandleCookies = true, + AllowAutoRedirect = false + }); + var authClient = new AuthApiClient(client); + + // Login first + var publicKeyResult = await authClient.GetPublicKeyAsync(); + var loginModel = new LoginModel { Username = "testuser", Password = "testpass" }; + var json = JsonSerializer.Serialize(loginModel); + using var rsa = RSA.Create(); + rsa.ImportFromPem(publicKeyResult.Value.PublicKeyPem); + var ciphertext = rsa.Encrypt(Encoding.UTF8.GetBytes(json), RSAEncryptionPadding.OaepSHA256); + await authClient.LoginAsync(new EncryptedLoginRequest(Convert.ToBase64String(ciphertext))); + + // Verify login worked + var beforeLogout = await authClient.GetCurrentUserAsync(); + beforeLogout.IsSuccess.ShouldBeTrue(); + + // Act - call logout (server returns 200 OK with empty body) + await authClient.LogoutAsync(); + + // Assert - verify session is invalidated (me endpoint should return unauthorized) + var meResult = await authClient.GetCurrentUserAsync(); + meResult.IsUnauthorized.ShouldBeTrue(); + } +}