| 1 | // Run: tsx src/__tests__/composer-content-sizing.test.ts |
| 2 | |
| 3 | import { resolveComposerContentSizing } from "../lib/composerSizing"; |
| 4 | |
| 5 | let passed = 0; |
| 6 | let failed = 0; |
| 7 | |
| 8 | function eq(actual: unknown, expected: unknown, label: string) { |
| 9 | if (actual === expected) { |
| 10 | process.stdout.write(` PASS ${label}\n`); |
| 11 | passed += 1; |
| 12 | } else { |
| 13 | process.stdout.write(` FAIL ${label}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}\n`); |
| 14 | failed += 1; |
| 15 | } |
| 16 | } |
| 17 | |
| 18 | console.log("\ncomposer content sizing"); |
| 19 | |
| 20 | const automatic = resolveComposerContentSizing({ |
| 21 | contentHeight: 86, |
| 22 | manualLogicalHeight: null, |
| 23 | maxLogicalHeight: 360, |
| 24 | reservedHeight: 58, |
| 25 | }); |
| 26 | eq(automatic.inputHeight, 86, "automatic composer follows its content height"); |
| 27 | eq(automatic.logicalHeight, null, "automatic composer keeps natural card sizing"); |
| 28 | eq(automatic.overflow, false, "automatic composer stays overflow-free below the cap"); |
| 29 | |
| 30 | const shortManual = resolveComposerContentSizing({ |
| 31 | contentHeight: 22, |
| 32 | manualLogicalHeight: 128, |
| 33 | maxLogicalHeight: 360, |
| 34 | reservedHeight: 58, |
| 35 | }); |
| 36 | eq(shortManual.inputHeight, 70, "manual height remains the minimum input baseline"); |
| 37 | eq(shortManual.logicalHeight, 128, "short content does not shrink below the manual baseline"); |
| 38 | |
| 39 | const growingManual = resolveComposerContentSizing({ |
| 40 | contentHeight: 108, |
| 41 | manualLogicalHeight: 128, |
| 42 | maxLogicalHeight: 360, |
| 43 | reservedHeight: 58, |
| 44 | }); |
| 45 | eq(growingManual.inputHeight, 108, "content can grow beyond the manual input baseline"); |
| 46 | eq(growingManual.logicalHeight, 166, "manual composer grows to reveal the longer draft"); |
| 47 | eq(growingManual.overflow, false, "growing content remains visible before the cap"); |
| 48 | |
| 49 | const cappedManual = resolveComposerContentSizing({ |
| 50 | contentHeight: 420, |
| 51 | manualLogicalHeight: 128, |
| 52 | maxLogicalHeight: 360, |
| 53 | reservedHeight: 58, |
| 54 | }); |
| 55 | eq(cappedManual.inputHeight, 302, "manual composer input stops at the viewport-aware cap"); |
| 56 | eq(cappedManual.logicalHeight, 360, "manual composer card stops at the logical maximum"); |
| 57 | eq(cappedManual.overflow, true, "content scrolls internally only after reaching the cap"); |
| 58 | |
| 59 | const shrunkManual = resolveComposerContentSizing({ |
| 60 | contentHeight: 30, |
| 61 | manualLogicalHeight: 128, |
| 62 | maxLogicalHeight: 360, |
| 63 | reservedHeight: 58, |
| 64 | }); |
| 65 | eq(shrunkManual.logicalHeight, 128, "deleting content returns the composer to its manual baseline"); |
| 66 | |
| 67 | console.log(`\n${passed} passed, ${failed} failed`); |
| 68 | if (failed > 0) process.exit(1); |
| 69 |