import { describe, expect, test } from "bun:test";
import { resolve } from "node:path";
import { buildEditorCommand, resolveEditorFile } from "../../src/server/editor.ts";

describe("open editor security", () => {
  const projectRoot = resolve("project");
  const pageFile = resolve(projectRoot, "app/pages/index.wrn");

  test("resolves project files", () => {
    expect(resolveEditorFile(projectRoot, "app/pages/index.wrn")).toBe(pageFile);
  });

  test("rejects traversal outside root", () => {
    expect(() => resolveEditorFile(projectRoot, "../secret.txt")).toThrow(
      "Source file is outside the configured project root.",
    );
  });

  test("builds argument array without shell", () => {
    expect(
      buildEditorCommand(
        {
          file: "app/pages/index.wrn",
          line: 8,
          column: 2,
        },
        {
          root: projectRoot,
          editor: "code",
        },
      ),
    ).toEqual(["code", "--goto", `${pageFile}:8:2`]);
  });

  test("rejects null bytes", () => {
    expect(() => resolveEditorFile(projectRoot, "app/pages/index.wrn\0.txt")).toThrow(
      "Invalid source file path.",
    );
  });

  test("rejects remote URLs", () => {
    expect(() => resolveEditorFile(projectRoot, "https://example.com/file.wrn")).toThrow(
      "Invalid source file path.",
    );
  });

  test("normalizes invalid line and column values", () => {
    expect(
      buildEditorCommand(
        {
          file: "app/pages/index.wrn",
          line: -10,
          column: 0,
        },
        {
          root: projectRoot,
          editor: "code",
        },
      ),
    ).toEqual(["code", "--goto", `${pageFile}:1:1`]);
  });
});
