w4c-workflows-api/w4c-workflows-api.Tests/CredentialExtractorTests.cs
2026-09-12 01:02:46 +03:00

67 lines
2.1 KiB
C#

using System.Text.Json.Nodes;
using w4c_workflows.Models.Credentials;
using w4c_workflows.Services.Credentials;
using Xunit;
namespace w4c_workflows.Tests;
/// <summary>
/// The extraction strategy reads an OAuth-style token response, including
/// non-standard token locations (e.g. Slack's <c>authed_user.access_token</c>).
/// </summary>
public class CredentialExtractorTests
{
private static readonly CredentialExtraction Extraction = new()
{
AccessTokenField = "authed_user.access_token",
TokenTypeField = "token_type",
ExpiresInField = "expires_in",
RefreshTokenField = "refresh_token",
ScopeField = "scope",
DefaultTokenType = "Bearer",
};
[Fact]
public void Reads_a_nested_access_token_and_the_standard_fields()
{
var response = JsonNode.Parse("""
{
"ok": true,
"authed_user": { "access_token": "xoxp-123" },
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "refresh-1",
"scope": "chat:write"
}
""")!.AsObject();
var tokens = CredentialExtractor.Extract(response, Extraction);
Assert.NotNull(tokens);
Assert.Equal("xoxp-123", tokens!.AccessToken);
Assert.Equal("bearer", tokens.TokenType);
Assert.Equal(3600, tokens.ExpiresInSeconds);
Assert.Equal("refresh-1", tokens.RefreshToken);
Assert.Equal("chat:write", tokens.Scope);
}
[Fact]
public void Falls_back_to_the_default_token_type()
{
var response = new JsonObject { ["access_token"] = "tok" };
var extraction = new CredentialExtraction { AccessTokenField = "access_token", DefaultTokenType = "Bearer" };
var tokens = CredentialExtractor.Extract(response, extraction);
Assert.Equal("Bearer", tokens!.TokenType);
Assert.Null(tokens.ExpiresInSeconds);
}
[Fact]
public void A_response_without_a_token_returns_null()
{
var response = new JsonObject { ["error"] = "invalid_grant" };
Assert.Null(CredentialExtractor.Extract(response, Extraction));
}
}