35 lines
5.1 KiB
JavaScript
35 lines
5.1 KiB
JavaScript
import { isDeepStrictEqual } from 'node:util'
|
|
import { readFile } from 'node:fs/promises'
|
|
import { resolve } from 'node:path'
|
|
|
|
const root = resolve(new URL('..', import.meta.url).pathname)
|
|
const report = JSON.parse(await readFile(resolve(root, 'config/freecad-property-linksublistglobal-failure.json'), 'utf8'))
|
|
const fail = (message) => { throw new Error(`FreeCAD PropertyLinkSubListGlobal failure check failed: ${message}`) }
|
|
if (report.schemaVersion !== 1 || report.status !== 'pass' || report.baselineId !== 'freecad-1.1.1-property-linksublistglobal-failure' || report.freecadVersion !== '1.1.1' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.propertyType !== 'App::PropertyLinkSubListGlobal' || report.caseCount !== 1) fail('baseline is invalid')
|
|
const entry = report.case
|
|
if (!entry || entry.objectTypeId !== 'PartDesign::ShapeBinder' || entry.objectName !== 'ShapeBinderProbe' || entry.propertyName !== 'Support') fail('fixture identity changed')
|
|
const initial = entry.initial
|
|
if (initial?.propertyTypeId !== report.propertyType || !isDeepStrictEqual(initial.propertyStatus, []) || !isDeepStrictEqual(initial.editorMode, []) || !isDeepStrictEqual(initial.value, [{ object: 'SourceBox', subElements: ['Face1', 'Face2'] }, { object: 'SecondBox', subElements: ['Face1'] }]) || initial.statusString !== 'Valid' || !isDeepStrictEqual(initial.ownerState, ['Up-to-date'])) fail('initial global link state is invalid')
|
|
const assertGeometryPreserved = (snapshot, label) => { if (!isDeepStrictEqual(snapshot.objectSet, initial.objectSet) || !isDeepStrictEqual(snapshot.targetShapeHashes, initial.targetShapeHashes)) fail(`${label} polluted objects or source Shapes`) }
|
|
const expectedInputs = new Map([
|
|
['scalar', { exception: ['TypeError', 'Expects sequence of items of type DocObj, (DocObj,SubName), or (DocObj, (SubName,...))'], value: initial.value, preserved: true }],
|
|
['singlePairShorthand', { exception: null, value: [{ object: 'SourceBox', subElements: ['Face1'] }], preserved: false }],
|
|
['stringObject', { exception: null, value: [], preserved: false }],
|
|
['integerObject', { exception: null, value: [], preserved: false }],
|
|
])
|
|
if (entry.inputs?.length !== expectedInputs.size) fail('invalid-input case count changed')
|
|
for (const input of entry.inputs) {
|
|
const expected = expectedInputs.get(input.id)
|
|
if (!expected || !isDeepStrictEqual(input.before, initial) || !isDeepStrictEqual(input.after.value, expected.value) || input.valuePreserved !== expected.preserved || (expected.exception === null ? input.exception !== null : input.exception?.type !== expected.exception[0] || input.exception.message !== expected.exception[1])) fail(`${input.id} classification changed`)
|
|
assertGeometryPreserved(input.after, input.id)
|
|
}
|
|
if (!entry.crossDocument?.exception || entry.crossDocument.valuePreserved !== true || entry.crossDocument.documentPreserved !== true || !isDeepStrictEqual(entry.crossDocument.before, initial) || !isDeepStrictEqual(entry.crossDocument.after, initial)) fail('cross-document boundary is not atomic')
|
|
assertGeometryPreserved(entry.crossDocument.after, 'cross-document')
|
|
if (entry.readOnly?.exception !== null || entry.readOnly.pythonBypassesEditorReadOnly !== true || !isDeepStrictEqual(entry.readOnly.after.value, [{ object: 'SecondBox', subElements: ['Face2'] }]) || !isDeepStrictEqual(entry.readOnly.after.propertyStatus, ['ReadOnly'])) fail('ReadOnly Python boundary changed')
|
|
if (entry.immutable?.exception?.type !== 'AttributeError' || entry.immutable.exception.message !== "Object attribute 'Support' is read-only" || entry.immutable.pythonBypassesImmutable !== false || !isDeepStrictEqual(entry.immutable.after.value, initial.value) || !isDeepStrictEqual(entry.immutable.after.propertyStatus, ['Immutable'])) fail('Immutable Python boundary changed')
|
|
const transaction = entry.transaction
|
|
if (transaction?.undoMode !== 1 || transaction.pendingAfterEdit !== true || transaction.pendingAfterAbort !== false || transaction.activeAfterEdit?.name !== 'property-linksublistglobal-cancel' || transaction.activeAfterAbort?.id !== 0 || !isDeepStrictEqual(transaction.before, transaction.afterAbort) || transaction.restored !== true || transaction.recomputeAfterAbort !== true) fail('transaction cancel and recovery changed')
|
|
if (report.cancellationBoundary?.supported !== false || report.cancellationBoundary.classification !== 'synchronous-property-setter' || report.cancellationBoundary.replacement !== 'abort-active-document-transaction') fail('cancellation boundary is incomplete')
|
|
if (entry.documentIntegrity?.objectsPreserved !== true || !isDeepStrictEqual(entry.documentIntegrity.initialObjects, entry.documentIntegrity.finalObjects)) fail('document object set was polluted')
|
|
console.log(JSON.stringify({ status: 'freecad-property-linksublistglobal-failure-pass', inputs: entry.inputs.map(({ id, exception, after }) => ({ id, exception, normalizedValue: after.value })), crossDocument: entry.crossDocument.exception, readOnlyPythonAccepted: entry.readOnly.pythonBypassesEditorReadOnly, immutablePythonAccepted: entry.immutable.pythonBypassesImmutable, transactionRestored: transaction.restored, cancellationBoundary: report.cancellationBoundary }, null, 2))
|