mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
176 lines
5.1 KiB
TypeScript
176 lines
5.1 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { Hono } from "hono";
|
|
import { Event, EventManager } from "../../src/core/events";
|
|
import { type Static, type StaticDecode, Type, parse } from "../../src/core/utils";
|
|
import { EventTrigger, Flow, HttpTrigger, type InputsMap, Task } from "../../src/flows";
|
|
import { dynamic } from "../../src/flows/tasks/Task";
|
|
|
|
class Passthrough extends Task {
|
|
type = "passthrough";
|
|
|
|
async execute(inputs: Map<string, any>) {
|
|
//console.log("executing passthrough", this.name, inputs);
|
|
return Array.from(inputs.values()).pop().output + "/" + this.name;
|
|
}
|
|
}
|
|
|
|
type OutputIn = Static<typeof OutputParamTask.schema>;
|
|
type OutputOut = StaticDecode<typeof OutputParamTask.schema>;
|
|
|
|
class OutputParamTask extends Task<typeof OutputParamTask.schema> {
|
|
type = "output-param";
|
|
|
|
static override schema = Type.Object({
|
|
number: dynamic(
|
|
Type.Number({
|
|
title: "Output number"
|
|
}),
|
|
Number.parseInt
|
|
)
|
|
});
|
|
|
|
async execute(inputs: InputsMap) {
|
|
//console.log("--***--- executing output", this.params);
|
|
return this.params.number;
|
|
}
|
|
}
|
|
|
|
class PassthroughFlowInput extends Task {
|
|
type = "passthrough-flow-input";
|
|
|
|
async execute(inputs: InputsMap) {
|
|
return inputs.get("flow")?.output;
|
|
}
|
|
}
|
|
|
|
describe("Flow task inputs", async () => {
|
|
test("types", async () => {
|
|
const schema = OutputParamTask.schema;
|
|
|
|
expect(parse(schema, { number: 123 })).toBeDefined();
|
|
expect(parse(schema, { number: "{{ some.path }}" })).toBeDefined();
|
|
|
|
const task = new OutputParamTask("", { number: 123 });
|
|
expect(task.params.number).toBe(123);
|
|
});
|
|
|
|
test("passthrough", async () => {
|
|
const task = new Passthrough("log");
|
|
const task2 = new Passthrough("log_2");
|
|
|
|
const flow = new Flow("test", [task, task2]);
|
|
flow.task(task).asInputFor(task2);
|
|
flow.setRespondingTask(task2);
|
|
|
|
const exec = await flow.start("pass-through");
|
|
|
|
/*console.log(
|
|
"---- log",
|
|
exec.logs.map(({ task, ...l }) => ({ ...l, ...task.toJSON() })),
|
|
);
|
|
console.log("---- result", exec.getResponse());*/
|
|
expect(exec.getResponse()).toBe("pass-through/log/log_2");
|
|
});
|
|
|
|
test("output/input", async () => {
|
|
const task = new OutputParamTask("task1", { number: 111 });
|
|
const task2 = new OutputParamTask("task2", {
|
|
number: "{{ task1.output }}"
|
|
});
|
|
|
|
const flow = new Flow("test", [task, task2]);
|
|
flow.task(task).asInputFor(task2);
|
|
flow.setRespondingTask(task2);
|
|
|
|
const exec = await flow.start();
|
|
|
|
/*console.log(
|
|
"---- log",
|
|
exec.logs.map(({ task, ...l }) => ({ ...l, ...task.toJSON() })),
|
|
);
|
|
console.log("---- result", exec.getResponse());*/
|
|
expect(exec.getResponse()).toBe(111);
|
|
});
|
|
|
|
test("input from flow", async () => {
|
|
const task = new OutputParamTask("task1", {
|
|
number: "{{flow.output.someFancyParam}}"
|
|
});
|
|
const task2 = new OutputParamTask("task2", {
|
|
number: "{{task1.output}}"
|
|
});
|
|
|
|
const flow = new Flow("test", [task, task2]);
|
|
flow.task(task).asInputFor(task2);
|
|
flow.setRespondingTask(task2);
|
|
|
|
// expect to throw because of missing input
|
|
//expect(flow.start()).rejects.toThrow();
|
|
|
|
const exec = await flow.start({ someFancyParam: 123 });
|
|
|
|
/*console.log(
|
|
"---- log",
|
|
exec.logs.map(({ task, ...l }) => ({ ...l, ...task.toJSON() })),
|
|
);
|
|
console.log("---- result", exec.getResponse());*/
|
|
|
|
expect(exec.getResponse()).toBe(123);
|
|
});
|
|
|
|
test("manual event trigger with inputs", async () => {
|
|
class EventTriggerClass extends Event<{ number: number }> {
|
|
static override slug = "test-event";
|
|
}
|
|
|
|
const emgr = new EventManager({ EventTriggerClass });
|
|
|
|
const task = new OutputParamTask("event", {
|
|
number: "{{flow.output.number}}"
|
|
});
|
|
const flow = new Flow(
|
|
"test",
|
|
[task],
|
|
[],
|
|
new EventTrigger({
|
|
event: "test-event",
|
|
mode: "sync"
|
|
})
|
|
);
|
|
flow.setRespondingTask(task);
|
|
flow.trigger.register(flow, emgr);
|
|
|
|
await emgr.emit(new EventTriggerClass({ number: 120 }));
|
|
const execs = flow.trigger.executions;
|
|
expect(execs.length).toBe(1);
|
|
expect(execs[0]!.getResponse()).toBe(120);
|
|
});
|
|
|
|
test("http trigger with response", async () => {
|
|
const task = new PassthroughFlowInput("");
|
|
const flow = new Flow(
|
|
"test",
|
|
[task],
|
|
[],
|
|
new HttpTrigger({
|
|
path: "/test",
|
|
method: "GET",
|
|
mode: "sync"
|
|
})
|
|
);
|
|
flow.setRespondingTask(task);
|
|
|
|
const hono = new Hono();
|
|
|
|
flow.trigger.register(flow, hono);
|
|
|
|
const res = await hono.request("/test?input=123");
|
|
const data = await res.json();
|
|
//console.log("response", data);
|
|
const execs = flow.trigger.executions;
|
|
expect(execs.length).toBe(1);
|
|
expect(execs[0]!.getResponse()).toBeInstanceOf(Request);
|
|
expect(execs[0]!.getResponse()?.url).toBe("http://localhost/test?input=123");
|
|
});
|
|
});
|