import { describe, expect, it } from 'vitest' import { MIN_GAP, SORT_GAP, needsRebalance, rebalancedOrders, sortOrderBetween, } from '../src/main/db/repositories/ordering' describe('ordering', () => { it('starts a fresh layer at the base gap', () => { expect(sortOrderBetween(null, null)).toBe(SORT_GAP) }) it('appends past the last item', () => { expect(sortOrderBetween(1024, null)).toBe(1024 + SORT_GAP) }) it('prepends before the first item', () => { expect(sortOrderBetween(null, 1024)).toBe(1024 - SORT_GAP / 2) }) it('lands strictly between two neighbours', () => { const mid = sortOrderBetween(1024, 2048) expect(mid).toBeGreaterThan(1024) expect(mid).toBeLessThan(2048) }) it('does not flag a healthy gap as needing rebalancing', () => { expect(needsRebalance(1024, 2048)).toBe(false) // A missing neighbour means "open end", not "collapsed". expect(needsRebalance(null, 1024)).toBe(false) expect(needsRebalance(1024, null)).toBe(false) }) it('flags a gap too small to split again', () => { expect(needsRebalance(1, 1 + MIN_GAP / 2)).toBe(true) expect(needsRebalance(1, 1 + MIN_GAP * 2)).toBe(false) }) it('exhausts precision after a bounded number of splits, then says so', () => { // The documented cost of fractional ordering. Repeatedly splitting the same // gap halves the interval each time, and a double cannot halve forever. // This test pins down that the limit is reached and, crucially, that it is // *detected* — an undetected collapse would silently make item order // arbitrary rather than raising an error. let current = 1024 const next = 2048 let splits = 0 while (!needsRebalance(current, next) && splits < 500) { current = sortOrderBetween(current, next) splits++ } expect(splits).toBeLessThan(500) expect(needsRebalance(current, next)).toBe(true) // Comfortably beyond any human drag-and-drop session, which is why the // tradeoff is worth taking. expect(splits).toBeGreaterThan(20) }) it('produces evenly spaced orders when rebalancing', () => { const orders = rebalancedOrders(4) expect(orders).toEqual([1024, 2048, 3072, 4096]) const gaps = orders.slice(1).map((v, i) => v - orders[i]) expect(new Set(gaps).size).toBe(1) }) })