125 lines
3.0 KiB
TypeScript
125 lines
3.0 KiB
TypeScript
import {
|
|
describe,
|
|
it,
|
|
expect,
|
|
vi,
|
|
beforeEach,
|
|
afterEach
|
|
} from 'vitest';
|
|
|
|
// Mock Electron modules before importing the module under test
|
|
const mockGetSystemIdleTime = vi.fn(() => 0);
|
|
const mockSend = vi.fn();
|
|
const mockGetMainWindow = vi.fn(() => ({
|
|
isDestroyed: () => false,
|
|
webContents: { send: mockSend }
|
|
}));
|
|
|
|
vi.mock('electron', () => ({
|
|
powerMonitor: {
|
|
getSystemIdleTime: mockGetSystemIdleTime
|
|
}
|
|
}));
|
|
|
|
vi.mock('../window/create-window', () => ({
|
|
getMainWindow: mockGetMainWindow
|
|
}));
|
|
|
|
import {
|
|
startIdleMonitor,
|
|
stopIdleMonitor,
|
|
getIdleState
|
|
} from './idle-monitor';
|
|
|
|
describe('idle-monitor', () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
mockGetSystemIdleTime.mockReturnValue(0);
|
|
mockSend.mockClear();
|
|
});
|
|
|
|
afterEach(() => {
|
|
stopIdleMonitor();
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('returns active when idle time is below threshold', () => {
|
|
mockGetSystemIdleTime.mockReturnValue(0);
|
|
expect(getIdleState()).toBe('active');
|
|
});
|
|
|
|
it('returns idle when idle time exceeds 15 minutes', () => {
|
|
mockGetSystemIdleTime.mockReturnValue(15 * 60);
|
|
expect(getIdleState()).toBe('idle');
|
|
});
|
|
|
|
it('sends idle-state-changed to renderer when transitioning to idle', () => {
|
|
startIdleMonitor();
|
|
|
|
mockGetSystemIdleTime.mockReturnValue(15 * 60);
|
|
vi.advanceTimersByTime(10_000);
|
|
|
|
expect(mockSend).toHaveBeenCalledWith('idle-state-changed', 'idle');
|
|
});
|
|
|
|
it('sends idle-state-changed to renderer when transitioning back to active', () => {
|
|
startIdleMonitor();
|
|
|
|
// Go idle
|
|
mockGetSystemIdleTime.mockReturnValue(15 * 60);
|
|
vi.advanceTimersByTime(10_000);
|
|
mockSend.mockClear();
|
|
|
|
// Go active
|
|
mockGetSystemIdleTime.mockReturnValue(5);
|
|
vi.advanceTimersByTime(10_000);
|
|
|
|
expect(mockSend).toHaveBeenCalledWith('idle-state-changed', 'active');
|
|
});
|
|
|
|
it('does not fire duplicates when state stays the same', () => {
|
|
startIdleMonitor();
|
|
|
|
mockGetSystemIdleTime.mockReturnValue(15 * 60);
|
|
vi.advanceTimersByTime(10_000);
|
|
vi.advanceTimersByTime(10_000);
|
|
vi.advanceTimersByTime(10_000);
|
|
|
|
// Only one transition, so only one call
|
|
const idleCalls = mockSend.mock.calls.filter(
|
|
([channel, state]: [string, string]) => channel === 'idle-state-changed' && state === 'idle'
|
|
);
|
|
|
|
expect(idleCalls.length).toBe(1);
|
|
});
|
|
|
|
it('stops polling after stopIdleMonitor', () => {
|
|
startIdleMonitor();
|
|
|
|
mockGetSystemIdleTime.mockReturnValue(15 * 60);
|
|
vi.advanceTimersByTime(10_000);
|
|
mockSend.mockClear();
|
|
|
|
stopIdleMonitor();
|
|
|
|
mockGetSystemIdleTime.mockReturnValue(0);
|
|
vi.advanceTimersByTime(10_000);
|
|
|
|
expect(mockSend).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('does not notify when main window is null', () => {
|
|
mockGetMainWindow.mockReturnValue(null);
|
|
startIdleMonitor();
|
|
|
|
mockGetSystemIdleTime.mockReturnValue(15 * 60);
|
|
vi.advanceTimersByTime(10_000);
|
|
|
|
expect(mockSend).not.toHaveBeenCalled();
|
|
mockGetMainWindow.mockReturnValue({
|
|
isDestroyed: () => false,
|
|
webContents: { send: mockSend }
|
|
});
|
|
});
|
|
});
|