Files
SlabUploader/frontend/src/measure/measure.test.ts
T
grokbot_ty 11c8124674 test(capture): expect tip-trimmed every-6in width stations
Ty UAT: width min/max must describe bulk, not tips. Pin L=48 tapered
case (7 interior stations, no tip endpoints), uniform mid-board count,
and L≤12 empty/zero fallback before the sampleWidths change lands.
2026-09-15 03:20:17 +00:00

59 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { minAreaRect, orientedRect } from '../geometry/rect.ts';
import { measure } from './measure.ts';
// Uniform slab, 10 px/in: full W×H canvas, axis +x via minAreaRect angle 0.
function uniform(W: number, H: number) {
const bitset = new Uint8Array(W * H).fill(1);
const box = orientedRect(minAreaRect(bitset, W, H)!, 0);
return { bitset, box, slabPx: W * H };
}
// Tapered slab, 10 px/in: tips under 6 in and past L−6 in are `tipPx` wide
// (centered), the bulk is full canvas height.
function tapered(W: number, H: number, lengthEighths: number, tipPx: number) {
const inIn = W / 10;
const bitset = new Uint8Array(W * H);
const half = tipPx / 2;
for (let x = 0; x < W; x++) {
const p = x / 10;
const w = p < 6 || p > inIn - 6 ? tipPx : H;
for (let y = (H - w) / 2; y < (H + w) / 2; y++) bitset[y * W + x] = 1;
}
const box = orientedRect(minAreaRect(bitset, W, H)!, 0);
return { bitset, box, slabPx: bitset.reduce((a, c) => a + c, 0), lengthEighths };
}
test('tapered 48in slab: min/max reflect the bulk, tips excluded', () => {
const { bitset, box, slabPx, lengthEighths } = tapered(480, 100, 384, 20); // tips 2in, bulk 10in
const m = measure(bitset, 480, 100, box, lengthEighths, 8, slabPx);
assert.equal(m.widths.every6In.length, 7, `stations ${m.widths.every6In.length} (6..42in)`);
for (const e of m.widths.every6In) {
assert.ok(e >= 76 && e <= 84, `station ${e / 8}in must be bulk (~10in)`);
}
assert.ok(m.widths.min >= 76 && m.widths.min <= 84, `min ${m.widths.min / 8}in`);
assert.ok(m.widths.max >= 76 && m.widths.max <= 84, `max ${m.widths.max / 8}in`);
});
test('uniform slab: interior stations keep the full width', () => {
const { bitset, box, slabPx } = uniform(480, 100);
const m = measure(bitset, 480, 100, box, 384, 8, slabPx);
assert.equal(m.widths.every6In.length, 7);
for (const e of m.widths.every6In) {
assert.ok(e >= 72 && e <= 104, `station ${e / 8}in`);
}
});
test('short slab L=12in: no interior stations, widths are empty/zero', () => {
const { bitset, box, slabPx } = uniform(120, 100);
const m = measure(bitset, 120, 100, box, 96, 8, slabPx);
assert.deepEqual(m.widths, { min: 0, max: 0, avg: 0, every6In: [] });
});
test('short slab L=10in: no interior stations, widths are empty/zero', () => {
const { bitset, box, slabPx } = uniform(100, 100);
const m = measure(bitset, 100, 100, box, 80, 8, slabPx);
assert.deepEqual(m.widths, { min: 0, max: 0, avg: 0, every6In: [] });
});