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`]); }); });