eigent/test/unit/electron/main/domReadyHandlers.test.ts
Tong Chen af93bb3065
feat: Add Lint & Format (#878)
Co-authored-by: a7m-1st <Ahmed.jimi.awelkeir500@gmail.com>
Co-authored-by: eigent-ai <camel@eigent.ai>
Co-authored-by: Wendong-Fan <133094783+Wendong-Fan@users.noreply.github.com>
Co-authored-by: Wendong-Fan <w3ndong.fan@gmail.com>
2026-02-01 23:16:18 +08:00

572 lines
19 KiB
TypeScript

// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
/**
* Tests for DOM ready event handlers in createWindow function
* These handlers manage localStorage injection for installation states
*/
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { setupMockEnvironment } from '../../../mocks/environmentMocks';
describe('createWindow - DOM Ready Event Handlers', () => {
let mockEnv: ReturnType<typeof setupMockEnvironment>;
let mockWebContents: any;
let mockWindow: any;
beforeEach(() => {
mockEnv = setupMockEnvironment();
// Mock webContents and window
mockWebContents = {
on: vi.fn(),
once: vi.fn(),
executeJavaScript: vi.fn(),
send: vi.fn(),
loadURL: vi.fn(),
loadFile: vi.fn(),
openDevTools: vi.fn(),
};
mockWindow = {
webContents: mockWebContents,
reload: vi.fn(),
};
// Reset all mocks
vi.clearAllMocks();
});
afterEach(() => {
mockEnv.reset();
});
describe('Fresh Installation - Carousel State Injection', () => {
it('should inject fresh auth-storage with carousel state', () => {
// Simulate fresh installation scenario
const needsInstallation = true;
// Set up DOM ready handler like createWindow does
if (needsInstallation) {
mockWebContents.on('dom-ready', () => {
const injectionScript = `
(function() {
try {
const newAuthStorage = {
state: {
token: null,
username: null,
email: null,
user_id: null,
appearance: 'light',
language: 'system',
isFirstLaunch: true,
modelType: 'cloud',
cloud_model_type: 'gpt-4.1',
initState: 'carousel',
share_token: null,
workerListData: {}
},
version: 0
};
localStorage.setItem('auth-storage', JSON.stringify(newAuthStorage));
console.log('[ELECTRON PRE-INJECT] Created fresh auth-storage with carousel state');
} catch (e) {
console.error('[ELECTRON PRE-INJECT] Failed to create storage:', e);
}
})();
`;
mockWebContents.executeJavaScript(injectionScript);
});
}
// Trigger DOM ready event
const domReadyCallback = mockWebContents.on.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
expect(domReadyCallback).toBeDefined();
if (domReadyCallback) {
domReadyCallback();
}
// Verify JavaScript injection was called with carousel state
expect(mockWebContents.executeJavaScript).toHaveBeenCalledWith(
expect.stringContaining("initState: 'carousel'")
);
expect(mockWebContents.executeJavaScript).toHaveBeenCalledWith(
expect.stringContaining('isFirstLaunch: true')
);
});
it('should handle JavaScript injection errors gracefully', () => {
const needsInstallation = true;
// Mock executeJavaScript to reject
mockWebContents.executeJavaScript.mockRejectedValue(
new Error('Injection failed')
);
// Set up DOM ready handler with error handling
if (needsInstallation) {
mockWebContents.on('dom-ready', () => {
const injectionScript = `/* injection script */`;
mockWebContents
.executeJavaScript(injectionScript)
.catch((err: Error) => {
// In real code, this is logged but doesn't throw
console.error('Failed to inject script:', err);
});
});
}
// Trigger DOM ready event
const domReadyCallback = mockWebContents.on.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
if (domReadyCallback) {
expect(() => domReadyCallback()).not.toThrow();
}
});
it('should include all required auth-storage properties', () => {
const needsInstallation = true;
if (needsInstallation) {
mockWebContents.on('dom-ready', () => {
const injectionScript = `
(function() {
try {
const newAuthStorage = {
state: {
token: null,
username: null,
email: null,
user_id: null,
appearance: 'light',
language: 'system',
isFirstLaunch: true,
modelType: 'cloud',
cloud_model_type: 'gpt-4.1',
initState: 'carousel',
share_token: null,
workerListData: {}
},
version: 0
};
localStorage.setItem('auth-storage', JSON.stringify(newAuthStorage));
} catch (e) {
console.error('Failed to create storage:', e);
}
})();
`;
mockWebContents.executeJavaScript(injectionScript);
});
}
const domReadyCallback = mockWebContents.on.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
if (domReadyCallback) {
domReadyCallback();
}
const injectedScript =
mockWebContents.executeJavaScript.mock.calls[0]?.[0];
// Verify all required properties are included
expect(injectedScript).toContain('token: null');
expect(injectedScript).toContain('username: null');
expect(injectedScript).toContain('email: null');
expect(injectedScript).toContain('user_id: null');
expect(injectedScript).toContain("appearance: 'light'");
expect(injectedScript).toContain("language: 'system'");
expect(injectedScript).toContain('isFirstLaunch: true');
expect(injectedScript).toContain("modelType: 'cloud'");
expect(injectedScript).toContain("cloud_model_type: 'gpt-4.1'");
expect(injectedScript).toContain("initState: 'carousel'");
expect(injectedScript).toContain('share_token: null');
expect(injectedScript).toContain('workerListData: {}');
expect(injectedScript).toContain('version: 0');
});
});
describe('Completed Installation - Done State Management', () => {
it('should check and update initState to done when installation is complete', () => {
const needsInstallation = false;
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
const checkScript = `
(function() {
try {
const authStorage = localStorage.getItem('auth-storage');
if (authStorage) {
const parsed = JSON.parse(authStorage);
if (parsed.state && parsed.state.initState !== 'done') {
console.log('[ELECTRON] Updating initState from', parsed.state.initState, 'to done');
parsed.state.initState = 'done';
localStorage.setItem('auth-storage', JSON.stringify(parsed));
console.log('[ELECTRON] initState updated to done, reloading page...');
return true;
}
}
return false;
} catch (e) {
console.error('[ELECTRON] Failed to update initState:', e);
return false;
}
})();
`;
mockWebContents.executeJavaScript(checkScript);
});
}
// Trigger DOM ready event
const domReadyCallback = mockWebContents.once.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
expect(domReadyCallback).toBeDefined();
if (domReadyCallback) {
domReadyCallback();
}
// Verify the check script was executed
expect(mockWebContents.executeJavaScript).toHaveBeenCalledWith(
expect.stringContaining("initState !== 'done'")
);
expect(mockWebContents.executeJavaScript).toHaveBeenCalledWith(
expect.stringContaining("initState = 'done'")
);
});
it('should trigger window reload when initState needs updating', async () => {
const needsInstallation = false;
// Mock executeJavaScript to return true (indicating reload needed)
mockWebContents.executeJavaScript.mockResolvedValue(true);
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
mockWebContents
.executeJavaScript(`/* check script */`)
.then((needsReload: boolean) => {
if (needsReload) {
mockWindow.reload();
}
});
});
}
// Trigger DOM ready event
const domReadyCallback = mockWebContents.once.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
if (domReadyCallback) {
domReadyCallback();
}
// Wait for async operations
await new Promise((resolve) => setTimeout(resolve, 10));
expect(mockWindow.reload).toHaveBeenCalled();
});
it('should not reload when initState is already done', async () => {
const needsInstallation = false;
// Mock executeJavaScript to return false (no reload needed)
mockWebContents.executeJavaScript.mockResolvedValue(false);
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
mockWebContents
.executeJavaScript(`/* check script */`)
.then((needsReload: boolean) => {
if (needsReload) {
mockWindow.reload();
}
});
});
}
const domReadyCallback = mockWebContents.once.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
if (domReadyCallback) {
domReadyCallback();
}
// Wait for async operations
await new Promise((resolve) => setTimeout(resolve, 10));
expect(mockWindow.reload).not.toHaveBeenCalled();
});
it('should handle localStorage parsing errors gracefully', async () => {
const needsInstallation = false;
// Mock executeJavaScript to simulate parsing error (return false)
mockWebContents.executeJavaScript.mockResolvedValue(false);
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
const checkScript = `
(function() {
try {
const authStorage = localStorage.getItem('auth-storage');
if (authStorage) {
const parsed = JSON.parse(authStorage); // This could throw
// ... rest of logic
}
return false;
} catch (e) {
console.error('[ELECTRON] Failed to update initState:', e);
return false; // Error case returns false
}
})();
`;
mockWebContents.executeJavaScript(checkScript);
});
}
const domReadyCallback = mockWebContents.once.mock.calls.find(
(call: any) => call[0] === 'dom-ready'
)?.[1];
if (domReadyCallback) {
expect(() => domReadyCallback()).not.toThrow();
}
await new Promise((resolve) => setTimeout(resolve, 10));
// Should not reload on error
expect(mockWindow.reload).not.toHaveBeenCalled();
});
});
describe('Event Handler Setup Differences', () => {
it('should use "on" event for fresh installation (can trigger multiple times)', () => {
const needsInstallation = true;
// Simulate the logic from createWindow
if (needsInstallation) {
mockWebContents.on('dom-ready', () => {
// Fresh installation handler
});
}
// Verify 'on' was used instead of 'once'
expect(mockWebContents.on).toHaveBeenCalledWith(
'dom-ready',
expect.any(Function)
);
expect(mockWebContents.once).not.toHaveBeenCalled();
});
it('should use "once" event for completed installation (single trigger)', () => {
const needsInstallation = false;
// Simulate the logic from createWindow
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
// Completed installation handler
});
}
// Verify 'once' was used instead of 'on'
expect(mockWebContents.once).toHaveBeenCalledWith(
'dom-ready',
expect.any(Function)
);
expect(mockWebContents.on).not.toHaveBeenCalled();
});
});
describe('JavaScript Execution Content Validation', () => {
it('should create properly structured auth-storage JSON for fresh installation', () => {
const needsInstallation = true;
if (needsInstallation) {
mockWebContents.on('dom-ready', () => {
const script = `
(function() {
try {
const newAuthStorage = {
state: {
token: null,
username: null,
email: null,
user_id: null,
appearance: 'light',
language: 'system',
isFirstLaunch: true,
modelType: 'cloud',
cloud_model_type: 'gpt-4.1',
initState: 'carousel',
share_token: null,
workerListData: {}
},
version: 0
};
localStorage.setItem('auth-storage', JSON.stringify(newAuthStorage));
console.log('[ELECTRON PRE-INJECT] Created fresh auth-storage with carousel state');
} catch (e) {
console.error('[ELECTRON PRE-INJECT] Failed to create storage:', e);
}
})();
`;
mockWebContents.executeJavaScript(script);
});
}
const domReadyCallback = mockWebContents.on.mock.calls[0]?.[1];
if (domReadyCallback) {
domReadyCallback();
}
const executedScript =
mockWebContents.executeJavaScript.mock.calls[0]?.[0];
// Verify the script is wrapped in IIFE
expect(executedScript).toMatch(/^\s*\(\s*function\s*\(\s*\)\s*\{/);
expect(executedScript).toMatch(/\}\s*\)\s*\(\s*\)\s*;?\s*$/);
// Verify it has try-catch error handling
expect(executedScript).toContain('try {');
expect(executedScript).toContain('} catch (e) {');
// Verify it sets localStorage
expect(executedScript).toContain("localStorage.setItem('auth-storage'");
expect(executedScript).toContain('JSON.stringify(newAuthStorage)');
});
it('should check localStorage properly for completed installation', () => {
const needsInstallation = false;
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
const script = `
(function() {
try {
const authStorage = localStorage.getItem('auth-storage');
if (authStorage) {
const parsed = JSON.parse(authStorage);
if (parsed.state && parsed.state.initState !== 'done') {
parsed.state.initState = 'done';
localStorage.setItem('auth-storage', JSON.stringify(parsed));
return true;
}
}
return false;
} catch (e) {
console.error('[ELECTRON] Failed to update initState:', e);
return false;
}
})();
`;
mockWebContents.executeJavaScript(script);
});
}
const domReadyCallback = mockWebContents.once.mock.calls[0]?.[1];
if (domReadyCallback) {
domReadyCallback();
}
const executedScript =
mockWebContents.executeJavaScript.mock.calls[0]?.[0];
// Verify it gets localStorage
expect(executedScript).toContain("localStorage.getItem('auth-storage')");
// Verify it parses JSON
expect(executedScript).toContain('JSON.parse(authStorage)');
// Verify it checks initState
expect(executedScript).toContain("initState !== 'done'");
// Verify it updates initState
expect(executedScript).toContain("initState = 'done'");
// Verify it returns boolean
expect(executedScript).toContain('return true');
expect(executedScript).toContain('return false');
});
});
describe('Console Logging in Injected Scripts', () => {
it('should include proper console logging for fresh installation', () => {
const needsInstallation = true;
if (needsInstallation) {
mockWebContents.on('dom-ready', () => {
const script = `
console.log('[ELECTRON PRE-INJECT] Created fresh auth-storage with carousel state');
console.error('[ELECTRON PRE-INJECT] Failed to create storage:', e);
`;
mockWebContents.executeJavaScript(script);
});
}
const domReadyCallback = mockWebContents.on.mock.calls[0]?.[1];
if (domReadyCallback) {
domReadyCallback();
}
const executedScript =
mockWebContents.executeJavaScript.mock.calls[0]?.[0];
// Verify console logging is included
expect(executedScript).toContain('[ELECTRON PRE-INJECT]');
expect(executedScript).toContain('console.log');
expect(executedScript).toContain('console.error');
});
it('should include proper console logging for completed installation', () => {
const needsInstallation = false;
if (!needsInstallation) {
mockWebContents.once('dom-ready', () => {
const script = `
console.log('[ELECTRON] Updating initState from', parsed.state.initState, 'to done');
console.log('[ELECTRON] initState updated to done, reloading page...');
console.error('[ELECTRON] Failed to update initState:', e);
`;
mockWebContents.executeJavaScript(script);
});
}
const domReadyCallback = mockWebContents.once.mock.calls[0]?.[1];
if (domReadyCallback) {
domReadyCallback();
}
const executedScript =
mockWebContents.executeJavaScript.mock.calls[0]?.[0];
// Verify console logging is included
expect(executedScript).toContain('[ELECTRON]');
expect(executedScript).toContain('console.log');
expect(executedScript).toContain('console.error');
});
});
});