Files
Twitch-VOD-Manager/src/main-shutdown.production-path.test.ts
T
Sucukdeluxe 9f1b052afd Release Twitch VOD Manager 1.0.18
Harden update, system-check, queue, cutter, streamer and shutdown state transitions.

Add multi-user installer recovery, secret-safe config migration, provider fallback handling, managed-tool validation and real media export coverage.

Refresh the English public documentation, release notes and 1.0.18 product screenshot.
2026-08-13 22:59:15 +02:00

67 lines
3.0 KiB
TypeScript

import { EventEmitter } from 'node:events';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { runInNewContext } from 'node:vm';
import { ModuleKind, ScriptTarget, transpileModule } from 'typescript';
import { describe, expect, test, vi } from 'vitest';
function mainSource(): string {
return readFileSync(join(__dirname, 'main.ts'), 'utf8');
}
function sourceFragment(start: string, end: string): string {
const source = mainSource();
const from = source.indexOf(start);
const to = source.indexOf(end, from);
if (from < 0 || to < 0) throw new Error('Missing main production fragment');
return source.slice(from, to);
}
describe('main shutdown production paths', () => {
test('does not spawn a cutter probe after shutdown starts', async () => {
const spawn = vi.fn(() => {
const child = Object.assign(new EventEmitter(), {
stderr: { resume: () => undefined },
stdout: new EventEmitter(),
kill: () => true,
});
queueMicrotask(() => child.emit('close', 0));
return child;
});
const context: Record<string, unknown> = {
appShutdownStarted: true,
spawn,
getFFmpegPath: () => 'ffmpeg.exe',
currentCutterProbeProcesses: new Set(),
setTimeout,
clearTimeout,
globalThis: null,
};
context.globalThis = context;
const fragment = sourceFragment('async function runCutterFfmpegProbe', 'async function getCutterHardwareEncoders');
const compiled = transpileModule(`${fragment}\nglobalThis.__runCutterFfmpegProbe = runCutterFfmpegProbe;`, {
compilerOptions: { module: ModuleKind.None, target: ScriptTarget.ES2022 },
}).outputText;
runInNewContext(compiled, context);
const result = await (context.__runCutterFfmpegProbe as (args: string[], capture: boolean) => Promise<{ success: boolean; output: string }>)([], false);
expect(result).toEqual({ success: false, output: '' });
expect(spawn).not.toHaveBeenCalled();
});
test('applies imported configuration through the shared transition before returning success', () => {
const handler = sourceFragment("ipcMain.handle('import-config'", 'function isTrustedRendererEvent');
const transition = sourceFragment('function applyConfigTransition', "ipcMain.handle('save-config'");
const appliedTransition = handler.indexOf('applyConfigTransition(previousConfig, merged);');
const returned = handler.indexOf('return { success: true');
const persisted = transition.indexOf('config = persistStateChange');
const appliedTheme = transition.indexOf('nativeTheme.themeSource = resolveNativeThemeSource(config.theme)');
expect(persisted).toBeGreaterThan(-1);
expect(appliedTheme).toBeGreaterThan(persisted);
expect(appliedTransition).toBeGreaterThan(-1);
expect(returned).toBeGreaterThan(appliedTransition);
});
});