Files
TREK/server/tests/unit/plugins/text-sanitize.test.ts
T
Maurice 724c88c201 style: format server and shared with prettier
A mechanical prettier --write over server/src, server/tests, server/scripts
and shared/src with the workspaces' .prettierrc; nothing but layout and
import order changes, and every file keeps the same set of imports. shared
is formatted throughout and its format baseline is empty. The server
baseline keeps the 35 files that Prettier would grow past their lint:size
limit (they need a split first, which is not a formatting change), and the
generated entity files stay as their generator writes them.
2026-10-10 21:23:37 +02:00

46 lines
2.1 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.
/**
* Emoji stripping at the render boundary — TREK renders plugin text with lucide icons,
* not emojis, so all natively-rendered plugin contributions + notifications are stripped.
*/
import { stripEmoji, hasEmoji } from '../../../src/nest/plugins/text-sanitize';
import { describe, it, expect } from 'vitest';
describe('stripEmoji', () => {
it('removes emojis and tidies the whitespace they leave behind', () => {
expect(stripEmoji('🔥 Hot deal')).toBe('Hot deal');
expect(stripEmoji('Price 💰 drop')).toBe('Price drop'); // collapses the double space
expect(stripEmoji('🎉🎊✨')).toBe(''); // all-emoji → empty
expect(stripEmoji('Trip to Japan 🇯🇵')).toBe('Trip to Japan'); // flag (regional indicators)
expect(stripEmoji('Done ✅️')).toBe('Done'); // variation selector
expect(stripEmoji('family 👨‍👩‍👧 outing')).toBe('family outing'); // ZWJ sequence, no stray glue
});
it('leaves plain text (incl. accents / CJK / punctuation) untouched', () => {
expect(stripEmoji('Zürich – 3 nights')).toBe('Zürich – 3 nights');
expect(stripEmoji('東京')).toBe('東京');
expect(stripEmoji('A, B & C (1/2)')).toBe('A, B & C (1/2)');
});
it('keeps legitimate text symbols a plugin might render', () => {
expect(stripEmoji('★★★☆☆')).toBe('★★★☆☆'); // rating stars
expect(stripEmoji('© 2026 Acme')).toBe('© 2026 Acme'); // copyright
expect(stripEmoji('Acme®')).toBe('Acme®');
expect(stripEmoji('Product™ GmbH')).toBe('Product™ GmbH');
});
it('strips a skin-tone modifier so no orphan swatch is left behind', () => {
expect(stripEmoji('👋🏻 hi')).toBe('hi');
});
it('keeps newlines/paragraphs — verbatim when nothing is stripped, and when it strips', () => {
expect(stripEmoji('Para1\n\nPara2')).toBe('Para1\n\nPara2'); // untouched
expect(stripEmoji('A 🔥\n\nB')).toBe('A\n\nB'); // only the horizontal gap closes
});
it('hasEmoji detects at least one emoji', () => {
expect(hasEmoji('plain')).toBe(false);
expect(hasEmoji('has 🚀')).toBe(true);
});
});