Files
autocad-mcp-pro/tests/test_sprint3_fixes.py
Umutcan EdizsalanandCursor 9ec6c4a989 style: apply ruff format across the repository
ruff format was never run repo-wide; CI now enforces 'ruff format --check', so normalize every module once. No behavior changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-23 15:14:51 +03:00

113 lines
4.7 KiB
Python

"""Regression tests for the CI-verifiable (ezdxf / shared) Sprint-3 fixes.
* N2 — drawing_save_as derives the on-disk format from the path extension
* N3 — ARC carries a `length` property; entity_select_smart length_range selects it
* N5 — properties parity: ezdxf sets bounding_box; MTEXT carries char_height + rotation
* NEW-dimauto-baseline-rotation — baseline dims run parallel to a rotated baseline
* NEW-dimauto-ordinate-misnomer — ordinate dims are staggered, not stacked at one offset
"""
from __future__ import annotations
import os
import tempfile
import pytest
pytestmark = pytest.mark.asyncio
class _Ctx:
def __init__(self, backend):
self.lifespan_context = {"backend": backend}
async def info(self, message):
pass
# ── N2 — format follows the file extension ──────────────────────────────────
async def test_save_as_derives_format_from_extension(backend):
import server
ctx = _Ctx(backend)
d = tempfile.mkdtemp()
res = await server.drawing_save_as(path=os.path.join(d, "part.dxf"), ctx=ctx)
assert res.get("format") == "dxf" # not the old "dwg" default
# ezdxf cannot write real DWG — must refuse rather than mislabel a .dwg file.
with pytest.raises(RuntimeError):
await server.drawing_save_as(path=os.path.join(d, "part.dwg"), ctx=ctx)
# ── N3 — ARC length + length_range selection ────────────────────────────────
async def test_arc_has_length_and_is_selectable(backend):
arc = await backend.entity_create_arc(0, 0, 10, 0, 90) # r=10, 90deg -> len ~15.708
info = await backend.entity_get(arc.handle)
assert info.properties.get("length") == pytest.approx(15.70796, rel=1e-4)
sel = await backend.entity_select_smart({"type": "ARC", "length_range": [15, 16]})
assert len(sel) == 1
# Out-of-range excludes it (was: all arcs silently rejected for lack of length).
assert await backend.entity_select_smart({"type": "ARC", "length_range": [1, 2]}) == []
# ── N5 — cross-backend property parity ──────────────────────────────────────
async def test_ezdxf_populates_bounding_box(backend):
line = await backend.entity_create_line(0, 0, 30, 40)
info = await backend.entity_get(line.handle)
bb = info.properties.get("bounding_box")
assert bb is not None and set(bb) == {"min", "max"} # same shape as COM
async def test_mtext_has_char_height_and_rotation(backend):
mt = await backend.entity_create_mtext("hello", 5, 5, height=2.5)
info = await backend.entity_get(mt.handle)
assert "char_height" in info.properties
assert "rotation" in info.properties
async def test_mtext_honors_caller_rotation(backend):
# NEW-mtext-1: entity_create_mtext now accepts a rotation that round-trips.
mt = await backend.entity_create_mtext("rot", 0, 0, width=50, height=2.5, rotation=30.0)
info = await backend.entity_get(mt.handle)
assert float(info.properties.get("rotation", 0.0)) == pytest.approx(30.0, abs=1e-6)
# ── NEW-dimauto-baseline-rotation ───────────────────────────────────────────
async def test_baseline_dim_runs_parallel_to_rotated_baseline(backend):
ln = await backend.entity_create_line(0, 0, 40, 40) # 45-degree baseline
dims = await backend.dimension_auto([ln.handle], style="baseline")
doc = backend._require_doc()
ent = doc.entitydb[dims[0].handle]
# Dimension line angle must match the baseline (45), not the old hardcoded 0.
assert ent.dxf.get("angle", 0.0) == pytest.approx(45.0, abs=1e-6)
assert ent.get_measurement() == pytest.approx(56.5685, rel=1e-3) # true len, not projection
# ── NEW-dimauto-ordinate-misnomer ───────────────────────────────────────────
async def test_ordinate_dims_are_staggered_not_overlapping(backend):
l1 = await backend.entity_create_line(0, 0, 20, 10)
l2 = await backend.entity_create_line(0, 0, 40, 30)
dims = await backend.dimension_auto([l1.handle, l2.handle], style="ordinate")
# Each segment emits an X and a Y dim; with per-feature staggering the
# X-dim reference Y-offsets differ between the two features.
doc = backend._require_doc()
y_offsets = []
for d in dims:
ent = doc.entitydb[d.handle]
dp = ent.dxf.get("defpoint", None)
if dp is not None:
y_offsets.append(round(float(dp[1]), 3))
# Not every dim collapses onto a single offset value.
assert len(set(y_offsets)) > 1