test(13-01): add failing aiCoordsToPagePdfSpace unit tests
- Add ai-coords.test.ts with 3 test cases covering US Letter (612x792 pts) - Tests import from lib/ai/field-placement which does not exist yet (RED phase) - Cases: text field near top, checkbox near bottom-right, client-sig at center
This commit is contained in:
@@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* Unit tests for aiCoordsToPagePdfSpace — AI top-left percentage coordinates to PDF bottom-left points.
|
||||||
|
*
|
||||||
|
* AI models return positions with top-left origin (0,0 = top-left corner of page).
|
||||||
|
* PDF user space uses bottom-left origin (0,0 = bottom-left corner of page).
|
||||||
|
* The conversion must flip the Y axis and multiply percentages by page dimensions.
|
||||||
|
*
|
||||||
|
* US Letter: 612 × 792 pts at 72 DPI.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { aiCoordsToPagePdfSpace } from '../../../lib/ai/field-placement';
|
||||||
|
|
||||||
|
const US_LETTER_W = 612; // pts
|
||||||
|
const US_LETTER_H = 792; // pts
|
||||||
|
|
||||||
|
describe('aiCoordsToPagePdfSpace — AI top-left percentage to PDF bottom-left points', () => {
|
||||||
|
test('text field near top of page', () => {
|
||||||
|
// xPct=10, yPct=5, widthPct=30, heightPct=5
|
||||||
|
// x = 612 * 0.10 = 61.2
|
||||||
|
// fieldH = 792 * 0.05 = 39.6
|
||||||
|
// screenY = 792 * 0.05 = 39.6
|
||||||
|
// y = 792 - 39.6 - 39.6 = 712.8
|
||||||
|
const result = aiCoordsToPagePdfSpace(
|
||||||
|
{
|
||||||
|
page: 1,
|
||||||
|
fieldType: 'text',
|
||||||
|
xPct: 10,
|
||||||
|
yPct: 5,
|
||||||
|
widthPct: 30,
|
||||||
|
heightPct: 5,
|
||||||
|
prefillValue: '',
|
||||||
|
},
|
||||||
|
US_LETTER_W,
|
||||||
|
US_LETTER_H,
|
||||||
|
);
|
||||||
|
expect(result.x).toBeCloseTo(61.2, 1);
|
||||||
|
expect(result.y).toBeCloseTo(712.8, 1);
|
||||||
|
expect(result.width).toBeCloseTo(183.6, 1);
|
||||||
|
expect(result.height).toBeCloseTo(39.6, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('checkbox near bottom-right', () => {
|
||||||
|
// xPct=90, yPct=95, widthPct=3, heightPct=3
|
||||||
|
// x = 612 * 0.90 = 550.8
|
||||||
|
// fieldH = 792 * 0.03 = 23.76
|
||||||
|
// screenY = 792 * 0.95 = 752.4
|
||||||
|
// y = 792 - 752.4 - 23.76 = 15.84
|
||||||
|
const result = aiCoordsToPagePdfSpace(
|
||||||
|
{
|
||||||
|
page: 1,
|
||||||
|
fieldType: 'checkbox',
|
||||||
|
xPct: 90,
|
||||||
|
yPct: 95,
|
||||||
|
widthPct: 3,
|
||||||
|
heightPct: 3,
|
||||||
|
prefillValue: '',
|
||||||
|
},
|
||||||
|
US_LETTER_W,
|
||||||
|
US_LETTER_H,
|
||||||
|
);
|
||||||
|
expect(result.x).toBeCloseTo(550.8, 1);
|
||||||
|
expect(result.y).toBeCloseTo(15.84, 1);
|
||||||
|
expect(result.width).toBeCloseTo(18.36, 1);
|
||||||
|
expect(result.height).toBeCloseTo(23.76, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('client-signature field at exact center', () => {
|
||||||
|
// xPct=50, yPct=50, widthPct=20, heightPct=5
|
||||||
|
// x = 612 * 0.50 = 306
|
||||||
|
// fieldH = 792 * 0.05 = 39.6
|
||||||
|
// screenY = 792 * 0.50 = 396
|
||||||
|
// y = 792 - 396 - 39.6 = 356.4
|
||||||
|
const result = aiCoordsToPagePdfSpace(
|
||||||
|
{
|
||||||
|
page: 1,
|
||||||
|
fieldType: 'client-signature',
|
||||||
|
xPct: 50,
|
||||||
|
yPct: 50,
|
||||||
|
widthPct: 20,
|
||||||
|
heightPct: 5,
|
||||||
|
prefillValue: '',
|
||||||
|
},
|
||||||
|
US_LETTER_W,
|
||||||
|
US_LETTER_H,
|
||||||
|
);
|
||||||
|
expect(result.x).toBeCloseTo(306, 1);
|
||||||
|
expect(result.y).toBeCloseTo(356.4, 1);
|
||||||
|
expect(result.width).toBeCloseTo(122.4, 1);
|
||||||
|
expect(result.height).toBeCloseTo(39.6, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user