Files
SubMiner/src/main/runtime/tray-lifecycle.test.ts
T

173 lines
4.9 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { createDestroyTrayHandler, createEnsureTrayHandler } from './tray-lifecycle';
test('ensure tray updates menu when tray already exists', () => {
const calls: string[] = [];
const tray = {
setContextMenu: () => calls.push('set-menu'),
setToolTip: () => calls.push('set-tooltip'),
on: () => calls.push('bind-click'),
destroy: () => calls.push('destroy'),
};
const ensureTray = createEnsureTrayHandler({
getTray: () => tray,
setTray: () => calls.push('set-tray'),
buildTrayMenu: () => ({}),
resolveTrayIconPath: () => null,
createImageFromPath: () =>
({
isEmpty: () => false,
resize: () => {
throw new Error('should not resize');
},
setTemplateImage: () => {},
}) as never,
createEmptyImage: () =>
({
isEmpty: () => true,
resize: () => {
throw new Error('should not resize');
},
setTemplateImage: () => {},
}) as never,
createTray: () => tray as never,
trayTooltip: 'SubMiner',
platform: 'darwin',
logWarn: () => calls.push('warn'),
ensureOverlayVisibleFromTrayClick: () => calls.push('show-overlay'),
});
ensureTray();
assert.deepEqual(calls, ['set-menu']);
});
test('ensure tray creates new tray and binds click handler', () => {
const calls: string[] = [];
let trayRef: unknown = null;
const ensureTray = createEnsureTrayHandler({
getTray: () => null,
setTray: (tray) => {
trayRef = tray;
calls.push('set-tray');
},
buildTrayMenu: () => ({ id: 'menu' }),
resolveTrayIconPath: () => '/tmp/icon.png',
createImageFromPath: () =>
({
isEmpty: () => false,
resize: (options: {
width: number;
height: number;
quality?: 'best' | 'better' | 'good';
}) => {
calls.push(`resize:${options.width}x${options.height}`);
return {
isEmpty: () => false,
resize: () => {
throw new Error('unexpected');
},
setTemplateImage: () => calls.push('template'),
};
},
setTemplateImage: () => calls.push('template'),
}) as never,
createEmptyImage: () =>
({
isEmpty: () => true,
resize: () => {
throw new Error('unexpected');
},
setTemplateImage: () => {},
}) as never,
createTray: () =>
({
setContextMenu: () => calls.push('set-menu'),
setToolTip: () => calls.push('set-tooltip'),
on: (_event: 'click', _handler: () => void) => {
calls.push('bind-click');
},
destroy: () => calls.push('destroy'),
}) as never,
trayTooltip: 'SubMiner',
platform: 'darwin',
logWarn: () => calls.push('warn'),
ensureOverlayVisibleFromTrayClick: () => calls.push('show-overlay'),
});
ensureTray();
assert.ok(trayRef);
assert.ok(calls.includes('set-tray'));
assert.ok(calls.includes('set-menu'));
assert.ok(calls.includes('bind-click'));
});
test('ensure tray logs Linux tray registration failures without crashing startup', () => {
const calls: string[] = [];
let trayRef: unknown = null;
const ensureTray = createEnsureTrayHandler({
getTray: () => null,
setTray: (tray) => {
trayRef = tray;
calls.push('set-tray');
},
buildTrayMenu: () => ({ id: 'menu' }),
resolveTrayIconPath: () => '/tmp/icon.png',
createImageFromPath: () =>
({
isEmpty: () => false,
resize: () => ({
isEmpty: () => false,
resize: () => {
throw new Error('unexpected');
},
setTemplateImage: () => {},
}),
setTemplateImage: () => {},
}) as never,
createEmptyImage: () =>
({
isEmpty: () => true,
resize: () => {
throw new Error('unexpected');
},
setTemplateImage: () => {},
}) as never,
createTray: () => {
throw new Error('StatusNotifier watcher unavailable');
},
trayTooltip: 'SubMiner',
platform: 'linux',
logWarn: (message) => calls.push(`warn:${message}`),
ensureOverlayVisibleFromTrayClick: () => calls.push('show-overlay'),
});
ensureTray();
assert.equal(trayRef, null);
assert.deepEqual(calls, [
'warn:Unable to create Linux tray icon. Ensure your desktop has a StatusNotifier/AppIndicator tray host. StatusNotifier watcher unavailable',
]);
});
test('destroy tray handler destroys active tray and clears ref', () => {
const calls: string[] = [];
let tray: { destroy: () => void } | null = {
destroy: () => calls.push('destroy'),
};
const destroyTray = createDestroyTrayHandler({
getTray: () => tray as never,
setTray: (next) => {
tray = next as never;
calls.push('set-null');
},
});
destroyTray();
assert.deepEqual(calls, ['destroy', 'set-null']);
assert.equal(tray, null);
});