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-linklisthidden-mutation.json'), 'utf8')) const fail = (message) => { throw new Error(`FreeCAD PropertyLinkListHidden mutation check failed: ${message}`) } if (report.schemaVersion !== 1 || report.status !== 'pass' || report.baselineId !== 'freecad-1.1.1-property-linklisthidden-mutation' || report.freecadVersion !== '1.1.1' || report.gitCommit !== '0108fd4b4850cc46e625b60e53cea7a7bbe69f8d' || report.propertyType !== 'App::PropertyLinkListHidden' || report.caseCount !== 2 || report.cases?.length !== 2) fail('baseline is invalid') const expectedHosts = new Map([ ['Sketcher::SketchObject', 'SketchProbe'], ['Sketcher::SketchObjectPython', 'SketchPythonProbe'], ]) const expectedObjects = (ownerName, ownerTypeId) => [ { name: ownerName, typeId: ownerTypeId }, { name: 'ExportA', typeId: 'Part::Feature' }, { name: 'ExportB', typeId: 'Part::Feature' }, ] for (const entry of report.cases) { const ownerName = expectedHosts.get(entry.objectTypeId) if (!ownerName || entry.objectName !== ownerName || entry.propertyName !== 'Exports' || entry.editRecomputeResult !== true || entry.restoreRecomputeResult !== true || entry.valueRestored !== true || entry.semanticStateRestored !== true) fail(`${entry.objectTypeId} mutation identity or recovery changed`) if (!isDeepStrictEqual(entry.before?.value, ['ExportA', 'ExportB']) || !isDeepStrictEqual(entry.touchedAfterEdit?.value, ['ExportB', 'ExportA', 'ExportB']) || !isDeepStrictEqual(entry.edited?.value, ['ExportB', 'ExportA', 'ExportB']) || !isDeepStrictEqual(entry.touchedAfterRestore?.value, ['ExportA', 'ExportB']) || !isDeepStrictEqual(entry.restored?.value, ['ExportA', 'ExportB'])) fail(`${entry.objectTypeId} value mutation changed`) if (!isDeepStrictEqual(entry.before.ownerState, ['Up-to-date']) || entry.before.statusString !== 'Valid' || !isDeepStrictEqual(entry.touchedAfterEdit.ownerState, ['Touched']) || entry.touchedAfterEdit.statusString !== 'Touched' || !isDeepStrictEqual(entry.edited.ownerState, ['Up-to-date']) || entry.edited.statusString !== 'Valid' || !isDeepStrictEqual(entry.touchedAfterRestore.ownerState, ['Touched']) || entry.touchedAfterRestore.statusString !== 'Touched' || !isDeepStrictEqual(entry.restored.ownerState, ['Up-to-date']) || entry.restored.statusString !== 'Valid') fail(`${entry.objectTypeId} state transition changed`) const baselineTargets = entry.before.targetShapes for (const [phase, snapshot] of Object.entries({ before: entry.before, touchedAfterEdit: entry.touchedAfterEdit, edited: entry.edited, touchedAfterRestore: entry.touchedAfterRestore, restored: entry.restored })) { if (snapshot.propertyTypeId !== 'App::PropertyLinkListHidden' || snapshot.group !== 'Sketch' || !isDeepStrictEqual(snapshot.propertyStatus, ['26']) || !isDeepStrictEqual(snapshot.editorMode, ['Hidden']) || snapshot.ownerShape?.isNull !== true || snapshot.ownerShape.solids !== 0 || snapshot.ownerShape.faces !== 0 || snapshot.ownerShape.edges !== 0 || snapshot.ownerShape.vertices !== 0 || snapshot.ownerShape.brepSha256 !== null) fail(`${entry.objectTypeId} ${phase} metadata or host Shape changed`) if (!isDeepStrictEqual(snapshot.ownerOutList, []) || !isDeepStrictEqual(snapshot.targetInLists, { ExportA: [], ExportB: [] }) || !isDeepStrictEqual(snapshot.targetShapes, baselineTargets) || !isDeepStrictEqual(snapshot.objectSet, expectedObjects(ownerName, entry.objectTypeId))) fail(`${entry.objectTypeId} ${phase} leaked dependencies or changed targets/objects`) } if (baselineTargets?.ExportA?.solids !== 1 || baselineTargets.ExportA.faces !== 6 || baselineTargets.ExportA.edges !== 12 || baselineTargets.ExportA.vertices !== 8 || baselineTargets.ExportB?.solids !== 1 || baselineTargets.ExportB.faces !== 3 || baselineTargets.ExportB.edges !== 3 || baselineTargets.ExportB.vertices !== 2) fail(`${entry.objectTypeId} target topology changed`) } console.log(JSON.stringify({ status: 'freecad-property-linklisthidden-mutation-pass', cases: report.cases.map(({ objectTypeId, before, edited, restored, semanticStateRestored }) => ({ objectTypeId, before: before.value, edited: edited.value, restored: restored.value, semanticStateRestored })) }, null, 2))