mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-07-29 19:21:33 -07:00
feat(sync-ui): defer app quit until async cleanup resolves
- check-host participates in active-run coordination and can be cancelled - shutdown() cancels and awaits the active launcher run on quit - onWillQuit calls preventDefault and re-triggers quit once cleanup settles - Snapshot mode awaits tracker quiescent before writing output - Auto-scheduler catches synchronous triggerHostSync failures - SCP endpoint accepts Windows absolute paths; cmd.exe rejects % in quoted values - runAppCommand unified (inherit vs pipe stdio) in launcher/mpv.ts - Docs: add --check, --json, --ui, --sync-cli, --make-temp/--remove-temp examples
This commit is contained in:
@@ -140,6 +140,38 @@ test('startAppLifecycle still acquires lock for startup commands', () => {
|
||||
assert.equal(getLockCalls(), 1);
|
||||
});
|
||||
|
||||
test('startAppLifecycle defers quit until async cleanup settles', async () => {
|
||||
let willQuit: ((event: { preventDefault(): void }) => void) | null = null;
|
||||
let releaseCleanup: (() => void) | null = null;
|
||||
const cleanupDone = new Promise<void>((resolve) => {
|
||||
releaseCleanup = resolve;
|
||||
});
|
||||
let prevented = false;
|
||||
const { deps, calls } = createDeps({
|
||||
shouldStartApp: () => true,
|
||||
onWillQuit: (handler) => {
|
||||
willQuit = handler;
|
||||
},
|
||||
onWillQuitCleanup: () => cleanupDone,
|
||||
});
|
||||
|
||||
startAppLifecycle(makeArgs({ start: true }), deps);
|
||||
assert.ok(willQuit);
|
||||
(willQuit as (event: { preventDefault(): void }) => void)({
|
||||
preventDefault: () => {
|
||||
prevented = true;
|
||||
},
|
||||
});
|
||||
assert.equal(prevented, true);
|
||||
assert.deepEqual(calls, []);
|
||||
|
||||
assert.ok(releaseCleanup);
|
||||
(releaseCleanup as () => void)();
|
||||
await cleanupDone;
|
||||
await Promise.resolve();
|
||||
assert.deepEqual(calls, ['quitApp']);
|
||||
});
|
||||
|
||||
test('startAppLifecycle app ping exits non-zero immediately when no running instance owns the lock', () => {
|
||||
const { deps, calls, getLockCalls } = createDeps({
|
||||
shouldStartApp: () => false,
|
||||
@@ -252,7 +284,7 @@ test('startAppLifecycle routes control socket commands through the second-instan
|
||||
},
|
||||
});
|
||||
|
||||
let willQuitHandler: (() => void) | null = null;
|
||||
let willQuitHandler: ((event: { preventDefault(): void }) => void) | null = null;
|
||||
deps.onWillQuit = (handler) => {
|
||||
willQuitHandler = handler;
|
||||
};
|
||||
@@ -274,7 +306,7 @@ test('startAppLifecycle routes control socket commands through the second-instan
|
||||
assert.deepEqual(handled, ['ready', 'second-instance:start']);
|
||||
|
||||
assert.ok(willQuitHandler);
|
||||
(willQuitHandler as () => void)();
|
||||
(willQuitHandler as (event: { preventDefault(): void }) => void)({ preventDefault: () => {} });
|
||||
assert.deepEqual(handled, ['ready', 'second-instance:start', 'control-close']);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user