50 lines
4.4 KiB
JavaScript
50 lines
4.4 KiB
JavaScript
import { readFile } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
import { isDeepStrictEqual } from 'node:util'
|
|
|
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
|
const report = JSON.parse(await readFile(resolve(root, 'config/freecad-property-area-mutation.json'), 'utf8'))
|
|
const fail = (message) => { throw new Error(`FreeCAD PropertyArea mutation check failed: ${message}`) }
|
|
const same = isDeepStrictEqual
|
|
const near = (left, right, tolerance = 2e-6) => Math.abs(left - right) <= tolerance
|
|
|
|
if (report.schemaVersion !== 1 || report.status !== 'pass' || report.baselineId !== 'freecad-1.1.1-property-area-mutation' || report.freecadVersion !== '1.1.1' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d') fail('baseline is invalid')
|
|
if (report.object?.name !== 'AreaProbe' || report.object.typeId !== 'Measure::MeasureArea' || report.property?.name !== 'Area' || report.property.typeId !== 'App::PropertyArea' || report.input?.name !== 'Elements' || report.input.typeId !== 'App::PropertyLinkSubList') fail('native object/property identity changed')
|
|
if (!(report.recompute?.initial > 0) || !(report.recompute.edit > 0) || !(report.recompute.restore > 0)) fail('initial, edit and restore were not recomputed')
|
|
|
|
const nominalElements = [{ object: 'AreaBox', typeId: 'Part::Box', subElements: ['Face1'] }]
|
|
const editedElements = [
|
|
{ object: 'AreaBox', typeId: 'Part::Box', subElements: ['Face1', 'Face2'] },
|
|
{ object: 'AreaCylinder', typeId: 'Part::Cylinder', subElements: ['Face1'] },
|
|
]
|
|
for (const [phase, expectedValue, expectedElements] of [
|
|
['before', 10, nominalElements],
|
|
['edited', 95.398223877, editedElements],
|
|
['restored', 10, nominalElements],
|
|
]) {
|
|
const snapshot = report[phase]
|
|
if (!near(snapshot?.value?.numeric, expectedValue) || typeof snapshot.value.unit !== 'string' || !snapshot.value.unit.includes('mm^2') || !same(snapshot.elements, expectedElements)) fail(`${phase} value or Elements changed`)
|
|
if (!same(snapshot.propertyStatus, ['24', '27']) || !same(snapshot.editorMode, ['ReadOnly']) || snapshot.shape?.applicable !== false || !same(snapshot.objectState, ['Up-to-date']) || snapshot.statusString !== 'Valid' || snapshot.mustExecute !== false) fail(`${phase} native semantic state is invalid`)
|
|
}
|
|
|
|
for (const [phase, expectedElements] of [['touchedAfterEdit', editedElements], ['touchedAfterRestore', nominalElements]]) {
|
|
const snapshot = report[phase]
|
|
if (!same(snapshot?.elements, expectedElements) || !same(snapshot.objectState, ['Touched']) || snapshot.mustExecute !== false) fail(`${phase} did not preserve the native dirty state before recompute`)
|
|
}
|
|
if (!near(report.touchedAfterEdit.value?.numeric, 95.398223877) || report.touchedAfterRestore.value?.numeric !== 10) fail('derived Area was not updated synchronously with Elements')
|
|
|
|
if (report.sources?.preserved !== true || !same(report.sources.before, report.sources.edited) || !same(report.sources.before, report.sources.restored) || report.sources.before?.length !== 2) fail('source geometry changed during Elements mutation')
|
|
for (const source of report.sources.before) if (source.valid !== true || source.shapeType !== 'Solid' || source.solids !== 1 || !(source.faces > 0) || !(source.area > 0) || !(source.volume > 0)) fail(`${source.name} source Shape evidence is invalid`)
|
|
if (report.document?.objectsPreserved !== true || !same(report.document.objectsBefore, report.document.objectsRestored) || report.document.objectsBefore?.length !== 3) fail('mutation polluted the document object set')
|
|
if (report.classification?.inputChanged !== true || report.classification.derivedValueChanged !== true || report.classification.inputRestored !== true || report.classification.derivedValueRestored !== true || report.classification.semanticStateRestored !== true || report.classification.sourceGeometryPreserved !== true || report.classification.geometry !== 'source-shapes-preserved-derived-measurement-has-no-shape') fail('mutation/restore classification is incomplete')
|
|
|
|
console.log(JSON.stringify({
|
|
status: 'freecad-property-area-mutation-pass',
|
|
recompute: report.recompute,
|
|
values: { before: report.before.value.numeric, edited: report.edited.value.numeric, restored: report.restored.value.numeric },
|
|
elements: { before: report.before.elements, edited: report.edited.elements, restored: report.restored.elements },
|
|
sourceGeometryPreserved: report.sources.preserved,
|
|
semanticStateRestored: report.classification.semanticStateRestored,
|
|
geometry: report.classification.geometry,
|
|
}, null, 2))
|