Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions electron/src/preload/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,10 @@ try {
url: string;
releaseNotes?: string;
}> => ipcRenderer.invoke('check-for-updates'),
getAutoCheckUpdates: (): Promise<boolean> =>
ipcRenderer.invoke('get-auto-check-updates'),
setAutoCheckUpdates: (value: boolean): Promise<void> =>
ipcRenderer.invoke('set-auto-check-updates', value),

// App Info
getVersion: (): Promise<string> => ipcRenderer.invoke('get-version'),
Expand Down
177 changes: 177 additions & 0 deletions electron/src/services/ipc/auto-check-updates-handlers.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { ipcMain } from 'electron';
import { setupAutoCheckUpdatesHandlers } from './auto-check-updates-handlers.js';

// Mock electron
vi.mock('electron', () => ({
ipcMain: {
handle: vi.fn(),
on: vi.fn(),
},
}));

describe('Auto-Check Updates Handlers', () => {
const mockPrisma = {
appSettings: {
findUnique: vi.fn(),
create: vi.fn(),
upsert: vi.fn(),
},
};

const mockDbManager = {
getPrisma: vi.fn(() => mockPrisma),
};

beforeEach(() => {
vi.clearAllMocks();
});

describe('setupAutoCheckUpdatesHandlers', () => {
it('should register get-auto-check-updates handler', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

expect(ipcMain.handle).toHaveBeenCalledWith(
'get-auto-check-updates',
expect.any(Function),
);
});

it('should register set-auto-check-updates handler', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

expect(ipcMain.handle).toHaveBeenCalledWith(
'set-auto-check-updates',
expect.any(Function),
);
});
});

describe('get-auto-check-updates handler', () => {
it('should return autoCheckUpdates value from database', async () => {
mockPrisma.appSettings.findUnique.mockResolvedValue({
id: 'app_settings',
darkMode: true,
language: 'es',
autoCheckUpdates: false,
createdAt: new Date(),
updatedAt: new Date(),
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

const handler = (ipcMain.handle as ReturnType<typeof vi.fn>).mock
.calls[0][1];
const result = await handler();

expect(result).toBe(false);
expect(mockPrisma.appSettings.findUnique).toHaveBeenCalledWith({
where: { id: 'app_settings' },
});
});

it('should return true when settings not found and create defaults', async () => {
mockPrisma.appSettings.findUnique.mockResolvedValue(null);
mockPrisma.appSettings.create.mockResolvedValue({
id: 'app_settings',
darkMode: true,
language: 'es',
autoCheckUpdates: true,
createdAt: new Date(),
updatedAt: new Date(),
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

const handler = (ipcMain.handle as ReturnType<typeof vi.fn>).mock
.calls[0][1];
const result = await handler();

expect(result).toBe(true);
expect(mockPrisma.appSettings.create).toHaveBeenCalledWith({
data: { id: 'app_settings', autoCheckUpdates: true },
});
});

it('should return true on database error', async () => {
mockPrisma.appSettings.findUnique.mockRejectedValue(
new Error('Database error'),
);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

const handler = (ipcMain.handle as ReturnType<typeof vi.fn>).mock
.calls[0][1];
const result = await handler();

expect(result).toBe(true);
});
});

describe('set-auto-check-updates handler', () => {
it('should save autoCheckUpdates to database', async () => {
mockPrisma.appSettings.upsert.mockResolvedValue({
id: 'app_settings',
darkMode: true,
language: 'es',
autoCheckUpdates: false,
createdAt: new Date(),
updatedAt: new Date(),
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

const handler = (ipcMain.handle as ReturnType<typeof vi.fn>).mock
.calls[1][1];
await handler({}, false);

expect(mockPrisma.appSettings.upsert).toHaveBeenCalledWith({
where: { id: 'app_settings' },
update: { autoCheckUpdates: false },
create: { id: 'app_settings', autoCheckUpdates: false },
});
});

it('should save true value correctly', async () => {
mockPrisma.appSettings.upsert.mockResolvedValue({
id: 'app_settings',
darkMode: true,
language: 'es',
autoCheckUpdates: true,
createdAt: new Date(),
updatedAt: new Date(),
});

// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

const handler = (ipcMain.handle as ReturnType<typeof vi.fn>).mock
.calls[1][1];
await handler({}, true);

expect(mockPrisma.appSettings.upsert).toHaveBeenCalledWith({
where: { id: 'app_settings' },
update: { autoCheckUpdates: true },
create: { id: 'app_settings', autoCheckUpdates: true },
});
});

it('should throw error on database failure', async () => {
mockPrisma.appSettings.upsert.mockRejectedValue(new Error('DB error'));

// eslint-disable-next-line @typescript-eslint/no-explicit-any
setupAutoCheckUpdatesHandlers(mockDbManager as any);

const handler = (ipcMain.handle as ReturnType<typeof vi.fn>).mock
.calls[1][1];

await expect(handler({}, false)).rejects.toThrow('DB error');
});
});
});
67 changes: 67 additions & 0 deletions electron/src/services/ipc/auto-check-updates-handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { ipcMain } from 'electron';
import { DatabaseManager } from '../database/database.js';

let dbManager: DatabaseManager | null = null;

/**
* Sets up auto-check updates related IPC handlers.
* Manages auto-check preference in app_settings table.
*/
export const setupAutoCheckUpdatesHandlers = (db: DatabaseManager): void => {
dbManager = db;

ipcMain.handle('get-auto-check-updates', async () => {
return getAutoCheckUpdatesFromDb();
});

ipcMain.handle('set-auto-check-updates', async (_event, value: boolean) => {
return saveAutoCheckUpdatesToDb(value);
});
};

/**
* Gets auto-check updates preference from database.
* Defaults to true if no setting exists.
*/
async function getAutoCheckUpdatesFromDb(): Promise<boolean> {
if (!dbManager) return true;

try {
const prisma = dbManager.getPrisma();
const settings = await prisma.appSettings.findUnique({
where: { id: 'app_settings' },
});

if (settings) {
return settings.autoCheckUpdates;
}

// Create default settings if not found
await prisma.appSettings.create({
data: { id: 'app_settings', autoCheckUpdates: true },
});
return true;
} catch (error) {
console.error('Error getting auto-check updates preference:', error);
return true;
}
}

/**
* Saves auto-check updates preference to database.
*/
async function saveAutoCheckUpdatesToDb(value: boolean): Promise<void> {
if (!dbManager) return;

try {
const prisma = dbManager.getPrisma();
await prisma.appSettings.upsert({
where: { id: 'app_settings' },
update: { autoCheckUpdates: value },
create: { id: 'app_settings', autoCheckUpdates: value },
});
} catch (error) {
console.error('Error saving auto-check updates preference:', error);
throw error;
}
}
2 changes: 2 additions & 0 deletions electron/src/services/ipc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { setupThemeHandlers } from './theme-handlers.js';
import { setupLanguageHandlers } from './language-handlers.js';
import { setupBackupHandlers } from './backup-handlers.js';
import { setupUpdateHandlers } from './update-handlers.js';
import { setupAutoCheckUpdatesHandlers } from './auto-check-updates-handlers.js';

import { setupSystemHandlers } from './system-handlers.js';

Expand All @@ -21,6 +22,7 @@ export const setupIpcHandlers = (
setupDatabaseHandlers(dbManager);
setupThemeHandlers(dbManager);
setupLanguageHandlers(dbManager);
setupAutoCheckUpdatesHandlers(dbManager);
}
if (backupService) {
setupBackupHandlers(backupService);
Expand Down
Loading