Asnip / test /features.test.mjs
teddyoas's picture
Duplicate from teddyoas/PHANTOM-v2
20f108c
Raw History Blame Contribute Delete
6.28 kB
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { runTool, runPipe, formatExternal } from "../lib/runtime.mjs";
import { hackerTools } from "../lib/tools.mjs";
describe("runTool wrapper", () => {
it("wraps a normal tool call", async () => {
const r = await runTool(hackerTools, "shell", "echo hello");
assert.match(r, /hello/);
});
it("returns error for unknown tool", async () => {
const r = await runTool(hackerTools, "nonexistent_tool_xyz", "");
assert.match(r, /Unknown tool/);
});
it("returns JSON when json=true", async () => {
const r = await runTool(hackerTools, "shell", "echo hi", { json: true });
const parsed = JSON.parse(r);
assert.equal(parsed.ok, true);
assert.equal(parsed.tool, "shell");
assert.match(parsed.data, /hi/);
});
it("JSON error for unknown tool", async () => {
const r = await runTool(hackerTools, "bad_tool", "", { json: true });
const parsed = JSON.parse(r);
assert.equal(parsed.ok, false);
assert.match(parsed.error, /Unknown tool/);
});
});
describe("runPipe chaining", () => {
it("single tool works like normal run", async () => {
const r = await runPipe(hackerTools, "shell|echo simple_pipe_test");
assert.match(r, /simple_pipe_test/);
});
it("two-tool pipe feeds output to next tool", async () => {
// shell -> hash (shell output becomes hash input)
const r = await runPipe(hackerTools, "shell|echo testdata | hash");
assert.match(r, /hash|testdata|[a-f0-9]/i);
});
it("single tool returns JSON with option", async () => {
const r = await runPipe(hackerTools, "shell|echo json_ok", { json: true });
const p = JSON.parse(r);
assert.equal(p.ok, true);
});
it("handles empty chain gracefully", async () => {
const r = await runPipe(hackerTools, "", {});
assert.match(r, /empty/i);
});
});
describe("formatExternal edge cases", () => {
it("handles very long target names", () => {
const long = "a".repeat(200);
const r = formatExternal("Test", long, ["result"]);
assert.match(r, new RegExp(long));
});
it("single line with maxLines=1", () => {
const r = formatExternal("T", "x", ["a", "b", "c"], 1);
assert.match(r, /and 2 more/);
});
it("empty lines array without target", () => {
const r = formatExternal("Tool", "", []);
assert.equal(r, "[Tool] No results for ");
});
});
describe("CLI --json smoke", () => {
it("--tool --json shell returns valid JSON", async () => {
const { execSync } = await import("child_process");
const out = execSync("node phantom.mjs --tool --json shell 'echo json_test_cli' 2>&1", { cwd: "/root/usb/Phantom", encoding: "utf-8", timeout: 10000 });
const parsed = JSON.parse(out);
assert.equal(parsed.ok, true);
assert.equal(parsed.tool, "shell");
assert.match(parsed.data, /json_test_cli/);
});
it("--tool --json with bad tool exits 1 with error", async () => {
const { execSync } = await import("child_process");
try {
execSync("node phantom.mjs --tool --json bad_tool_xyz '' 2>&1", { cwd: "/root/usb/Phantom", encoding: "utf-8", timeout: 10000 });
assert.fail("Should have thrown");
} catch (e) {
const out = e.stdout;
const parsed = JSON.parse(out);
assert.equal(parsed.ok, false);
assert.match(parsed.error, /Unknown tool/);
}
});
});
describe("schedule tool", () => {
it("returns usage for no args", async () => {
const r = await hackerTools.schedule("");
assert.match(r, /Usage/);
});
it("returns empty list when no schedules active", async () => {
const r = await hackerTools.schedule("list");
assert.match(r, /No active schedules/);
});
it("returns error for unknown tool in schedule", async () => {
const r = await hackerTools.schedule("daily|bad_tool_xyz|target.com");
assert.match(r, /Unknown tool/);
});
});
describe("hackerone tool", () => {
it("returns help for no args", async () => {
const r = await hackerTools.hackerone("");
assert.match(r, /HackerOne Tool/);
assert.match(r, /programs/);
assert.match(r, /scope/);
assert.match(r, /reports/);
assert.match(r, /report/);
assert.match(r, /submit/);
assert.match(r, /me/);
assert.match(r, /test/);
});
it("returns help for 'help' command", async () => {
const r = await hackerTools.hackerone("help");
assert.match(r, /HackerOne Tool/);
});
it("returns help for 'list' command", async () => {
const r = await hackerTools.hackerone("list");
assert.match(r, /HackerOne Tool/);
});
it("handles 'programs' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone("programs");
// Just verify it returns a string response (not an exception)
assert.ok(typeof r === "string" && r.length > 0);
});
it("handles 'scope' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone("scope acme-corp");
assert.ok(typeof r === "string" && r.length > 0);
});
it("handles 'reports' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone("reports acme-corp");
assert.ok(typeof r === "string" && r.length > 0);
});
it("handles 'report' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone("report 1234567");
assert.ok(typeof r === "string" && r.length > 0);
});
it("handles 'submit' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone('submit acme-corp "XSS" high "details"');
assert.ok(typeof r === "string" && r.length > 0);
});
it("handles 'me' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone("me");
assert.ok(typeof r === "string" && r.length > 0);
});
it("handles 'test' command (credentials may or may not work)", async () => {
const r = await hackerTools.hackerone("test");
assert.ok(typeof r === "string" && r.length > 0);
});
it("returns unknown command error for invalid command", async () => {
const r = await hackerTools.hackerone("invalid_command");
assert.match(r, /Unknown command/);
});
});