This commit is contained in:
210
tests/unit/utils.test.ts
Normal file
210
tests/unit/utils.test.ts
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
import { OSUtils, osUtils } from '../../src/utils/osUtils';
|
||||||
|
import { ShellUtils, shellUtils } from '../../src/utils/shellUtils';
|
||||||
|
import { TemplateUtils, templateUtils } from '../../src/utils/templateUtils';
|
||||||
|
import { Layout, Template, TerminalType } from '../../src/models/types';
|
||||||
|
|
||||||
|
describe('OSUtils', () => {
|
||||||
|
describe('getPlatform', () => {
|
||||||
|
it('should return current platform', () => {
|
||||||
|
const platform = osUtils.getPlatform();
|
||||||
|
expect(['darwin', 'linux', 'win32']).toContain(platform);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isMacOS', () => {
|
||||||
|
it('should return true on macOS', () => {
|
||||||
|
const isMac = osUtils.isMacOS();
|
||||||
|
expect(typeof isMac).toBe('boolean');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isLinux', () => {
|
||||||
|
it('should return true on Linux', () => {
|
||||||
|
const isLinux = osUtils.isLinux();
|
||||||
|
expect(typeof isLinux).toBe('boolean');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getHomeDir', () => {
|
||||||
|
it('should return home directory', () => {
|
||||||
|
const homeDir = osUtils.getHomeDir();
|
||||||
|
expect(homeDir).toBeTruthy();
|
||||||
|
expect(homeDir.startsWith('/home') || homeDir.startsWith('/Users')).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('expandPath', () => {
|
||||||
|
it('should expand tilde to home directory', () => {
|
||||||
|
const home = osUtils.getHomeDir();
|
||||||
|
const expanded = osUtils.expandPath('~/test');
|
||||||
|
expect(expanded).toBe(`${home}/test`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not modify absolute paths', () => {
|
||||||
|
const expanded = osUtils.expandPath('/usr/local/bin');
|
||||||
|
expect(expanded).toBe('/usr/local/bin');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('detectTerminalType', () => {
|
||||||
|
it('should detect terminal type based on platform', () => {
|
||||||
|
const terminalType = osUtils.detectTerminalType();
|
||||||
|
expect(['tmux', 'screen', 'iterm2', 'unknown']).toContain(terminalType);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ShellUtils', () => {
|
||||||
|
describe('isCommandAvailable', () => {
|
||||||
|
it('should return boolean for valid command', async () => {
|
||||||
|
const available = await shellUtils.isCommandAvailable('ls');
|
||||||
|
expect(typeof available).toBe('boolean');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for invalid command', async () => {
|
||||||
|
const available = await shellUtils.isCommandAvailable('__invalid_command_12345__');
|
||||||
|
expect(available).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exec', () => {
|
||||||
|
it('should return result object for command', async () => {
|
||||||
|
const result = await shellUtils.exec('echo "test"');
|
||||||
|
expect(typeof result.success).toBe('boolean');
|
||||||
|
expect(typeof result.stdout).toBe('string');
|
||||||
|
expect(typeof result.stderr).toBe('string');
|
||||||
|
expect(typeof result.exitCode).toBe('number');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return failure for invalid command', async () => {
|
||||||
|
const result = await shellUtils.exec('__invalid_command_12345__');
|
||||||
|
expect(result.success).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('TemplateUtils', () => {
|
||||||
|
describe('extractVariables', () => {
|
||||||
|
it('should extract variables from template', () => {
|
||||||
|
const template: Template = {
|
||||||
|
name: 'test',
|
||||||
|
displayName: 'Test',
|
||||||
|
description: 'Test template',
|
||||||
|
variables: [
|
||||||
|
{ name: 'PROJECT_DIR', description: 'Project dir', required: true },
|
||||||
|
{ name: 'SERVER_URL', description: 'Server URL', required: false },
|
||||||
|
],
|
||||||
|
layout: {
|
||||||
|
version: '1.0.0',
|
||||||
|
terminalType: 'tmux' as TerminalType,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
session: {
|
||||||
|
id: 's1',
|
||||||
|
name: 'test',
|
||||||
|
windows: [],
|
||||||
|
activeWindowIndex: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const layoutWithVars: Layout = {
|
||||||
|
...template.layout,
|
||||||
|
session: {
|
||||||
|
...template.layout.session,
|
||||||
|
windows: [
|
||||||
|
{
|
||||||
|
id: 'w1',
|
||||||
|
index: 0,
|
||||||
|
name: 'main',
|
||||||
|
panes: [
|
||||||
|
{
|
||||||
|
id: 'p1',
|
||||||
|
index: 0,
|
||||||
|
layout: { x: 0, y: 0, width: 80, height: 24 },
|
||||||
|
command: 'cd ${PROJECT_DIR} && npm run dev',
|
||||||
|
cwd: '${PROJECT_DIR}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const variables = templateUtils.extractVariables({ ...template, layout: layoutWithVars });
|
||||||
|
expect(variables).toContain('PROJECT_DIR');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('substituteVariables', () => {
|
||||||
|
it('should substitute variables in layout', () => {
|
||||||
|
const layout: Layout = {
|
||||||
|
version: '1.0.0',
|
||||||
|
terminalType: 'tmux' as TerminalType,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
session: {
|
||||||
|
id: 's1',
|
||||||
|
name: 'test',
|
||||||
|
windows: [
|
||||||
|
{
|
||||||
|
id: 'w1',
|
||||||
|
index: 0,
|
||||||
|
name: 'main',
|
||||||
|
panes: [
|
||||||
|
{
|
||||||
|
id: 'p1',
|
||||||
|
index: 0,
|
||||||
|
layout: { x: 0, y: 0, width: 80, height: 24 },
|
||||||
|
command: 'cd ${PROJECT_DIR} && npm run dev',
|
||||||
|
cwd: '${PROJECT_DIR}',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
activeWindowIndex: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const variables: Record<string, string> = {
|
||||||
|
PROJECT_DIR: '/home/user/projects/myapp',
|
||||||
|
};
|
||||||
|
|
||||||
|
const substituted = templateUtils.substituteVariables(layout, variables);
|
||||||
|
expect(substituted.session.windows[0].panes[0].command).toBe(
|
||||||
|
'cd /home/user/projects/myapp && npm run dev'
|
||||||
|
);
|
||||||
|
expect(substituted.session.windows[0].panes[0].cwd).toBe('/home/user/projects/myapp');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateTemplateVariables', () => {
|
||||||
|
it('should return missing required variables', () => {
|
||||||
|
const template: Template = {
|
||||||
|
name: 'test',
|
||||||
|
displayName: 'Test',
|
||||||
|
description: 'Test template',
|
||||||
|
variables: [
|
||||||
|
{ name: 'REQUIRED_VAR', description: 'Required', required: true },
|
||||||
|
{ name: 'OPTIONAL_VAR', description: 'Optional', required: false, defaultValue: 'default' },
|
||||||
|
],
|
||||||
|
layout: {
|
||||||
|
version: '1.0.0',
|
||||||
|
terminalType: 'tmux' as TerminalType,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
session: {
|
||||||
|
id: 's1',
|
||||||
|
name: 'test',
|
||||||
|
windows: [],
|
||||||
|
activeWindowIndex: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const missing = templateUtils.validateTemplateVariables(template, {});
|
||||||
|
expect(missing).toContain('REQUIRED_VAR');
|
||||||
|
expect(missing).not.toContain('OPTIONAL_VAR');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user