atagen

malice

public
Star0
Watch0
e590609b63434b8b595b383f8124dea45191bd6e
2
ssh://brewery@pls.lobotomise.me:33/atagen/malice.git

Blame: web/test/quick-reactions.test.ts

5059ed753f8batagen2026-10-27 07:20 UTC1
import assert from 'node:assert/strict';
5059ed753f8batagen2026-10-27 07:20 UTC2
import { test } from 'node:test';
5059ed753f8batagen2026-10-27 07:20 UTC3
import { enabledQuickReactions } from '../src/lib/pack-preferences-model.ts';
5059ed753f8batagen2026-10-27 07:20 UTC4
import {
5059ed753f8batagen2026-10-27 07:20 UTC5
  isSeparator,
5059ed753f8batagen2026-10-27 07:20 UTC6
  normaliseQuick,
5059ed753f8batagen2026-10-27 07:20 UTC7
  parseQuickReactions,
5059ed753f8batagen2026-10-27 07:20 UTC8
  quickColumns,
5059ed753f8batagen2026-10-27 07:20 UTC9
  quickGroups,
5059ed753f8batagen2026-10-27 07:20 UTC10
  sameQuick
5059ed753f8batagen2026-10-27 07:20 UTC11
} from '../src/lib/quick-reactions-model.ts';
5059ed753f8batagen2026-10-27 07:20 UTC12
import type { QuickEntry } from '../src/lib/types.ts';
5059ed753f8batagen2026-10-27 07:20 UTC13
5059ed753f8batagen2026-10-27 07:20 UTC14
const r = (key: string): QuickEntry => ({ key, shortcode: null });
5059ed753f8batagen2026-10-27 07:20 UTC15
const sep = (): QuickEntry => ({ separator: true });
5059ed753f8batagen2026-10-27 07:20 UTC16
const shape = (list: QuickEntry[]) => list.map((e) => (isSeparator(e) ? '|' : e.key)).join(' ');
5059ed753f8batagen2026-10-27 07:20 UTC17
5059ed753f8batagen2026-10-27 07:20 UTC18
test('normalising drops leading, trailing and doubled separators', () => {
5059ed753f8batagen2026-10-27 07:20 UTC19
  assert.equal(shape(normaliseQuick([sep(), r('a'), sep(), sep(), r('b'), sep()])), 'a | b');
5059ed753f8batagen2026-10-27 07:20 UTC20
  assert.equal(shape(normaliseQuick([sep(), sep()])), '');
5059ed753f8batagen2026-10-27 07:20 UTC21
  assert.equal(shape(normaliseQuick([])), '');
5059ed753f8batagen2026-10-27 07:20 UTC22
});
5059ed753f8batagen2026-10-27 07:20 UTC23
5059ed753f8batagen2026-10-27 07:20 UTC24
test('normalising dedupes keys and keeps the break between survivors', () => {
5059ed753f8batagen2026-10-27 07:20 UTC25
  assert.equal(shape(normaliseQuick([r('a'), sep(), r('a'), sep(), r('b')])), 'a | b');
5059ed753f8batagen2026-10-27 07:20 UTC26
  assert.equal(shape(normaliseQuick([r('a'), r('b'), sep(), r('a'), sep(), r('c')])), 'a b | c');
5059ed753f8batagen2026-10-27 07:20 UTC27
});
5059ed753f8batagen2026-10-27 07:20 UTC28
5059ed753f8batagen2026-10-27 07:20 UTC29
test('normalising keeps separator identity and leaves the input alone', () => {
5059ed753f8batagen2026-10-27 07:20 UTC30
  const middle = sep();
5059ed753f8batagen2026-10-27 07:20 UTC31
  const input = [r('a'), middle, r('b'), sep()];
5059ed753f8batagen2026-10-27 07:20 UTC32
  const out = normaliseQuick(input);
5059ed753f8batagen2026-10-27 07:20 UTC33
  assert.equal(out[1], middle);
5059ed753f8batagen2026-10-27 07:20 UTC34
  assert.equal(input.length, 4);
5059ed753f8batagen2026-10-27 07:20 UTC35
});
5059ed753f8batagen2026-10-27 07:20 UTC36
5059ed753f8batagen2026-10-27 07:20 UTC37
test('parsing keeps separators and tolerates what older builds wrote', () => {
5059ed753f8batagen2026-10-27 07:20 UTC38
  const parsed = parseQuickReactions({
5059ed753f8batagen2026-10-27 07:20 UTC39
    reactions: [{ key: 'a', shortcode: 'x' }, { separator: true }, { key: 'b' }, 7, null, { key: '' }, { key: 'a' }, { separator: true }]
5059ed753f8batagen2026-10-27 07:20 UTC40
  });
5059ed753f8batagen2026-10-27 07:20 UTC41
  assert.deepEqual(parsed, [{ key: 'a', shortcode: 'x' }, { separator: true }, { key: 'b', shortcode: null }]);
5059ed753f8batagen2026-10-27 07:20 UTC42
});
5059ed753f8batagen2026-10-27 07:20 UTC43
5059ed753f8batagen2026-10-27 07:20 UTC44
test('parsing rejects data without a reactions list', () => {
5059ed753f8batagen2026-10-27 07:20 UTC45
  assert.equal(parseQuickReactions(null), null);
5059ed753f8batagen2026-10-27 07:20 UTC46
  assert.equal(parseQuickReactions({ reactions: 'a' }), null);
5059ed753f8batagen2026-10-27 07:20 UTC47
  assert.equal(parseQuickReactions('a'), null);
5059ed753f8batagen2026-10-27 07:20 UTC48
  assert.deepEqual(parseQuickReactions({ reactions: [] }), []);
5059ed753f8batagen2026-10-27 07:20 UTC49
});
5059ed753f8batagen2026-10-27 07:20 UTC50
5059ed753f8batagen2026-10-27 07:20 UTC51
test('only a literal true makes a separator', () => {
5059ed753f8batagen2026-10-27 07:20 UTC52
  assert.deepEqual(parseQuickReactions({ reactions: [{ separator: 'yes' }, { separator: false, key: 'a' }] }), [{ key: 'a', shortcode: null }]);
5059ed753f8batagen2026-10-27 07:20 UTC53
});
5059ed753f8batagen2026-10-27 07:20 UTC54
5059ed753f8batagen2026-10-27 07:20 UTC55
test('groups split at separators and skip empty runs', () => {
5059ed753f8batagen2026-10-27 07:20 UTC56
  const groups = quickGroups([r('a'), r('b'), sep(), sep(), r('c'), sep()]);
5059ed753f8batagen2026-10-27 07:20 UTC57
  assert.deepEqual(groups.map((g) => g.map((e) => e.key)), [['a', 'b'], ['c']]);
5059ed753f8batagen2026-10-27 07:20 UTC58
  assert.deepEqual(quickGroups([]), []);
5059ed753f8batagen2026-10-27 07:20 UTC59
  assert.deepEqual(quickGroups([sep()]), []);
5059ed753f8batagen2026-10-27 07:20 UTC60
});
5059ed753f8batagen2026-10-27 07:20 UTC61
5059ed753f8batagen2026-10-27 07:20 UTC62
test('the toolbar is as wide as its widest group up to the row limit', () => {
5059ed753f8batagen2026-10-27 07:20 UTC63
  const groups = quickGroups([r('a'), r('b'), r('c'), sep(), r('d')]);
5059ed753f8batagen2026-10-27 07:20 UTC64
  assert.equal(quickColumns(groups, 8), 3);
5059ed753f8batagen2026-10-27 07:20 UTC65
  assert.equal(quickColumns(groups, 2), 2);
5059ed753f8batagen2026-10-27 07:20 UTC66
  assert.equal(quickColumns([], 8), 0);
5059ed753f8batagen2026-10-27 07:20 UTC67
});
5059ed753f8batagen2026-10-27 07:20 UTC68
5059ed753f8batagen2026-10-27 07:20 UTC69
test('comparison looks at order, keys and separator positions', () => {
5059ed753f8batagen2026-10-27 07:20 UTC70
  assert.ok(sameQuick([r('a'), sep(), r('b')], [r('a'), sep(), r('b')]));
5059ed753f8batagen2026-10-27 07:20 UTC71
  assert.ok(!sameQuick([r('a'), sep(), r('b')], [r('a'), r('b')]));
5059ed753f8batagen2026-10-27 07:20 UTC72
  assert.ok(!sameQuick([r('a'), r('b')], [r('b'), r('a')]));
5059ed753f8batagen2026-10-27 07:20 UTC73
  assert.ok(!sameQuick([sep()], [r('a')]));
5059ed753f8batagen2026-10-27 07:20 UTC74
});
5059ed753f8batagen2026-10-27 07:20 UTC75
5059ed753f8batagen2026-10-27 07:20 UTC76
test('a hidden pack image leaves no empty group or doubled break', () => {
5059ed753f8batagen2026-10-27 07:20 UTC77
  const pack = {
5059ed753f8batagen2026-10-27 07:20 UTC78
    id: 'p',
5059ed753f8batagen2026-10-27 07:20 UTC79
    display_name: null,
5059ed753f8batagen2026-10-27 07:20 UTC80
    avatar: null,
5059ed753f8batagen2026-10-27 07:20 UTC81
    attribution: 'source',
5059ed753f8batagen2026-10-27 07:20 UTC82
    source: 'User' as const,
5059ed753f8batagen2026-10-27 07:20 UTC83
    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] }],
5059ed753f8batagen2026-10-27 07:20 UTC84
    editable: true,
5059ed753f8batagen2026-10-27 07:20 UTC85
    enabled_everywhere: false
5059ed753f8batagen2026-10-27 07:20 UTC86
  };
5059ed753f8batagen2026-10-27 07:20 UTC87
  const list = [r('a'), sep(), r('mxc://x/one'), sep(), r('b')];
5059ed753f8batagen2026-10-27 07:20 UTC88
  const visible = normaliseQuick(enabledQuickReactions(list, [pack], { p: ['one'] }));
5059ed753f8batagen2026-10-27 07:20 UTC89
  assert.equal(shape(visible), 'a | b');
5059ed753f8batagen2026-10-27 07:20 UTC90
  assert.equal(shape(normaliseQuick(enabledQuickReactions([r('mxc://x/one'), sep(), r('a')], [pack], { p: ['one'] }))), 'a');
5059ed753f8batagen2026-10-27 07:20 UTC91
});