CI / Build & Quality Checks (pull_request) Failing after 3m21s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Playwright smoke (e2e) (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 8s
Giphy and Tenor link previews forced every GIF into the same box — full card width, max 200px tall, object-fit: cover — whatever its shape: a square GIF lost half its height, a portrait one three quarters (only the middle band showed, so captions and faces at the top/bottom were cut), and a 100×80 GIF was blown up 4×. utils/gifPreviewSize.ts (unit-tested) fits the GIF inside 400×320 from og:image:width/height, keeping its aspect ratio and enlarging small GIFs at most 2×. The card centres the GIF on the surface colour with object-fit: contain, reserves the box before it loads, and the GIF badge sits on the GIF's corner. Without dimensions it shows at natural size, capped by the card. The >10 MB thumbnail fallback is requested at 2× the box (800×640) so it isn't upscaled. Verified headless (fixture previews, desktop / Pixel 7 / 320px phone): 480×200 → 398×166, 300×300 → 320×320 (292×292 on 320px), 240×480 → 160×320, 100×80 → 200×160, all 100% visible; the no-dimension fallback and narrow cards keep the ratio. tsc clean, 1325 unit tests pass, eslint 0 errors (36 warnings, unchanged), prettier clean. Fixes #341 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
37 lines
1.6 KiB
TypeScript
37 lines
1.6 KiB
TypeScript
import { test } from 'node:test';
|
||
import assert from 'node:assert/strict';
|
||
import { gifPreviewBox } from './gifPreviewSize';
|
||
|
||
test('gifPreviewBox: a landscape GIF wider than the card fills its width', () => {
|
||
assert.deepEqual(gifPreviewBox(480, 270), { width: 400, height: 225 });
|
||
assert.deepEqual(gifPreviewBox(480, 200), { width: 400, height: 167 });
|
||
});
|
||
|
||
test('gifPreviewBox: square and portrait GIFs keep their shape instead of being cropped', () => {
|
||
assert.deepEqual(gifPreviewBox(300, 300), { width: 320, height: 320 });
|
||
assert.deepEqual(gifPreviewBox(480, 480), { width: 320, height: 320 });
|
||
assert.deepEqual(gifPreviewBox(240, 480), { width: 160, height: 320 });
|
||
});
|
||
|
||
test('gifPreviewBox: a small GIF is enlarged at most 2×', () => {
|
||
assert.deepEqual(gifPreviewBox(100, 80), { width: 200, height: 160 });
|
||
assert.deepEqual(gifPreviewBox(150, 150), { width: 300, height: 300 });
|
||
});
|
||
|
||
test('gifPreviewBox: extreme aspect ratios stay inside the box and never collapse to 0', () => {
|
||
assert.deepEqual(gifPreviewBox(2000, 50), { width: 400, height: 10 });
|
||
assert.deepEqual(gifPreviewBox(1, 10000), { width: 1, height: 320 });
|
||
});
|
||
|
||
test('gifPreviewBox: accepts numeric strings and rejects unknown sizes', () => {
|
||
assert.deepEqual(gifPreviewBox('480', '270'), { width: 400, height: 225 });
|
||
assert.equal(gifPreviewBox(undefined, 270), undefined);
|
||
assert.equal(gifPreviewBox(480, 0), undefined);
|
||
assert.equal(gifPreviewBox('wide', 270), undefined);
|
||
assert.equal(gifPreviewBox(Number.NaN, 270), undefined);
|
||
});
|
||
|
||
test('gifPreviewBox: custom limits', () => {
|
||
assert.deepEqual(gifPreviewBox(480, 270, 200, 200, 1), { width: 200, height: 113 });
|
||
});
|