vrcauthproxy/Tests/Integration/ProgramRedisIntegrationTests.cs
MiscFrizzy 4936481ffc ### Commit Message Summary
**Enhancements to Redis Integration and Testing**

- **RedisService.cs**:
  - Implemented a Redis service for storing and retrieving authentication tokens.
  - Added methods for saving, retrieving, and removing tokens using Redis.
  - Introduced a constructor for dependency injection to facilitate testing.

- **RedisFixture.cs**:
  - Created a test fixture to ensure a Redis instance is available for integration tests.
  - Implemented a check to verify if Redis is running before executing tests.

- **ProgramRedisIntegrationTests.cs**:
  - Added integration tests to validate the login process and token storage in Redis.
  - Implemented tests to check the reuse of stored tokens and the correct handling of authentication.

- **RedisIntegrationTests.cs**:
  - Developed integration tests for saving, retrieving, and deleting authentication tokens in Redis.
  - Ensured that all tokens are correctly stored and can be retrieved as expected.

- **RedisServiceTests.cs**:
  - Created unit tests using an in-memory implementation of the Redis service for isolated testing.
  - Validated the functionality of saving, retrieving, and removing tokens without a real Redis connection.

### Notes
- All tests are designed to ensure the reliability of the Redis integration and the overall functionality of the VRCAuthProxy service.
- Integration tests are marked to skip execution unless a Redis instance is available.
2025-04-07 08:04:52 -04:00

143 lines
No EOL
5.9 KiB
C#

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<TestSetup>
{
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<Cookie>()
.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<string, string>
{
{ "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);
}
}
}