mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-05-23 21:06:50 +00:00
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>
634 lines
22 KiB
TypeScript
634 lines
22 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. =========
|
||
|
||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||
import { setupMockEnvironment } from '../../mocks/environmentMocks';
|
||
|
||
// Set up global mock environment before any imports
|
||
const globalMockEnv = setupMockEnvironment();
|
||
|
||
// Mock all dependencies at the top level
|
||
vi.mock('node:fs', () => ({
|
||
...globalMockEnv.fsMock,
|
||
default: globalMockEnv.fsMock,
|
||
}));
|
||
vi.mock('node:path', () => ({
|
||
...globalMockEnv.pathMock,
|
||
default: globalMockEnv.pathMock,
|
||
}));
|
||
vi.mock('child_process', () => ({
|
||
...globalMockEnv.processMock,
|
||
default: globalMockEnv.processMock,
|
||
}));
|
||
vi.mock('electron-log', () => ({ default: globalMockEnv.logMock }));
|
||
vi.mock('electron', () => ({
|
||
app: globalMockEnv.appMock,
|
||
BrowserWindow: vi.fn(),
|
||
}));
|
||
vi.mock(
|
||
'../../../electron/main/utils/process',
|
||
() => globalMockEnv.processUtilsMock
|
||
);
|
||
vi.mock('../../../electron/main/init', () => ({
|
||
getMainWindow: vi.fn().mockReturnValue({
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
}),
|
||
}));
|
||
vi.mock('../../../electron/main/utils/safeWebContentsSend', () => ({
|
||
safeMainWindowSend: vi.fn().mockReturnValue(true),
|
||
}));
|
||
|
||
// Import the module under test after mocking
|
||
let installDeps: any;
|
||
|
||
describe('Install Deps Module', () => {
|
||
let mockEnv: ReturnType<typeof setupMockEnvironment>;
|
||
|
||
beforeEach(async () => {
|
||
// Reset the mock environment state for each test
|
||
mockEnv = globalMockEnv;
|
||
mockEnv.reset();
|
||
|
||
// Set up the shared state
|
||
mockEnv.processMock.setupSpawnMock(mockEnv.mockState);
|
||
mockEnv.appMock.setup(mockEnv.mockState);
|
||
mockEnv.osMock.setup(mockEnv.mockState);
|
||
mockEnv.processUtilsMock.setup(mockEnv.mockState);
|
||
|
||
// Import the module under test fresh for each test
|
||
installDeps = await import('../../../electron/main/install-deps');
|
||
});
|
||
|
||
afterEach(() => {
|
||
vi.clearAllMocks();
|
||
mockEnv.reset();
|
||
});
|
||
|
||
describe('checkAndInstallDepsOnUpdate', () => {
|
||
it('should skip installation when version has not changed and tools are installed', async () => {
|
||
// Set up scenario where version is the same and tools exist
|
||
mockEnv.mockState.filesystem.versionFileExists = true;
|
||
mockEnv.mockState.filesystem.versionFileContent = '1.0.0';
|
||
mockEnv.mockState.app.currentVersion = '1.0.0';
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: true, bun: true };
|
||
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
};
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: false,
|
||
});
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Version not changed');
|
||
expect(mockEnv.fsMock.writeFileSync).not.toHaveBeenCalledWith(
|
||
expect.stringContaining('version.txt'),
|
||
expect.any(String)
|
||
);
|
||
});
|
||
|
||
it('should install dependencies when version file does not exist', async () => {
|
||
// Set up fresh installation scenario
|
||
mockEnv.scenarios.freshInstall();
|
||
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
};
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: false,
|
||
});
|
||
console.log(result);
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Dependencies installed successfully');
|
||
expect(mockWin.webContents.send).toHaveBeenCalledWith(
|
||
'update-notification',
|
||
expect.objectContaining({
|
||
type: 'version-update',
|
||
reason: 'version file not exist',
|
||
})
|
||
);
|
||
});
|
||
|
||
it('should install dependencies when version has changed', async () => {
|
||
// Set up version update scenario
|
||
mockEnv.scenarios.versionUpdate('0.9.0', '1.0.0');
|
||
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
};
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: false,
|
||
});
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Dependencies installed successfully');
|
||
expect(mockWin.webContents.send).toHaveBeenCalledWith(
|
||
'update-notification',
|
||
expect.objectContaining({
|
||
type: 'version-update',
|
||
currentVersion: '1.0.0',
|
||
previousVersion: '0.9.0',
|
||
reason: 'version not match',
|
||
})
|
||
);
|
||
});
|
||
|
||
it('should install when command tools are missing', async () => {
|
||
// Same version but tools missing
|
||
mockEnv.mockState.filesystem.versionFileExists = true;
|
||
mockEnv.mockState.filesystem.versionFileContent = '1.0.0';
|
||
mockEnv.mockState.app.currentVersion = '1.0.0';
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: false, bun: true };
|
||
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
};
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: false,
|
||
});
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Dependencies installed successfully');
|
||
});
|
||
|
||
it('should force install when forceInstall is true', async () => {
|
||
// Set up scenario where normally no installation would be needed
|
||
mockEnv.mockState.filesystem.versionFileExists = true;
|
||
mockEnv.mockState.filesystem.versionFileContent = '1.0.0';
|
||
mockEnv.mockState.app.currentVersion = '1.0.0';
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: true, bun: true };
|
||
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
};
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: true,
|
||
});
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Dependencies installed successfully');
|
||
});
|
||
|
||
it('should handle installation failure', async () => {
|
||
// Set up failure scenario
|
||
mockEnv.scenarios.completeFailure();
|
||
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(false),
|
||
};
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: true,
|
||
});
|
||
|
||
expect(result.success).toBe(false);
|
||
expect(result.message).toContain('Install dependencies failed');
|
||
});
|
||
|
||
it('should handle window being destroyed', async () => {
|
||
const mockWin = {
|
||
webContents: { send: vi.fn() },
|
||
isDestroyed: vi.fn().mockReturnValue(true),
|
||
};
|
||
|
||
mockEnv.scenarios.versionUpdate('0.9.0', '1.0.0');
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: mockWin,
|
||
forceInstall: false,
|
||
});
|
||
|
||
// Should still complete successfully
|
||
expect(result.success).toBe(true);
|
||
// Should not try to send notifications to destroyed window
|
||
expect(mockWin.webContents.send).not.toHaveBeenCalled();
|
||
});
|
||
|
||
it('should handle null window gracefully', async () => {
|
||
mockEnv.scenarios.versionUpdate('0.9.0', '1.0.0');
|
||
|
||
const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
win: null,
|
||
forceInstall: false,
|
||
});
|
||
|
||
expect(result.success).toBe(true);
|
||
// Should not crash when window is null
|
||
});
|
||
});
|
||
|
||
describe('installCommandTool', () => {
|
||
it('should install uv and bun when not available', async () => {
|
||
// Set up scenario where tools are not available initially
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: false, bun: false };
|
||
|
||
// Simulate successful installation
|
||
let uvCallCount = 0;
|
||
let bunCallCount = 0;
|
||
mockEnv.processUtilsMock.isBinaryExists.mockImplementation(
|
||
async (name: string) => {
|
||
if (name === 'uv') {
|
||
uvCallCount++;
|
||
return uvCallCount > 1; // False first time, true after "installation"
|
||
}
|
||
if (name === 'bun') {
|
||
bunCallCount++;
|
||
return bunCallCount > 1; // False first time, true after "installation"
|
||
}
|
||
return false;
|
||
}
|
||
);
|
||
|
||
const result = await installDeps.installCommandTool();
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Command tools installed successfully');
|
||
expect(mockEnv.processUtilsMock.runInstallScript).toHaveBeenCalledTimes(
|
||
2
|
||
); // uv and bun
|
||
});
|
||
|
||
it('should skip installation when tools are already available', async () => {
|
||
// Tools are available by default in mockState
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: true, bun: true };
|
||
|
||
const result = await installDeps.installCommandTool();
|
||
|
||
expect(result.success).toBe(true);
|
||
expect(result.message).toContain('Command tools installed successfully');
|
||
expect(mockEnv.processUtilsMock.runInstallScript).not.toHaveBeenCalled();
|
||
});
|
||
|
||
it('should handle uv installation failure', async () => {
|
||
// Mock uv installation failure
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: false, bun: true };
|
||
|
||
// uv remains unavailable even after installation attempt
|
||
mockEnv.processUtilsMock.isBinaryExists.mockImplementation(
|
||
async (name: string) => {
|
||
if (name === 'uv') return false; // Always fails
|
||
if (name === 'bun') return true;
|
||
return false;
|
||
}
|
||
);
|
||
|
||
const result = await installDeps.installCommandTool();
|
||
|
||
expect(result.success).toBe(false);
|
||
expect(result.message).toContain('uv installation failed');
|
||
});
|
||
|
||
it('should handle bun installation failure', async () => {
|
||
// Mock bun installation failure
|
||
mockEnv.mockState.filesystem.binariesExist = { uv: true, bun: false };
|
||
|
||
// bun remains unavailable even after installation attempt
|
||
mockEnv.processUtilsMock.isBinaryExists.mockImplementation(
|
||
async (name: string) => {
|
||
if (name === 'uv') return true;
|
||
if (name === 'bun') return false; // Always fails
|
||
return false;
|
||
}
|
||
);
|
||
|
||
const result = await installDeps.installCommandTool();
|
||
|
||
expect(result.success).toBe(false);
|
||
expect(result.message).toContain('bun installation failed');
|
||
});
|
||
});
|
||
});
|
||
|
||
// describe('getInstallationStatus', () => {
|
||
// it('should return correct status when installation is in progress', async () => {
|
||
// mockEnv.scenarios.installationInProgress()
|
||
|
||
// const status = await installDeps.getInstallationStatus()
|
||
|
||
// expect(status.isInstalling).toBe(true)
|
||
// expect(status.hasLockFile).toBe(true)
|
||
// expect(status.installedExists).toBe(false)
|
||
// })
|
||
|
||
// it('should return correct status when installation is completed', async () => {
|
||
// // Default state has installation completed
|
||
// mockEnv.mockState.filesystem.installingLockExists = false
|
||
// mockEnv.mockState.filesystem.installedLockExists = true
|
||
|
||
// const status = await installDeps.getInstallationStatus()
|
||
|
||
// expect(status.isInstalling).toBe(false)
|
||
// expect(status.hasLockFile).toBe(true)
|
||
// expect(status.installedExists).toBe(true)
|
||
// })
|
||
|
||
// it('should return correct status when no installation has occurred', async () => {
|
||
// mockEnv.mockState.filesystem.installingLockExists = false
|
||
// mockEnv.mockState.filesystem.installedLockExists = false
|
||
|
||
// const status = await installDeps.getInstallationStatus()
|
||
|
||
// expect(status.isInstalling).toBe(false)
|
||
// expect(status.hasLockFile).toBe(false)
|
||
// expect(status.installedExists).toBe(false)
|
||
// })
|
||
|
||
// it('should handle file system errors gracefully', async () => {
|
||
// // Mock fs.existsSync to throw an error
|
||
// mockEnv.fsMock.existsSync.mockImplementation(() => {
|
||
// throw new Error('File system error')
|
||
// })
|
||
|
||
// const status = await installDeps.getInstallationStatus()
|
||
|
||
// expect(status.isInstalling).toBe(false)
|
||
// expect(status.hasLockFile).toBe(false)
|
||
// expect(status.installedExists).toBe(false)
|
||
// })
|
||
// })
|
||
|
||
// describe('installDependencies', () => {
|
||
// it('should successfully install dependencies with default settings', async () => {
|
||
// // Set up successful installation scenario
|
||
// mockEnv.mockState.processes.uvAvailable = true
|
||
// mockEnv.mockState.network.canConnectToDefault = true
|
||
|
||
// const result = await installDeps.installDependencies('1.0.0')
|
||
|
||
// expect(result.success).toBe(true)
|
||
// expect(result.message).toContain('Dependencies installed successfully')
|
||
// expect(mockEnv.fsMock.writeFileSync).toHaveBeenCalledWith(
|
||
// expect.stringContaining('uv_installed.lock'),
|
||
// ''
|
||
// )
|
||
// })
|
||
|
||
// it('should fall back to mirror when default fails', async () => {
|
||
// // Set up network issues scenario - first install fails, mirror succeeds
|
||
// mockEnv.scenarios.networkIssues()
|
||
|
||
// const result = await installDeps.installDependencies('1.0.0')
|
||
|
||
// expect(result.success).toBe(true)
|
||
// expect(result.message).toContain('Dependencies installed successfully with mirror')
|
||
// })
|
||
|
||
// it('should fail when both default and mirror fail', async () => {
|
||
// mockEnv.scenarios.completeFailure()
|
||
|
||
// const result = await installDeps.installDependencies('1.0.0')
|
||
|
||
// expect(result.success).toBe(false)
|
||
// expect(result.message).toContain('Both default and mirror install failed')
|
||
// })
|
||
|
||
// it('should handle command tool installation failure', async () => {
|
||
// // Set up scenario where command tool installation fails
|
||
// mockEnv.mockState.filesystem.binariesExist = { 'uv': false, 'bun': false }
|
||
|
||
// // Mock tools to remain unavailable
|
||
// mockEnv.processUtilsMock.isBinaryExists.mockResolvedValue(false)
|
||
|
||
// const result = await installDeps.installDependencies('1.0.0')
|
||
|
||
// expect(result.success).toBe(false)
|
||
// expect(result.message).toContain('Command tool installation failed')
|
||
// })
|
||
|
||
// it('should create and clean up lock files correctly', async () => {
|
||
// mockEnv.mockState.processes.uvAvailable = true
|
||
// mockEnv.mockState.network.canConnectToDefault = true
|
||
|
||
// await installDeps.installDependencies('1.0.0')
|
||
|
||
// // Verify that installation lock is created and then cleaned up
|
||
// expect(mockEnv.fsMock.writeFileSync).toHaveBeenCalledWith(
|
||
// expect.stringContaining('uv_installing.lock'),
|
||
// ''
|
||
// )
|
||
// expect(mockEnv.fsMock.unlinkSync).toHaveBeenCalledWith(
|
||
// expect.stringContaining('uv_installing.lock')
|
||
// )
|
||
// expect(mockEnv.fsMock.writeFileSync).toHaveBeenCalledWith(
|
||
// expect.stringContaining('uv_installed.lock'),
|
||
// ''
|
||
// )
|
||
// })
|
||
|
||
// it('should clean up old virtual environments after successful installation', async () => {
|
||
// mockEnv.scenarios.multipleOldVenvs('1.0.0')
|
||
// mockEnv.mockState.processes.uvAvailable = true
|
||
// mockEnv.mockState.network.canConnectToDefault = true
|
||
|
||
// await installDeps.installDependencies('1.0.0')
|
||
|
||
// expect(mockEnv.processUtilsMock.cleanupOldVenvs).toHaveBeenCalledWith('1.0.0')
|
||
// })
|
||
// })
|
||
|
||
// describe('detectInstallationLogs', () => {
|
||
// beforeEach(() => {
|
||
// // Reset the module-level state variables
|
||
// vi.resetModules()
|
||
// })
|
||
|
||
// it('should detect UV dependency installation patterns', () => {
|
||
// const installationPatterns = [
|
||
// 'Resolved 10 packages in 1.2s',
|
||
// 'Downloaded package xyz',
|
||
// 'Installing numpy==1.21.0',
|
||
// 'Built wheel for package',
|
||
// 'Prepared virtual environment',
|
||
// 'Syncing dependencies',
|
||
// 'Creating virtualenv at .venv',
|
||
// 'Updating package index',
|
||
// 'Audited 15 packages'
|
||
// ]
|
||
|
||
// installationPatterns.forEach(pattern => {
|
||
// // The function has side effects, so we can't easily test return values
|
||
// // Instead, we test that it doesn't throw and processes the input
|
||
// expect(() => installDeps.detectInstallationLogs(pattern)).not.toThrow()
|
||
// })
|
||
// })
|
||
|
||
// it('should handle uvicorn startup messages', () => {
|
||
// const uvicornMessages = [
|
||
// 'Uvicorn running on http://127.0.0.1:8000',
|
||
// 'Application startup complete',
|
||
// 'Server started successfully'
|
||
// ]
|
||
|
||
// uvicornMessages.forEach(message => {
|
||
// expect(() => installDeps.detectInstallationLogs(message)).not.toThrow()
|
||
// })
|
||
// })
|
||
|
||
// it('should handle installation failure messages', () => {
|
||
// const failureMessages = [
|
||
// '× No solution found when resolving dependencies',
|
||
// 'failed to resolve dependencies',
|
||
// 'installation failed'
|
||
// ]
|
||
|
||
// failureMessages.forEach(message => {
|
||
// expect(() => installDeps.detectInstallationLogs(message)).not.toThrow()
|
||
// })
|
||
// })
|
||
// })
|
||
|
||
// describe('Error Handling and Edge Cases', () => {
|
||
// it('should handle file system permission errors gracefully', async () => {
|
||
// // Mock filesystem error
|
||
// mockEnv.fsMock.writeFileSync.mockImplementation((path: string) => {
|
||
// if (path.includes('version.txt')) {
|
||
// throw new Error('Permission denied')
|
||
// }
|
||
// })
|
||
|
||
// const mockWin = {
|
||
// webContents: { send: vi.fn() },
|
||
// isDestroyed: vi.fn().mockReturnValue(false)
|
||
// }
|
||
|
||
// // The function should handle errors gracefully
|
||
// const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
// win: mockWin,
|
||
// forceInstall: true
|
||
// })
|
||
|
||
// // Should still return a result, even if there are file system errors
|
||
// expect(result).toBeDefined()
|
||
// expect(typeof result.success).toBe('boolean')
|
||
// expect(typeof result.message).toBe('string')
|
||
// })
|
||
|
||
// it('should handle timezone-based mirror selection for China', async () => {
|
||
// // Mock Intl.DateTimeFormat for China timezone
|
||
// const originalDateTimeFormat = global.Intl.DateTimeFormat
|
||
// const mockDateTimeFormat = vi.fn().mockImplementation(() => ({
|
||
// resolvedOptions: () => ({ timeZone: 'Asia/Shanghai' })
|
||
// })) as any
|
||
// global.Intl.DateTimeFormat = mockDateTimeFormat
|
||
|
||
// try {
|
||
// // Set up scenario where default fails but mirror succeeds
|
||
// mockEnv.scenarios.networkIssues()
|
||
|
||
// const result = await installDeps.installDependencies('1.0.0')
|
||
|
||
// expect(result.success).toBe(true)
|
||
// expect(result.message).toContain('Dependencies installed successfully with mirror')
|
||
// } finally {
|
||
// // Restore original
|
||
// global.Intl.DateTimeFormat = originalDateTimeFormat
|
||
// }
|
||
// })
|
||
|
||
// it('should handle invalid version strings', async () => {
|
||
// const result = await installDeps.installDependencies('')
|
||
|
||
// // Should handle empty version string gracefully
|
||
// expect(result).toBeDefined()
|
||
// expect(typeof result.success).toBe('boolean')
|
||
// })
|
||
|
||
// it('should handle missing backend directory', async () => {
|
||
// mockEnv.mockState.filesystem.backendPathExists = false
|
||
|
||
// const result = await installDeps.installDependencies('1.0.0')
|
||
|
||
// // Should create the directory and continue
|
||
// expect(mockEnv.fsMock.mkdirSync).toHaveBeenCalledWith(
|
||
// expect.stringContaining('backend'),
|
||
// { recursive: true }
|
||
// )
|
||
// expect(result).toBeDefined()
|
||
// })
|
||
// })
|
||
|
||
// describe('Integration Tests', () => {
|
||
// it('should handle complete fresh installation workflow', async () => {
|
||
// // Set up completely fresh system
|
||
// mockEnv.scenarios.freshInstall()
|
||
|
||
// const mockWin = {
|
||
// webContents: { send: vi.fn() },
|
||
// isDestroyed: vi.fn().mockReturnValue(false)
|
||
// }
|
||
|
||
// const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
// win: mockWin,
|
||
// forceInstall: false
|
||
// })
|
||
|
||
// expect(result.success).toBe(true)
|
||
// expect(mockWin.webContents.send).toHaveBeenCalledWith(
|
||
// 'update-notification',
|
||
// expect.objectContaining({
|
||
// type: 'version-update',
|
||
// reason: 'version file not exist'
|
||
// })
|
||
// )
|
||
// })
|
||
|
||
// it('should handle version update with missing tools', async () => {
|
||
// // Version file exists but tools are missing
|
||
// mockEnv.mockState.filesystem.versionFileExists = true
|
||
// mockEnv.mockState.filesystem.versionFileContent = '0.9.0'
|
||
// mockEnv.mockState.app.currentVersion = '1.0.0'
|
||
// mockEnv.mockState.filesystem.binariesExist = { 'uv': false, 'bun': false }
|
||
|
||
// const mockWin = {
|
||
// webContents: { send: vi.fn() },
|
||
// isDestroyed: vi.fn().mockReturnValue(false)
|
||
// }
|
||
|
||
// const result = await installDeps.checkAndInstallDepsOnUpdate({
|
||
// win: mockWin,
|
||
// forceInstall: false
|
||
// })
|
||
|
||
// expect(result.success).toBe(true)
|
||
// expect(mockWin.webContents.send).toHaveBeenCalledWith(
|
||
// 'update-notification',
|
||
// expect.objectContaining({
|
||
// type: 'version-update',
|
||
// currentVersion: '1.0.0',
|
||
// previousVersion: '0.9.0',
|
||
// reason: 'version not match'
|
||
// })
|
||
// )
|
||
// })
|
||
// })
|
||
// })
|