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>
113 lines
4.7 KiB
Python
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
|