/** * Tests for window event setup and lifecycle management in createWindow function * Covers dev tools shortcuts, external link handling, before close handling, * auto-update integration, webview manager, and file reader initialization */ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { setupMockEnvironment } from '../../../mocks/environmentMocks' describe('createWindow - Window Event Setup and Lifecycle', () => { let mockEnv: ReturnType let mockWebContents: any let mockWindow: any let mockFileReader: any let mockWebViewManager: any let mockUpdate: any let mockMenu: any beforeEach(() => { mockEnv = setupMockEnvironment() // Mock webContents mockWebContents = { on: vi.fn(), once: vi.fn(), executeJavaScript: vi.fn(), send: vi.fn(), loadURL: vi.fn(), loadFile: vi.fn(), openDevTools: vi.fn(), toggleDevTools: vi.fn() } // Mock window mockWindow = { webContents: mockWebContents, reload: vi.fn() } // Mock FileReader class mockFileReader = vi.fn() // Mock WebViewManager class mockWebViewManager = vi.fn().mockImplementation(() => ({ createWebview: vi.fn() })) // Mock update function mockUpdate = vi.fn() // Mock Menu mockMenu = { setApplicationMenu: vi.fn() } // Reset all mocks vi.clearAllMocks() }) afterEach(() => { mockEnv.reset() }) describe('FileReader and WebViewManager Initialization', () => { it.skip('should create 8 webviews with correct IDs', () => { const webViewManager = new mockWebViewManager(mockWindow) const instance = mockWebViewManager.mock.instances[0] // Simulate the loop that creates webviews for (let i = 1; i <= 8; i++) { instance.createWebview(i === 1 ? undefined : i.toString()) } expect(instance.createWebview).toHaveBeenCalledTimes(8) expect(instance.createWebview).toHaveBeenNthCalledWith(1, undefined) expect(instance.createWebview).toHaveBeenNthCalledWith(2, '2') expect(instance.createWebview).toHaveBeenNthCalledWith(3, '3') expect(instance.createWebview).toHaveBeenNthCalledWith(4, '4') expect(instance.createWebview).toHaveBeenNthCalledWith(5, '5') expect(instance.createWebview).toHaveBeenNthCalledWith(6, '6') expect(instance.createWebview).toHaveBeenNthCalledWith(7, '7') expect(instance.createWebview).toHaveBeenNthCalledWith(8, '8') }) }) describe('Window Event Listeners Setup', () => { it('should disable application menu', () => { // Simulate setupWindowEventListeners mockMenu.setApplicationMenu(null) expect(mockMenu.setApplicationMenu).toHaveBeenCalledWith(null) }) it('should set up application menu only once', () => { // Simulate multiple calls to setupWindowEventListeners mockMenu.setApplicationMenu(null) mockMenu.setApplicationMenu(null) expect(mockMenu.setApplicationMenu).toHaveBeenCalledTimes(2) expect(mockMenu.setApplicationMenu).toHaveBeenCalledWith(null) }) }) describe('DevTools Shortcuts Setup', () => { it('should set up before-input-event listener for dev tools shortcuts', () => { // Simulate setupDevToolsShortcuts mockWebContents.on('before-input-event', expect.any(Function)) expect(mockWebContents.on).toHaveBeenCalledWith('before-input-event', expect.any(Function)) }) it('should handle F12 key to toggle dev tools', () => { let beforeInputCallback: any mockWebContents.on.mockImplementation((event: string, callback: any) => { if (event === 'before-input-event') { beforeInputCallback = callback } }) // Simulate setupDevToolsShortcuts mockWebContents.on('before-input-event', (event: any, input: any) => { if (input.key === 'F12' && input.type === 'keyDown') { mockWebContents.toggleDevTools() } }) // Trigger F12 key if (beforeInputCallback) { const mockEvent = { preventDefault: vi.fn() } const mockInput = { key: 'F12', type: 'keyDown' } beforeInputCallback(mockEvent, mockInput) } expect(mockWebContents.toggleDevTools).toHaveBeenCalled() }) it('should handle Ctrl+Shift+I to toggle dev tools on Windows/Linux', () => { let beforeInputCallback: any mockWebContents.on.mockImplementation((event: string, callback: any) => { if (event === 'before-input-event') { beforeInputCallback = callback } }) // Simulate setupDevToolsShortcuts mockWebContents.on('before-input-event', (event: any, input: any) => { if (input.control && input.shift && input.key.toLowerCase() === 'i' && input.type === 'keyDown') { mockWebContents.toggleDevTools() } }) // Trigger Ctrl+Shift+I if (beforeInputCallback) { const mockEvent = { preventDefault: vi.fn() } const mockInput = { control: true, shift: true, key: 'I', type: 'keyDown' } beforeInputCallback(mockEvent, mockInput) } expect(mockWebContents.toggleDevTools).toHaveBeenCalled() }) it('should handle Cmd+Shift+I to toggle dev tools on Mac', () => { let beforeInputCallback: any mockWebContents.on.mockImplementation((event: string, callback: any) => { if (event === 'before-input-event') { beforeInputCallback = callback } }) // Simulate setupDevToolsShortcuts mockWebContents.on('before-input-event', (event: any, input: any) => { if (input.meta && input.shift && input.key.toLowerCase() === 'i' && input.type === 'keyDown') { mockWebContents.toggleDevTools() } }) // Trigger Cmd+Shift+I if (beforeInputCallback) { const mockEvent = { preventDefault: vi.fn() } const mockInput = { meta: true, shift: true, key: 'I', type: 'keyDown' } beforeInputCallback(mockEvent, mockInput) } expect(mockWebContents.toggleDevTools).toHaveBeenCalled() }) it('should not trigger dev tools on key up events', () => { let beforeInputCallback: any mockWebContents.on.mockImplementation((event: string, callback: any) => { if (event === 'before-input-event') { beforeInputCallback = callback } }) // Simulate setupDevToolsShortcuts mockWebContents.on('before-input-event', (event: any, input: any) => { if (input.key === 'F12' && input.type === 'keyDown') { mockWebContents.toggleDevTools() } }) // Trigger F12 key up (should not toggle) if (beforeInputCallback) { const mockEvent = { preventDefault: vi.fn() } const mockInput = { key: 'F12', type: 'keyUp' } beforeInputCallback(mockEvent, mockInput) } expect(mockWebContents.toggleDevTools).not.toHaveBeenCalled() }) it('should not trigger dev tools on wrong key combinations', () => { let beforeInputCallback: any mockWebContents.on.mockImplementation((event: string, callback: any) => { if (event === 'before-input-event') { beforeInputCallback = callback } }) // Simulate setupDevToolsShortcuts mockWebContents.on('before-input-event', (event: any, input: any) => { if (input.control && input.shift && input.key.toLowerCase() === 'i' && input.type === 'keyDown') { mockWebContents.toggleDevTools() } }) // Trigger wrong combination (Ctrl+I without Shift) if (beforeInputCallback) { const mockEvent = { preventDefault: vi.fn() } const mockInput = { control: true, shift: false, key: 'I', type: 'keyDown' } beforeInputCallback(mockEvent, mockInput) } expect(mockWebContents.toggleDevTools).not.toHaveBeenCalled() }) }) describe('Auto-Update Integration', () => { it('should call update function with window reference', () => { // Simulate auto-update setup mockUpdate(mockWindow) expect(mockUpdate).toHaveBeenCalledWith(mockWindow) }) it('should call update function only once', () => { // Simulate auto-update setup mockUpdate(mockWindow) expect(mockUpdate).toHaveBeenCalledTimes(1) }) }) describe('Event Handler Organization', () => { it('should set up event handlers in correct order', () => { const eventSetupOrder: string[] = [] // Mock all the setup functions to track order const setupWindowEventListeners = () => { eventSetupOrder.push('windowEventListeners') mockMenu.setApplicationMenu(null) } const setupDevToolsShortcuts = () => { eventSetupOrder.push('devToolsShortcuts') mockWebContents.on('before-input-event', vi.fn()) } const setupExternalLinkHandling = () => { eventSetupOrder.push('externalLinkHandling') } const handleBeforeClose = () => { eventSetupOrder.push('beforeClose') } // Simulate the order in createWindow setupWindowEventListeners() setupDevToolsShortcuts() setupExternalLinkHandling() handleBeforeClose() expect(eventSetupOrder).toEqual([ 'windowEventListeners', 'devToolsShortcuts', 'externalLinkHandling', 'beforeClose' ]) }) }) describe('Window State Management', () => { it('should handle window ready state correctly', async () => { let didFinishLoadCallback: (() => void) | undefined // Mock the did-finish-load event listener mockWebContents.once.mockImplementation((event: string, callback: () => void) => { if (event === 'did-finish-load') { didFinishLoadCallback = callback } }) // Simulate waiting for window ready const windowReadyPromise = new Promise(resolve => { mockWebContents.once('did-finish-load', () => { resolve() }) }) // Trigger the event if (didFinishLoadCallback) { didFinishLoadCallback() } // Should resolve without throwing await expect(windowReadyPromise).resolves.toBeUndefined() }) it('should log appropriate messages during window setup', () => { // In a real test, you would verify that appropriate log messages are called // This ensures the window setup process is properly logged const mockLog = { info: vi.fn(), error: vi.fn() } // Simulate logging calls that would happen during window setup mockLog.info('Window content loaded, starting dependency check immediately...') mockLog.info('.eigent directory structure ensured') expect(mockLog.info).toHaveBeenCalledWith( 'Window content loaded, starting dependency check immediately...' ) expect(mockLog.info).toHaveBeenCalledWith( '.eigent directory structure ensured' ) }) }) describe('Integration Points', () => { it('should properly coordinate between file reader and webview manager', () => { const fileReader = new mockFileReader(mockWindow) const webViewManager = new mockWebViewManager(mockWindow) // Both should be initialized with the same window expect(mockFileReader).toHaveBeenCalledWith(mockWindow) expect(mockWebViewManager).toHaveBeenCalledWith(mockWindow) }) it('should handle window initialization errors gracefully', () => { // Mock FileReader to throw during initialization mockFileReader.mockImplementation(() => { throw new Error('FileReader initialization failed') }) // Should handle gracefully in real implementation expect(() => { try { new mockFileReader(mockWindow) } catch (error) { // Log error but don't stop execution console.error('FileReader initialization error:', error) } }).not.toThrow() }) }) describe('Memory Management', () => { it('should properly clean up event listeners when window is destroyed', () => { // In a real scenario, you would test that event listeners are removed // when the window is closed to prevent memory leaks const mockRemoveListener = vi.fn() mockWebContents.removeListener = mockRemoveListener // Simulate cleanup const cleanup = () => { mockWebContents.removeListener('before-input-event', vi.fn()) mockWebContents.removeListener('dom-ready', vi.fn()) } cleanup() expect(mockRemoveListener).toHaveBeenCalledTimes(2) }) }) })