import { describe, it, expect } from 'vitest';
import type { Response } from 'express';
import { setUntrustedFileResponseHeaders, ensurePathWithin } from './local-api-helpers.js';

function fakeRes(): { res: Response; headers: Record<string, string> } {
  const headers: Record<string, string> = {};
  const res = {
    setHeader(name: string, value: string) {
      headers[name] = value;
    },
  } as unknown as Response;
  return { res, headers };
}

describe('setUntrustedFileResponseHeaders', () => {
  it('disables MIME sniffing and sandboxes the document', () => {
    const { res, headers } = fakeRes();
    setUntrustedFileResponseHeaders(res);
    // nosniff: a text/* file cannot be re-interpreted as executable HTML
    expect(headers['X-Content-Type-Options']).toBe('nosniff');
    // CSP sandbox (no allow-scripts token) => scripts disabled + opaque origin,
    // so HTML/SVG written into a workspace cannot run on our origin or ride the
    // viewer's session (stored XSS, incl. the unauthenticated share endpoint).
    expect(headers['Content-Security-Policy']).toBe('sandbox');
    expect(headers['Content-Security-Policy']).not.toContain('allow-scripts');
  });
});

describe('ensurePathWithin (regression: no escape, no sibling-prefix bypass)', () => {
  it('allows a path inside the base', () => {
    const base = '/tmp/ws';
    expect(ensurePathWithin(base, 'output/a.txt')).toBe('/tmp/ws/output/a.txt');
  });
  it('rejects traversal out of the base', () => {
    expect(() => ensurePathWithin('/tmp/ws', '../etc/passwd')).toThrow();
  });
  it('rejects a sibling dir sharing the base prefix', () => {
    // /tmp/ws-evil must not pass the /tmp/ws containment check
    expect(() => ensurePathWithin('/tmp/ws', '../ws-evil/x')).toThrow();
  });
});
