Files
oh-my-pi/packages/coding-agent/test/loop-limit.test.ts
T
can1357 741558a6d4 feat(coding-agent): removed background mode command and runtime plumbing
- Removed the built-in `background` (`bg`) slash command and its `handleBackgroundCommand` path from the interactive flow.
- Deleted background event subscription and shutdown handling by removing `handleBackgroundEvent` from the event, input, and interactive controllers.
- Simplified `InteractiveModeContext` by dropping background-only fields and helpers such as `isBackgrounded`, background UI context creation, and background event callbacks.
2026-06-07 05:43:59 +02:00

71 lines
2.9 KiB
TypeScript

import { describe, expect, test, vi } from "bun:test";
import {
consumeLoopLimitIteration,
createLoopLimitRuntime,
isLoopDurationExpired,
parseLoopLimitArgs,
} from "@oh-my-pi/pi-coding-agent/modes/loop-limit";
import type { BuiltinSlashCommandRuntime } from "@oh-my-pi/pi-coding-agent/slash-commands/builtin-registry";
import { executeBuiltinSlashCommand } from "@oh-my-pi/pi-coding-agent/slash-commands/builtin-registry";
describe("/loop slash command", () => {
test("accepts an optional limit argument", async () => {
const handleLoopCommand = vi.fn(async (_args?: string) => {});
const runtime = {
ctx: {
handleLoopCommand,
editor: { setText: vi.fn() },
},
} as unknown as BuiltinSlashCommandRuntime;
const result = await executeBuiltinSlashCommand("/loop 10min", runtime);
expect(result).toBe(true);
expect(handleLoopCommand).toHaveBeenCalledWith("10min");
});
});
describe("loop limit parsing", () => {
test("parses a bare positive integer as an iteration limit", () => {
expect(parseLoopLimitArgs("10")).toEqual({ kind: "iterations", iterations: 10 });
});
test("parses minute duration aliases", () => {
expect(parseLoopLimitArgs("10m")).toEqual({ kind: "duration", durationMs: 600_000 });
expect(parseLoopLimitArgs("10min")).toEqual({ kind: "duration", durationMs: 600_000 });
expect(parseLoopLimitArgs("10 minutes")).toEqual({ kind: "duration", durationMs: 600_000 });
});
test("rejects zero, negative, and unknown limits", () => {
expect(parseLoopLimitArgs("0")).toBe("Loop count must be a positive integer.");
expect(parseLoopLimitArgs("-1")).toContain("Usage: /loop");
expect(parseLoopLimitArgs("10fortnights")).toBe("Loop duration unit must be seconds, minutes, or hours.");
});
});
describe("loop limit runtime", () => {
test("allows exactly the configured number of auto-submitted iterations", () => {
const config = parseLoopLimitArgs("3");
expect(config).toEqual({ kind: "iterations", iterations: 3 });
if (!config || typeof config === "string") throw new Error("expected parsed config");
const limit = createLoopLimitRuntime(config);
expect(consumeLoopLimitIteration(limit)).toBe(true);
expect(consumeLoopLimitIteration(limit)).toBe(true);
expect(consumeLoopLimitIteration(limit)).toBe(true);
expect(consumeLoopLimitIteration(limit)).toBe(false);
expect(limit).toEqual({ kind: "iterations", initial: 3, remaining: 0 });
});
test("stops duration-limited loops at the configured deadline", () => {
const config = parseLoopLimitArgs("10m");
expect(config).toEqual({ kind: "duration", durationMs: 600_000 });
if (!config || typeof config === "string") throw new Error("expected parsed config");
const limit = createLoopLimitRuntime(config, 1_000);
expect(consumeLoopLimitIteration(limit, 600_999)).toBe(true);
expect(isLoopDurationExpired(limit, 600_999)).toBe(false);
expect(consumeLoopLimitIteration(limit, 601_000)).toBe(false);
expect(isLoopDurationExpired(limit, 601_000)).toBe(true);
});
});