**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.
143 lines
No EOL
5.9 KiB
C#
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);
|
|
}
|
|
}
|
|
} |