Files
cinny/src/app/plugins/recent-emoji.test.ts
T

118 lines
3.7 KiB
TypeScript
Raw Normal View History

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { MatrixClient, MatrixEvent } from 'matrix-js-sdk';
import { addRecentEmoji, getRecentEmojis, IRecentEmojiContent } from './recent-emoji';
import { AccountDataEvent } from '../../types/matrix/accountData';
import { emojis, loadEmojiData } from './emoji';
// A Map-backed MatrixClient stub supporting get/setAccountData.
const createMx = () => {
const store = new Map<string, unknown>();
const mx = {
getAccountData: (type: string): MatrixEvent | undefined => {
if (!store.has(type)) return undefined;
const content = store.get(type);
return { getContent: () => content } as unknown as MatrixEvent;
},
setAccountData: (type: string, content: unknown) => {
store.set(type, content);
return Promise.resolve({});
},
};
return { mx: mx as unknown as MatrixClient, store };
};
const getStored = (store: Map<string, unknown>): IRecentEmojiContent['recent_emoji'] =>
(store.get(AccountDataEvent.ElementRecentEmoji) as IRecentEmojiContent | undefined)?.recent_emoji;
// Emoji data is now loaded lazily; populate `emojis` before the round trips.
await loadEmojiData();
// Pick two real unicode emojis to drive add->get round trips.
const u1 = emojis[0].unicode;
const u2 = emojis[1].unicode;
test('getRecentEmojis returns [] when there is no account data', () => {
const { mx } = createMx();
assert.deepEqual(getRecentEmojis(mx), []);
});
test('getRecentEmojis returns [] when content is not an array', () => {
const { mx, store } = createMx();
store.set(AccountDataEvent.ElementRecentEmoji, { recent_emoji: 'nope' });
assert.deepEqual(getRecentEmojis(mx), []);
});
test('addRecentEmoji creates an entry with count 1', () => {
const { mx, store } = createMx();
addRecentEmoji(mx, u1);
assert.deepEqual(getStored(store), [[u1, 1]]);
});
test('adding the same emoji again increments its count and keeps it at front', () => {
const { mx, store } = createMx();
addRecentEmoji(mx, u1);
addRecentEmoji(mx, u1);
assert.deepEqual(getStored(store), [[u1, 2]]);
});
test('a newly added emoji is promoted to the front', () => {
const { mx, store } = createMx();
addRecentEmoji(mx, u1);
addRecentEmoji(mx, u2);
assert.deepEqual(getStored(store), [
[u2, 1],
[u1, 1],
]);
});
test('re-adding an existing emoji promotes it to front and increments', () => {
const { mx, store } = createMx();
addRecentEmoji(mx, u1);
addRecentEmoji(mx, u2);
addRecentEmoji(mx, u1);
assert.deepEqual(getStored(store), [
[u1, 2],
[u2, 1],
]);
});
test('list is capped at 100 entries', () => {
const { mx, store } = createMx();
for (let i = 0; i < 120; i += 1) {
addRecentEmoji(mx, `:emoji-${i}:`);
}
const stored = getStored(store)!;
assert.equal(stored.length, 100);
// most recently added is at the front
assert.equal(stored[0][0], ':emoji-119:');
});
test('getRecentEmojis resolves stored unicodes to known emoji objects', () => {
const { mx } = createMx();
addRecentEmoji(mx, u1);
addRecentEmoji(mx, u2);
const recent = getRecentEmojis(mx);
assert.equal(recent.length, 2);
assert.equal(recent[0].unicode, u2);
assert.equal(recent[1].unicode, u1);
});
test('getRecentEmojis skips unicodes with no matching emoji definition', () => {
const { mx } = createMx();
addRecentEmoji(mx, ':not-a-real-emoji:');
addRecentEmoji(mx, u1);
const recent = getRecentEmojis(mx);
assert.equal(recent.length, 1);
assert.equal(recent[0].unicode, u1);
});
test('getRecentEmojis respects the limit argument (slice before resolve)', () => {
const { mx } = createMx();
addRecentEmoji(mx, u1);
addRecentEmoji(mx, u2);
const recent = getRecentEmojis(mx, 1);
assert.equal(recent.length, 1);
assert.equal(recent[0].unicode, u2);
});