feat(pack-shelf): height-sort desc shelf packing with oversize loud-error

This commit is contained in:
Axel Meyer
2026-06-16 21:09:06 +02:00
parent 61c44b4569
commit 348b226c26
2 changed files with 125 additions and 0 deletions

71
tests/pack-shelf.test.js Normal file
View File

@@ -0,0 +1,71 @@
const { test } = require('node:test');
const assert = require('node:assert');
const { packShelf } = require('../src/pack-shelf');
test('pack-shelf: 3 equal rects fit horizontally', () => {
const rects = [
{ alias: 'a', w: 32, h: 32 },
{ alias: 'b', w: 32, h: 32 },
{ alias: 'c', w: 32, h: 32 },
];
const r = packShelf(rects, 4096);
assert.strictEqual(r.error, undefined);
assert.strictEqual(r.placed.length, 3);
// All in one row at y=0; row height = 32
assert.strictEqual(r.boundsH, 32);
assert.strictEqual(r.boundsW, 96);
assert.strictEqual(r.placed[0].x, 0);
assert.strictEqual(r.placed[0].y, 0);
});
test('pack-shelf: height-sort desc — tall sprite first', () => {
const rects = [
{ alias: 'short', w: 32, h: 16 },
{ alias: 'tall', w: 32, h: 64 },
{ alias: 'mid', w: 32, h: 32 },
];
const r = packShelf(rects, 4096);
// Row 0 contains tall (64) + mid (32) + short (16) — all fit in row height 64
assert.strictEqual(r.boundsH, 64);
// Tall placed at x=0
const tall = r.placed.find(p => p.alias === 'tall');
assert.strictEqual(tall.x, 0);
assert.strictEqual(tall.y, 0);
});
test('pack-shelf: row wrap when max-width exceeded', () => {
const rects = [
{ alias: 'a', w: 60, h: 20 },
{ alias: 'b', w: 60, h: 20 },
];
const r = packShelf(rects, 100);
// a fits at (0,0). b needs to wrap to next row.
const a = r.placed.find(p => p.alias === 'a');
const b = r.placed.find(p => p.alias === 'b');
assert.strictEqual(a.y, 0);
assert.strictEqual(b.y, 20); // shelf height after row 0 = 20
});
test('pack-shelf: oversize beyond max-size -> error', () => {
const rects = [{ alias: 'huge', w: 200, h: 200 }];
const r = packShelf(rects, 100);
assert.strictEqual(r.error, 'oversize');
assert.match(r.message, /max-size/);
});
test('pack-shelf: deterministic across runs', () => {
const rects = [
{ alias: 'a', w: 32, h: 32 },
{ alias: 'b', w: 64, h: 48 },
{ alias: 'c', w: 16, h: 16 },
];
const r1 = packShelf(rects, 4096);
const r2 = packShelf(rects, 4096);
assert.deepStrictEqual(r1.placed, r2.placed);
});
test('pack-shelf: preserves rect aux fields', () => {
const rects = [{ alias: 'a', w: 32, h: 32, sourceFile: 'A.png' }];
const r = packShelf(rects, 4096);
assert.strictEqual(r.placed[0].sourceFile, 'A.png');
});