thalos-service/tests/Thalos.Service.Application.UnitTests/StartIdentitySessionUseCaseTests.cs
2026-03-11 04:27:02 -06:00

139 lines
5.2 KiB
C#

using BuildingBlock.Identity.Contracts.Conventions;
using BuildingBlock.Identity.Contracts.Requests;
using BuildingBlock.Identity.Contracts.Responses;
using Thalos.Service.Application.Oidc;
using Thalos.Service.Application.Sessions;
using Thalos.Service.Application.UseCases;
using Thalos.Service.Identity.Abstractions.Contracts;
using ExchangeRequest = BuildingBlock.Identity.Contracts.Requests.ExchangeIdentityProviderTokenRequest;
using ExchangeResponse = BuildingBlock.Identity.Contracts.Responses.ExchangeIdentityProviderTokenResponse;
using IdentityIssueRequest = BuildingBlock.Identity.Contracts.Requests.IssueIdentityTokenRequest;
using IdentityIssueResponse = BuildingBlock.Identity.Contracts.Responses.IssueIdentityTokenResponse;
namespace Thalos.Service.Application.UnitTests;
public class StartIdentitySessionUseCaseTests
{
[Fact]
public async Task HandleAsync_WhenCalled_IssuesTokenAndRefreshToken()
{
var issueUseCase = new FakeIssueUseCase();
var useCase = new StartIdentitySessionUseCase(
issueUseCase,
new FakeExchangeService(),
new FakeSessionTokenCodec());
var response = await useCase.HandleAsync(new StartIdentitySessionRequest("user-1", "tenant-1", IdentityAuthProvider.InternalJwt));
Assert.Equal("token-abc", response.AccessToken);
Assert.Equal(1800, response.ExpiresInSeconds);
Assert.Equal("user-1", response.SubjectId);
Assert.Equal("tenant-1", response.TenantId);
Assert.Equal("refresh-user-1-tenant-1", response.RefreshToken);
Assert.NotNull(issueUseCase.LastRequest);
Assert.Equal("user-1", issueUseCase.LastRequest!.SubjectId);
}
[Fact]
public async Task HandleAsync_WhenGoogleProviderAndExchangeSucceeds_UsesExchangedSubject()
{
var issueUseCase = new FakeIssueUseCase();
var exchangeService = new FakeExchangeService
{
NextResponse = new ExchangeResponse(
"google-sub-123",
"tenant-1",
IdentityAuthProvider.Google,
true)
};
var useCase = new StartIdentitySessionUseCase(
issueUseCase,
exchangeService,
new FakeSessionTokenCodec());
var response = await useCase.HandleAsync(new StartIdentitySessionRequest(
string.Empty,
"tenant-1",
IdentityAuthProvider.Google,
"google-id-token",
"corr-1"));
Assert.Equal("token-abc", response.AccessToken);
Assert.Equal("google-sub-123", response.SubjectId);
Assert.Equal(IdentityAuthProvider.Google, response.Provider);
Assert.NotNull(issueUseCase.LastRequest);
Assert.Equal("google-sub-123", issueUseCase.LastRequest!.SubjectId);
Assert.Equal("google-id-token", issueUseCase.LastRequest.ExternalToken);
}
[Fact]
public async Task HandleAsync_WhenGoogleExchangeFails_ReturnsFailedSession()
{
var issueUseCase = new FakeIssueUseCase();
var exchangeService = new FakeExchangeService
{
NextResponse = new ExchangeResponse(
string.Empty,
"tenant-1",
IdentityAuthProvider.Google,
false)
};
var useCase = new StartIdentitySessionUseCase(
issueUseCase,
exchangeService,
new FakeSessionTokenCodec());
var response = await useCase.HandleAsync(new StartIdentitySessionRequest(
string.Empty,
"tenant-1",
IdentityAuthProvider.Google,
"invalid-token",
"corr-2"));
Assert.Equal(string.Empty, response.AccessToken);
Assert.Equal(string.Empty, response.RefreshToken);
Assert.Equal(0, response.ExpiresInSeconds);
Assert.Null(issueUseCase.LastRequest);
}
private sealed class FakeIssueUseCase : IIssueIdentityTokenUseCase
{
public IdentityIssueRequest? LastRequest { get; private set; }
public Task<IdentityIssueResponse> HandleAsync(IdentityIssueRequest request)
{
LastRequest = request;
return Task.FromResult(new IdentityIssueResponse("token-abc", 1800));
}
}
private sealed class FakeExchangeService : IIdentityProviderTokenExchangeService
{
public ExchangeResponse NextResponse { get; set; } = new(
string.Empty,
string.Empty,
IdentityAuthProvider.Google,
false);
public Task<ExchangeResponse> ExchangeAsync(ExchangeRequest request, CancellationToken cancellationToken = default)
{
return Task.FromResult(NextResponse);
}
}
private sealed class FakeSessionTokenCodec : IIdentitySessionTokenCodec
{
public string Encode(IdentitySessionDescriptor descriptor)
{
return $"refresh-{descriptor.SubjectId}-{descriptor.TenantId}";
}
public bool TryDecode(string token, out IdentitySessionDescriptor descriptor)
{
descriptor = new IdentitySessionDescriptor(string.Empty, string.Empty, IdentityAuthProvider.InternalJwt, DateTimeOffset.UtcNow);
return false;
}
}
}