using Kompas.Mcp.Core.Query;
namespace Kompas.Mcp.Tests;
/// Юнит-тесты чистого рендера/группировки структурного «паспорта». COM не требуется.
[Trait("Category", "Unit")]
public sealed class InspectionTextTests
{
// ── Детект пустой модели по габариту ──────────────────────────────────
[Fact]
public void IsEmptyGabarit_true_for_sentinel()
=> Assert.True(InspectionText.IsEmptyGabarit(double.MaxValue, double.MaxValue, double.MaxValue));
[Fact]
public void IsEmptyGabarit_true_for_all_zero()
=> Assert.True(InspectionText.IsEmptyGabarit(0, 0, 0));
[Fact]
public void IsEmptyGabarit_false_for_real_part()
=> Assert.False(InspectionText.IsEmptyGabarit(40, 20, 15));
// ── Группировка типов ────────────────────────────────────────────────
[Fact]
public void GroupTypes_orders_by_count_desc()
{
var s = InspectionText.GroupTypes(new[] { "plane", "cylinder", "plane", "plane", "cylinder" });
Assert.Equal("3 plane, 2 cylinder", s);
}
[Fact]
public void GroupTypes_empty_returns_dash()
=> Assert.Equal("—", InspectionText.GroupTypes(Array.Empty()));
// ── Детект импорта без истории ───────────────────────────────────────
private static FeatureInfo Feat(int i, string name, string kind) => new() { Index = i, Name = name, Kind = kind };
[Fact]
public void IsImported_true_for_bare_origin_and_body()
{
var fs = new[] { Feat(0, "Начало координат", "origin"), Feat(1, "Body1", "other") };
Assert.True(InspectionText.IsImported(fs, bodyCount: 1));
}
[Fact]
public void IsImported_false_when_tree_has_edit_history()
{
// Импорт, отредактированный move_face: origin + тело + 5 узлов-правок (>2) — это уже история.
var fs = new[]
{
Feat(0, "Начало координат", "origin"), Feat(1, "Body1", "other"),
Feat(2, "Смещенная плоскость:1", "other"), Feat(3, "Разрезать:1", "other"),
Feat(4, "Переместить грани:1", "other"), Feat(5, "Булева операция:1", "other"),
};
Assert.False(InspectionText.IsImported(fs, bodyCount: 1));
}
[Fact]
public void IsImported_false_for_native_part_with_operations()
{
var fs = new[]
{
Feat(0, "Начало координат", "origin"), Feat(1, "Эскиз:1", "sketch"),
Feat(2, "Элемент выдавливания:1", "extrusion"), Feat(3, "Скругление:1", "fillet"),
};
Assert.False(InspectionText.IsImported(fs, bodyCount: 1));
}
[Fact]
public void IsImported_false_without_body()
=> Assert.False(InspectionText.IsImported(new[] { Feat(0, "Начало координат", "origin") }, bodyCount: 0));
// ── Рендер: родная параметрическая деталь ────────────────────────────
[Fact]
public void Render_native_part_shows_tree_with_params()
{
var d = new ModelDescription
{
Name = "demo",
IsEmpty = false,
Box = new BoundingBox { MinX = -20, MinY = -10, MinZ = 0, MaxX = 20, MaxY = 10, MaxZ = 15 },
Mass = new PartInfo { Volume = 11961, Mass = 0.094, Area = 3370, CenterX = 0, CenterY = 0, CenterZ = 7.5 },
Bodies = new[] { new BodyInfo { Index = 0, IsSolid = true, FaceCount = 7 } },
FaceTypes = new[] { "plane", "plane", "cylinder" },
EdgeTypes = new[] { "line", "line" },
Imported = false,
Features = new[]
{
new FeatureInfo { Index = 0, Name = "Начало координат", Kind = "origin" },
new FeatureInfo { Index = 1, Name = "Эскиз:1", Kind = "sketch" },
new FeatureInfo { Index = 2, Name = "Элемент выдавливания:1", Kind = "extrusion", Detail = "глубина 15.00 мм" },
new FeatureInfo { Index = 3, Name = "Скругление:1", Kind = "fillet", Detail = "R3.00 мм" },
},
Variables = Array.Empty(),
};
var text = InspectionText.Render(d);
Assert.Contains("Документ: «demo»", text);
Assert.Contains("Габарит (Д×Ш×В): 40.00 × 20.00 × 15.00 мм", text);
Assert.Contains("Тела: 1", text);
Assert.Contains("граней 3 (2 plane, 1 cylinder)", text);
Assert.Contains("Дерево построения (4", text);
Assert.Contains("«Элемент выдавливания:1» — глубина 15.00 мм", text);
Assert.Contains("«Скругление:1» — R3.00 мм", text);
Assert.Contains("Переменные: нет", text);
}
// ── Рендер: импортированная модель (флаг Imported) ───────────────────
[Fact]
public void Render_imported_model_notes_no_history()
{
var d = new ModelDescription
{
Name = "top_spacer",
IsEmpty = false,
Box = new BoundingBox { MinX = 0, MinY = 0, MinZ = 0, MaxX = 18, MaxY = 8, MaxZ = 39 },
Mass = new PartInfo { Volume = 2463, Mass = 0.019, Area = 2053, CenterX = 0, CenterY = 0, CenterZ = 21 },
Bodies = new[] { new BodyInfo { Index = 0, IsSolid = true, FaceCount = 61 } },
FaceTypes = new[] { "plane", "cylinder" },
EdgeTypes = new[] { "line" },
Imported = true,
Features = new[]
{
new FeatureInfo { Index = 0, Name = "Начало координат", Kind = "origin" },
new FeatureInfo { Index = 1, Name = "Body1", Kind = "body" },
},
Variables = Array.Empty(),
};
var text = InspectionText.Render(d);
Assert.Contains("импортирован", text.ToLowerInvariant());
Assert.DoesNotContain("Дерево построения (", text); // не показываем как параметрическое дерево
}
// ── Рендер: пустая модель ────────────────────────────────────────────
[Fact]
public void Render_empty_model()
{
var d = new ModelDescription
{
Name = "empty", IsEmpty = true,
Bodies = Array.Empty(), FaceTypes = Array.Empty(), EdgeTypes = Array.Empty(),
Imported = false, Features = Array.Empty(), Variables = Array.Empty(),
};
var text = InspectionText.Render(d);
Assert.Contains("Модель пуста", text);
}
// ── Рендер переменных ────────────────────────────────────────────────
[Fact]
public void Render_variables_listed_with_flags()
{
var d = new ModelDescription
{
Name = "p", IsEmpty = false,
Box = new BoundingBox { MinX = 0, MinY = 0, MinZ = 0, MaxX = 1, MaxY = 1, MaxZ = 1 },
Mass = new PartInfo { Volume = 1, Mass = 1, Area = 6, CenterX = 0, CenterY = 0, CenterZ = 0 },
Bodies = new[] { new BodyInfo { Index = 0, IsSolid = true, FaceCount = 6 } },
FaceTypes = new[] { "plane" }, EdgeTypes = new[] { "line" },
Imported = false, Features = Array.Empty(),
Variables = new[]
{
new VariableInfo { Name = "L", Expression = "80", Value = 80, External = true, Information = false },
new VariableInfo { Name = "v", Expression = "L/2", Value = 40, External = false, Information = true },
},
};
var text = InspectionText.Render(d);
Assert.Contains("Переменные (2):", text);
Assert.Contains("L = 80", text);
Assert.Contains("[внешняя]", text);
Assert.Contains("[инфо]", text);
}
}