Files
mikhail 56ed2cb0cf feat(drawing): формат и ориентация листа (drawing_set_sheet_format)
Задать формат (A0–A5/user) и ориентацию (книжная/альбомная) листа чертежа через
API7 ILayoutSheet.Format (ISheetFormat). Стандартный формат — размеры авто; user —
явные width/height (landscape игнорируется, ориентация из соотношения сторон).

- DrawingService.SetSheetFormatAsync + RequireLayoutSheet
- PaperFormat (enum + Parse/ToKompas/FromKompas), SheetFormatResult
- DrawingValidation.ValidateFormatDimensions (user: >0; стандартный: размеры запрещены)
- 19 unit + 7 интеграционных тестов (всего 304 зелёных), сборка Release чистая

Спайк подтвердил: дефолт A4 portrait; стандартный формат пересчитывает W/H авто
(A3 landscape→420×297); user применяет width/height. Ревью спека pi/glm-5.1 + pi/kimi-k2.6
учтено (FromKompas для дружелюбного имени, запрет размеров у стандартного, sheetNumber>0,
landscape игнорируется для user).

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

123 lines
4.7 KiB
C#

using Kompas.Mcp.Core.Drawings;
namespace Kompas.Mcp.Tests;
[Trait("Category", "Unit")]
public sealed class DrawingValidationTests
{
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void NormalizeModelPath_throws_on_empty(string? path)
=> Assert.Throws<ArgumentException>(() => DrawingValidation.NormalizeModelPath(path));
[Theory]
[InlineData(@"C:\m\part.step")]
[InlineData(@"C:\m\part.txt")]
[InlineData(@"C:\m\part")]
public void NormalizeModelPath_throws_on_wrong_extension(string path)
=> Assert.Throws<ArgumentException>(() => DrawingValidation.NormalizeModelPath(path));
[Theory]
[InlineData(@"C:\m\part.m3d", ".m3d")]
[InlineData(@"C:\m\frame.a3d", ".a3d")]
[InlineData(@" C:\m\part.M3D ", ".m3d")]
[InlineData(@"C:\модели\деталь.m3d", ".m3d")] // кириллица в пути
public void NormalizeModelPath_accepts_model_files(string path, string expectedExt)
{
var result = DrawingValidation.NormalizeModelPath(path);
Assert.True(Path.IsPathFullyQualified(result));
Assert.EndsWith(expectedExt, result, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void NormalizeModelPath_preserves_cyrillic()
{
var result = DrawingValidation.NormalizeModelPath(@"C:\модели\деталь.m3d");
Assert.Contains("деталь", result);
Assert.Contains("модели", result);
}
[Theory]
[InlineData(0)]
[InlineData(-1)]
[InlineData(double.NaN)]
[InlineData(double.PositiveInfinity)]
public void RequireScale_throws_on_non_positive_or_non_finite(double scale)
=> Assert.Throws<ArgumentOutOfRangeException>(() => DrawingValidation.RequireScale(scale));
[Theory]
[InlineData(1.0)]
[InlineData(0.5)]
[InlineData(2.0)]
public void RequireScale_accepts_positive(double scale)
=> Assert.Null(Record.Exception(() => DrawingValidation.RequireScale(scale)));
[Fact]
public void RequireFiniteCoords_throws_on_non_finite()
{
Assert.Throws<ArgumentException>(() => DrawingValidation.RequireFiniteCoords(0, double.NaN));
Assert.Throws<ArgumentException>(() => DrawingValidation.RequireFiniteCoords(double.PositiveInfinity));
Assert.Null(Record.Exception(() => DrawingValidation.RequireFiniteCoords(0, 1, -5, 40)));
}
[Fact]
public void RequireDistinctPoints_throws_on_coincident()
{
Assert.Throws<ArgumentException>(() => DrawingValidation.RequireDistinctPoints(10, 20, 10, 20));
Assert.Null(Record.Exception(() => DrawingValidation.RequireDistinctPoints(0, 0, 40, 0)));
}
[Theory]
[InlineData(0)]
[InlineData(-5)]
[InlineData(double.NaN)]
[InlineData(double.PositiveInfinity)]
public void RequirePositiveRadius_throws_on_non_positive_or_non_finite(double radius)
=> Assert.Throws<ArgumentOutOfRangeException>(() => DrawingValidation.RequirePositiveRadius(radius));
[Fact]
public void RequirePositiveRadius_accepts_positive()
=> Assert.Null(Record.Exception(() => DrawingValidation.RequirePositiveRadius(15)));
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
public void RequireNonEmptyText_throws_on_empty(string? text)
=> Assert.Throws<ArgumentException>(() => DrawingValidation.RequireNonEmptyText(text, "text"));
[Fact]
public void RequireNonEmptyText_accepts_non_empty()
=> Assert.Null(Record.Exception(() => DrawingValidation.RequireNonEmptyText("Ra 1.6", "text")));
[Theory]
[InlineData(0, 300)]
[InlineData(500, 0)]
[InlineData(-1, 300)]
[InlineData(double.NaN, 300)]
[InlineData(500, double.PositiveInfinity)]
public void ValidateFormatDimensions_user_throws_on_non_positive_or_non_finite(double w, double h)
=> Assert.Throws<ArgumentOutOfRangeException>(
() => DrawingValidation.ValidateFormatDimensions(PaperFormat.User, w, h));
[Fact]
public void ValidateFormatDimensions_user_accepts_positive()
=> Assert.Null(Record.Exception(
() => DrawingValidation.ValidateFormatDimensions(PaperFormat.User, 500, 300)));
[Theory]
[InlineData(500, 0)]
[InlineData(0, 300)]
[InlineData(500, 300)]
public void ValidateFormatDimensions_standard_throws_when_dimensions_given(double w, double h)
=> Assert.Throws<ArgumentException>(
() => DrawingValidation.ValidateFormatDimensions(PaperFormat.A3, w, h));
[Fact]
public void ValidateFormatDimensions_standard_accepts_zero_dimensions()
=> Assert.Null(Record.Exception(
() => DrawingValidation.ValidateFormatDimensions(PaperFormat.A3, 0, 0)));
}