e127cebb49
По протоколу регресс-прогона (46 вызовов против 90 в прошлом): feature_delete — ksDocument3D.DeleteObject + RebuildDocument, зависимые уходят каскадом. Неудачная проба больше не требует пересобирать документ (у субагента таких кругов было три). align/vAlign у примитива text: сервер строит, замеряет и сдвигает надпись сам. Ловушка, стоившая двух заходов: ksMoveObj и ksDeleteObj по ссылке от ksConvertTextToCurve возвращают успех и не делают ничего — двигать надо по ссылке ТЕКСТА, а габарит после сдвига считать арифметикой (по текстовой ссылке рамка идёт по ячейке). Поймано тестом, который сверяет заявленный габарит с выдавленной геометрией. list_edges: отбор по типу и координатному окну + концы рёбер в списке. Так адресуется нижний контур под фаску, который иначе не выбрать: индексов не отфильтровать, точек не угадать. Навык: wf меряет пропорцию крупно (1.0→1.25 = +29 %), но квантован ступенями — точную ширину набирают height; прирост каймы указан НА СТОРОНУ и зависит от начертания, а не от шрифта; добавлено предупреждение, что primitive(subtract) режет наехавшие буквы.
72 lines
2.8 KiB
C#
72 lines
2.8 KiB
C#
using Kompas.Mcp.Core.Modeling;
|
||
|
||
namespace Kompas.Mcp.Tests;
|
||
|
||
/// <summary>
|
||
/// Выравнивание надписи. КОМПАС кладёт строку только вправо-вверх от точки вставки, поэтому
|
||
/// «по центру» — это пересчёт по фактическому габариту глифов; раньше его делал агент отдельным
|
||
/// кругом «вставил → замерил → пересобрал».
|
||
/// </summary>
|
||
[Trait("Category", "Unit")]
|
||
public sealed class TextAlignsTests
|
||
{
|
||
[Theory]
|
||
[InlineData(null, TextAlign.Left)]
|
||
[InlineData("", TextAlign.Left)]
|
||
[InlineData("left", TextAlign.Left)]
|
||
[InlineData("CENTER", TextAlign.Center)]
|
||
[InlineData(" centre ", TextAlign.Center)]
|
||
[InlineData("right", TextAlign.Right)]
|
||
public void Horizontal_alignment_is_parsed(string? value, TextAlign expected)
|
||
=> Assert.Equal(expected, TextAligns.Parse(value));
|
||
|
||
[Theory]
|
||
[InlineData(null, TextVAlign.Baseline)]
|
||
[InlineData("bottom", TextVAlign.Bottom)]
|
||
[InlineData("middle", TextVAlign.Middle)]
|
||
[InlineData("top", TextVAlign.Top)]
|
||
public void Vertical_alignment_is_parsed(string? value, TextVAlign expected)
|
||
=> Assert.Equal(expected, TextAligns.ParseVertical(value));
|
||
|
||
[Fact]
|
||
public void Unknown_alignment_lists_the_allowed_values()
|
||
{
|
||
var ex = Assert.Throws<ArgumentException>(() => TextAligns.Parse("justify"));
|
||
Assert.Contains("left", ex.Message, StringComparison.Ordinal);
|
||
Assert.Contains("center", ex.Message, StringComparison.Ordinal);
|
||
}
|
||
|
||
[Fact]
|
||
public void Centering_moves_the_box_middle_onto_the_anchor()
|
||
{
|
||
// Глифы легли на 10…30 (середина 20), якорь — 0: сдвиг −20.
|
||
var (dx, dy) = TextAligns.Offset((10, 0, 30, 12), (0, 0), TextAlign.Center, TextVAlign.Baseline);
|
||
|
||
Assert.Equal(-20, dx, 9);
|
||
Assert.Equal(0, dy, 9);
|
||
}
|
||
|
||
[Fact]
|
||
public void Right_alignment_puts_the_box_end_onto_the_anchor()
|
||
{
|
||
var (dx, _) = TextAligns.Offset((10, 0, 30, 12), (90, 0), TextAlign.Right, TextVAlign.Baseline);
|
||
Assert.Equal(60, dx, 9); // 90 − 30
|
||
}
|
||
|
||
[Fact]
|
||
public void Vertical_middle_uses_the_glyph_box_not_the_baseline()
|
||
{
|
||
// Выносные ушли ниже базовой линии: габарит −3…12, середина 4.5.
|
||
var (_, dy) = TextAligns.Offset((0, -3, 20, 12), (0, 0), TextAlign.Left, TextVAlign.Middle);
|
||
Assert.Equal(-4.5, dy, 9);
|
||
}
|
||
|
||
[Fact]
|
||
public void Left_baseline_is_a_no_op()
|
||
{
|
||
var (dx, dy) = TextAligns.Offset((10, -3, 30, 12), (5, 7), TextAlign.Left, TextVAlign.Baseline);
|
||
Assert.Equal(0, dx, 9);
|
||
Assert.Equal(0, dy, 9);
|
||
}
|
||
}
|