import { describe, it, expect } from 'vitest';
import { sanitizeFolderName } from '../project_bootstrap.js';

describe('sanitizeFolderName', () => {
  it('passes through a normal slug-like name', () => {
    expect(sanitizeFolderName('my-project')).toBe('my-project');
  });

  it('lowercases and replaces whitespace with hyphens', () => {
    expect(sanitizeFolderName('Hello World')).toBe('hello-world');
  });

  it('strips path-traversal characters', () => {
    // dots and slashes fall outside [a-z0-9-] and are removed entirely.
    expect(sanitizeFolderName('../etc/passwd')).toBe('etcpasswd');
  });

  it('strips trailing and leading dots and slashes', () => {
    expect(sanitizeFolderName('./foo/')).toBe('foo');
  });

  it('collapses runs of hyphens and strips leading/trailing ones', () => {
    expect(sanitizeFolderName('---foo---')).toBe('foo');
  });

  it('returns empty string when nothing survives sanitization', () => {
    // NOTE: sanitizeFolderName itself does NOT throw — it returns ''. The
    // BootstrapNameError is raised by the caller (bootstrapProject) when the
    // sanitized result fails the SAFE_NAME regex. The spec's "throws" phrasing
    // refers to that caller-level validation, not this pure function.
    expect(sanitizeFolderName('...')).toBe('');
    expect(sanitizeFolderName('   ')).toBe('');
  });

  it('strips control characters and null bytes', () => {
    // Null bytes and control characters are not in [a-z0-9-] so they're
    // filtered out (effectively rejected as folder-name content).
    expect(sanitizeFolderName('my\x00proj\x01')).toBe('myproj');
    expect(sanitizeFolderName('foo\x00bar')).toBe('foobar');
  });

  it('truncates names longer than 64 characters', () => {
    const long = 'a'.repeat(100);
    expect(sanitizeFolderName(long)).toBe('a'.repeat(64));
    expect(sanitizeFolderName(long)).toHaveLength(64);
  });
});
