feat(core): add Electron runtime, services, and app composition

This commit is contained in:
2026-02-22 21:43:43 -08:00
parent 448ce03fd4
commit d3fd47f0ec
562 changed files with 69719 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
import test from 'node:test';
import assert from 'node:assert/strict';
import {
createLaunchBackgroundWarmupTaskHandler,
createStartBackgroundWarmupsHandler,
} from './startup-warmups';
function shouldAutoConnectJellyfinRemote(config: {
enabled: boolean;
remoteControlEnabled: boolean;
remoteControlAutoConnect: boolean;
}): boolean {
return config.enabled && config.remoteControlEnabled && config.remoteControlAutoConnect;
}
test('launchBackgroundWarmupTask logs completion timing', async () => {
const debugLogs: string[] = [];
const launchTask = createLaunchBackgroundWarmupTaskHandler({
now: (() => {
let tick = 0;
return () => ++tick * 10;
})(),
logDebug: (message) => debugLogs.push(message),
logWarn: () => {},
});
launchTask('demo', async () => {});
await Promise.resolve();
assert.ok(debugLogs.some((line) => line.includes('[startup-warmup] demo completed in')));
});
test('startBackgroundWarmups no-ops when already started', () => {
let launches = 0;
const startWarmups = createStartBackgroundWarmupsHandler({
getStarted: () => true,
setStarted: () => {},
isTexthookerOnlyMode: () => false,
launchTask: () => {
launches += 1;
},
createMecabTokenizerAndCheck: async () => {},
ensureYomitanExtensionLoaded: async () => {},
prewarmSubtitleDictionaries: async () => {},
shouldAutoConnectJellyfinRemote: () => false,
startJellyfinRemoteSession: async () => {},
});
startWarmups();
assert.equal(launches, 0);
});
test('startBackgroundWarmups does not schedule jellyfin warmup when jellyfin.enabled is false', () => {
const labels: string[] = [];
let started = false;
const startWarmups = createStartBackgroundWarmupsHandler({
getStarted: () => started,
setStarted: (value) => {
started = value;
},
isTexthookerOnlyMode: () => false,
launchTask: (label) => {
labels.push(label);
},
createMecabTokenizerAndCheck: async () => {},
ensureYomitanExtensionLoaded: async () => {},
prewarmSubtitleDictionaries: async () => {},
shouldAutoConnectJellyfinRemote: () =>
shouldAutoConnectJellyfinRemote({
enabled: false,
remoteControlEnabled: true,
remoteControlAutoConnect: true,
}),
startJellyfinRemoteSession: async () => {},
});
startWarmups();
assert.equal(started, true);
assert.deepEqual(labels, ['mecab', 'yomitan-extension', 'subtitle-dictionaries']);
});
test('startBackgroundWarmups schedules jellyfin warmup when all jellyfin flags are enabled', () => {
const labels: string[] = [];
let started = false;
const startWarmups = createStartBackgroundWarmupsHandler({
getStarted: () => started,
setStarted: (value) => {
started = value;
},
isTexthookerOnlyMode: () => false,
launchTask: (label) => {
labels.push(label);
},
createMecabTokenizerAndCheck: async () => {},
ensureYomitanExtensionLoaded: async () => {},
prewarmSubtitleDictionaries: async () => {},
shouldAutoConnectJellyfinRemote: () =>
shouldAutoConnectJellyfinRemote({
enabled: true,
remoteControlEnabled: true,
remoteControlAutoConnect: true,
}),
startJellyfinRemoteSession: async () => {},
});
startWarmups();
assert.equal(started, true);
assert.deepEqual(labels, [
'mecab',
'yomitan-extension',
'subtitle-dictionaries',
'jellyfin-remote-session',
]);
});