Test-coverage expansion (2-agent reviewed, both SHIP). The named candidates
(roomToUnread, markedUnread, serverAcl, plaintextCaches, recent*) were already
tested, so this targets genuinely-untested pure logic.
- dom.test.ts: getThumbnailDimensions (scaling math incl. just-over-cap
boundaries), tryDecodeURIComponent, syntaxErrorPosition, and the three
scroll-view geometry helpers (via duck-typed element mocks — no jsdom).
- emoji.test.ts: getHexcodeForEmoji (astral codepoints, 4-digit zero-pad,
FE0F/FE0E/200D stripping on and off, keycap sequences, degenerate inputs)
and the pre-load `undefined` contract for getShortcode(s)For.
Fix (found while writing the tests): syntaxErrorPosition required whitespace
AFTER the digits (`/position\s(\d+)\s/`), but real V8/Node JSON.parse errors
put the number at end-of-string ("... at position N"), so it returned
undefined for every real error and the three dev-tools JSON editors silently
pointed their cursor at position 0. Dropped the trailing `\s`; tests now assert
extraction at end-of-string.
Gates: tsc 0, eslint 0, prettier clean, 891 tests, build ok.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
2.4 KiB
TypeScript
64 lines
2.4 KiB
TypeScript
import { describe, it } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { getHexcodeForEmoji, getShortcodeFor, getShortcodesFor } from './emoji';
|
|
|
|
describe('getHexcodeForEmoji', () => {
|
|
it('converts a single astral codepoint to an uppercase hexcode', () => {
|
|
// 😀 = U+1F600
|
|
assert.equal(getHexcodeForEmoji('😀'), '1F600');
|
|
});
|
|
|
|
it('zero-pads BMP codepoints to at least four hex digits', () => {
|
|
// ☺ = U+263A ; # = U+0023 (must pad "23" -> "0023")
|
|
assert.equal(getHexcodeForEmoji('☺'), '263A');
|
|
assert.equal(getHexcodeForEmoji('#'), '0023');
|
|
});
|
|
|
|
it('strips the FE0F variation selector by default', () => {
|
|
// ❤️ = U+2764 U+FE0F
|
|
assert.equal(getHexcodeForEmoji('❤️'), '2764');
|
|
});
|
|
|
|
it('keeps the variation selector when strip is false', () => {
|
|
assert.equal(getHexcodeForEmoji('❤️', false), '2764-FE0F');
|
|
});
|
|
|
|
it('strips ZWJ (200D) joiners from a sequence by default', () => {
|
|
// 👨👩👧 = 1F468 200D 1F469 200D 1F467
|
|
assert.equal(getHexcodeForEmoji('👨👩👧'), '1F468-1F469-1F467');
|
|
});
|
|
|
|
it('keeps ZWJ joiners when strip is false', () => {
|
|
assert.equal(getHexcodeForEmoji('👨👩👧', false), '1F468-200D-1F469-200D-1F467');
|
|
});
|
|
|
|
it('strips the FE0E text-presentation selector too', () => {
|
|
// ▶ = U+25B6 ; ▶︎ = U+25B6 U+FE0E (text presentation)
|
|
assert.equal(getHexcodeForEmoji('▶︎'), '25B6');
|
|
assert.equal(getHexcodeForEmoji('▶︎', false), '25B6-FE0E');
|
|
});
|
|
|
|
it('handles a keycap sequence (padding + selector strip together)', () => {
|
|
// #️⃣ = U+0023 U+FE0F U+20E3 -> "0023" + (FE0F stripped) + "20E3"
|
|
assert.equal(getHexcodeForEmoji('#️⃣'), '0023-20E3');
|
|
});
|
|
|
|
it('handles degenerate inputs (empty string, plain ASCII per codepoint)', () => {
|
|
assert.equal(getHexcodeForEmoji(''), '');
|
|
assert.equal(getHexcodeForEmoji('ab'), '0061-0062');
|
|
});
|
|
});
|
|
|
|
describe('getShortcodesFor / getShortcodeFor before emoji data is loaded', () => {
|
|
// These gracefully degrade to `undefined` until loadEmojiData() has populated
|
|
// the shortcode maps — the contract that lets tooltips/aria-labels render
|
|
// eagerly without pulling the emojibase runtime into the eager graph.
|
|
it('returns undefined for getShortcodesFor', () => {
|
|
assert.equal(getShortcodesFor('1F600'), undefined);
|
|
});
|
|
|
|
it('returns undefined for getShortcodeFor', () => {
|
|
assert.equal(getShortcodeFor('1F600'), undefined);
|
|
});
|
|
});
|