Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions tests/args.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import test from "node:test";
import assert from "node:assert/strict";

import { parseArgs, splitRawArgumentString } from "../plugins/codex/scripts/lib/args.mjs";

// --- parseArgs ---

test("parseArgs: boolean flag --flag=true sets true, --flag=false sets false", () => {
const configTrue = parseArgs(["--verbose=true"], { booleanOptions: ["verbose"] });
assert.equal(configTrue.options.verbose, true);

const configFalse = parseArgs(["--verbose=false"], { booleanOptions: ["verbose"] });
assert.equal(configFalse.options.verbose, false);
});

test("parseArgs: value option --output consumes next token", () => {
const { options } = parseArgs(["--output", "/tmp/out.txt"], { valueOptions: ["output"] });
assert.equal(options.output, "/tmp/out.txt");
});

test("parseArgs: inline value --output=path uses inline value", () => {
const { options } = parseArgs(["--output=/tmp/out.txt"], { valueOptions: ["output"] });
assert.equal(options.output, "/tmp/out.txt");
});

test("parseArgs: short alias -o resolved via aliasMap", () => {
const { options } = parseArgs(["-o", "/tmp/out.txt"], {
valueOptions: ["output"],
aliasMap: { o: "output" },
});
assert.equal(options.output, "/tmp/out.txt");
});

test("parseArgs: positionals after -- land in positionals array", () => {
const { options, positionals } = parseArgs(
["--verbose", "--", "--not-a-flag", "file.txt"],
{ booleanOptions: ["verbose"] }
);
assert.equal(options.verbose, true);
assert.deepEqual(positionals, ["--not-a-flag", "file.txt"]);
});

test("parseArgs: missing value for value option throws Error", () => {
assert.throws(
() => parseArgs(["--output"], { valueOptions: ["output"] }),
{ message: "Missing value for --output" }
);
});

// --- splitRawArgumentString ---

test("splitRawArgumentString: space-separated tokens", () => {
assert.deepEqual(splitRawArgumentString("foo bar baz"), ["foo", "bar", "baz"]);
});

test("splitRawArgumentString: single-quoted string with spaces becomes one token", () => {
assert.deepEqual(splitRawArgumentString("hello 'foo bar' world"), ["hello", "foo bar", "world"]);
});

test("splitRawArgumentString: double-quoted string with spaces becomes one token", () => {
assert.deepEqual(splitRawArgumentString('hello "foo bar" world'), ["hello", "foo bar", "world"]);
});

test("splitRawArgumentString: backslash escape preserves next char", () => {
assert.deepEqual(splitRawArgumentString("foo\\ bar baz"), ["foo bar", "baz"]);
});

test("splitRawArgumentString: trailing backslash appended literally", () => {
assert.deepEqual(splitRawArgumentString("foo\\"), ["foo\\"]);
});
25 changes: 25 additions & 0 deletions tests/prompts.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import test from "node:test";
import assert from "node:assert/strict";

import { interpolateTemplate } from "../plugins/codex/scripts/lib/prompts.mjs";

test("interpolateTemplate: replaces {{KEY}} with provided variable", () => {
assert.equal(interpolateTemplate("Hello {{NAME}}", { NAME: "World" }), "Hello World");
});

test("interpolateTemplate: replaces multiple different keys in one pass", () => {
const result = interpolateTemplate("{{GREETING}}, {{NAME}}!", { GREETING: "Hi", NAME: "Alice" });
assert.equal(result, "Hi, Alice!");
});

test("interpolateTemplate: unknown key is replaced with empty string", () => {
assert.equal(interpolateTemplate("Hello {{MISSING}}", {}), "Hello ");
});

test("interpolateTemplate: template with no placeholders is returned unchanged", () => {
assert.equal(interpolateTemplate("no placeholders here", { KEY: "val" }), "no placeholders here");
});

test("interpolateTemplate: key appearing twice is replaced both times", () => {
assert.equal(interpolateTemplate("{{X}} and {{X}}", { X: "ok" }), "ok and ok");
});