Files
SubMiner/launcher/jellyfin.test.ts
T

135 lines
4.0 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import type { Args } from './types.js';
import { runJellyfinPlayMenuWithDeps } from './jellyfin.js';
function createArgs(): Args {
return {
backend: 'auto',
directory: '.',
recursive: false,
profile: '',
startOverlay: false,
youtubeMode: 'download',
whisperBin: '',
whisperModel: '',
whisperVadModel: '',
whisperThreads: 0,
youtubeSubgenOutDir: '',
youtubeSubgenAudioFormat: '',
youtubeSubgenKeepTemp: false,
youtubeFixWithAi: false,
youtubePrimarySubLangs: [],
youtubeSecondarySubLangs: [],
youtubeAudioLangs: [],
youtubeWhisperSourceLanguage: '',
aiConfig: {},
useTexthooker: false,
autoStartOverlay: false,
texthookerOnly: false,
texthookerOpenBrowser: false,
useRofi: false,
logLevel: 'info',
logRotation: 7,
passwordStore: '',
target: '',
targetKind: '',
jimakuApiKey: '',
jimakuApiKeyCommand: '',
jimakuApiBaseUrl: '',
jimakuLanguagePreference: 'ja',
jimakuMaxEntryResults: 20,
jellyfin: false,
jellyfinLogin: false,
jellyfinLogout: false,
jellyfinPlay: false,
jellyfinDiscovery: false,
dictionary: false,
dictionaryCandidates: false,
dictionarySelect: false,
stats: false,
doctor: false,
doctorRefreshKnownWords: false,
logsExport: false,
version: false,
settings: false,
configPath: false,
configShow: false,
mpvIdle: false,
mpvSocket: false,
mpvStatus: false,
mpvArgs: '',
appPassthrough: false,
appArgs: [],
jellyfinServer: 'https://jellyfin.example.test',
jellyfinUsername: '',
jellyfinPassword: '',
launchMode: 'normal',
};
}
test('Jellyfin playback ensures Linux runtime plugin before detached idle mpv bootstrap', async () => {
const originalAccessToken = process.env.SUBMINER_JELLYFIN_ACCESS_TOKEN;
const originalUserId = process.env.SUBMINER_JELLYFIN_USER_ID;
process.env.SUBMINER_JELLYFIN_ACCESS_TOKEN = 'token';
process.env.SUBMINER_JELLYFIN_USER_ID = 'user';
const calls: string[] = [];
try {
await assert.rejects(
() =>
runJellyfinPlayMenuWithDeps(
'/tmp/SubMiner.AppImage',
createArgs(),
'/tmp/subminer',
'/tmp/subminer.sock',
{
loadLauncherJellyfinConfig: () => ({}),
findRofiTheme: () => null,
resolveJellyfinSelection: async () => 'item-123',
resolveJellyfinSelectionViaApp: async () => {
throw new Error('unexpected app-based selection');
},
hasStoredJellyfinSession: () => true,
requestJellyfinPreviewAuthFromApp: async () => null,
resolveLauncherMainConfigPath: () => '/tmp/SubMiner/config.jsonc',
pathExists: () => false,
ensureRuntimePluginReady: async () => {
calls.push('plugin');
},
waitForUnixSocketReady: async () => {
calls.push('wait');
return true;
},
launchMpvIdleDetached: async () => {
calls.push('launch');
},
resolveLauncherRuntimePluginPath: () => {
calls.push('resolve');
return '/tmp/plugin/main.lua';
},
runAppCommandWithInheritLogged: () => {
calls.push('handoff');
throw new Error('stop after handoff');
},
log: () => {},
},
),
/stop after handoff/,
);
assert.deepEqual(calls, ['plugin', 'resolve', 'launch', 'wait', 'handoff']);
} finally {
if (originalAccessToken === undefined) {
delete process.env.SUBMINER_JELLYFIN_ACCESS_TOKEN;
} else {
process.env.SUBMINER_JELLYFIN_ACCESS_TOKEN = originalAccessToken;
}
if (originalUserId === undefined) {
delete process.env.SUBMINER_JELLYFIN_USER_ID;
} else {
process.env.SUBMINER_JELLYFIN_USER_ID = originalUserId;
}
}
});