5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 1 | import assert from 'node:assert/strict'; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 2 | import { test } from 'node:test'; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 3 | import { enabledQuickReactions } from '../src/lib/pack-preferences-model.ts'; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 4 | import { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 5 | isSeparator, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 6 | normaliseQuick, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 7 | parseQuickReactions, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 8 | quickColumns, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 9 | quickGroups, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 10 | sameQuick |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 11 | } from '../src/lib/quick-reactions-model.ts'; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 12 | import type { QuickEntry } from '../src/lib/types.ts'; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 13 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 14 | const r = (key: string): QuickEntry => ({ key, shortcode: null }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 15 | const sep = (): QuickEntry => ({ separator: true }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 16 | const shape = (list: QuickEntry[]) => list.map((e) => (isSeparator(e) ? '|' : e.key)).join(' '); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 17 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 18 | test('normalising drops leading, trailing and doubled separators', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 19 | assert.equal(shape(normaliseQuick([sep(), r('a'), sep(), sep(), r('b'), sep()])), 'a | b'); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 20 | assert.equal(shape(normaliseQuick([sep(), sep()])), ''); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 21 | assert.equal(shape(normaliseQuick([])), ''); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 22 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 23 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 24 | test('normalising dedupes keys and keeps the break between survivors', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 25 | assert.equal(shape(normaliseQuick([r('a'), sep(), r('a'), sep(), r('b')])), 'a | b'); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 26 | assert.equal(shape(normaliseQuick([r('a'), r('b'), sep(), r('a'), sep(), r('c')])), 'a b | c'); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 27 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 28 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 29 | test('normalising keeps separator identity and leaves the input alone', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 30 | const middle = sep(); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 31 | const input = [r('a'), middle, r('b'), sep()]; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 32 | const out = normaliseQuick(input); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 33 | assert.equal(out[1], middle); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 34 | assert.equal(input.length, 4); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 35 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 36 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 37 | test('parsing keeps separators and tolerates what older builds wrote', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 38 | const parsed = parseQuickReactions({ |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 39 | reactions: [{ key: 'a', shortcode: 'x' }, { separator: true }, { key: 'b' }, 7, null, { key: '' }, { key: 'a' }, { separator: true }] |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 40 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 41 | assert.deepEqual(parsed, [{ key: 'a', shortcode: 'x' }, { separator: true }, { key: 'b', shortcode: null }]); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 42 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 43 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 44 | test('parsing rejects data without a reactions list', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 45 | assert.equal(parseQuickReactions(null), null); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 46 | assert.equal(parseQuickReactions({ reactions: 'a' }), null); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 47 | assert.equal(parseQuickReactions('a'), null); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 48 | assert.deepEqual(parseQuickReactions({ reactions: [] }), []); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 49 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 50 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 51 | test('only a literal true makes a separator', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 52 | assert.deepEqual(parseQuickReactions({ reactions: [{ separator: 'yes' }, { separator: false, key: 'a' }] }), [{ key: 'a', shortcode: null }]); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 53 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 54 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 55 | test('groups split at separators and skip empty runs', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 56 | const groups = quickGroups([r('a'), r('b'), sep(), sep(), r('c'), sep()]); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 57 | assert.deepEqual(groups.map((g) => g.map((e) => e.key)), [['a', 'b'], ['c']]); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 58 | assert.deepEqual(quickGroups([]), []); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 59 | assert.deepEqual(quickGroups([sep()]), []); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 60 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 61 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 62 | test('the toolbar is as wide as its widest group up to the row limit', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 63 | const groups = quickGroups([r('a'), r('b'), r('c'), sep(), r('d')]); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 64 | assert.equal(quickColumns(groups, 8), 3); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 65 | assert.equal(quickColumns(groups, 2), 2); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 66 | assert.equal(quickColumns([], 8), 0); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 67 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 68 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 69 | test('comparison looks at order, keys and separator positions', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 70 | assert.ok(sameQuick([r('a'), sep(), r('b')], [r('a'), sep(), r('b')])); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 71 | assert.ok(!sameQuick([r('a'), sep(), r('b')], [r('a'), r('b')])); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 72 | assert.ok(!sameQuick([r('a'), r('b')], [r('b'), r('a')])); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 73 | assert.ok(!sameQuick([sep()], [r('a')])); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 74 | }); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 75 | |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 76 | test('a hidden pack image leaves no empty group or doubled break', () => { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 77 | const pack = { |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 78 | id: 'p', |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 79 | display_name: null, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 80 | avatar: null, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 81 | attribution: 'source', |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 82 | source: 'User' as const, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 83 | images: [{ shortcode: 'one', media_id: 'mxc://x/one', reaction_key: 'mxc://x/one', body: null, mimetype: null, width: null, height: null, usage: ['Emoticon' as const] }], |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 84 | editable: true, |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 85 | enabled_everywhere: false |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 86 | }; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 87 | const list = [r('a'), sep(), r('mxc://x/one'), sep(), r('b')]; |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 88 | const visible = normaliseQuick(enabledQuickReactions(list, [pack], { p: ['one'] })); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 89 | assert.equal(shape(visible), 'a | b'); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 90 | assert.equal(shape(normaliseQuick(enabledQuickReactions([r('mxc://x/one'), sep(), r('a')], [pack], { p: ['one'] }))), 'a'); |
5059ed753f8b | atagen | 2026-10-27 07:20 UTC | 91 | }); |