using System.Net; using System.Text; using FluentAssertions; using VRCAuthProxy.Services; using VRCAuthProxy.Tests.Helpers; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using Xunit; namespace VRCAuthProxy.Tests.Integration { [Trait("Category", "Integration")] [Collection("Redis")] public class ProgramRedisIntegrationTests : IClassFixture { private readonly TestSetup _testSetup; private readonly RedisService _redisService; public ProgramRedisIntegrationTests(TestSetup testSetup) { _testSetup = testSetup; _redisService = new RedisService("localhost:6379"); } [Fact(Skip = "Requires Redis instance - for manual integration testing")] public async Task LoginShouldStoreAuthTokenInRedis() { // Arrange var mockServer = _testSetup.MockVRChatApi; var testUsername = "redis-test-user"; var testPassword = "redis-test-password"; // Clean up any existing tokens await _redisService.RemoveAuthToken(testUsername); // Mock the authentication endpoint mockServer.Given(Request.Create() .WithPath("/api/1/auth/user") .UsingGet() .WithHeader("Authorization", "*")) .RespondWith(Response.Create() .WithStatusCode(200) .WithHeader("Content-Type", "application/json") .WithHeader("Set-Cookie", "auth=test-redis-auth-token; path=/; secure; httponly") .WithBodyAsJson(new VRCAuthProxy.types.User { displayName = "RedisTestUser" })); var mockServerUrl = mockServer.Urls.First(); // Create a config with test account var config = TestSetup.CreateTestConfig(); config.Accounts.Clear(); config.Accounts.Add(new ConfigAccount { username = testUsername, password = testPassword }); // Act - Call the login method (simplified version of what Program.cs does) var handler = new HttpClientHandler { UseCookies = true }; var cookieContainer = handler.CookieContainer; var httpClient = new HttpClientCookieContainer(handler) { BaseAddress = new Uri(mockServerUrl), Username = testUsername }; // Simulate login process string authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{testUsername}:{testPassword}")); var request = new HttpRequestMessage(HttpMethod.Get, "/api/1/auth/user"); request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString); var response = await httpClient.SendAsync(request); // Store cookies in Redis (like in Program.cs) var cookies = cookieContainer.GetAllCookies().Cast() .ToDictionary(c => c.Name, c => c.Value); await _redisService.SaveAuthToken(testUsername, cookies); // Assert var storedToken = await _redisService.GetAuthToken(testUsername); storedToken.Should().NotBeNull(); if (storedToken != null) { storedToken.Should().ContainKey("auth"); storedToken["auth"].Should().Be("test-redis-auth-token"); } // Clean up await _redisService.RemoveAuthToken(testUsername); } [Fact(Skip = "Requires Redis instance - for manual integration testing")] public async Task LoginWithStoredTokenShouldReuseRedisToken() { // Arrange var mockServer = _testSetup.MockVRChatApi; var testUsername = "redis-existing-user"; // Setup stored token in Redis var existingCookies = new Dictionary { { "auth", "existing-redis-token" } }; await _redisService.SaveAuthToken(testUsername, existingCookies); // Mock the user endpoint for a successful request with the token mockServer.Given(Request.Create() .WithPath("/api/1/auth/user") .UsingGet() .WithCookie("auth", "existing-redis-token")) .RespondWith(Response.Create() .WithStatusCode(200) .WithHeader("Content-Type", "application/json") .WithBodyAsJson(new VRCAuthProxy.types.User { displayName = "ExistingRedisUser" })); var mockServerUrl = mockServer.Urls.First(); // Act - Simulate restoring cookies and making request var handler = new HttpClientHandler { UseCookies = true }; var cookieContainer = handler.CookieContainer; // Restore cookies from Redis var storedCookies = await _redisService.GetAuthToken(testUsername); if (storedCookies != null) { foreach (var cookie in storedCookies) { cookieContainer.Add(new Uri(mockServerUrl), new Cookie(cookie.Key, cookie.Value)); } } var httpClient = new HttpClient(handler); var response = await httpClient.GetAsync($"{mockServerUrl}/api/1/auth/user"); // Assert response.StatusCode.Should().Be(HttpStatusCode.OK); var responseContent = await response.Content.ReadAsStringAsync(); responseContent.Should().Contain("ExistingRedisUser"); // Clean up await _redisService.RemoveAuthToken(testUsername); } } }