Files
mikhail 742a97177b feat: drawing_fill_title_block — основная надпись чертежа (API7)
Веха 2D-ЧЕРТЁЖ, инкремент 2 (оформление). DrawingService.FillTitleBlockAsync:
LayoutSheets.ItemByNumber[1].Stamp.Text[id].Str = text → Update(). Enum StampField
→ номер графы ГОСТ (designation=2, name=1, material=3). Заполнение нескольких
граф за вызов; перезапись (Str замещает, Clear не нужен — подтверждено спайком).
Новый инструмент drawing_fill_title_block; ReadStampCellAsync для проверки.

Ревью Codex спека учтено: Update() результат проверяется; null-checks
(LayoutSheets/sheet/Stamp); RequireActiveDrawing выделен (сохраняет cast-проверку);
ColumnId switch с дефолтным throw; счётчик = непустые поля; name=графа 1 однозначно.

Валидация — чистый StampFields (ColumnId + Collect). Тесты: +7 unit (StampFields),
+4 integration (DrawingStampTests: заполнение+reread 3 граф, перезапись, пустой
ввод, не-чертёж). Итого 123 unit + 65 integration = 188.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 17:20:16 +03:00

86 lines
3.1 KiB
C#

using Kompas.Mcp.Core.Documents;
using Kompas.Mcp.Core.Drawings;
using Kompas.Mcp.Core.Modeling;
namespace Kompas.Mcp.Tests.Integration;
/// <summary>Интеграция: заполнение основной надписи чертежа (API7 IStamp.Text).</summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class DrawingStampTests : IntegrationTestBase
{
private readonly DocumentService _docs;
private readonly DrawingService _drawing;
private readonly PartModeler _modeler;
public DrawingStampTests(KompasFixture fx) : base(fx)
{
_docs = new DocumentService(fx.Session, fx.Dispatcher);
_drawing = new DrawingService(fx.Session, fx.Dispatcher);
_modeler = new PartModeler(fx.Session, fx.Dispatcher);
}
[Fact]
public async Task Fills_and_reads_back_title_block_cells()
{
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
var filled = await _drawing.FillTitleBlockAsync(
designation: "ДЕТАЛЬ.001", name: "Кронштейн", material: "Сталь 45");
Assert.Equal(3, filled);
// Явный reread каждой графы (графа 2/1/3).
Assert.Equal("ДЕТАЛЬ.001", await _drawing.ReadStampCellAsync(2));
Assert.Equal("Кронштейн", await _drawing.ReadStampCellAsync(1));
Assert.Equal("Сталь 45", await _drawing.ReadStampCellAsync(3));
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Overwrites_existing_cell_text()
{
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
await _drawing.FillTitleBlockAsync(designation: "СТАРОЕ.000");
await _drawing.FillTitleBlockAsync(designation: "НОВОЕ.111");
// Перезапись, не дописывание.
Assert.Equal("НОВОЕ.111", await _drawing.ReadStampCellAsync(2));
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Empty_input_throws()
{
await _docs.CreateAsync(KompasDocumentType.Drawing);
try
{
await Assert.ThrowsAsync<ArgumentException>(
() => _drawing.FillTitleBlockAsync(null, " ", null));
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Rejects_non_drawing_document()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
// Деталь — не чертёж: FillTitleBlock должен бросить.
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
await _modeler.AddRectangleAsync(s, 0, 0, 10, 10);
await _modeler.CloseSketchAsync(s);
await _modeler.ExtrudeAsync(s, depth: 5);
await Assert.ThrowsAsync<InvalidOperationException>(
() => _drawing.FillTitleBlockAsync(designation: "X"));
}
finally { await _docs.CloseAsync(save: false); }
}
}