fix: OCAS_DIR → OCAS_HOME in test helpers #59
@@ -19,7 +19,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"prepublishOnly": "echo 'Use pnpm run release from repo root' && exit 1",
|
"prepublishOnly": "echo 'Use pnpm run release from repo root' && exit 1",
|
||||||
"test": "vitest run __tests__/",
|
"test": "vitest run __tests__/",
|
||||||
"test:ci": "vitest run __tests__/"
|
"test:ci": "vitest run __tests__/ --exclude __tests__/integration/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ocas/core": "^0.3.0",
|
"@ocas/core": "^0.3.0",
|
||||||
|
|||||||
@@ -241,7 +241,9 @@ describe("E2E mock-agent: full uwf pipeline", () => {
|
|||||||
expect(finalEntry!.head).toBe(step2.head);
|
expect(finalEntry!.head).toBe(step2.head);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("2. branching workflow loops developer→reviewer→developer→reviewer→$END", async () => {
|
test("2. branching workflow loops developer→reviewer→developer→reviewer→$END", {
|
||||||
|
timeout: 30_000,
|
||||||
|
}, async () => {
|
||||||
await writeMockConfig("e2e-loop.mock.yaml");
|
await writeMockConfig("e2e-loop.mock.yaml");
|
||||||
const workflowHash = await addWorkflow("e2e-loop.workflow.yaml", "test-loop");
|
const workflowHash = await addWorkflow("e2e-loop.workflow.yaml", "test-loop");
|
||||||
|
|
||||||
@@ -299,7 +301,9 @@ describe("E2E mock-agent: full uwf pipeline", () => {
|
|||||||
expect(finalEntry!.status).toBe("completed");
|
expect(finalEntry!.status).toBe("completed");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("3. role mismatch in mock data makes the agent exit with an error", async () => {
|
test("3. role mismatch in mock data makes the agent exit with an error", {
|
||||||
|
timeout: 30_000,
|
||||||
|
}, async () => {
|
||||||
// Reuses the linear workflow but with a mock whose step[1].role is wrong.
|
// Reuses the linear workflow but with a mock whose step[1].role is wrong.
|
||||||
await writeMockConfig("e2e-mismatch.mock.yaml");
|
await writeMockConfig("e2e-mismatch.mock.yaml");
|
||||||
const workflowHash = await addWorkflow("e2e-linear.workflow.yaml", "test-linear");
|
const workflowHash = await addWorkflow("e2e-linear.workflow.yaml", "test-linear");
|
||||||
@@ -325,7 +329,9 @@ describe("E2E mock-agent: full uwf pipeline", () => {
|
|||||||
expect(entry!.head).toBe(step1.head);
|
expect(entry!.head).toBe(step1.head);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("4. planner $SUSPEND then resume re-runs planner and reaches $END", async () => {
|
test("4. planner $SUSPEND then resume re-runs planner and reaches $END", {
|
||||||
|
timeout: 30_000,
|
||||||
|
}, async () => {
|
||||||
await writeMockConfig("e2e-suspend.mock.yaml");
|
await writeMockConfig("e2e-suspend.mock.yaml");
|
||||||
const workflowHash = await addWorkflow("e2e-suspend.workflow.yaml", "test-suspend");
|
const workflowHash = await addWorkflow("e2e-suspend.workflow.yaml", "test-suspend");
|
||||||
|
|
||||||
@@ -372,7 +378,9 @@ describe("E2E mock-agent: full uwf pipeline", () => {
|
|||||||
expect(finalEntry!.head).toBe(resumeOut.head);
|
expect(finalEntry!.head).toBe(resumeOut.head);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("5. --count 3 runs the whole linear pipeline in one invocation", async () => {
|
test("5. --count 3 runs the whole linear pipeline in one invocation", {
|
||||||
|
timeout: 30_000,
|
||||||
|
}, async () => {
|
||||||
await writeMockConfig("e2e-count.mock.yaml");
|
await writeMockConfig("e2e-count.mock.yaml");
|
||||||
const workflowHash = await addWorkflow("e2e-count.workflow.yaml", "test-count");
|
const workflowHash = await addWorkflow("e2e-count.workflow.yaml", "test-count");
|
||||||
|
|
||||||
@@ -412,7 +420,9 @@ describe("E2E mock-agent: full uwf pipeline", () => {
|
|||||||
expect(finalEntry!.head).toBe(results[2].head);
|
expect(finalEntry!.head).toBe(results[2].head);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("6. mustache edge prompt renders planner variables into the worker step", async () => {
|
test("6. mustache edge prompt renders planner variables into the worker step", {
|
||||||
|
timeout: 30_000,
|
||||||
|
}, async () => {
|
||||||
await writeMockConfig("e2e-mustache.mock.yaml");
|
await writeMockConfig("e2e-mustache.mock.yaml");
|
||||||
const workflowHash = await addWorkflow("e2e-mustache.workflow.yaml", "test-mustache");
|
const workflowHash = await addWorkflow("e2e-mustache.workflow.yaml", "test-mustache");
|
||||||
|
|
||||||
@@ -441,7 +451,9 @@ describe("E2E mock-agent: full uwf pipeline", () => {
|
|||||||
expect(workerStep.edgePrompt).toBe("Work on branch fix/42-auth in /tmp/my-repo");
|
expect(workerStep.edgePrompt).toBe("Work on branch fix/42-auth in /tmp/my-repo");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("7. completed thread can be resumed (衔尾蛇: end → start)", async () => {
|
test("7. completed thread can be resumed (衔尾蛇: end → start)", {
|
||||||
|
timeout: 30_000,
|
||||||
|
}, async () => {
|
||||||
// Reuse the suspend workflow (planner with ready → $END), but mock data
|
// Reuse the suspend workflow (planner with ready → $END), but mock data
|
||||||
// goes straight to ready on first run, then ready again after resume.
|
// goes straight to ready on first run, then ready again after resume.
|
||||||
await writeMockConfig("e2e-completed-resume.mock.yaml");
|
await writeMockConfig("e2e-completed-resume.mock.yaml");
|
||||||
|
|||||||
@@ -88,11 +88,11 @@ describe("prompt commands", () => {
|
|||||||
expect(result).toContain("version");
|
expect(result).toContain("version");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("prompt help subcommand is suppressed", () => {
|
test("prompt help subcommand is suppressed", { timeout: 30_000 }, () => {
|
||||||
const output = execFileSync("npx", ["tsx", "src/cli.ts", "prompt", "--help"], {
|
const cliPath = join(__dirname, "..", "..", "dist", "cli.js");
|
||||||
cwd: join(__dirname, "..", ".."),
|
const output = execFileSync("node", [cliPath, "prompt", "--help"], {
|
||||||
encoding: "utf-8",
|
encoding: "utf-8",
|
||||||
env: { ...process.env, PATH: `/opt/homebrew/bin:${process.env.PATH}` },
|
env: { ...process.env },
|
||||||
});
|
});
|
||||||
expect(output).not.toMatch(/help\s+\[command\]/i);
|
expect(output).not.toMatch(/help\s+\[command\]/i);
|
||||||
expect(output).toContain("usage");
|
expect(output).toContain("usage");
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
async function makeUwfStore(storageRoot: string) {
|
async function makeUwfStore(storageRoot: string) {
|
||||||
const casDir = join(storageRoot, "cas");
|
const casDir = join(storageRoot, "cas");
|
||||||
await mkdir(casDir, { recursive: true });
|
await mkdir(casDir, { recursive: true });
|
||||||
process.env.OCAS_DIR = casDir;
|
process.env.OCAS_HOME = casDir;
|
||||||
return createUwfStore(storageRoot);
|
return createUwfStore(storageRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ describe("uwf thread resume - completed threads", () => {
|
|||||||
cwd: tmpDir,
|
cwd: tmpDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
process.env.OCAS_DIR = casDir;
|
process.env.OCAS_HOME = casDir;
|
||||||
|
|
||||||
const workerOutputHash = await store.cas.put(outputSchemaHash, { $status: "_" });
|
const workerOutputHash = await store.cas.put(outputSchemaHash, { $status: "_" });
|
||||||
const reviewerOutputHash = await store.cas.put(outputSchemaHash, { $status: "_" });
|
const reviewerOutputHash = await store.cas.put(outputSchemaHash, { $status: "_" });
|
||||||
@@ -539,9 +539,7 @@ describe("uwf thread resume - completed threads", () => {
|
|||||||
const { createUwfStore, getThread } = await import("../store.js");
|
const { createUwfStore, getThread } = await import("../store.js");
|
||||||
const verifyUwf = await createUwfStore(tmpDir);
|
const verifyUwf = await createUwfStore(tmpDir);
|
||||||
const verifyEntry = getThread(verifyUwf.varStore, THREAD_ID);
|
const verifyEntry = getThread(verifyUwf.varStore, THREAD_ID);
|
||||||
// biome-ignore lint/suspicious/noConsole: test debugging
|
|
||||||
console.log("Seeded entry status:", verifyEntry?.status);
|
console.log("Seeded entry status:", verifyEntry?.status);
|
||||||
// biome-ignore lint/suspicious/noConsole: test debugging
|
|
||||||
console.log("Seeded entry:", JSON.stringify(verifyEntry, null, 2));
|
console.log("Seeded entry:", JSON.stringify(verifyEntry, null, 2));
|
||||||
|
|
||||||
const promptCapturePath = join(tmpDir, "captured-prompt-completed.txt");
|
const promptCapturePath = join(tmpDir, "captured-prompt-completed.txt");
|
||||||
@@ -601,7 +599,6 @@ echo '${adapterJson}'
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (result.status !== 0) {
|
if (result.status !== 0) {
|
||||||
// biome-ignore lint/suspicious/noConsole: test debugging
|
|
||||||
console.error("Command failed:", result.stderr);
|
console.error("Command failed:", result.stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -654,7 +651,7 @@ echo '${adapterJson}'
|
|||||||
cwd: tmpDir,
|
cwd: tmpDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
process.env.OCAS_DIR = casDir;
|
process.env.OCAS_HOME = casDir;
|
||||||
await seedThreads(tmpDir, {
|
await seedThreads(tmpDir, {
|
||||||
[THREAD_ID]: {
|
[THREAD_ID]: {
|
||||||
head: startHash,
|
head: startHash,
|
||||||
@@ -702,7 +699,7 @@ echo '${adapterJson}'
|
|||||||
cwd: tmpDir,
|
cwd: tmpDir,
|
||||||
});
|
});
|
||||||
|
|
||||||
process.env.OCAS_DIR = casDir;
|
process.env.OCAS_HOME = casDir;
|
||||||
await seedThreads(tmpDir, { [THREAD_ID]: startHash });
|
await seedThreads(tmpDir, { [THREAD_ID]: startHash });
|
||||||
|
|
||||||
const result = runUwf(["thread", "resume", THREAD_ID], casDir);
|
const result = runUwf(["thread", "resume", THREAD_ID], casDir);
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { dirname, join } from "node:path";
|
|||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { describe, expect, test } from "vitest";
|
import { describe, expect, test } from "vitest";
|
||||||
|
|
||||||
const CLI_PATH = join(dirname(fileURLToPath(import.meta.url)), "..", "cli.js");
|
const CLI_PATH = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "dist", "cli.js");
|
||||||
|
|
||||||
function runCli(args: string[]): { stdout: string; stderr: string; exitCode: number } {
|
function runCli(args: string[]): { stdout: string; stderr: string; exitCode: number } {
|
||||||
try {
|
try {
|
||||||
const stdout = execFileSync("npx", ["tsx", CLI_PATH, ...args], {
|
const stdout = execFileSync("node", [CLI_PATH, ...args], {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
env: { ...process.env, UWF_HOME: "/tmp/uwf-test-nonexistent" },
|
env: { ...process.env, UWF_HOME: "/tmp/uwf-test-nonexistent" },
|
||||||
stdio: ["ignore", "pipe", "pipe"],
|
stdio: ["ignore", "pipe", "pipe"],
|
||||||
@@ -24,19 +24,21 @@ function runCli(args: string[]): { stdout: string; stderr: string; exitCode: num
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("thread exec --count CLI parsing", () => {
|
describe("thread exec --count CLI parsing", () => {
|
||||||
test("--help shows -c/--count option", () => {
|
test("--help shows -c/--count option", { timeout: 30_000 }, () => {
|
||||||
const result = runCli(["thread", "exec", "--help"]);
|
const result = runCli(["thread", "exec", "--help"]);
|
||||||
expect(result.stdout).toContain("--count");
|
const combined = result.stdout + result.stderr;
|
||||||
expect(result.stdout).toContain("-c");
|
expect(combined).toContain("--count");
|
||||||
|
expect(combined).toContain("-c");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("description says 'one or more steps'", () => {
|
test("description says 'one or more steps'", { timeout: 30_000 }, () => {
|
||||||
const result = runCli(["thread", "exec", "--help"]);
|
const result = runCli(["thread", "exec", "--help"]);
|
||||||
expect(result.stdout).toContain("one or more steps");
|
const combined = result.stdout + result.stderr;
|
||||||
|
expect(combined).toContain("one or more steps");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("cmdThreadExec count logic", () => {
|
describe("cmdThreadExec count logic", { timeout: 30_000 }, () => {
|
||||||
test("count=0 fails with validation error", () => {
|
test("count=0 fails with validation error", () => {
|
||||||
const result = runCli(["thread", "exec", "FAKE_THREAD_ID", "-c", "0"]);
|
const result = runCli(["thread", "exec", "FAKE_THREAD_ID", "-c", "0"]);
|
||||||
expect(result.exitCode).not.toBe(0);
|
expect(result.exitCode).not.toBe(0);
|
||||||
|
|||||||
Reference in New Issue
Block a user