using System.Text.Json.Nodes; using Deal.Ai.Llm; namespace Deal.Ai.Tests.Support; /// /// Unit-тесты извлечения JSON из ответа модели /// public sealed class JsonExtractorTests { /// /// Чистая JSON-строка объекта разбирается как есть. /// [Fact] public void TryExtractObject_PlainObject_Parses() { JsonObject? json = JsonExtractor.TryExtractObject("""{"pass": true, "reason": "ок"}"""); Assert.NotNull(json); Assert.True((bool)json!["pass"]!); } /// /// Markdown-обёртка ```json снимается /// [Fact] public void TryExtractObject_JsonFence_Unwraps() { JsonObject? json = JsonExtractor.TryExtractObject("```json\n{\"fit\": 1}\n```"); Assert.NotNull(json); Assert.Equal(1, (int)json!["fit"]!); } /// /// Обёртка без метки языка и с прозой вокруг — тоже снимается. /// [Fact] public void TryExtractObject_PlainFenceWithProse_Unwraps() { const string answer = "Вот результат:\n```\n{\"keywords\": [\"php\"]}\n```\nНадеюсь, поможет."; JsonObject? json = JsonExtractor.TryExtractObject(answer); Assert.NotNull(json); Assert.Single((JsonArray)json!["keywords"]!); } /// /// JSON внутри произвольного текста берётся срезом между первой «{» и последней «}». /// [Fact] public void TryExtractObject_JsonInsideProse_Slices() { JsonObject? json = JsonExtractor.TryExtractObject("модель решила: {\"pass\": false} конец"); Assert.NotNull(json); Assert.False((bool)json!["pass"]!); } /// /// Текст без JSON — null /// [Fact] public void TryExtractObject_NoJson_ReturnsNull() { Assert.Null(JsonExtractor.TryExtractObject("извините, не могу ответить")); } /// /// Незакрытая обёртка и битый JSON — null, а не исключение. /// [Fact] public void TryExtractObject_BrokenJson_ReturnsNull() { Assert.Null(JsonExtractor.TryExtractObject("```json\n{\"pass\": tru")); Assert.Null(JsonExtractor.TryExtractObject("{\"pass\": ")); } /// /// JSON верхнего уровня не объект /// [Fact] public void TryExtractObject_NonObjectRoot_ReturnsNull() { Assert.Null(JsonExtractor.TryExtractObject("[\"php\", \"c#\"]")); Assert.Null(JsonExtractor.TryExtractObject("\"просто строка\"")); } /// /// Пустой/пробельный текст — null. /// [Fact] public void TryExtractObject_Empty_ReturnsNull() { Assert.Null(JsonExtractor.TryExtractObject(string.Empty)); Assert.Null(JsonExtractor.TryExtractObject(" ")); } }