Commit all scripts
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
namespace ColaFlow.Modules.Identity.IntegrationTests.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// Database Fixture for In-Memory Database Tests
|
||||
/// Implements IClassFixture for xUnit test lifecycle management
|
||||
/// Each test class gets its own isolated database instance
|
||||
/// </summary>
|
||||
public class DatabaseFixture : IDisposable
|
||||
{
|
||||
public ColaFlowWebApplicationFactory Factory { get; }
|
||||
public HttpClient Client { get; }
|
||||
|
||||
public DatabaseFixture()
|
||||
{
|
||||
// Use In-Memory Database for fast, isolated tests
|
||||
Factory = new ColaFlowWebApplicationFactory(useInMemoryDatabase: true);
|
||||
Client = Factory.CreateClient();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Client?.Dispose();
|
||||
Factory?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
using ColaFlow.Modules.Identity.Infrastructure.Persistence;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace ColaFlow.Modules.Identity.IntegrationTests.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// Database Fixture for Real PostgreSQL Database Tests
|
||||
/// Use this for more realistic integration tests that verify actual database behavior
|
||||
/// Requires PostgreSQL to be running on localhost
|
||||
/// </summary>
|
||||
public class RealDatabaseFixture : IDisposable
|
||||
{
|
||||
public ColaFlowWebApplicationFactory Factory { get; }
|
||||
public HttpClient Client { get; }
|
||||
private readonly string _testDatabaseName;
|
||||
|
||||
public RealDatabaseFixture()
|
||||
{
|
||||
_testDatabaseName = $"test_{Guid.NewGuid():N}";
|
||||
|
||||
// Use Real PostgreSQL Database
|
||||
Factory = new ColaFlowWebApplicationFactory(
|
||||
useInMemoryDatabase: false,
|
||||
testDatabaseName: _testDatabaseName
|
||||
);
|
||||
|
||||
Client = Factory.CreateClient();
|
||||
|
||||
// Clean up any existing test data
|
||||
CleanupDatabase();
|
||||
}
|
||||
|
||||
private void CleanupDatabase()
|
||||
{
|
||||
using var scope = Factory.Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<IdentityDbContext>();
|
||||
|
||||
// Clear all data from test database
|
||||
db.RefreshTokens.RemoveRange(db.RefreshTokens);
|
||||
db.Users.RemoveRange(db.Users);
|
||||
db.Tenants.RemoveRange(db.Tenants);
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Clean up test database
|
||||
using (var scope = Factory.Services.CreateScope())
|
||||
{
|
||||
var db = scope.ServiceProvider.GetRequiredService<IdentityDbContext>();
|
||||
db.Database.EnsureDeleted();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
|
||||
Client?.Dispose();
|
||||
Factory?.Dispose();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Net.Http.Json;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace ColaFlow.Modules.Identity.IntegrationTests.Infrastructure;
|
||||
|
||||
/// <summary>
|
||||
/// Helper class for authentication-related test operations
|
||||
/// Provides utilities for registration, login, token parsing, and common test scenarios
|
||||
/// </summary>
|
||||
public static class TestAuthHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Register a new tenant and return the access token and refresh token
|
||||
/// </summary>
|
||||
public static async Task<(string accessToken, string refreshToken)> RegisterAndGetTokensAsync(
|
||||
HttpClient client,
|
||||
string? tenantSlug = null,
|
||||
string? email = null,
|
||||
string? password = null)
|
||||
{
|
||||
var slug = tenantSlug ?? $"test-{Guid.NewGuid():N}";
|
||||
var adminEmail = email ?? $"admin-{Guid.NewGuid():N}@test.com";
|
||||
var adminPassword = password ?? "Admin@1234";
|
||||
|
||||
var request = new
|
||||
{
|
||||
tenantName = "Test Corp",
|
||||
tenantSlug = slug,
|
||||
subscriptionPlan = "Professional",
|
||||
adminEmail,
|
||||
adminPassword,
|
||||
adminFullName = "Test Admin"
|
||||
};
|
||||
|
||||
var response = await client.PostAsJsonAsync("/api/tenants/register", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<RegisterResponse>();
|
||||
|
||||
return (result!.AccessToken, result.RefreshToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Login with credentials and return tokens
|
||||
/// </summary>
|
||||
public static async Task<(string accessToken, string refreshToken)> LoginAndGetTokensAsync(
|
||||
HttpClient client,
|
||||
string tenantSlug,
|
||||
string email,
|
||||
string password)
|
||||
{
|
||||
var request = new
|
||||
{
|
||||
tenantSlug,
|
||||
email,
|
||||
password
|
||||
};
|
||||
|
||||
var response = await client.PostAsJsonAsync("/api/auth/login", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var result = await response.Content.ReadFromJsonAsync<LoginResponse>();
|
||||
|
||||
return (result!.AccessToken, result.RefreshToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse JWT token and extract claims
|
||||
/// </summary>
|
||||
public static IEnumerable<Claim> ParseJwtToken(string token)
|
||||
{
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
var jwtToken = handler.ReadJwtToken(token);
|
||||
return jwtToken.Claims;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get specific claim value from token
|
||||
/// </summary>
|
||||
public static string? GetClaimValue(string token, string claimType)
|
||||
{
|
||||
var claims = ParseJwtToken(token);
|
||||
return claims.FirstOrDefault(c => c.Type == claimType)?.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify token contains expected role
|
||||
/// </summary>
|
||||
public static bool HasRole(string token, string role)
|
||||
{
|
||||
var claims = ParseJwtToken(token);
|
||||
return claims.Any(c => c.Type == "role" && c.Value == role) ||
|
||||
claims.Any(c => c.Type == "tenant_role" && c.Value == role);
|
||||
}
|
||||
}
|
||||
|
||||
// Response DTOs
|
||||
public record RegisterResponse(string AccessToken, string RefreshToken);
|
||||
public record LoginResponse(string AccessToken, string RefreshToken);
|
||||
public record RefreshResponse(string AccessToken, string RefreshToken);
|
||||
public record UserInfoResponse(
|
||||
string UserId,
|
||||
string TenantId,
|
||||
string Email,
|
||||
string FullName,
|
||||
string TenantSlug,
|
||||
string TenantRole);
|
||||
Reference in New Issue
Block a user