Skip to content
Closed
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "flycli",
"version": "1.3.1",
"version": "1.4.0",
"description": "A reliable CLI tool for Betaflight flight controller interaction and automation.",
"license": "MIT",
"keywords": [
Expand Down
5 changes: 5 additions & 0 deletions src/infrastructure/cad/EnvironmentManager.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import fs from 'fs/promises';
import path from 'path';

/**
* @module EnvironmentManager
Expand All @@ -16,6 +17,10 @@ const WINDOWS_PATHS = [
'C:\\Program Files\\FreeCAD 0.21\\bin\\FreeCAD.exe',
'C:\\Program Files\\FreeCAD 0.20\\bin\\FreeCAD.exe',
'C:\\Program Files\\FreeCAD 1.0\\bin\\FreeCAD.exe',
// Per-user installations
path.join(process.env.LOCALAPPDATA || '', 'Programs', 'FreeCAD 1.0', 'bin', 'freecad.exe'),
path.join(process.env.LOCALAPPDATA || '', 'Programs', 'FreeCAD 0.21', 'bin', 'freecad.exe'),
path.join(process.env.LOCALAPPDATA || '', 'Programs', 'FreeCAD 0.22', 'bin', 'freecad.exe'),
];

const UNIX_PATHS = [
Expand Down
57 changes: 57 additions & 0 deletions test/unit/EnvironmentManager.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { jest } from '@jest/globals';

// Mock fs/promises
const mockStat = jest.fn();
jest.unstable_mockModule('fs/promises', () => ({
default: {
stat: mockStat,
},
}));

const { EnvironmentManager } = await import('../../src/infrastructure/cad/EnvironmentManager.js');

describe('EnvironmentManager', () => {
beforeEach(() => {
jest.clearAllMocks();
delete process.env.FREECAD_PATH;
});

it('should find FreeCAD using FREECAD_PATH override', async () => {
const customPath = '/custom/path/freecad';
process.env.FREECAD_PATH = customPath;
mockStat.mockResolvedValue({ isFile: () => true });

const env = new EnvironmentManager({ info: jest.fn() });
const found = await env.ensureEnvironmentReady();

expect(found).toBe(customPath);
expect(mockStat).toHaveBeenCalledWith(customPath);
});

it('should find FreeCAD in standard Windows paths', async () => {
// Simulate Windows platform for this test if needed,

Check failure on line 32 in test/unit/EnvironmentManager.test.js

View workflow job for this annotation

GitHub Actions / test (20.x)

Expected a block comment instead of consecutive line comments

Check failure on line 32 in test/unit/EnvironmentManager.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

Expected a block comment instead of consecutive line comments
// but the list is always present in the code.

// Mock the first path as missing and the second as existing

Check failure on line 35 in test/unit/EnvironmentManager.test.js

View workflow job for this annotation

GitHub Actions / test (20.x)

Expected a block comment instead of consecutive line comments

Check failure on line 35 in test/unit/EnvironmentManager.test.js

View workflow job for this annotation

GitHub Actions / test (18.x)

Expected a block comment instead of consecutive line comments
// C:\Program Files\...
mockStat
.mockRejectedValueOnce(new Error('Not found'))
.mockRejectedValueOnce(new Error('Not found'))
.mockRejectedValueOnce(new Error('Not found'))
// AppData path
.mockResolvedValueOnce({ isFile: () => true });

const env = new EnvironmentManager({ info: jest.fn() });
const found = await env.ensureEnvironmentReady();

expect(found).toBeDefined();
expect(mockStat).toHaveBeenCalled();
});

it('should throw error if FreeCAD is not found', async () => {
mockStat.mockRejectedValue(new Error('Not found'));

const env = new EnvironmentManager({ info: jest.fn() });
await expect(env.ensureEnvironmentReady()).rejects.toThrow(/FreeCAD installation not found/);
});
});
Loading