Files
buzz/desktop/src/features/workflows/ui/workflowConditionExpression.test.mjs
2026-08-13 22:35:03 -07:00

148 lines
3.7 KiB
JavaScript

import assert from "node:assert/strict";
import { test } from "node:test";
import {
buildConditionExpression,
conditionFieldsForTrigger,
conditionOperatorsForField,
normalizeWebhookField,
parseConditionExpression,
} from "./workflowConditionExpression.ts";
test("builds the supported string conditions", () => {
assert.equal(
buildConditionExpression({
field: "trigger_text",
operator: "contains",
value: "deploy",
}),
'str_contains(trigger_text, "deploy")',
);
assert.equal(
buildConditionExpression({
field: "trigger_text",
operator: "not_contains",
value: "draft",
}),
'!str_contains(trigger_text, "draft")',
);
assert.equal(
buildConditionExpression({
field: "trigger_author",
operator: "equals",
value: "abc123",
}),
'trigger_author == "abc123"',
);
});
test("escapes values before placing them in an expression", () => {
assert.equal(
buildConditionExpression({
field: "trigger_text",
operator: "equals",
value: 'say "hello"\\world',
}),
'trigger_text == "say \\"hello\\"\\\\world"',
);
});
test("builds empty checks without requiring comparison text", () => {
assert.equal(
buildConditionExpression({
field: "trigger_emoji",
operator: "is_not_empty",
value: "",
}),
"str_len(trigger_emoji) > 0",
);
});
test("normalizes safe webhook fields and rejects reserved or invalid names", () => {
assert.equal(normalizeWebhookField("environment"), "trigger_environment");
assert.equal(normalizeWebhookField("deploy_id"), "trigger_deploy_id");
assert.equal(normalizeWebhookField("trigger_text"), null);
assert.equal(normalizeWebhookField("bad-name"), null);
});
test("shows trigger-relevant fields", () => {
assert.deepEqual(
conditionFieldsForTrigger("reaction_added").map((field) => field.value),
["trigger_emoji", "trigger_author", "trigger_message_id"],
);
assert.equal(conditionFieldsForTrigger("webhook")[0].value, "webhook_field");
for (const triggerType of ["message_posted", "diff_posted"]) {
assert.equal(
conditionFieldsForTrigger(triggerType).some(
(field) => field.value === "trigger_message_id",
),
false,
);
}
for (const triggerType of [
"message_posted",
"diff_posted",
"reaction_added",
"webhook",
"schedule",
]) {
assert.equal(
conditionFieldsForTrigger(triggerType).some(
(field) => field.value === "trigger_channel_id",
),
false,
);
}
});
test("limits opaque identifiers to equality operators", () => {
for (const field of [
"trigger_author",
"trigger_emoji",
"trigger_channel_id",
"trigger_message_id",
"future_resource_id",
]) {
assert.deepEqual(conditionOperatorsForField(field), [
"equals",
"not_equals",
]);
}
assert.equal(conditionOperatorsForField("trigger_text").length, 8);
});
test("parses generated conditions back into editor fields", () => {
assert.deepEqual(
parseConditionExpression(
'str_contains(trigger_text, "deploy \\"buzz\\"")',
"message_posted",
),
{
field: "trigger_text",
operator: "contains",
value: 'deploy "buzz"',
webhookField: "",
},
);
assert.deepEqual(
parseConditionExpression('trigger_environment == "prod"', "webhook"),
{
field: "webhook_field",
operator: "equals",
value: "prod",
webhookField: "environment",
},
);
});
test("keeps unsupported expressions in custom mode", () => {
assert.equal(
parseConditionExpression("trigger_timestamp > 0", "message_posted"),
null,
);
assert.equal(
parseConditionExpression('trigger_emoji == "👍"', "message_posted"),
null,
);
});