test(FN-4639): complete Step 5 — add sandbox exports and tests

Fusion-Task-Id: FN-4639
Fusion-Task-Lineage: 40745d49-dd20-4c51-87e3-42062417f788
This commit is contained in:
Fusion
2026-05-15 10:30:58 -07:00
committed by gsxdsm
parent c56ca5d5dd
commit 56a88de4a0
4 changed files with 175 additions and 2 deletions

View File

@@ -0,0 +1,55 @@
import { describe, expect, it } from "vitest";
import { SANDBOX_BACKEND_NAMES } from "../settings-validation.js";
import { parseSandboxPromptOverride, resolveSandboxBackend } from "../sandbox-prompt-override.js";
describe("sandbox prompt override", () => {
describe("parseSandboxPromptOverride", () => {
it.each(SANDBOX_BACKEND_NAMES)("parses %s", (backend) => {
expect(parseSandboxPromptOverride(`**Sandbox:** ${backend}`)).toBe(backend);
});
it("parses when prefix casing varies", () => {
expect(parseSandboxPromptOverride("**sAnDbOx:** native")).toBe("native");
});
it("does not accept mixed-case backend values", () => {
expect(parseSandboxPromptOverride("**Sandbox:** Docker")).toBeUndefined();
});
it("parses in multi-line prompt content", () => {
expect(parseSandboxPromptOverride("# Task\nSome content\n**Sandbox:** podman\nMore text")).toBe("podman");
});
it("returns undefined for missing or malformed inputs", () => {
expect(parseSandboxPromptOverride(undefined)).toBeUndefined();
expect(parseSandboxPromptOverride("")).toBeUndefined();
expect(parseSandboxPromptOverride("Sandbox: docker")).toBeUndefined();
expect(parseSandboxPromptOverride("**Sandbox:** firejail")).toBeUndefined();
});
});
describe("resolveSandboxBackend", () => {
it("prefers prompt override", () => {
expect(
resolveSandboxBackend(
{ sandbox: { backend: "docker" } },
"**Sandbox:** bubblewrap",
),
).toEqual({ backend: "bubblewrap", source: "prompt" });
});
it("falls back to project setting", () => {
expect(resolveSandboxBackend({ sandbox: { backend: "podman" } }, undefined)).toEqual({
backend: "podman",
source: "project",
});
});
it("falls back to default", () => {
expect(resolveSandboxBackend(undefined, undefined)).toEqual({
backend: "native",
source: "default",
});
});
});
});

View File

@@ -0,0 +1,105 @@
import { describe, expect, it } from "vitest";
import {
DEFAULT_PROJECT_SETTINGS,
GLOBAL_SETTINGS_KEYS,
PROJECT_SETTINGS_KEYS,
SANDBOX_BACKEND_NAMES,
SANDBOX_FAILURE_MODES,
validateSandboxBackendName,
validateSandboxFailureMode,
validateSandboxPolicy,
validateSandboxProjectSettings,
} from "../index.js";
describe("sandbox settings", () => {
it("defines sandbox defaults and scope keys", () => {
expect(DEFAULT_PROJECT_SETTINGS.sandbox).toEqual({
backend: "native",
policy: { allowNetwork: true, allowedPaths: [] },
failureMode: "fail-hard",
});
expect(PROJECT_SETTINGS_KEYS).toContain("sandbox");
expect(GLOBAL_SETTINGS_KEYS).not.toContain("sandbox");
});
describe("validateSandboxBackendName", () => {
it.each(SANDBOX_BACKEND_NAMES)("accepts %s", (backend) => {
expect(validateSandboxBackendName(backend)).toBe(backend);
});
it("rejects invalid values", () => {
expect(validateSandboxBackendName("firejail")).toBeUndefined();
expect(validateSandboxBackendName(123)).toBeUndefined();
expect(validateSandboxBackendName(null)).toBeUndefined();
expect(validateSandboxBackendName(undefined)).toBeUndefined();
expect(validateSandboxBackendName("")).toBeUndefined();
});
});
describe("validateSandboxFailureMode", () => {
it.each(SANDBOX_FAILURE_MODES)("accepts %s", (mode) => {
expect(validateSandboxFailureMode(mode)).toBe(mode);
});
it("rejects invalid values", () => {
expect(validateSandboxFailureMode("fallback")).toBeUndefined();
expect(validateSandboxFailureMode({})).toBeUndefined();
expect(validateSandboxFailureMode(null)).toBeUndefined();
expect(validateSandboxFailureMode(undefined)).toBeUndefined();
expect(validateSandboxFailureMode("")).toBeUndefined();
});
});
describe("validateSandboxPolicy", () => {
it("accepts individual valid keys", () => {
expect(validateSandboxPolicy({ allowNetwork: true })).toEqual({ allowNetwork: true });
expect(validateSandboxPolicy({ allowedPaths: ["foo", "bar/baz"] })).toEqual({
allowedPaths: ["foo", "bar/baz"],
});
});
it("rejects invalid policy payloads", () => {
expect(validateSandboxPolicy({ allowedPaths: [""] })).toBeUndefined();
expect(validateSandboxPolicy({ allowedPaths: "not-an-array" })).toBeUndefined();
expect(validateSandboxPolicy(null)).toBeUndefined();
expect(validateSandboxPolicy([])).toBeUndefined();
expect(validateSandboxPolicy(42)).toBeUndefined();
});
it("drops invalid sub-fields when a valid field remains", () => {
expect(validateSandboxPolicy({ allowNetwork: true, allowedPaths: ["", "ok"] })).toEqual({
allowNetwork: true,
});
expect(validateSandboxPolicy({ allowNetwork: "yes", allowedPaths: ["ok"] })).toEqual({
allowedPaths: ["ok"],
});
});
it("rejects traversal and tilde paths", () => {
expect(validateSandboxPolicy({ allowedPaths: ["../etc"] })).toBeUndefined();
expect(validateSandboxPolicy({ allowedPaths: ["~/secret"] })).toBeUndefined();
});
});
describe("validateSandboxProjectSettings", () => {
it("composes valid nested settings", () => {
expect(
validateSandboxProjectSettings({
backend: "docker",
failureMode: "fallback-native",
policy: { allowNetwork: false, allowedPaths: ["src/**"] },
}),
).toEqual({
backend: "docker",
failureMode: "fallback-native",
policy: { allowNetwork: false, allowedPaths: ["src/**"] },
});
});
it("returns undefined for empty and invalid inputs", () => {
expect(validateSandboxProjectSettings({})).toBeUndefined();
expect(validateSandboxProjectSettings({ backend: "firejail", policy: { allowedPaths: [""] } })).toBeUndefined();
expect(validateSandboxProjectSettings("nope")).toBeUndefined();
});
});
});