using System.Text; using System.Text.Json.Nodes; using w4c_workflows.Models.Credentials; using w4c_workflows.Services.Credentials; using Xunit; namespace w4c_workflows.Tests; /// /// The injection strategy turns a resolved credential into request material: /// Basic/Bearer authorization, a custom header, or a query parameter. /// public class CredentialInjectorTests { private static readonly CredentialTypeCatalog Catalog = new(); private static HttpRequestMessage Request() => new(HttpMethod.Get, "https://api.example.com/items"); [Fact] public void Basic_sets_the_authorization_header() { var request = Request(); var credential = new CredentialData("httpBasicAuth", new JsonObject { ["username"] = "ada", ["password"] = "secret", }); Assert.Null(CredentialInjector.Apply(credential, Catalog, request)); var expected = "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes("ada:secret")); Assert.Equal(expected, request.Headers.Authorization!.ToString()); } [Fact] public void Bearer_sets_the_authorization_header_with_the_prefix() { var request = Request(); var credential = new CredentialData("httpBearerAuth", new JsonObject { ["token"] = "tok-123" }); Assert.Null(CredentialInjector.Apply(credential, Catalog, request)); Assert.Equal("Bearer tok-123", request.Headers.Authorization!.ToString()); } [Fact] public void Header_adds_a_custom_request_header() { var request = Request(); var credential = new CredentialData("httpHeaderAuth", new JsonObject { ["name"] = "X-API-Key", ["value"] = "abc", }); Assert.Null(CredentialInjector.Apply(credential, Catalog, request)); Assert.Equal("abc", request.Headers.GetValues("X-API-Key").Single()); } [Fact] public void Query_appends_a_parameter() { var request = Request(); var credential = new CredentialData("httpQueryAuth", new JsonObject { ["name"] = "api_key", ["value"] = "abc", }); Assert.Null(CredentialInjector.Apply(credential, Catalog, request)); Assert.Contains("api_key=abc", request.RequestUri!.Query); } [Fact] public void A_missing_required_field_is_reported() { var request = Request(); var credential = new CredentialData("httpBearerAuth", new JsonObject()); var error = CredentialInjector.Apply(credential, Catalog, request); Assert.NotNull(error); Assert.Contains("token", error); } [Fact] public void An_unknown_type_is_reported() { var request = Request(); var credential = new CredentialData("nope", new JsonObject()); Assert.Equal("unknown credential type 'nope'", CredentialInjector.Apply(credential, Catalog, request)); } [Fact] public void None_injection_leaves_the_request_untouched() { var request = Request(); var credential = new CredentialData("telegramApi", new JsonObject { ["token"] = "123:ABC" }); Assert.Null(CredentialInjector.Apply(credential, Catalog, request)); Assert.Equal("https://api.example.com/items", request.RequestUri!.ToString()); Assert.Null(request.Headers.Authorization); } [Fact] public void Catalog_exposes_the_url_embedded_credential_types() { var telegram = Catalog.Get("telegramApi"); var discord = Catalog.Get("discordWebhook"); Assert.NotNull(telegram); Assert.NotNull(discord); Assert.Equal(CredentialInjectionKind.None, telegram!.Injection.Kind); Assert.Equal(CredentialInjectionKind.None, discord!.Injection.Kind); Assert.Contains(telegram.Fields, f => f.Name == "token"); Assert.Contains(discord.Fields, f => f.Name == "url"); } }