using System.Text.Json; using FluentAssertions; using FreeCode.ApiProviders; using FreeCode.Core.Models; using FreeCode.Tests.Unit.Helpers; using Xunit; namespace FreeCode.Tests.Unit.ApiProviders; public sealed class AnthropicProviderTests { [Fact] public async Task StreamAsync_ParsesStreamingTextDeltas() { var response = string.Join("\n\n", [ "data: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"Hello\"}}", "data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"text\":\" world\"}}", "data: {\"type\":\"message_stop\"}" ]); var handler = new MockHttpHandler(response); var provider = new AnthropicProvider(new HttpClient(handler)); var messages = await provider.StreamAsync(TestHelper.CreateMinimalApiRequest()).ToListAsync(); messages.Should().ContainEquivalentOf(new SDKMessage.StreamingDelta("Hello")); messages.Should().ContainEquivalentOf(new SDKMessage.StreamingDelta(" world")); } [Fact] public async Task StreamAsync_ParsesToolUseBlocks() { var response = string.Join("\n\n", [ "data: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"tool_use\",\"id\":\"tool-1\",\"name\":\"Read\"}}", "data: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"partial_json\":\"{\\\"path\\\":\\\"/tmp/file.txt\\\"}\"}}", "data: {\"type\":\"content_block_stop\",\"index\":1}", "data: {\"type\":\"message_stop\"}" ]); var handler = new MockHttpHandler(response); var provider = new AnthropicProvider(new HttpClient(handler)); var messages = await provider.StreamAsync(TestHelper.CreateMinimalApiRequest()).ToListAsync(); var toolUse = messages.OfType().Single(); toolUse.ToolUseId.Should().Be("tool-1"); toolUse.ToolName.Should().Be("Read"); toolUse.Input.GetProperty("path").GetString().Should().Be("/tmp/file.txt"); } [Fact] public async Task StreamAsync_SendsExpectedHeaders() { const string apiKey = "test-key"; Environment.SetEnvironmentVariable("ANTHROPIC_API_KEY", apiKey); try { var handler = new MockHttpHandler("data: {\"type\":\"message_stop\"}"); var provider = new AnthropicProvider(new HttpClient(handler)); _ = await provider.StreamAsync(new ApiRequest("prompt", ParseJson("[]"), ParseJson("[]"))).ToListAsync(); handler.LastRequest.Should().NotBeNull(); handler.LastRequest!.Headers.GetValues("anthropic-version").Should().Contain("2023-06-01"); handler.LastRequest.Headers.GetValues("x-api-key").Should().Contain(apiKey); handler.LastRequest.Headers.GetValues("authorization").Should().Contain($"Bearer {apiKey}"); } finally { Environment.SetEnvironmentVariable("ANTHROPIC_API_KEY", null); } } private static JsonElement ParseJson(string json) { using var document = JsonDocument.Parse(json); return document.RootElement.Clone(); } }