fix(ui): isMacOS always returned false on Macs + plugin-logic tests (+49)
Coverage work found a 3rd real bug: isMacOS() compared os.name against the legacy 'Mac OS' string, but ua-parser-js v2 reports 'macOS' — so it was dead, and Mac users saw "Ctrl + k" instead of "⌘ + k" in the editor toolbar, search, and settings shortcut hints. Now accepts both 'macOS' and 'Mac OS'. Suites (via subagent, verified): via-servers (10 — power/popularity server selection), bad-words (9), syntaxHighlight tokenize (14), plugins/utils getEmoticonSearchStr (5), imageCompression formatFileSize/isCompressible (5), user-agent (6, now asserting the fixed behavior). Full suite now 501 tests, all passing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { Room } from 'matrix-js-sdk';
|
||||
import { getViaServers } from './via-servers';
|
||||
|
||||
type StubEvent =
|
||||
| {
|
||||
content: Record<string, unknown>;
|
||||
sender?: string;
|
||||
}
|
||||
| undefined;
|
||||
|
||||
type RoomStub = {
|
||||
members: string[];
|
||||
create?: StubEvent;
|
||||
power?: StubEvent;
|
||||
};
|
||||
|
||||
const makeRoom = (opts: RoomStub): Room => {
|
||||
const stateEvents: Record<string, StubEvent> = {};
|
||||
if (opts.create) stateEvents['m.room.create'] = opts.create;
|
||||
if (opts.power) stateEvents['m.room.power_levels'] = opts.power;
|
||||
|
||||
const mkEvent = (e: StubEvent) =>
|
||||
e
|
||||
? {
|
||||
getContent: () => e.content,
|
||||
getSender: () => e.sender,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
getMembers: () => opts.members.map((userId) => ({ userId })),
|
||||
getLiveTimeline: () => ({
|
||||
getState: () => ({
|
||||
getStateEvents: (type: string) => mkEvent(stateEvents[type]),
|
||||
}),
|
||||
}),
|
||||
} as unknown as Room;
|
||||
};
|
||||
|
||||
test('with no power user it returns the top 3 most-populated servers, descending', () => {
|
||||
const room = makeRoom({
|
||||
// s3 x2, s1 x2, s2 x1, s4 x1 — order between equal counts follows insertion
|
||||
members: ['@a:s1.com', '@b:s1.com', '@c:s2.com', '@d:s3.com', '@e:s3.com', '@f:s4.com'],
|
||||
});
|
||||
assert.deepEqual(getViaServers(room), ['s1.com', 's3.com', 's2.com']);
|
||||
});
|
||||
|
||||
test('the highest-power user server is placed first, ahead of the populous servers', () => {
|
||||
const room = makeRoom({
|
||||
// s3 is most populous (3), but the power user is on s2
|
||||
members: ['@a:s1.com', '@b:s1.com', '@c:s2.com', '@d:s3.com', '@e:s3.com', '@f:s3.com'],
|
||||
power: { content: { users: { '@c:s2.com': 100 }, users_default: 0 } },
|
||||
});
|
||||
// power-user server first, then the top populated servers, s2 deduped
|
||||
assert.deepEqual(getViaServers(room), ['s2.com', 's3.com', 's1.com']);
|
||||
});
|
||||
|
||||
test('a power-user server that is also the most populous is deduped, result capped at 3', () => {
|
||||
const room = makeRoom({
|
||||
members: [
|
||||
'@a:s1.com',
|
||||
'@b:s1.com',
|
||||
'@c:s1.com',
|
||||
'@d:s2.com',
|
||||
'@e:s3.com',
|
||||
'@f:s4.com',
|
||||
'@g:s5.com',
|
||||
],
|
||||
power: { content: { users: { '@a:s1.com': 100 }, users_default: 0 } },
|
||||
});
|
||||
// s1 (power + most pop) first, then next 2 of the top-3 populated list
|
||||
assert.deepEqual(getViaServers(room), ['s1.com', 's2.com', 's3.com']);
|
||||
});
|
||||
|
||||
test('picks the user with the strictly highest power level', () => {
|
||||
const room = makeRoom({
|
||||
members: ['@low:s1.com', '@high:s2.com', '@c:s3.com'],
|
||||
power: {
|
||||
content: {
|
||||
users: { '@low:s1.com': 50, '@high:s2.com': 100 },
|
||||
users_default: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
assert.equal(getViaServers(room)[0], 's2.com');
|
||||
});
|
||||
|
||||
test('ignores users whose power is not above users_default', () => {
|
||||
const room = makeRoom({
|
||||
members: ['@a:s1.com', '@b:s2.com'],
|
||||
// @a power equals users_default, so it is not treated as a power user
|
||||
power: { content: { users: { '@a:s1.com': 50 }, users_default: 50 } },
|
||||
});
|
||||
// falls back to populated servers only
|
||||
assert.deepEqual(getViaServers(room), ['s1.com', 's2.com']);
|
||||
});
|
||||
|
||||
test('uses the create-event sender when the room version supports creators', () => {
|
||||
const room = makeRoom({
|
||||
members: ['@a:s1.com', '@b:s2.com', '@c:s2.com'],
|
||||
create: { content: { room_version: '12' }, sender: '@a:s1.com' },
|
||||
// power levels would point elsewhere, but creatorsSupported short-circuits
|
||||
power: { content: { users: { '@c:s2.com': 100 }, users_default: 0 } },
|
||||
});
|
||||
assert.equal(getViaServers(room)[0], 's1.com');
|
||||
});
|
||||
|
||||
test('falls back to power levels when the room version does not support creators', () => {
|
||||
const room = makeRoom({
|
||||
members: ['@a:s1.com', '@b:s2.com', '@c:s2.com'],
|
||||
create: { content: { room_version: '11' }, sender: '@a:s1.com' },
|
||||
power: { content: { users: { '@c:s2.com': 100 }, users_default: 0 } },
|
||||
});
|
||||
assert.equal(getViaServers(room)[0], 's2.com');
|
||||
});
|
||||
|
||||
test('ignores members with unparseable user ids when counting populations', () => {
|
||||
const room = makeRoom({
|
||||
members: ['@a:s1.com', 'broken-id', '@b:s1.com', '@c:s2.com'],
|
||||
});
|
||||
assert.deepEqual(getViaServers(room), ['s1.com', 's2.com']);
|
||||
});
|
||||
|
||||
test('returns an empty array for a room with no resolvable servers', () => {
|
||||
const room = makeRoom({ members: ['broken-id', 'also-broken'] });
|
||||
assert.deepEqual(getViaServers(room), []);
|
||||
});
|
||||
|
||||
test('result never exceeds three servers', () => {
|
||||
const room = makeRoom({
|
||||
members: ['@a:s1.com', '@b:s2.com', '@c:s3.com', '@d:s4.com', '@e:s5.com'],
|
||||
power: { content: { users: { '@a:s1.com': 100 }, users_default: 0 } },
|
||||
});
|
||||
assert.ok(getViaServers(room).length <= 3);
|
||||
});
|
||||
Reference in New Issue
Block a user