mirror of
https://github.com/usebruno/bruno.git
synced 2026-07-08 14:35:03 +00:00
248 lines
11 KiB
JavaScript
248 lines
11 KiB
JavaScript
// Mock platform module for Unix before importing path utilities
|
|
jest.mock('platform', () => ({
|
|
os: {
|
|
family: 'Unix'
|
|
}
|
|
}));
|
|
|
|
import path from 'path';
|
|
import { getRelativePath, getBasename, getAbsoluteFilePath, getRelativePathWithinBasePath, isPathExternalToBasePath } from './path';
|
|
|
|
describe('Path Utilities - Unix Platform', () => {
|
|
describe('getRelativePath', () => {
|
|
it('should return relative path between two directories', () => {
|
|
expect(getRelativePath('/users/john/projects', '/users/john/projects/app')).toBe('app');
|
|
});
|
|
|
|
it('should return "." when both paths are the same', () => {
|
|
expect(getRelativePath('/users/john/projects', '/users/john/projects')).toBe('.');
|
|
});
|
|
|
|
it('should return parent directory path', () => {
|
|
expect(getRelativePath('/users/john/projects', '/users/john/docs/readme.md')).toBe('../docs/readme.md');
|
|
});
|
|
|
|
it('should return nested subdirectory path', () => {
|
|
expect(getRelativePath('/users/john/projects', '/users/john/projects/src/components')).toBe('src/components');
|
|
});
|
|
|
|
it('should return ".." for direct parent directory', () => {
|
|
expect(getRelativePath('/users/john/projects', '/users/john')).toBe('..');
|
|
});
|
|
|
|
it('should handle null/undefined inputs', () => {
|
|
expect(getRelativePath(null, '/users/john/projects')).toBe('/users/john/projects');
|
|
expect(getRelativePath(undefined, '/users/john/projects')).toBe('/users/john/projects');
|
|
});
|
|
});
|
|
|
|
describe('getBasename', () => {
|
|
it('should return filename from relative path', () => {
|
|
expect(getBasename('/users/john/projects', '../docs/readme.md')).toBe('readme.md');
|
|
});
|
|
|
|
it('should return filename from subdirectory path', () => {
|
|
expect(getBasename('/users/john/projects', 'subfolder/config.json')).toBe('config.json');
|
|
});
|
|
|
|
it('should return filename from direct file path', () => {
|
|
expect(getBasename('/users/john/projects', 'package.json')).toBe('package.json');
|
|
});
|
|
|
|
it('should return directory name for parent directory', () => {
|
|
expect(getBasename('/users/john/projects', '..')).toBe('john');
|
|
});
|
|
|
|
it('should return directory name for current directory', () => {
|
|
expect(getBasename('/users/john/projects', '.')).toBe('projects');
|
|
});
|
|
|
|
it('should return filename from nested path', () => {
|
|
expect(getBasename('/users/john/projects', 'src/components/Button.jsx')).toBe('Button.jsx');
|
|
});
|
|
|
|
it('should return empty string for falsy relativePath', () => {
|
|
expect(getBasename('/users/john/projects', '')).toBe('');
|
|
expect(getBasename('/users/john/projects', null)).toBe('');
|
|
expect(getBasename('/users/john/projects', undefined)).toBe('');
|
|
});
|
|
|
|
it('should handle complex relative paths', () => {
|
|
expect(getBasename('/users/john/projects', '../../docs/api/spec.md')).toBe('spec.md');
|
|
});
|
|
|
|
it('should handle paths with multiple extensions', () => {
|
|
expect(getBasename('/users/john/projects', 'src/utils/common/path.spec.js')).toBe('path.spec.js');
|
|
});
|
|
});
|
|
|
|
describe('getAbsoluteFilePath', () => {
|
|
it('should resolve relative file path against collection path', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', 'config/settings.json');
|
|
expect(result).toBe('/users/john/collections/config/settings.json');
|
|
});
|
|
|
|
it('should handle nested file paths', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', 'api/v1/users.json');
|
|
expect(result).toBe('/users/john/collections/api/v1/users.json');
|
|
});
|
|
|
|
it('should handle parent directory references', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections/api', '../shared/config.json');
|
|
expect(result).toBe('/users/john/collections/shared/config.json');
|
|
});
|
|
|
|
it('should handle empty file path', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', '');
|
|
expect(result).toBe('/users/john/collections');
|
|
});
|
|
|
|
it('should handle current directory reference', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', '.');
|
|
expect(result).toBe('/users/john/collections');
|
|
});
|
|
|
|
it('should handle previous directory reference', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', '..');
|
|
expect(result).toBe('/users/john');
|
|
});
|
|
|
|
it('should handle root file path', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', '/absolute/path/file.json');
|
|
expect(result).toBe('/absolute/path/file.json');
|
|
});
|
|
|
|
it('should handle current directory reference', () => {
|
|
const result = getAbsoluteFilePath('/users/john/collections', './local-file.json');
|
|
expect(result).toBe('/users/john/collections/local-file.json');
|
|
});
|
|
});
|
|
|
|
describe('getRelativePathWithinBasePath', () => {
|
|
it('should store in-collection files as relative paths', () => {
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', '/users/john/collections/api/files/payload.txt');
|
|
expect(result).toBe('files/payload.txt');
|
|
});
|
|
|
|
it('should handle collection paths with trailing separators', () => {
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api/', '/users/john/collections/api/files/payload.txt');
|
|
expect(result).toBe('files/payload.txt');
|
|
});
|
|
|
|
it('should resolve dot segments before deciding whether a file is inside the collection', () => {
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', '/users/john/collections/api/files/../payload.txt');
|
|
expect(result).toBe('payload.txt');
|
|
});
|
|
|
|
it('should keep paths that resolve outside the collection absolute', () => {
|
|
const filePath = '/users/john/collections/api/../payload.txt';
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', filePath);
|
|
expect(result).toBe(filePath);
|
|
});
|
|
|
|
it('should keep outside collection paths absolute', () => {
|
|
const filePath = '/users/john/downloads/payload.txt';
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', filePath);
|
|
expect(result).toBe(filePath);
|
|
});
|
|
|
|
it('should keep sibling prefix paths absolute', () => {
|
|
const filePath = '/users/john/collections/api-other/payload.txt';
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', filePath);
|
|
expect(result).toBe(filePath);
|
|
});
|
|
|
|
it('should keep same-path values unchanged', () => {
|
|
const filePath = '/users/john/collections/api';
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', filePath);
|
|
expect(result).toBe(filePath);
|
|
});
|
|
|
|
it('should store in-collection paths whose names begin with two dots as relative paths', () => {
|
|
const result = getRelativePathWithinBasePath('/users/john/collections/api', '/users/john/collections/api/..payload.txt');
|
|
expect(result).toBe('..payload.txt');
|
|
});
|
|
|
|
it('should keep the original file path when inputs are missing', () => {
|
|
expect(getRelativePathWithinBasePath('', '/users/john/downloads/payload.txt')).toBe('/users/john/downloads/payload.txt');
|
|
expect(getRelativePathWithinBasePath('/users/john/collections/api', '')).toBe('');
|
|
});
|
|
|
|
it('should treat relative collection path as cwd-relative when file path is absolute', () => {
|
|
const collectionPath = 'collections/api';
|
|
const filePath = path.resolve(collectionPath, 'files/payload.txt');
|
|
const result = getRelativePathWithinBasePath(collectionPath, filePath);
|
|
expect(result).toBe('files/payload.txt');
|
|
});
|
|
|
|
it('should treat relative file path as cwd-relative when collection path is absolute', () => {
|
|
const collectionPath = path.resolve('collections/api');
|
|
const filePath = 'collections/api/files/payload.txt';
|
|
const result = getRelativePathWithinBasePath(collectionPath, filePath);
|
|
expect(result).toBe('files/payload.txt');
|
|
});
|
|
|
|
it('should treat both relative paths as cwd-relative for containment checks', () => {
|
|
const collectionPath = 'collections/api';
|
|
const filePath = 'collections/api/files/payload.txt';
|
|
const result = getRelativePathWithinBasePath(collectionPath, filePath);
|
|
expect(result).toBe('files/payload.txt');
|
|
});
|
|
});
|
|
|
|
describe('isPathExternalToBasePath', () => {
|
|
it('should return false for a collection directly inside the base path', () => {
|
|
expect(isPathExternalToBasePath('/users/john/workspace', '/users/john/workspace/collections/api')).toBe(false);
|
|
});
|
|
|
|
it('should return false for a deeply nested collection', () => {
|
|
expect(isPathExternalToBasePath('/users/john/workspace', '/users/john/workspace/a/b/c')).toBe(false);
|
|
});
|
|
|
|
it('should return true for a collection outside the base path', () => {
|
|
expect(isPathExternalToBasePath('/users/john/workspace', '/users/john/downloads/api')).toBe(true);
|
|
});
|
|
|
|
it('should return true for a sibling whose name is a prefix of the base path', () => {
|
|
// /workspace-other must not be treated as inside /workspace
|
|
expect(isPathExternalToBasePath('/users/john/workspace', '/users/john/workspace-other/api')).toBe(true);
|
|
});
|
|
|
|
it('should resolve dot segments before deciding', () => {
|
|
// resolves to /users/john/workspace/b — inside
|
|
expect(isPathExternalToBasePath('/users/john/workspace', '/users/john/workspace/a/../b')).toBe(false);
|
|
// resolves to /users/john/b — outside
|
|
expect(isPathExternalToBasePath('/users/john/workspace/a', '/users/john/workspace/a/../../b')).toBe(true);
|
|
});
|
|
|
|
it('should ignore a trailing separator on the base path', () => {
|
|
expect(isPathExternalToBasePath('/users/john/workspace/', '/users/john/workspace/collections/api')).toBe(false);
|
|
});
|
|
|
|
it('should return false when either input is missing', () => {
|
|
expect(isPathExternalToBasePath('', '/users/john/workspace/api')).toBe(false);
|
|
expect(isPathExternalToBasePath('/users/john/workspace', '')).toBe(false);
|
|
expect(isPathExternalToBasePath(undefined, undefined)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('Edge cases', () => {
|
|
it('should handle very long paths', () => {
|
|
const longPath = '/users/john/projects/' + 'a'.repeat(100);
|
|
const result = getBasename(longPath, 'file.txt');
|
|
expect(result).toBe('file.txt');
|
|
});
|
|
|
|
it('should handle paths with special characters', () => {
|
|
expect(getBasename('/users/john/projects', 'file with spaces.txt')).toBe('file with spaces.txt');
|
|
expect(getBasename('/users/john/projects', 'file-with-dashes.txt')).toBe('file-with-dashes.txt');
|
|
expect(getBasename('/users/john/projects', 'file_with_underscores.txt')).toBe('file_with_underscores.txt');
|
|
});
|
|
|
|
it('should handle paths with unicode characters', () => {
|
|
expect(getBasename('/users/john/projects', 'файл.txt')).toBe('файл.txt');
|
|
expect(getBasename('/users/john/projects', '文件.txt')).toBe('文件.txt');
|
|
});
|
|
});
|
|
});
|