using Xunit; using FluentAssertions; using NSubstitute; using System.Text.Json; using FreeCode.Core.Models; namespace FreeCode.Tests.Unit.Models; public sealed class ApiRequestTests { [Fact] public void ApiRequest_HoldsProvidedSystemPrompt() { var request = new ApiRequest("system", ParseJson("[]"), ParseJson("[]"), "model"); request.SystemPrompt.Should().Be("system"); } [Fact] public void ApiRequest_HoldsMessagesJson() { var messages = ParseJson("[{\"role\":\"user\",\"content\":\"hello\"}]"); var request = new ApiRequest("system", messages, ParseJson("[]")); request.Messages.ValueKind.Should().Be(JsonValueKind.Array); request.Messages[0].GetProperty("role").GetString().Should().Be("user"); } [Fact] public void ApiRequest_HoldsToolsJson() { var tools = ParseJson("[{\"name\":\"bash\"}]"); var request = new ApiRequest("system", ParseJson("[]"), tools); request.Tools.ValueKind.Should().Be(JsonValueKind.Array); request.Tools[0].GetProperty("name").GetString().Should().Be("bash"); } [Fact] public void ApiRequest_AllowsNullModel() { var request = new ApiRequest("system", ParseJson("[]"), ParseJson("[]")); request.Model.Should().BeNull(); } [Fact] public void ApiRequest_HoldsProvidedModel() { var request = new ApiRequest("system", ParseJson("[]"), ParseJson("[]"), "claude"); request.Model.Should().Be("claude"); } [Fact] public void ApiRequest_AllowsEmptySystemPrompt() { var request = new ApiRequest(string.Empty, ParseJson("[]"), ParseJson("[]")); request.SystemPrompt.Should().BeEmpty(); } [Fact] public void ApiRequest_CanStoreObjectMessagesPayload() { var messages = ParseJson("{\"items\":[]}"); var request = new ApiRequest("system", messages, ParseJson("[]")); request.Messages.ValueKind.Should().Be(JsonValueKind.Object); request.Messages.TryGetProperty("items", out _).Should().BeTrue(); } [Fact] public void ApiRequest_DoesNotUseStructuralJsonEqualityAcrossDifferentJsonClones() { var left = new ApiRequest("system", ParseJson("[]"), ParseJson("[{\"name\":\"bash\"}]"), "model"); var right = new ApiRequest("system", ParseJson("[]"), ParseJson("[{\"name\":\"bash\"}]"), "model"); left.Should().NotBe(right); } [Fact] public void ApiRequest_IsNotEqualWhenModelDiffers() { var left = new ApiRequest("system", ParseJson("[]"), ParseJson("[]"), "model-a"); var right = new ApiRequest("system", ParseJson("[]"), ParseJson("[]"), "model-b"); left.Should().NotBe(right); } [Fact] public void ApiRequest_DeconstructsIntoOriginalValues() { var request = new ApiRequest("system", ParseJson("[]"), ParseJson("[{\"name\":\"bash\"}]"), "model"); var (systemPrompt, messages, tools, model) = request; systemPrompt.Should().Be("system"); messages.ValueKind.Should().Be(JsonValueKind.Array); tools[0].GetProperty("name").GetString().Should().Be("bash"); model.Should().Be("model"); } private static JsonElement ParseJson(string json) { using var document = JsonDocument.Parse(json); return document.RootElement.Clone(); } }