Skip to content
Draft
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
23 changes: 22 additions & 1 deletion src/main-process/comfyInstallation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import log from 'electron-log/main';
import { rm } from 'node:fs/promises';

import { ComfyConfigManager } from '../config/comfyConfigManager';

Check failure on line 4 in src/main-process/comfyInstallation.ts

View workflow job for this annotation

GitHub Actions / lint-and-format (windows-latest)

tests/unit/main-process/comfyInstallation.test.ts

Error: [vitest] There was an error when mocking a module. If you are using "vi.mock" factory, make sure there are no top level variables inside, since this call is hoisted to top of the file. Read more: https://vitest.dev/api/vi.html#vi-mock ❯ src/main-process/comfyInstallation.ts:4:1 Caused by: Caused by: ReferenceError: Cannot access 'createDirectories' before initialization ❯ tests/unit/main-process/comfyInstallation.test.ts:24:29 ❯ src/main-process/comfyInstallation.ts:4:1
import { ComfyServerConfig } from '../config/comfyServerConfig';
import { ComfySettings, useComfySettings } from '../config/comfySettings';
import { evaluatePathRestrictions } from '../handlers/pathHandlers';
Expand Down Expand Up @@ -135,7 +136,8 @@
} else {
await this.updateBasePathAndVenv(basePath);

validation.basePath = 'OK';
const hasDirectories = this.ensureBaseDirectoryStructure(basePath);
validation.basePath = hasDirectories ? 'OK' : 'error';
}

this.onUpdate?.(validation);
Expand Down Expand Up @@ -260,4 +262,23 @@
}
await useDesktopConfig().permanentlyDeleteConfigFile();
}

/**
* Ensure the base path contains the expected ComfyUI directory structure.
* Creates missing directories; returns false if the structure is still invalid.
*/
private ensureBaseDirectoryStructure(basePath: string): boolean {
try {
ComfyConfigManager.createComfyDirectories(basePath);
} catch (error) {
log.error('Failed to create ComfyUI directories at base path.', error);
return false;
}

const isValid = ComfyConfigManager.isComfyUIDirectory(basePath);
if (!isValid) {
log.error(`Base path is missing required ComfyUI directories after creation attempt. [${basePath}]`);
}
return isValid;
}
}
97 changes: 97 additions & 0 deletions tests/unit/main-process/comfyInstallation.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';

import { ComfyInstallation } from '@/main-process/comfyInstallation';
import type { ITelemetry } from '@/services/telemetry';

vi.mock('electron-log/main', () => ({
default: {
info: vi.fn(),
warn: vi.fn(),
error: vi.fn(),
verbose: vi.fn(),
},
}));

vi.mock('@/virtualEnvironment', () => ({
VirtualEnvironment: vi.fn(() => ({})),
}));

const createDirectories = vi.fn();
const isComfyDirectory = vi.fn();

vi.mock('@/config/comfyConfigManager', () => ({
ComfyConfigManager: {
createComfyDirectories: createDirectories,
isComfyUIDirectory: isComfyDirectory,
},
}));

vi.mock('@/store/desktopConfig', () => ({
useDesktopConfig: vi.fn(() => ({
get: vi.fn((key: string) => {
if (key === 'selectedDevice') return 'cpu';
if (key === 'basePath') return '/base/path';
return undefined;
}),
set: vi.fn(),
})),
}));

vi.mock('@/config/comfySettings', () => ({
useComfySettings: vi.fn(() => ({
get: vi.fn(),
set: vi.fn(),
})),
ComfySettings: {
load: vi.fn(),
},
}));

const telemetry: ITelemetry = {
track: vi.fn(),
hasConsent: true,
flush: vi.fn(),
registerHandlers: vi.fn(),
loadGenerationCount: vi.fn(),
};

describe('ComfyInstallation.ensureBaseDirectoryStructure', () => {
const basePath = '/base/path';
let installation: ComfyInstallation;

beforeEach(() => {
vi.clearAllMocks();
installation = new ComfyInstallation('installed', basePath, telemetry);
Comment on lines +62 to +64

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reset mock implementation between tests

The second test replaces createComfyDirectories with a throwing implementation (lines 77‑80), but the beforeEach only calls vi.clearAllMocks (lines 62‑64), which clears call history without restoring implementations. As a result, the third test still uses the throwing mock and will fail before reaching isComfyDirectory, so the new suite is red as soon as the failing mock is set. Reset the mock implementation (e.g., mockReset/resetAllMocks) or reassign it per test so the later cases run with the intended behavior.

Useful? React with 👍 / 👎.

});

it('creates and validates directory structure', () => {
isComfyDirectory.mockReturnValue(true);

const result = (installation as any).ensureBaseDirectoryStructure(basePath);

expect(result).toBe(true);
expect(createDirectories).toHaveBeenCalledWith(basePath);
expect(isComfyDirectory).toHaveBeenCalledWith(basePath);
});

it('returns false when directory creation throws', () => {
createDirectories.mockImplementation(() => {
throw new Error('fail');
});

const result = (installation as any).ensureBaseDirectoryStructure(basePath);

expect(result).toBe(false);
expect(isComfyDirectory).not.toHaveBeenCalled();
});

it('returns false when directory validation fails', () => {
isComfyDirectory.mockReturnValue(false);

const result = (installation as any).ensureBaseDirectoryStructure(basePath);

expect(result).toBe(false);
expect(createDirectories).toHaveBeenCalledWith(basePath);
expect(isComfyDirectory).toHaveBeenCalledWith(basePath);
});
});
Loading