Files
openchamber/packages/ui/src/lib/pathNormalization.test.ts
T

100 lines
3.3 KiB
TypeScript
Raw Normal View History

import { describe, expect, test } from 'bun:test';
import { normalizePath } from './pathNormalization';
describe('normalizePath', () => {
describe('non-string inputs', () => {
test('returns null for null', () => {
expect(normalizePath(null)).toBeNull();
});
test('returns null for undefined', () => {
expect(normalizePath(undefined)).toBeNull();
});
test('returns null for empty string', () => {
expect(normalizePath('')).toBeNull();
});
test('returns null for whitespace-only', () => {
expect(normalizePath(' ')).toBeNull();
});
});
describe('backslashes', () => {
test('converts backslashes to forward slashes', () => {
expect(normalizePath('C:\\Users\\me\\project')).toBe('C:/Users/me/project');
});
});
describe('drive letter casing', () => {
test('uppercases lowercase Windows drive letter', () => {
expect(normalizePath('c:\\Users\\me\\project')).toBe('C:/Users/me/project');
});
test('preserves already-uppercase drive letter', () => {
expect(normalizePath('C:\\Users\\me\\project')).toBe('C:/Users/me/project');
});
test('does not match multi-character tokens before colon', () => {
expect(normalizePath('abc:def')).toBe('abc:def');
});
test('does not touch drive letter in middle of path', () => {
// Only the leading drive letter is touched; a "c:" later in the
// path is left alone (no upper-casing, no backslash conversion of
// the surrounding characters beyond the backslash-to-slash step).
expect(normalizePath('/foo/c:\\bar')).toBe('/foo/c:/bar');
});
});
describe('trailing slashes', () => {
test('strips a single trailing slash', () => {
expect(normalizePath('C:/Users/me/')).toBe('C:/Users/me');
});
test('strips multiple trailing slashes', () => {
expect(normalizePath('C:/Users/me///')).toBe('C:/Users/me');
});
test('preserves root /', () => {
expect(normalizePath('/')).toBe('/');
});
test('preserves single-char after slash strip', () => {
expect(normalizePath('C:/')).toBe('C:');
});
});
describe('degenerate slash-only inputs', () => {
// '///' → stays '///' after backslash replace → trailing-slash strip
// yields '' → null. This is the new defensive behavior.
test('returns null for multiple forward slashes', () => {
expect(normalizePath('///')).toBeNull();
});
// '\\\\' in source = 2 backslash chars → replace to '//' → strip → '' → null.
test('returns null for multiple backslashes', () => {
expect(normalizePath('\\\\')).toBeNull();
});
// A single backslash '\\' is normalized to a single forward slash
// and treated as the filesystem root, returned as '/'. (This is the
// pre-existing behavior; the defensive fix only adds null for
// slash-only inputs that strip down to ''.)
test('normalizes a single backslash to the root "/"', () => {
expect(normalizePath('\\')).toBe('/');
});
});
describe('Unix paths', () => {
test('passes through a Unix path unchanged', () => {
expect(normalizePath('/home/user/project')).toBe('/home/user/project');
});
test('strips trailing slashes from Unix paths', () => {
expect(normalizePath('/home/user/project/')).toBe('/home/user/project');
});
});
});