Files
upstream-mirror 30810eecd7
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:21:02 +05:00

161 lines
9.7 KiB
TypeScript
Raw Permalink 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.
import { parse } from '../src';
import { ALL_EMOJI, EMOJIBASE_VERSION } from './fixtures/allEmoji';
import { emoji, bigEmoji, paragraph, plain, emojiUnicode } from './helpers';
test.each([
[':smile: asd', [paragraph([emoji('smile'), plain(' asd')])]],
[':smile:asd', [paragraph([plain(':smile:asd')])]],
['text:inner:outer', [paragraph([plain('text:inner:outer')])]],
['10:20:30', [paragraph([plain('10:20:30')])]],
['10:20:30:', [paragraph([plain('10:20:30:')])]],
['":smile:"', [paragraph([plain('":smile:"')])]],
['":smile: "', [paragraph([plain('":smile: "')])]],
['" :smile: "', [paragraph([plain('" '), emoji('smile'), plain(' "')])]],
[
`:smile:
:smile:
`,
[bigEmoji([emoji('smile'), emoji('smile')])],
],
['asdas :smile: asd', [paragraph([plain('asdas '), emoji('smile'), plain(' asd')])]],
[
'normal emojis :smile: :smile: :smile:',
[paragraph([plain('normal emojis '), emoji('smile'), plain(' '), emoji('smile'), plain(' '), emoji('smile')])],
],
[':smile::smile::smile:', [bigEmoji([emoji('smile'), emoji('smile'), emoji('smile')])]],
[' :smile::smile::smile: ', [bigEmoji([emoji('smile'), emoji('smile'), emoji('smile')])]],
['\n :smile::smile::smile: \n', [bigEmoji([emoji('smile'), emoji('smile'), emoji('smile')])]],
[':smile: :smile: :smile:', [bigEmoji([emoji('smile'), emoji('smile'), emoji('smile')])]],
[':smile::smile:', [bigEmoji([emoji('smile'), emoji('smile')])]],
[':smile:a:smile:', [paragraph([plain(':smile:a:smile:')])]],
[':smile:', [bigEmoji([emoji('smile')])]],
['Hi :+1:', [paragraph([plain('Hi '), emoji('+1')])]],
['Hi :+1_tone4:', [paragraph([plain('Hi '), emoji('+1_tone4')])]],
['Hi :thumbsup_tone3:', [paragraph([plain('Hi '), emoji('thumbsup_tone3')])]],
['Hi :yes_tone3:', [paragraph([plain('Hi '), emoji('yes_tone3')])]],
['Hi :clapping_hands_tone2:', [paragraph([plain('Hi '), emoji('clapping_hands_tone2')])]],
['Hi :pray_tone4:', [paragraph([plain('Hi '), emoji('pray_tone4')])]],
['Hi :regional_indicator_a:', [paragraph([plain('Hi '), emoji('regional_indicator_a')])]],
['Hi :digit_zero:', [paragraph([plain('Hi '), emoji('digit_zero')])]],
['Hi :pound_symbol:', [paragraph([plain('Hi '), emoji('pound_symbol')])]],
['Hi :asterisk_symbol:', [paragraph([plain('Hi '), emoji('asterisk_symbol')])]],
['Hi :tone3:', [paragraph([plain('Hi '), emoji('tone3')])]],
[':thumbsup_tone3:', [bigEmoji([emoji('thumbsup_tone3')])]],
[':regional_indicator_a:', [bigEmoji([emoji('regional_indicator_a')])]],
[':digit_zero:', [bigEmoji([emoji('digit_zero')])]],
])('parses %p', (input, output) => {
expect(parse(input)).toEqual(output);
});
// Tests for unicode emojis
test.each([
['😀', [bigEmoji([emojiUnicode('😀')])]],
['😃', [bigEmoji([emojiUnicode('😃')])]],
['🥵', [bigEmoji([emojiUnicode('🥵')])]],
['🧿', [bigEmoji([emojiUnicode('🧿')])]],
['🐶', [bigEmoji([emojiUnicode('🐶')])]],
['🍏', [bigEmoji([emojiUnicode('🍏')])]],
['⚽', [bigEmoji([emojiUnicode('⚽')])]],
['⚽️', [bigEmoji([emojiUnicode('⚽️')])]],
['👨‍👩‍👧‍👦', [bigEmoji([emojiUnicode('👨‍👩‍👧‍👦')])]],
['🚗', [bigEmoji([emojiUnicode('🚗')])]],
['⌚️', [bigEmoji([emojiUnicode('⌚️')])]],
['❤️', [bigEmoji([emojiUnicode('❤️')])]],
['🏳️', [bigEmoji([emojiUnicode('🏳️')])]],
['🧑🏾‍💻', [bigEmoji([emojiUnicode('🧑🏾‍💻')])]],
['🧑🏾‍💻🧑🏾‍💻', [bigEmoji([emojiUnicode('🧑🏾‍💻'), emojiUnicode('🧑🏾‍💻')])]],
['🧑🏾‍💻🧑🏾‍💻🧑🏾‍💻', [bigEmoji([emojiUnicode('🧑🏾‍💻'), emojiUnicode('🧑🏾‍💻'), emojiUnicode('🧑🏾‍💻')])]],
['👆🏽', [bigEmoji([emojiUnicode('👆🏽')])]],
['👆🏽👆🏽', [bigEmoji([emojiUnicode('👆🏽'), emojiUnicode('👆🏽')])]],
['👆🏽👆🏽👆🏽', [bigEmoji([emojiUnicode('👆🏽'), emojiUnicode('👆🏽'), emojiUnicode('👆🏽')])]],
['👆🏺', [bigEmoji([emojiUnicode('👆'), emojiUnicode('🏺')])]],
['✋🏽', [bigEmoji([emojiUnicode('✋🏽')])]],
['✌🏽', [bigEmoji([emojiUnicode('✌🏽')])]],
['✍🏽', [bigEmoji([emojiUnicode('✍🏽')])]],
['☝🏽', [bigEmoji([emojiUnicode('☝🏽')])]],
['⛹🏽', [bigEmoji([emojiUnicode('⛹🏽')])]],
['✋🏽✌🏽', [bigEmoji([emojiUnicode('✋🏽'), emojiUnicode('✌🏽')])]],
['✋🏺', [bigEmoji([emojiUnicode('✋'), emojiUnicode('🏺')])]],
['Hi ✋🏽', [paragraph([plain('Hi '), emojiUnicode('✋🏽')])]],
['Hi 👍', [paragraph([plain('Hi '), emojiUnicode('👍')])]],
// Symbols and Pictographs Extended-A (U+1FA00–U+1FAFF) — Unicode 13+/14+
['🫠', [bigEmoji([emojiUnicode('🫠')])]],
['🫡', [bigEmoji([emojiUnicode('🫡')])]],
['🫶', [bigEmoji([emojiUnicode('🫶')])]],
['Hi 🫠', [paragraph([plain('Hi '), emojiUnicode('🫠')])]],
// ZWJ sequences involving Dingbats (❤️ U+2764) — couple/kiss emojis
['👨‍❤️‍💋‍👨', [bigEmoji([emojiUnicode('👨‍❤️‍💋‍👨')])]],
['👩‍❤️‍💋‍👩', [bigEmoji([emojiUnicode('👩‍❤️‍💋‍👩')])]],
['👨‍❤️‍👨', [bigEmoji([emojiUnicode('👨‍❤️‍👨')])]],
['💑', [bigEmoji([emojiUnicode('💑')])]],
['Hi 👨‍❤️‍💋‍👨', [paragraph([plain('Hi '), emojiUnicode('👨‍❤️‍💋‍👨')])]],
// ZWJ sequences involving Misc Symbols (⚕️, ⚖️, ✈️) — profession emojis
['👨‍⚕️', [bigEmoji([emojiUnicode('👨‍⚕️')])]],
['👩‍⚖️', [bigEmoji([emojiUnicode('👩‍⚖️')])]],
['👨‍✈️', [bigEmoji([emojiUnicode('👨‍✈️')])]],
['🩷', [bigEmoji([emojiUnicode('🩷')])]], // v15
['🫱🏿‍🫲🏻', [bigEmoji([emojiUnicode('🫱🏿‍🫲🏻')])]], // v14
['🫩', [bigEmoji([emojiUnicode('🫩')])]], // v16
['🇨🇶', [bigEmoji([emojiUnicode('🇨🇶')])]], // v16
// ZWJ sequences anchored by an Emoticon (U+1F600-U+1F64F)
['😶‍🌫️', [bigEmoji([emojiUnicode('😶‍🌫️')])]],
['😮‍💨', [bigEmoji([emojiUnicode('😮‍💨')])]],
['😵‍💫', [bigEmoji([emojiUnicode('😵‍💫')])]],
['Hi 😶‍🌫️', [paragraph([plain('Hi '), emojiUnicode('😶‍🌫️')])]],
['😶‍🌫️😮‍💨', [bigEmoji([emojiUnicode('😶‍🌫️'), emojiUnicode('😮‍💨')])]],
['🙋🏽‍♂️', [bigEmoji([emojiUnicode('🙋🏽‍♂️')])]],
['😀', [bigEmoji([emojiUnicode('😀')])]], // standalone emoticon still matches
// Emoji tag sequences — England/Scotland/Wales flags
['🏴󠁧󠁢󠁥󠁮󠁧󠁿', [bigEmoji([emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿')])]],
['🏴󠁧󠁢󠁳󠁣󠁴󠁿', [bigEmoji([emojiUnicode('🏴󠁧󠁢󠁳󠁣󠁴󠁿')])]],
['🏴󠁧󠁢󠁷󠁬󠁳󠁿', [bigEmoji([emojiUnicode('🏴󠁧󠁢󠁷󠁬󠁳󠁿')])]],
['Hi 🏴󠁧󠁢󠁥󠁮󠁧󠁿', [paragraph([plain('Hi '), emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿')])]],
['🏴', [bigEmoji([emojiUnicode('🏴')])]], // standalone black flag still matches
['🏴‍☠️', [bigEmoji([emojiUnicode('🏴‍☠️')])]], // pirate flag (ZWJ, not tag sequence) still matches
// Consecutive sequence emojis — each sequence must be consumed whole, without stealing from its neighbor
['🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴󠁧󠁢󠁳󠁣󠁴󠁿🏴󠁧󠁢󠁷󠁬󠁳󠁿', [bigEmoji([emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿'), emojiUnicode('🏴󠁧󠁢󠁳󠁣󠁴󠁿'), emojiUnicode('🏴󠁧󠁢󠁷󠁬󠁳󠁿')])]],
['🏴🏴󠁧󠁢󠁥󠁮󠁧󠁿', [bigEmoji([emojiUnicode('🏴'), emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿')])]],
['🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴', [bigEmoji([emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿'), emojiUnicode('🏴')])]],
['😶‍🌫️😮‍💨😵‍💫', [bigEmoji([emojiUnicode('😶‍🌫️'), emojiUnicode('😮‍💨'), emojiUnicode('😵‍💫')])]],
['😀😶‍🌫️', [bigEmoji([emojiUnicode('😀'), emojiUnicode('😶‍🌫️')])]],
['😶‍🌫️🏴󠁧󠁢󠁥󠁮󠁧󠁿🏴‍☠️', [bigEmoji([emojiUnicode('😶‍🌫️'), emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿'), emojiUnicode('🏴‍☠️')])]],
// More than 3 emojis: no BigEmoji, plain paragraph of emoji tokens
['😶‍🌫️😮‍💨😵‍💫👍', [paragraph([emojiUnicode('😶‍🌫️'), emojiUnicode('😮‍💨'), emojiUnicode('😵‍💫'), emojiUnicode('👍')])]],
['England 🏴󠁧󠁢󠁥󠁮󠁧󠁿 and Scotland 🏴󠁧󠁢󠁳󠁣󠁴󠁿', [paragraph([plain('England '), emojiUnicode('🏴󠁧󠁢󠁥󠁮󠁧󠁿'), plain(' and Scotland '), emojiUnicode('🏴󠁧󠁢󠁳󠁣󠁴󠁿')])]],
])('parses %p', (input, output) => {
expect(parse(input)).toEqual(output);
});
// KNOWN_UNSUPPORTED: the 26 regional indicators. Alone they're just letters, not emojis; combined
// in a pair they form a flag (🇺 + 🇸 = 🇺🇸). Real letter emojis (🅰️ Ⓜ️) are supported. Stale check
// below keeps the list honest.
// prettier-ignore
const KNOWN_UNSUPPORTED = new Set('🇦 🇧 🇨 🇩 🇪 🇫 🇬 🇭 🇮 🇯 🇰 🇱 🇲 🇳 🇴 🇵 🇶 🇷 🇸 🇹 🇺 🇻 🇼 🇽 🇾 🇿'.split(' '));
function parsesWhole(input: string): boolean {
const nodes = parse(input);
if (!Array.isArray(nodes) || nodes.length !== 1) {
return false;
}
const [node] = nodes;
if (node.type !== 'BIG_EMOJI' || node.value.length !== 1) {
return false;
}
const [child] = node.value;
if (child.type !== 'EMOJI' || !('unicode' in child)) {
return false;
}
return child.unicode === input;
}
test(`every emoji parses as one token, except documented components (emojibase@${EMOJIBASE_VERSION})`, () => {
expect(ALL_EMOJI.length).toBeGreaterThan(3000);
const inFixture = new Set(ALL_EMOJI);
expect(ALL_EMOJI.filter((e) => !KNOWN_UNSUPPORTED.has(e) && !parsesWhole(e))).toEqual([]);
expect([...KNOWN_UNSUPPORTED].filter((e) => !inFixture.has(e) || parsesWhole(e))).toEqual([]);
});