Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62634b5511 | ||
|
|
27223f587d | ||
|
|
1d35801980 | ||
|
|
269ad18ed6 | ||
|
|
9b9b977ae6 | ||
|
|
f4daaa8ca1 |
No files matched your search
@@ -2,6 +2,18 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## [0.15.1](https://github.com/evandrodevbr/GeminiNexus/compare/v0.15.0...v0.15.1) (2026-05-02)
|
||||
|
||||
### ✅ Tests
|
||||
|
||||
* add universal electron mock to fix headless CI test runs ([1d35801](https://github.com/evandrodevbr/GeminiNexus/commit/1d35801980e3e54cec1d3e52ed75850eb7eec350))
|
||||
* fix test environments failing due to missing IS_DEV_ENVIRONMENT mock export ([269ad18](https://github.com/evandrodevbr/GeminiNexus/commit/269ad18ed6c09585e881d0d916558b1bcc7ad940))
|
||||
* update proxy-advanced-handler tests to reflect optional service registration ([f4daaa8](https://github.com/evandrodevbr/GeminiNexus/commit/f4daaa8ca13bc75c7e5090905176c06b61ecfedc))
|
||||
|
||||
### 👷 Build System
|
||||
|
||||
* replace MakerSquirrel with MakerZIP for Windows ([27223f5](https://github.com/evandrodevbr/GeminiNexus/commit/27223f587d7facf25beef77aa6984cd248f2703d))
|
||||
|
||||
## [0.15.0](https://github.com/evandrodevbr/GeminiNexus/compare/v0.14.0...v0.15.0) (2026-05-02)
|
||||
|
||||
### ✨ Features
|
||||
|
||||
+1
-6
@@ -10,7 +10,6 @@ import type {
|
||||
import { MakerDeb } from '@electron-forge/maker-deb';
|
||||
import { MakerDMG } from '@electron-forge/maker-dmg';
|
||||
import { MakerRpm } from '@electron-forge/maker-rpm';
|
||||
import { MakerSquirrel } from '@electron-forge/maker-squirrel';
|
||||
import { MakerWix } from '@electron-forge/maker-wix';
|
||||
import { MakerZIP } from '@electron-forge/maker-zip';
|
||||
import { AutoUnpackNativesPlugin } from '@electron-forge/plugin-auto-unpack-natives';
|
||||
@@ -441,10 +440,6 @@ const config: ForgeConfig = {
|
||||
},
|
||||
},
|
||||
makers: [
|
||||
new MakerSquirrel({
|
||||
setupIcon: 'images/icon.ico',
|
||||
iconUrl: 'https://raw.githubusercontent.com/evandrodevbr/GeminiNexus/main/images/icon.ico',
|
||||
}),
|
||||
...(process.platform === 'win32' && process.arch === 'x64' && isWixAvailable()
|
||||
? [
|
||||
new MakerWix({
|
||||
@@ -463,7 +458,7 @@ const config: ForgeConfig = {
|
||||
},
|
||||
['darwin'],
|
||||
),
|
||||
new MakerZIP({}, ['darwin']),
|
||||
new MakerZIP({}, ['darwin', 'win32']),
|
||||
appImageMaker,
|
||||
new MakerRpm({}),
|
||||
new MakerDeb({}),
|
||||
|
||||
+1
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "gemini-nexus",
|
||||
"productName": "Gemini Nexus",
|
||||
"version": "0.15.0",
|
||||
"version": "0.15.1",
|
||||
"description": "Gemini Nexus - Electron App",
|
||||
"main": ".vite/build/main.js",
|
||||
"private": true,
|
||||
@@ -32,7 +32,6 @@
|
||||
"@electron-forge/maker-deb": "^7.11.1",
|
||||
"@electron-forge/maker-dmg": "^7.11.1",
|
||||
"@electron-forge/maker-rpm": "^7.11.1",
|
||||
"@electron-forge/maker-squirrel": "^7.11.1",
|
||||
"@electron-forge/maker-wix": "^7.9.0",
|
||||
"@electron-forge/maker-zip": "^7.11.1",
|
||||
"@electron-forge/plugin-auto-unpack-natives": "^7.11.1",
|
||||
|
||||
Generated
+2986
-8662
File diff suppressed because it is too large.
Load diff
@@ -16,7 +16,8 @@ import { getSwitchGuardSnapshot } from '../../ipc/switchGuard';
|
||||
vi.mock('../../utils/paths', async () => {
|
||||
const path = await import('path');
|
||||
const agentDir = path.join(process.cwd(), 'temp_test_agent');
|
||||
return {
|
||||
return {
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getAgentDir: vi.fn(() => agentDir),
|
||||
getAccountsFilePath: vi.fn(() => path.join(agentDir, 'accounts.json')),
|
||||
getBackupsDir: vi.fn(() => path.join(agentDir, 'backups')),
|
||||
|
||||
@@ -57,7 +57,8 @@ vi.mock('../../ipc/database/dbConnection', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getGeminiNexusDbPaths: () => ['mock-db'],
|
||||
getCloudAccountsDbPath: () => 'mock-cloud-db',
|
||||
getAgentDir: vi.fn(() => '/mock/agent/dir'),
|
||||
|
||||
@@ -21,7 +21,8 @@ vi.mock('../../ipc/database/dbConnection', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getGeminiNexusDbPaths: () => ['mock-db'],
|
||||
}));
|
||||
|
||||
|
||||
@@ -47,7 +47,8 @@ vi.mock('../../utils/logger', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getGeminiNexusDbPaths: vi.fn().mockReturnValue(['/tmp/test.vscdb']),
|
||||
}));
|
||||
|
||||
|
||||
@@ -64,7 +64,8 @@ vi.mock('../../../ipc/database/dbConnection', () => ({
|
||||
configureDatabase: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getCloudAccountsDbPath: vi.fn(() => '/mock/db/path.sqlite'),
|
||||
}));
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ vi.mock('../../../utils/logger', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getGeminiNexusDbPaths: vi.fn().mockReturnValue(['/tmp/test.vscdb']),
|
||||
}));
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ vi.mock('../../../utils/logger', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getGeminiNexusStoragePaths: vi.fn().mockReturnValue(['/tmp/storage.json']),
|
||||
getGeminiNexusDbPaths: vi.fn().mockReturnValue(['/tmp/state.vscdb']),
|
||||
getAgentDir: vi.fn().mockReturnValue('/tmp/agent'),
|
||||
|
||||
@@ -48,14 +48,19 @@ vi.mock('../../../ipc/proxy-advanced/service-registry', () => {
|
||||
function getServiceOrThrow(key: string) {
|
||||
const service = (proxyAdvancedRegistry as Record<string, unknown>)[key];
|
||||
if (!service) {
|
||||
throw new Error(`${key} is not registered`);
|
||||
throw new Error(`ProxyAdvanced service '${key}' is not registered`);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
function getServiceOptional(key: string) {
|
||||
return (proxyAdvancedRegistry as Record<string, unknown>)[key];
|
||||
}
|
||||
|
||||
return {
|
||||
proxyAdvancedRegistry,
|
||||
getServiceOrThrow,
|
||||
getServiceOptional,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -176,10 +181,10 @@ describe('Proxy Advanced Handler', () => {
|
||||
});
|
||||
|
||||
describe('getParityCounters', () => {
|
||||
it('should return error when tokenManager is null', async () => {
|
||||
it('should return empty counters when tokenManager is null', async () => {
|
||||
const result = await getParityCounters();
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Proxy advanced service not initialized');
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data?.totalRequests).toBe(0);
|
||||
});
|
||||
|
||||
it('should return counters from tokenManager', async () => {
|
||||
@@ -200,10 +205,10 @@ describe('Proxy Advanced Handler', () => {
|
||||
});
|
||||
|
||||
describe('getCircuitBreakerStatus', () => {
|
||||
it('should return error when tokenManager is null', async () => {
|
||||
it('should return empty status when tokenManager is null', async () => {
|
||||
const result = await getCircuitBreakerStatus();
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Proxy advanced service not initialized');
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data?.states).toEqual({});
|
||||
});
|
||||
|
||||
it('should return mapped status from tokenManager', async () => {
|
||||
@@ -222,10 +227,10 @@ describe('Proxy Advanced Handler', () => {
|
||||
});
|
||||
|
||||
describe('getProxyMetrics', () => {
|
||||
it('should return error when proxyMetrics is null', async () => {
|
||||
it('should return zero metrics when proxyMetrics is null', async () => {
|
||||
const result = await getProxyMetrics();
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Proxy advanced service not initialized');
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data?.totalRequests).toBe(0);
|
||||
});
|
||||
|
||||
it('should return metrics from proxyMetrics service', async () => {
|
||||
@@ -249,10 +254,10 @@ describe('Proxy Advanced Handler', () => {
|
||||
});
|
||||
|
||||
describe('getRecentRequests', () => {
|
||||
it('should return error when proxyReplay is null', async () => {
|
||||
it('should return empty array when proxyReplay is null', async () => {
|
||||
const result = await getRecentRequests();
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Proxy advanced service not initialized');
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return recent requests from proxyReplay', async () => {
|
||||
@@ -410,10 +415,10 @@ describe('Proxy Advanced Handler', () => {
|
||||
});
|
||||
|
||||
describe('generateIdeConfig', () => {
|
||||
it('should return error when proxyIdeConfig is null', async () => {
|
||||
it('should generate fallback config when proxyIdeConfig is null', async () => {
|
||||
const result = await generateIdeConfig('vscode');
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Proxy advanced service not initialized');
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.data?.name).toBe('VS Code');
|
||||
});
|
||||
|
||||
it('should return error for unsupported IDE', async () => {
|
||||
@@ -428,7 +433,8 @@ describe('Proxy Advanced Handler', () => {
|
||||
vi.mocked(proxyAdvancedRegistry).proxyIdeConfig = {
|
||||
generateConfigForCurrentServer: vi.fn().mockReturnValue({
|
||||
ide: 'vscode',
|
||||
content: null,
|
||||
format: 'json',
|
||||
content: { 'openai.url': 'http://localhost:8045/v1', 'openai.apiKey': 'key' },
|
||||
}),
|
||||
} as any;
|
||||
|
||||
@@ -443,7 +449,8 @@ describe('Proxy Advanced Handler', () => {
|
||||
vi.mocked(proxyAdvancedRegistry).proxyIdeConfig = {
|
||||
generateConfigForCurrentServer: vi.fn().mockReturnValue({
|
||||
ide: 'cursor',
|
||||
content: null,
|
||||
format: 'json',
|
||||
content: { OPENAI_BASE_URL: 'http://localhost:8045/v1', OPENAI_API_KEY: 'key' },
|
||||
}),
|
||||
} as any;
|
||||
|
||||
@@ -453,16 +460,5 @@ describe('Proxy Advanced Handler', () => {
|
||||
expect(result.data?.proxySetting).toBe('OPENAI_BASE_URL');
|
||||
vi.mocked(proxyAdvancedRegistry).proxyIdeConfig = null;
|
||||
});
|
||||
|
||||
it('should handle null result from config generator', async () => {
|
||||
vi.mocked(proxyAdvancedRegistry).proxyIdeConfig = {
|
||||
generateConfigForCurrentServer: vi.fn().mockReturnValue(null),
|
||||
} as any;
|
||||
|
||||
const result = await generateIdeConfig('vscode');
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.error).toBe('Failed to generate IDE config: server not configured');
|
||||
vi.mocked(proxyAdvancedRegistry).proxyIdeConfig = null;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -24,7 +24,8 @@ vi.mock('../../../ipc/database/cloudHandler', () => ({
|
||||
ensureDatabaseInitialized: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
vi.mock('../../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getCloudAccountsDbPath: vi.fn(() => '/mock/db/path.sqlite'),
|
||||
}));
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import path from 'path';
|
||||
|
||||
vi.mock('../../utils/paths', async () => {
|
||||
const path = await import('path');
|
||||
return {
|
||||
return {
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getAgentDir: vi.fn(() => path.join(process.cwd(), 'temp_test_logs')),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -59,3 +59,81 @@ class MockIntersectionObserver {
|
||||
disconnect() {}
|
||||
}
|
||||
(globalThis as any).IntersectionObserver = MockIntersectionObserver;
|
||||
|
||||
// Universal Electron mock for testing environments
|
||||
vi.mock('electron', () => {
|
||||
return {
|
||||
app: {
|
||||
getPath: vi.fn((name) => `/mock/path/${name}`),
|
||||
getName: vi.fn(() => 'Gemini Nexus Test'),
|
||||
getVersion: vi.fn(() => '1.0.0'),
|
||||
isPackaged: false,
|
||||
getLocale: vi.fn(() => 'en-US'),
|
||||
getPreferredSystemLanguages: vi.fn(() => ['en-US']),
|
||||
requestSingleInstanceLock: vi.fn(() => true),
|
||||
quit: vi.fn(),
|
||||
disableHardwareAcceleration: vi.fn(),
|
||||
setName: vi.fn(),
|
||||
commandLine: {
|
||||
appendSwitch: vi.fn(),
|
||||
},
|
||||
},
|
||||
ipcMain: {
|
||||
on: vi.fn(),
|
||||
handle: vi.fn(),
|
||||
removeHandler: vi.fn(),
|
||||
removeAllListeners: vi.fn(),
|
||||
},
|
||||
ipcRenderer: {
|
||||
on: vi.fn(),
|
||||
off: vi.fn(),
|
||||
once: vi.fn(),
|
||||
invoke: vi.fn(),
|
||||
send: vi.fn(),
|
||||
postMessage: vi.fn(),
|
||||
},
|
||||
BrowserWindow: vi.fn().mockImplementation(() => ({
|
||||
loadURL: vi.fn(),
|
||||
loadFile: vi.fn(),
|
||||
show: vi.fn(),
|
||||
close: vi.fn(),
|
||||
destroy: vi.fn(),
|
||||
webContents: {
|
||||
send: vi.fn(),
|
||||
on: vi.fn(),
|
||||
session: {
|
||||
webRequest: {
|
||||
onBeforeSendHeaders: vi.fn(),
|
||||
}
|
||||
}
|
||||
},
|
||||
on: vi.fn(),
|
||||
})),
|
||||
dialog: {
|
||||
showMessageBox: vi.fn().mockResolvedValue({ response: 0 }),
|
||||
showOpenDialog: vi.fn().mockResolvedValue({ canceled: true, filePaths: [] }),
|
||||
showSaveDialog: vi.fn().mockResolvedValue({ canceled: true, filePath: '' }),
|
||||
},
|
||||
shell: {
|
||||
openPath: vi.fn(),
|
||||
openExternal: vi.fn(),
|
||||
},
|
||||
contextBridge: {
|
||||
exposeInMainWorld: vi.fn(),
|
||||
},
|
||||
Tray: vi.fn().mockImplementation(() => ({
|
||||
setToolTip: vi.fn(),
|
||||
setContextMenu: vi.fn(),
|
||||
on: vi.fn(),
|
||||
destroy: vi.fn(),
|
||||
})),
|
||||
Menu: {
|
||||
buildFromTemplate: vi.fn(),
|
||||
},
|
||||
nativeTheme: {
|
||||
themeSource: 'system',
|
||||
shouldUseDarkColors: true,
|
||||
on: vi.fn(),
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -25,7 +25,8 @@ vi.mock('../../ipc/database/cloudHandler', () => ({
|
||||
ensureDatabaseInitialized: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
vi.mock('../../utils/paths', () => ({
|
||||
IS_DEV_ENVIRONMENT: false,
|
||||
getCloudAccountsDbPath: vi.fn(() => '/mock/db/path.sqlite'),
|
||||
}));
|
||||
|
||||
|
||||
Reference in new issue
Block a user