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
161 lines
9.7 KiB
TypeScript
161 lines
9.7 KiB
TypeScript
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([]);
|
||
});
|