103 lines
3.5 KiB
TypeScript
103 lines
3.5 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
import { BackgroundLifecycleController } from '../../electron/main/background-lifecycle';
|
|
|
|
describe('BackgroundLifecycleController', () => {
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('stops an idle hidden/inactive desktop after the grace period', async () => {
|
|
vi.useFakeTimers();
|
|
const onSleep = vi.fn().mockResolvedValue(undefined);
|
|
const onStopRuntime = vi.fn().mockResolvedValue(undefined);
|
|
const controller = new BackgroundLifecycleController({
|
|
idleStopMs: 60_000,
|
|
onSleep,
|
|
onStopRuntime,
|
|
});
|
|
|
|
controller.setActivity({ visible: false, module: 'painting' });
|
|
await vi.advanceTimersByTimeAsync(59_999);
|
|
expect(onSleep).not.toHaveBeenCalled();
|
|
expect(onStopRuntime).not.toHaveBeenCalled();
|
|
|
|
await vi.advanceTimersByTimeAsync(1);
|
|
expect(onSleep).toHaveBeenCalledTimes(1);
|
|
expect(onStopRuntime).toHaveBeenCalledTimes(1);
|
|
controller.dispose();
|
|
});
|
|
|
|
it('keeps the runtime alive while an active task lease exists', async () => {
|
|
vi.useFakeTimers();
|
|
const onSleep = vi.fn().mockResolvedValue(undefined);
|
|
const onStopRuntime = vi.fn().mockResolvedValue(undefined);
|
|
const controller = new BackgroundLifecycleController({
|
|
idleStopMs: 60_000,
|
|
onSleep,
|
|
onStopRuntime,
|
|
});
|
|
const release = controller.acquireLease({ id: 'release:1', kind: 'publish' });
|
|
|
|
controller.setActivity({ visible: false, module: 'programming' });
|
|
await vi.advanceTimersByTimeAsync(60_000);
|
|
expect(controller.getLeaseCount()).toBe(1);
|
|
expect(onStopRuntime).not.toHaveBeenCalled();
|
|
|
|
release();
|
|
await vi.advanceTimersByTimeAsync(60_000);
|
|
expect(onSleep).toHaveBeenCalledTimes(1);
|
|
expect(onStopRuntime).toHaveBeenCalledTimes(1);
|
|
controller.dispose();
|
|
});
|
|
|
|
it('does not stop the runtime when a lease is acquired while sleep preparation is in flight', async () => {
|
|
vi.useFakeTimers();
|
|
let finishSleepPreparation!: () => void;
|
|
const sleepPreparation = new Promise<void>((resolve) => {
|
|
finishSleepPreparation = resolve;
|
|
});
|
|
const onSleep = vi.fn(() => sleepPreparation);
|
|
const onStopRuntime = vi.fn().mockResolvedValue(undefined);
|
|
const controller = new BackgroundLifecycleController({
|
|
idleStopMs: 60_000,
|
|
onSleep,
|
|
onStopRuntime,
|
|
});
|
|
|
|
controller.setActivity({ visible: false, module: 'learning' });
|
|
await vi.advanceTimersByTimeAsync(60_000);
|
|
expect(onSleep).toHaveBeenCalledTimes(1);
|
|
|
|
const release = controller.acquireLease({ id: 'coding-run:1', kind: 'coding-run' });
|
|
finishSleepPreparation();
|
|
await vi.runAllTicks();
|
|
|
|
expect(onStopRuntime).not.toHaveBeenCalled();
|
|
|
|
release();
|
|
await vi.advanceTimersByTimeAsync(60_000);
|
|
expect(onStopRuntime).toHaveBeenCalledTimes(1);
|
|
controller.dispose();
|
|
});
|
|
|
|
it('cancels the idle stop when programming becomes visible again', async () => {
|
|
vi.useFakeTimers();
|
|
const onSleep = vi.fn();
|
|
const onStopRuntime = vi.fn();
|
|
const controller = new BackgroundLifecycleController({
|
|
idleStopMs: 60_000,
|
|
onSleep,
|
|
onStopRuntime,
|
|
});
|
|
|
|
controller.setActivity({ visible: false, module: 'learning' });
|
|
await vi.advanceTimersByTimeAsync(30_000);
|
|
controller.setActivity({ visible: true, module: 'programming' });
|
|
await vi.advanceTimersByTimeAsync(90_000);
|
|
|
|
expect(onSleep).not.toHaveBeenCalled();
|
|
expect(onStopRuntime).not.toHaveBeenCalled();
|
|
controller.dispose();
|
|
});
|
|
});
|