Files
lobster/test/condition_comparison.test.ts

140 lines
4.5 KiB
TypeScript

import test from "node:test";
import assert from "node:assert/strict";
import { promises as fsp } from "node:fs";
import os from "node:os";
import path from "node:path";
import { runWorkflowFile } from "../src/workflows/file.js";
async function runWorkflow(workflow: unknown) {
const tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), "lobster-cond-"));
const stateDir = path.join(tmpDir, "state");
const filePath = path.join(tmpDir, "workflow.lobster");
await fsp.writeFile(filePath, JSON.stringify(workflow, null, 2), "utf8");
return runWorkflowFile({
filePath,
ctx: {
stdin: process.stdin,
stdout: process.stdout,
stderr: process.stderr,
env: { ...process.env, LOBSTER_STATE_DIR: stateDir },
mode: "tool",
},
});
}
test("condition > works with numbers", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({count:5}))"' },
{ id: "check", command: 'echo "big"', when: "$data.json.count > 3" },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["big\n"]);
});
test("condition > skips when false", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({count:1}))"' },
{ id: "check", command: 'echo "big"', when: "$data.json.count > 3" },
{ id: "fallback", command: 'echo "small"' },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["small\n"]);
});
test("condition < works", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({val:2}))"' },
{ id: "check", command: 'echo "low"', when: "$data.json.val < 10" },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["low\n"]);
});
test("condition >= works at boundary", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({val:5}))"' },
{ id: "check", command: 'echo "yes"', when: "$data.json.val >= 5" },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["yes\n"]);
});
test("condition <= works at boundary", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({val:5}))"' },
{ id: "check", command: 'echo "yes"', when: "$data.json.val <= 5" },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["yes\n"]);
});
test("comparison operators combine with boolean operators", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({a:5,b:20}))"' },
{ id: "check", command: 'echo "in range"', when: "$data.json.a >= 1 && $data.json.b < 100" },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["in range\n"]);
});
test("comparison with non-numeric string returns false", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({val:\\"hello\\"}))"' },
{ id: "check", command: 'echo "yes"', when: "$data.json.val > 3" },
{ id: "fallback", command: 'echo "no"' },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["no\n"]);
});
test("comparison rejects boolean as non-numeric", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({val:true}))"' },
{ id: "check", command: 'echo "yes"', when: "$data.json.val > 0" },
{ id: "fallback", command: 'echo "no"' },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["no\n"]);
});
test("comparison rejects null as non-numeric", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({val:null}))"' },
{ id: "check", command: 'echo "yes"', when: "$data.json.val >= 0" },
{ id: "fallback", command: 'echo "no"' },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["no\n"]);
});
test("existing == and != still work with new operators", async () => {
const result = await runWorkflow({
steps: [
{ id: "data", command: 'node -e "process.stdout.write(JSON.stringify({status:\\"ok\\"}))"' },
{ id: "check", command: 'echo "good"', when: '$data.json.status == "ok"' },
],
});
assert.equal(result.status, "ok");
assert.deepEqual(result.output, ["good\n"]);
});