Files
SubMiner/src/main/runtime/overlay-runtime-main-actions.test.ts
2026-03-01 02:36:51 -08:00

141 lines
4.4 KiB
TypeScript

import assert from 'node:assert/strict';
import test from 'node:test';
import {
createBroadcastRuntimeOptionsChangedHandler,
createGetRuntimeOptionsStateHandler,
createOpenRuntimeOptionsPaletteHandler,
createRestorePreviousSecondarySubVisibilityHandler,
createSendToActiveOverlayWindowHandler,
createSetOverlayDebugVisualizationEnabledHandler,
} from './overlay-runtime-main-actions';
test('runtime options state handler returns empty list without manager', () => {
const getState = createGetRuntimeOptionsStateHandler({
getRuntimeOptionsManager: () => null,
});
assert.deepEqual(getState(), []);
});
test('runtime options state handler returns list from manager', () => {
const getState = createGetRuntimeOptionsStateHandler({
getRuntimeOptionsManager: () =>
({
listOptions: () => [
{
id: 'anki.autoUpdateNewCards',
label: 'X',
scope: 'ankiConnect',
valueType: 'boolean',
value: true,
allowedValues: [true, false],
requiresRestart: false,
},
],
}) as never,
});
assert.deepEqual(getState(), [
{
id: 'anki.autoUpdateNewCards',
label: 'X',
scope: 'ankiConnect',
valueType: 'boolean',
value: true,
allowedValues: [true, false],
requiresRestart: false,
},
]);
});
test('restore previous secondary subtitle visibility no-ops without connected mpv client', () => {
let restored = false;
const restore = createRestorePreviousSecondarySubVisibilityHandler({
getMpvClient: () => ({
connected: false,
restorePreviousSecondarySubVisibility: () => (restored = true),
}),
});
restore();
assert.equal(restored, false);
});
test('restore previous secondary subtitle visibility calls runtime when connected', () => {
let restored = false;
const restore = createRestorePreviousSecondarySubVisibilityHandler({
getMpvClient: () => ({
connected: true,
restorePreviousSecondarySubVisibility: () => (restored = true),
}),
});
restore();
assert.equal(restored, true);
});
test('broadcast runtime options changed passes through state getter and broadcaster', () => {
const calls: string[] = [];
const broadcast = createBroadcastRuntimeOptionsChangedHandler({
broadcastRuntimeOptionsChangedRuntime: (getState, emit) => {
calls.push(`state:${JSON.stringify(getState())}`);
emit('runtime-options:changed', { id: 1 });
},
getRuntimeOptionsState: () => [
{
id: 'anki.autoUpdateNewCards',
label: 'X',
scope: 'ankiConnect',
valueType: 'boolean',
value: true,
allowedValues: [true, false],
requiresRestart: false,
},
],
broadcastToOverlayWindows: (channel, payload) =>
calls.push(`emit:${channel}:${JSON.stringify(payload)}`),
});
broadcast();
assert.deepEqual(calls, [
'state:[{"id":"anki.autoUpdateNewCards","label":"X","scope":"ankiConnect","valueType":"boolean","value":true,"allowedValues":[true,false],"requiresRestart":false}]',
'emit:runtime-options:changed:{"id":1}',
]);
});
test('send to active overlay window delegates to runtime sender', () => {
const send = createSendToActiveOverlayWindowHandler({
sendToActiveOverlayWindowRuntime: (channel, payload) => channel === 'ok' && payload === 1,
});
assert.equal(send('ok', 1), true);
assert.equal(send('no', 1), false);
});
test('set overlay debug visualization enabled delegates with current state and broadcast', () => {
const calls: string[] = [];
let current = false;
const setEnabled = createSetOverlayDebugVisualizationEnabledHandler({
setOverlayDebugVisualizationEnabledRuntime: (curr, next, setCurrent) => {
calls.push(`runtime:${curr}->${next}`);
setCurrent(next);
// no renderer-level side effects for this legacy debug path.
},
getCurrentEnabled: () => current,
setCurrentEnabled: (enabled) => {
current = enabled;
calls.push(`set:${enabled}`);
},
});
setEnabled(true);
assert.equal(current, true);
assert.deepEqual(calls, ['runtime:false->true', 'set:true']);
});
test('open runtime options palette handler delegates to runtime', () => {
let opened = false;
const open = createOpenRuntimeOptionsPaletteHandler({
openRuntimeOptionsPaletteRuntime: () => {
opened = true;
},
});
open();
assert.equal(opened, true);
});