Files
ccs/tests/unit/utils/expand-path.test.ts

107 lines
3.8 KiB
TypeScript

import { expect, test, describe, beforeEach, afterEach } from 'bun:test';
import * as path from 'path';
import * as os from 'os';
import { expandPath } from '../../../src/utils/helpers';
describe('expandPath', () => {
const originalEnv = { ...process.env };
const HOME = os.homedir();
beforeEach(() => {
process.env.TEST_HOME = '/custom/home';
process.env.TEST_VAR = 'foo';
});
afterEach(() => {
process.env = { ...originalEnv };
});
test('1. Tilde expansion: ~/path -> /home/user/path', () => {
expect(expandPath('~/test/file.txt')).toBe(path.join(HOME, 'test/file.txt'));
});
test('2. Windows tilde with backslash: ~\\path', () => {
// expandPath handles both ~/ and ~\ regardless of platform
expect(expandPath('~\\test\\file.txt')).toBe(path.join(HOME, 'test/file.txt'));
});
test('3. Environment variable expansion: ${VAR}/path', () => {
expect(expandPath('${TEST_HOME}/file.txt')).toBe(path.normalize('/custom/home/file.txt'));
});
test('4. Dollar sign env vars: $VAR/path', () => {
expect(expandPath('$TEST_HOME/file.txt')).toBe(path.normalize('/custom/home/file.txt'));
});
test('5. Windows %VAR% expansion: %VAR%\\path (simulated)', () => {
// We can't easily mock process.platform if it's not win32,
// but the function check process.platform === 'win32'
if (process.platform === 'win32') {
expect(expandPath('%TEST_HOME%\\file.txt')).toBe(path.normalize('/custom/home/file.txt'));
} else {
// Should remain unchanged on non-windows (but separators normalized)
expect(expandPath('%TEST_HOME%\\file.txt')).toBe(path.normalize('%TEST_HOME%/file.txt'));
}
});
test('6. Mixed path separators normalization', () => {
const result = expandPath('path/to\\some/file');
expect(result).toBe(path.normalize('path/to/some/file'));
});
test('7. Nested env vars: ${HOME}/${VAR}/path', () => {
expect(expandPath('${TEST_HOME}/${TEST_VAR}/file.txt')).toBe(
path.normalize('/custom/home/foo/file.txt')
);
});
test('8. Empty/null path handling', () => {
expect(expandPath('')).toBe('.');
});
test('9. Already absolute paths stay unchanged', () => {
const absPath = '/absolute/path';
expect(expandPath(absPath)).toBe(path.normalize(absPath));
});
test('10. Undefined env vars -> empty string', () => {
expect(expandPath('${UNDEFINED_VAR}/file.txt')).toBe(path.normalize('/file.txt'));
expect(expandPath('$UNDEFINED_VAR/file.txt')).toBe(path.normalize('/file.txt'));
});
test('11. Windows drive letters stay intact', () => {
// Windows drive letter paths should be preserved
const result = expandPath('C:\\Users\\test\\file.txt');
expect(result).toContain('Users');
expect(result).toContain('test');
});
test('12. Windows UNC paths handled', () => {
// UNC paths start with \\
const uncPath = '\\\\server\\share\\folder';
const result = expandPath(uncPath);
// Should normalize but preserve the structure
expect(result).toContain('server');
expect(result).toContain('share');
});
test('13. Null-like input throws TypeError', () => {
// Function requires string input - documents current behavior
// @ts-ignore - testing runtime edge case
expect(() => expandPath(undefined as unknown as string)).toThrow(TypeError);
// @ts-ignore - testing runtime edge case
expect(() => expandPath(null as unknown as string)).toThrow(TypeError);
});
test('14. Path with spaces preserved', () => {
const pathWithSpaces = '~/My Documents/file.txt';
const result = expandPath(pathWithSpaces);
expect(result).toContain('My Documents');
});
test('15. Multiple consecutive slashes normalized', () => {
const result = expandPath('path//to///file.txt');
expect(result).toBe(path.normalize('path/to/file.txt'));
});
});