@skynetxbt/flow-input
Version:
Input Flow for iterative operations with done/continue logic
220 lines (173 loc) • 7.99 kB
text/typescript
import { describe, test, expect } from "bun:test";
import { InputFlow } from "./index";
import type { FlowContext } from "@skynetxbt/core";
// Mock FlowContext helper
const createMockContext = (message: any): FlowContext => ({
agentId: {
generation: 1,
familyCode: "test",
serialNumber: "001"
},
userPublicKey: "mock-key",
message,
timestamp: Date.now(),
variables: {},
userId: "test-user",
sessionId: "test-session"
});
describe("InputFlow", () => {
describe("constructor", () => {
test("should initialize with input template", () => {
const flow = new InputFlow("hello world");
expect(flow.flowConfig.name).toBe("InputFlow");
expect(flow.flowConfig.description).toBe("Input Flow for processing user inputs");
expect(flow.input).toBe("hello world");
});
});
describe("static template handling (regression fix)", () => {
test("should return static template when no placeholder is present", async () => {
const flow = new InputFlow("hello");
const context = createMockContext("world");
const result = await flow.execute(context);
expect(result).toBe("hello"); // Should return the template, not the context message
});
test("should return static template for complex strings without placeholder", async () => {
const flow = new InputFlow("This is a static template");
const context = createMockContext("user input");
const result = await flow.execute(context);
expect(result).toBe("This is a static template");
});
test("should return static template even when context is empty", async () => {
const flow = new InputFlow("static text");
const context = createMockContext("");
const result = await flow.execute(context);
expect(result).toBe("static text");
});
test("should return static template even when context is null", async () => {
const flow = new InputFlow("static text");
const context = createMockContext(null);
const result = await flow.execute(context);
expect(result).toBe("static text");
});
});
describe("template with placeholder", () => {
test("should replace placeholder with context message", async () => {
const flow = new InputFlow("Hello {{$input}}!");
const context = createMockContext("world");
const result = await flow.execute(context);
expect(result).toBe("Hello world!");
});
test("should handle multiple placeholders", async () => {
const flow = new InputFlow("{{$input}} says {{$input}} twice");
const context = createMockContext("echo");
const result = await flow.execute(context);
expect(result).toBe("echo says echo twice");
});
test("should handle placeholder in middle of template", async () => {
const flow = new InputFlow("Start {{$input}} end");
const context = createMockContext("middle");
const result = await flow.execute(context);
expect(result).toBe("Start middle end");
});
test("should handle empty context with placeholder", async () => {
const flow = new InputFlow("Value: {{$input}}");
const context = createMockContext("");
const result = await flow.execute(context);
expect(result).toBe("Value: ");
});
test("should handle null context with placeholder", async () => {
const flow = new InputFlow("Value: {{$input}}");
const context = createMockContext(null);
const result = await flow.execute(context);
expect(result).toBe("Value: null");
});
test("should handle numeric context with placeholder", async () => {
const flow = new InputFlow("Number: {{$input}}");
const context = createMockContext(42);
const result = await flow.execute(context);
expect(result).toBe("Number: 42");
});
test("should handle object context with placeholder", async () => {
const flow = new InputFlow("Object: {{$input}}");
const context = createMockContext({ key: "value" });
const result = await flow.execute(context);
expect(result).toBe("Object: [object Object]");
});
});
describe("processInput method directly", () => {
test("should process input with placeholder directly", async () => {
const flow = new InputFlow("Hello {{$input}}!");
const result = await flow.processInput("test");
expect(result).toBe("Hello test!");
});
test("should return template when no placeholder (direct call)", async () => {
const flow = new InputFlow("static template");
const result = await flow.processInput("ignored input");
expect(result).toBe("static template");
});
test("should handle complex placeholders", async () => {
const flow = new InputFlow("Before {{$input}} after {{$input}} end");
const result = await flow.processInput("REPLACE");
expect(result).toBe("Before REPLACE after REPLACE end");
});
});
describe("edge cases", () => {
test("should handle template that looks like placeholder but isn't exact", async () => {
const flow = new InputFlow("This has {$input} but not exact placeholder");
const context = createMockContext("test");
const result = await flow.execute(context);
expect(result).toBe("This has {$input} but not exact placeholder");
});
test("should handle template with only opening braces", async () => {
const flow = new InputFlow("{{incomplete");
const context = createMockContext("test");
const result = await flow.execute(context);
expect(result).toBe("{{incomplete");
});
test("should handle template with only closing braces", async () => {
const flow = new InputFlow("incomplete}}");
const context = createMockContext("test");
const result = await flow.execute(context);
expect(result).toBe("incomplete}}");
});
test("should handle empty template", async () => {
const flow = new InputFlow("");
const context = createMockContext("test");
const result = await flow.execute(context);
expect(result).toBe("");
});
test("should handle template that is only the placeholder", async () => {
const flow = new InputFlow("{{$input}}");
const context = createMockContext("replacement");
const result = await flow.execute(context);
expect(result).toBe("replacement");
});
});
describe("regression verification", () => {
test("regression example: new InputFlow('hello').execute({message: 'world'}) should return 'hello'", async () => {
const flow = new InputFlow("hello");
const context = createMockContext("world");
const result = await flow.execute(context);
// Before fix: would return "world"
// After fix: should return "hello"
expect(result).toBe("hello");
});
test("regression example: template with placeholder should still work", async () => {
const flow = new InputFlow("hello {{$input}}");
const context = createMockContext("world");
const result = await flow.execute(context);
expect(result).toBe("hello world");
});
test("multiple regression scenarios", async () => {
// Static template scenarios
const staticFlow = new InputFlow("static");
expect(await staticFlow.execute(createMockContext("dynamic"))).toBe("static");
// Dynamic template scenarios
const dynamicFlow = new InputFlow("{{$input}} template");
expect(await dynamicFlow.execute(createMockContext("dynamic"))).toBe("dynamic template");
// Complex static template
const complexFlow = new InputFlow("Complex static template with symbols @#$%");
expect(await complexFlow.execute(createMockContext("ignored"))).toBe("Complex static template with symbols @#$%");
});
});
});