diff --git a/scripts/run-api-tests.mjs b/scripts/run-api-tests.mjs index 2b9b32e3..36f8aac0 100644 --- a/scripts/run-api-tests.mjs +++ b/scripts/run-api-tests.mjs @@ -37,6 +37,7 @@ const AVAILABLE_SUITES = [ { id: 'scale', name: 'Scale Tests (45 tests)', pattern: '@scale' }, { id: 'rotation', name: 'Rotation Tests', pattern: '@rotation' }, { id: 'translation', name: 'Translation/Movement Tests', pattern: '@translation' }, + { id: 'translate', name: 'Translation/Movement Tests (alias)', pattern: '@translation' }, { id: 'animate', name: 'Animation API Tests', pattern: 'Animation API Tests' }, { id: 'glide', name: 'Glide Animation Tests', pattern: 'glideTo function tests' }, { id: 'ui', name: 'UI Text/Button Tests', pattern: 'UIText, UIButton, UIInput, and UISlider function tests' }, @@ -55,7 +56,12 @@ const verbose = args.includes('--verbose') || args.includes('-v'); const logTests = args.includes('--log-tests'); const logApi = args.includes('--log-api'); const logAll = args.includes('--log-all'); -const suite = args.find(arg => !arg.startsWith('--')) || 'all'; +const requestedSuite = args.find(arg => !arg.startsWith('--')) || 'all'; +const suiteAliases = { + translate: 'translation', + movement: 'translation', +}; +const suite = suiteAliases[requestedSuite] || requestedSuite; // Enable both logs if --log-all is specified if (logAll) { diff --git a/tests/transform.translate.test.js b/tests/transform.translate.test.js index c6472098..8ebffdbb 100644 --- a/tests/transform.translate.test.js +++ b/tests/transform.translate.test.js @@ -113,6 +113,63 @@ export function runTranslationTests(flock) { }); }); + describe("Current inspector-vs-block placement semantics @translation", function () { + let boxId; + + beforeEach(async function () { + boxId = `box_semantics_${Date.now()}`; + flock.createBox(boxId, { + color: "#00AAFF", + width: 2, + height: 2, + depth: 2, + position: [0, 0, 0], + }); + + await flock.setAnchor(boxId, { + xPivot: "CENTER", + yPivot: "MIN", + zPivot: "CENTER", + }); + }); + + afterEach(function () { + if (boxId) flock.dispose(boxId); + }); + + it("should keep requested Y aligned to base/pivot while mesh.position.y stays offset", async function () { + await flock.positionAt(boxId, { x: 2, y: 3, z: 4, useY: true }); + + const box = flock.scene.getMeshByName(boxId); + const bounds = box.getBoundingInfo().boundingBox; + const pivotWorld = box.getAbsolutePivotPoint(); + + expect(bounds.minimumWorld.y).to.be.closeTo(3, 0.01); + expect(pivotWorld.y).to.be.closeTo(3, 0.01); + expect(box.position.y).to.be.greaterThan(3.9); + expect(box.position.y).to.be.lessThan(4.1); + }); + + it("should preserve existing Y offset semantics when useY is false", async function () { + await flock.positionAt(boxId, { x: 0, y: 10, z: 0, useY: true }); + + const box = flock.scene.getMeshByName(boxId); + const beforeMinY = box.getBoundingInfo().boundingBox.minimumWorld.y; + const beforePositionY = box.position.y; + + await flock.positionAt(boxId, { x: 5, y: 999, z: -3, useY: false }); + + box.computeWorldMatrix(true); + box.refreshBoundingInfo(); + const afterMinY = box.getBoundingInfo().boundingBox.minimumWorld.y; + + expect(afterMinY).to.be.closeTo(beforeMinY, 0.01); + expect(box.position.y).to.be.closeTo(beforePositionY, 0.01); + expect(box.position.x).to.be.closeTo(5, 0.01); + expect(box.position.z).to.be.closeTo(-3, 0.01); + }); + }); + describe("moveTo API Tests @translation", function () { let box1Id, box2Id;