P5: expose Sketcher solve command and OCCT dress-up features

This commit is contained in:
2026-08-02 10:29:30 -04:00
parent 6a1bd18384
commit 64b7369918
8 changed files with 65 additions and 6 deletions

View File

@@ -7,7 +7,7 @@ import { DependencyGraph } from '../src/facade/dependencyGraph'
import { evaluateQuantityExpression, quantityFromNumber } from '../src/facade/units'
import { createSubshapeRefs, matchSubshapes, signatureForFace } from '../src/facade/topologyNaming'
import { createSketch, solveSketch } from '../src/facade/sketcher'
import { assertShapeHandleIntegrity, normalizeBitbybitMesh, validateBooleanUnionInput, validateBoxInput, validateConeInput, validateCylinderInput, validatePadInput, validatePlacementInput, validatePlanarProfile, validateRevolutionInput, validateSphereInput } from '../src/facade/geometryRuntime'
import { assertShapeHandleIntegrity, normalizeBitbybitMesh, validateBooleanUnionInput, validateBoxInput, validateChamferInput, validateConeInput, validateCylinderInput, validateFilletInput, validatePadInput, validatePlacementInput, validatePlanarProfile, validateRevolutionInput, validateSphereInput } from '../src/facade/geometryRuntime'
import type { ShapeHandle } from '../src/facade/types'
test('facade exposes a stable initial document projection', () => {
@@ -45,6 +45,8 @@ test('boolean geometry rejects cross-document and future-version operands', () =
assert.throws(() => validateBooleanUnionInput({ shapes: [first, { ...second, documentId: 'doc-two' }], documentId: 'doc-one', documentVersion: 3 }), /another document/)
assert.throws(() => validateBooleanUnionInput({ shapes: [first, second], documentId: 'doc-one', documentVersion: 2 }), /newer/)
assert.throws(() => validateBooleanUnionInput({ shapes: [first], documentId: 'doc-one', documentVersion: 2 }), /at least 2/)
assert.throws(() => validateFilletInput({ base: first, radius: 0, documentId: 'doc-one', documentVersion: 2 }), /radius/)
assert.throws(() => validateChamferInput({ base: first, distance: 1, indexes: [-1], documentId: 'doc-one', documentVersion: 2 }), /indexes/)
})
test('feature profiles reject degenerate and non-planar geometry', () => {
@@ -145,6 +147,19 @@ test('sketcher operations are facade transactions and survive the project fallba
assert.equal(loaded?.objects.find((object) => object.id === 'sketch')?.sketch?.constraints[0].id, 'horizontal-1')
})
test('Sketcher solve command is selection-aware and emits the standard command lifecycle', () => {
const facade = createMockFacade()
facade.gui.workbench.setActive('Sketcher')
facade.selection.select('sketch')
const events: string[] = []
facade.subscribe((event) => { if (event.type.startsWith('command.')) events.push(event.type) })
facade.gui.command.execute({ commandId: 'solve-sketch' })
assert.deepEqual(events, ['command.started', 'command.completed'])
assert.equal(facade.app.document.getObject('sketch')?.sketch?.solver.status, 'solved')
facade.selection.clear()
assert.equal(facade.gui.command.getState('solve-sketch').status, 'disabled')
})
test('dependency graph propagates dirty state and orders dependencies', () => {
const graph = new DependencyGraph([
{ sourceId: 'pocket', targetId: 'pad', relation: 'link' },