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>
349 lines
9.3 KiB
TypeScript
349 lines
9.3 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 { setupElectronMocks, TestScenarios } from './electronMocks';
|
|
import { setupMockEnvironment } from './environmentMocks';
|
|
|
|
/**
|
|
* Complete test setup utility that combines all mocks and provides
|
|
* easy-to-use functions for testing installation flows
|
|
*/
|
|
export function createTestEnvironment() {
|
|
const { electronAPI, ipcRenderer } = setupElectronMocks();
|
|
const mockEnv = setupMockEnvironment();
|
|
|
|
return {
|
|
electronAPI,
|
|
ipcRenderer,
|
|
mockEnv,
|
|
|
|
// Quick scenario setups
|
|
scenarios: {
|
|
/**
|
|
* Fresh installation - no .venv, no version file, tools not installed
|
|
*/
|
|
freshInstall: () => {
|
|
TestScenarios.freshInstall(electronAPI);
|
|
mockEnv.scenarios.freshInstall();
|
|
},
|
|
|
|
/**
|
|
* Version update - version file exists but version changed
|
|
*/
|
|
versionUpdate: (
|
|
oldVersion: string = '0.9.0',
|
|
newVersion: string = '1.0.0'
|
|
) => {
|
|
TestScenarios.versionUpdate(electronAPI);
|
|
mockEnv.scenarios.versionUpdate(oldVersion, newVersion);
|
|
},
|
|
|
|
/**
|
|
* .venv removed - version file exists but .venv is missing
|
|
*/
|
|
venvRemoved: () => {
|
|
TestScenarios.venvRemoved(electronAPI);
|
|
mockEnv.scenarios.venvRemoved();
|
|
},
|
|
|
|
/**
|
|
* Installation in progress - when user opens app during installation
|
|
*/
|
|
installationInProgress: () => {
|
|
TestScenarios.installationInProgress(electronAPI);
|
|
mockEnv.scenarios.installationInProgress();
|
|
},
|
|
|
|
/**
|
|
* Installation error - installation fails
|
|
*/
|
|
installationError: () => {
|
|
TestScenarios.installationError(electronAPI);
|
|
mockEnv.scenarios.completeFailure();
|
|
},
|
|
|
|
/**
|
|
* Uvicorn startup with dependency installation
|
|
*/
|
|
uvicornDepsInstall: () => {
|
|
TestScenarios.uvicornDepsInstall(electronAPI);
|
|
mockEnv.scenarios.uvicornStartupInstall();
|
|
},
|
|
|
|
/**
|
|
* Network issues - default mirror fails, backup succeeds
|
|
*/
|
|
networkIssues: () => {
|
|
TestScenarios.allGood(electronAPI);
|
|
mockEnv.scenarios.networkIssues();
|
|
},
|
|
|
|
/**
|
|
* All good - no installation needed
|
|
*/
|
|
allGood: () => {
|
|
TestScenarios.allGood(electronAPI);
|
|
// Use default mockEnv state (all good)
|
|
},
|
|
},
|
|
|
|
// Simulation utilities
|
|
simulate: {
|
|
/**
|
|
* Simulate a complete successful installation flow
|
|
*/
|
|
successfulInstallation: async (delay: number = 100) => {
|
|
electronAPI.simulateInstallationStart();
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Resolving dependencies...'
|
|
);
|
|
}, delay);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Downloading packages...'
|
|
);
|
|
}, delay * 2);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Installing packages...'
|
|
);
|
|
}, delay * 3);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationComplete(true);
|
|
}, delay * 4);
|
|
},
|
|
|
|
/**
|
|
* Simulate a failed installation flow
|
|
*/
|
|
failedInstallation: async (
|
|
delay: number = 100,
|
|
errorMessage: string = 'Installation failed'
|
|
) => {
|
|
electronAPI.simulateInstallationStart();
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Resolving dependencies...'
|
|
);
|
|
}, delay);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stderr',
|
|
`Error: ${errorMessage}`
|
|
);
|
|
}, delay * 2);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationComplete(false, errorMessage);
|
|
}, delay * 3);
|
|
},
|
|
|
|
/**
|
|
* Simulate uvicorn startup that detects missing dependencies
|
|
*/
|
|
uvicornWithDeps: async (delay: number = 100) => {
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Uvicorn detected missing dependencies'
|
|
);
|
|
}, delay);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationStart();
|
|
}, delay * 2);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Resolving dependencies...'
|
|
);
|
|
}, delay * 3);
|
|
|
|
setTimeout(() => {
|
|
electronAPI.simulateInstallationLog(
|
|
'stdout',
|
|
'Uvicorn running on http://127.0.0.1:8000'
|
|
);
|
|
electronAPI.simulateInstallationComplete(true);
|
|
}, delay * 4);
|
|
},
|
|
},
|
|
|
|
// State inspection utilities
|
|
inspect: {
|
|
/**
|
|
* Get current installation state summary
|
|
*/
|
|
getInstallationState: () => ({
|
|
electronState: electronAPI.mockState,
|
|
envState: mockEnv.mockState,
|
|
isInstalling:
|
|
electronAPI.mockState.isInstalling ||
|
|
mockEnv.mockState.processes.installationInProgress,
|
|
hasLockFiles:
|
|
mockEnv.mockState.filesystem.installingLockExists ||
|
|
mockEnv.mockState.filesystem.installedLockExists,
|
|
toolsAvailable:
|
|
mockEnv.mockState.processes.uvAvailable &&
|
|
mockEnv.mockState.processes.bunAvailable,
|
|
venvExists:
|
|
electronAPI.mockState.venvExists &&
|
|
mockEnv.mockState.filesystem.venvExists,
|
|
}),
|
|
|
|
/**
|
|
* Check if environment is in expected state for a scenario
|
|
*/
|
|
verifyScenario: (scenarioName: string) => {
|
|
const state = mockEnv.mockState;
|
|
const electronState = electronAPI.mockState;
|
|
|
|
switch (scenarioName) {
|
|
case 'freshInstall':
|
|
return (
|
|
!state.filesystem.venvExists &&
|
|
!state.filesystem.versionFileExists &&
|
|
!electronState.toolInstalled
|
|
);
|
|
|
|
case 'versionUpdate':
|
|
return (
|
|
state.filesystem.versionFileExists &&
|
|
state.app.currentVersion !== state.filesystem.versionFileContent
|
|
);
|
|
|
|
case 'venvRemoved':
|
|
return (
|
|
!state.filesystem.venvExists && state.filesystem.versionFileExists
|
|
);
|
|
|
|
case 'installationInProgress':
|
|
return (
|
|
state.filesystem.installingLockExists ||
|
|
electronState.isInstalling
|
|
);
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
},
|
|
},
|
|
|
|
// Reset everything
|
|
reset: () => {
|
|
electronAPI.reset();
|
|
mockEnv.reset();
|
|
},
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Helper function to wait for installation state changes
|
|
*/
|
|
export async function waitForInstallationState(
|
|
getState: () => any,
|
|
expectedState: string,
|
|
timeout: number = 1000
|
|
): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const startTime = Date.now();
|
|
|
|
const check = () => {
|
|
if (getState().state === expectedState) {
|
|
resolve();
|
|
} else if (Date.now() - startTime > timeout) {
|
|
reject(
|
|
new Error(
|
|
`Timeout waiting for state ${expectedState}, current: ${getState().state}`
|
|
)
|
|
);
|
|
} else {
|
|
setTimeout(check, 10);
|
|
}
|
|
};
|
|
|
|
check();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Helper function to wait for multiple logs
|
|
*/
|
|
export async function waitForLogs(
|
|
getLogs: () => any[],
|
|
expectedCount: number,
|
|
timeout: number = 1000
|
|
): Promise<void> {
|
|
return new Promise((resolve, reject) => {
|
|
const startTime = Date.now();
|
|
|
|
const check = () => {
|
|
if (getLogs().length >= expectedCount) {
|
|
resolve();
|
|
} else if (Date.now() - startTime > timeout) {
|
|
reject(
|
|
new Error(
|
|
`Timeout waiting for ${expectedCount} logs, got: ${getLogs().length}`
|
|
)
|
|
);
|
|
} else {
|
|
setTimeout(check, 10);
|
|
}
|
|
};
|
|
|
|
check();
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Example usage in tests:
|
|
*
|
|
* ```typescript
|
|
* import { createTestEnvironment, waitForInstallationState } from '../mocks/testUtils'
|
|
*
|
|
* describe('Installation Flow', () => {
|
|
* let testEnv: ReturnType<typeof createTestEnvironment>
|
|
*
|
|
* beforeEach(() => {
|
|
* testEnv = createTestEnvironment()
|
|
* })
|
|
*
|
|
* it('should handle fresh installation', async () => {
|
|
* testEnv.scenarios.freshInstall()
|
|
*
|
|
* // Verify scenario setup
|
|
* expect(testEnv.inspect.verifyScenario('freshInstall')).toBe(true)
|
|
*
|
|
* // Simulate installation
|
|
* await testEnv.simulate.successfulInstallation()
|
|
*
|
|
* // Verify result
|
|
* const state = testEnv.inspect.getInstallationState()
|
|
* expect(state.isInstalling).toBe(false)
|
|
* })
|
|
* })
|
|
* ```
|
|
*/
|