import assert from 'node:assert/strict'; import test from 'node:test'; import { beginRuleReorder, crossedRuleIndex, edgeScrollDelta, endRuleReorder, keyboardRuleIndex, moveRule, restoreRuleOrder, RULE_DROP_DURATION_MS, RULE_REORDER_DURATION_MS, shouldLiftRule, } from '../../.test-dist/src/web/features/routing/ruleReorderModel.js'; test('rule drag lifts only after four vertical pixels', () => { assert.equal(shouldLiftRule(100, 103), false); assert.equal(shouldLiftRule(100, 104), true); assert.equal(shouldLiftRule(100, 96), true); assert.equal(shouldLiftRule(100, 100), false, 'horizontal-only movement leaves Y unchanged'); }); test('center crossing moves one or many slots without changing stable row identity', () => { const rules = [{ _key: 'a' }, { _key: 'b' }, { _key: 'c' }]; assert.equal(crossedRuleIndex(0, 149, [100, 150, 200]), 0); assert.equal(crossedRuleIndex(0, 151, [100, 150, 200]), 1); assert.equal(crossedRuleIndex(0, 201, [100, 150, 200]), 2); assert.equal(crossedRuleIndex(2, 149, [100, 150, 200]), 1); assert.equal(crossedRuleIndex(2, 99, [100, 150, 200]), 0); const moved = moveRule(rules, 0, 2); assert.deepEqual(moved.map(({ _key }) => _key), ['b', 'c', 'a']); assert.strictEqual(moved[2], rules[0]); const edited = [{ _key: 'b', value: 2 }, { _key: 'a', value: 10 }, { _key: 'd', value: 4 }]; const restored = restoreRuleOrder(rules, edited, ({ _key }) => _key); assert.deepEqual(restored.map(({ _key }) => _key), ['a', 'b', 'd']); assert.equal(restored[0].value, 10, 'cancel restores order without reverting edits'); }); test('one lifecycle owner covers pointer, keyboard, cleanup and reduced motion', () => { const pointer = beginRuleReorder(null, 'a', 'pointer'); assert.deepEqual(pointer, { key: 'a', input: 'pointer', lifted: false }); assert.equal(beginRuleReorder(pointer, 'b', 'keyboard'), null, 'a second handle cannot replace the session'); const liftedPointer = { ...pointer, lifted: true }; assert.deepEqual(endRuleReorder(liftedPointer, 'drop'), { restoreOrder: false, stopAutoScroll: true, restoreFocus: true, releasePointerCapture: true, animateDrop: true, }); assert.equal(endRuleReorder(liftedPointer, 'drop', true).animateDrop, false); assert.equal(endRuleReorder(liftedPointer, 'lost-capture').releasePointerCapture, false); assert.equal(endRuleReorder(liftedPointer, 'cancel').restoreOrder, true); assert.equal(endRuleReorder(liftedPointer, 'unmount').restoreFocus, false); const keyboard = beginRuleReorder(null, 'b', 'keyboard'); assert.deepEqual(keyboard, { key: 'b', input: 'keyboard', lifted: true }); const focusLeave = endRuleReorder(keyboard, 'focus-leave'); assert.equal(focusLeave.restoreOrder, true); assert.equal(focusLeave.stopAutoScroll, true); assert.equal(focusLeave.restoreFocus, false); assert.equal(focusLeave.releasePointerCapture, false); }); test('keyboard movement stops at list boundaries', () => { assert.equal(keyboardRuleIndex(0, -1, 3), 0); assert.equal(keyboardRuleIndex(0, 1, 3), 1); assert.equal(keyboardRuleIndex(2, 1, 3), 2); }); test('edge scrolling has direction, bounded speed and a zero outside its 32px zone', () => { assert.equal(edgeScrollDelta(99, 100, 300), 0); assert.equal(edgeScrollDelta(100, 100, 300), -12); assert.ok(edgeScrollDelta(131, 100, 300) <= -2); assert.equal(edgeScrollDelta(132, 100, 300), 0); assert.equal(edgeScrollDelta(268, 100, 300), 0); assert.ok(edgeScrollDelta(269, 100, 300) >= 2); assert.equal(edgeScrollDelta(300, 100, 300), 12); assert.equal(edgeScrollDelta(301, 100, 300), 0); assert.equal(RULE_REORDER_DURATION_MS, 220); assert.equal(RULE_DROP_DURATION_MS, 260); });