feat: create tm-core and apps/cli (#1093)
- add typescript - add npm workspaces
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @fileoverview Unit tests for ConfigLoader service
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
|
||||
import { promises as fs } from 'node:fs';
|
||||
import { ConfigLoader } from './config-loader.service.js';
|
||||
import { DEFAULT_CONFIG_VALUES } from '../../interfaces/configuration.interface.js';
|
||||
|
||||
vi.mock('node:fs', () => ({
|
||||
promises: {
|
||||
readFile: vi.fn(),
|
||||
access: vi.fn()
|
||||
}
|
||||
}));
|
||||
|
||||
describe('ConfigLoader', () => {
|
||||
let configLoader: ConfigLoader;
|
||||
const testProjectRoot = '/test/project';
|
||||
|
||||
beforeEach(() => {
|
||||
configLoader = new ConfigLoader(testProjectRoot);
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe('getDefaultConfig', () => {
|
||||
it('should return default configuration values', () => {
|
||||
const config = configLoader.getDefaultConfig();
|
||||
|
||||
expect(config.models).toEqual({
|
||||
main: DEFAULT_CONFIG_VALUES.MODELS.MAIN,
|
||||
fallback: DEFAULT_CONFIG_VALUES.MODELS.FALLBACK
|
||||
});
|
||||
|
||||
expect(config.storage).toEqual({
|
||||
type: DEFAULT_CONFIG_VALUES.STORAGE.TYPE,
|
||||
encoding: DEFAULT_CONFIG_VALUES.STORAGE.ENCODING,
|
||||
enableBackup: false,
|
||||
maxBackups: DEFAULT_CONFIG_VALUES.STORAGE.MAX_BACKUPS,
|
||||
enableCompression: false,
|
||||
atomicOperations: true
|
||||
});
|
||||
|
||||
expect(config.version).toBe(DEFAULT_CONFIG_VALUES.VERSION);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadLocalConfig', () => {
|
||||
it('should load and parse local configuration file', async () => {
|
||||
const mockConfig = {
|
||||
models: { main: 'test-model' },
|
||||
storage: { type: 'api' as const }
|
||||
};
|
||||
|
||||
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(mockConfig));
|
||||
|
||||
const result = await configLoader.loadLocalConfig();
|
||||
|
||||
expect(fs.readFile).toHaveBeenCalledWith(
|
||||
'/test/project/.taskmaster/config.json',
|
||||
'utf-8'
|
||||
);
|
||||
expect(result).toEqual(mockConfig);
|
||||
});
|
||||
|
||||
it('should return null when config file does not exist', async () => {
|
||||
const error = new Error('File not found') as any;
|
||||
error.code = 'ENOENT';
|
||||
vi.mocked(fs.readFile).mockRejectedValue(error);
|
||||
|
||||
const result = await configLoader.loadLocalConfig();
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('should throw TaskMasterError for other file errors', async () => {
|
||||
const error = new Error('Permission denied');
|
||||
vi.mocked(fs.readFile).mockRejectedValue(error);
|
||||
|
||||
await expect(configLoader.loadLocalConfig()).rejects.toThrow(
|
||||
'Failed to load local configuration'
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error for invalid JSON', async () => {
|
||||
vi.mocked(fs.readFile).mockResolvedValue('invalid json');
|
||||
|
||||
await expect(configLoader.loadLocalConfig()).rejects.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadGlobalConfig', () => {
|
||||
it('should return null (not implemented yet)', async () => {
|
||||
const result = await configLoader.loadGlobalConfig();
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasLocalConfig', () => {
|
||||
it('should return true when local config exists', async () => {
|
||||
vi.mocked(fs.access).mockResolvedValue(undefined);
|
||||
|
||||
const result = await configLoader.hasLocalConfig();
|
||||
|
||||
expect(fs.access).toHaveBeenCalledWith(
|
||||
'/test/project/.taskmaster/config.json'
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when local config does not exist', async () => {
|
||||
vi.mocked(fs.access).mockRejectedValue(new Error('Not found'));
|
||||
|
||||
const result = await configLoader.hasLocalConfig();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasGlobalConfig', () => {
|
||||
it('should check global config path', async () => {
|
||||
vi.mocked(fs.access).mockResolvedValue(undefined);
|
||||
|
||||
const result = await configLoader.hasGlobalConfig();
|
||||
|
||||
expect(fs.access).toHaveBeenCalledWith(
|
||||
expect.stringContaining('.taskmaster/config.json')
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when global config does not exist', async () => {
|
||||
vi.mocked(fs.access).mockRejectedValue(new Error('Not found'));
|
||||
|
||||
const result = await configLoader.hasGlobalConfig();
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user