mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Clarify workflow step conditions
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
This commit is contained in:
@@ -179,9 +179,7 @@ export function WorkflowConditionBuilder({
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<fieldset aria-label="Condition">
|
||||
<legend className="mb-2 text-sm font-medium text-foreground">
|
||||
Run when
|
||||
</legend>
|
||||
<legend className="sr-only">Condition</legend>
|
||||
<div className="grid grid-cols-2 gap-2.5">
|
||||
{fieldOptions.map((field) => {
|
||||
const isMatchAll = field.value === "";
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Button } from "@/shared/ui/button";
|
||||
import { Input } from "@/shared/ui/input";
|
||||
import { Textarea } from "@/shared/ui/textarea";
|
||||
import { ChannelCombobox } from "./ChannelCombobox";
|
||||
import { WorkflowConditionBuilder } from "./WorkflowConditionBuilder";
|
||||
import { WorkflowEmojiField } from "./WorkflowEmojiField";
|
||||
import { WorkflowTemplateTextarea } from "./WorkflowTemplateTextarea";
|
||||
import { FieldLabel, FormSelect } from "./workflowFormPrimitives";
|
||||
@@ -378,6 +379,23 @@ export function WorkflowStepCard({
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section className="space-y-4 border-t border-border/50 py-5">
|
||||
<SectionHeading title="Step condition" />
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Checked after the workflow starts. If it does not match, Buzz skips
|
||||
only this step and continues the run.
|
||||
</p>
|
||||
<WorkflowConditionBuilder
|
||||
channels={channels}
|
||||
disabled={disabled}
|
||||
idPrefix={`${prefix}-condition`}
|
||||
matchAllLabel="Always run this step"
|
||||
onChange={(condition) => onUpdate({ ...step, condition })}
|
||||
triggerType={triggerType}
|
||||
value={step.condition ?? ""}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section className="space-y-4 border-t border-border/50 py-5">
|
||||
<SectionHeading title="Step timeout" />
|
||||
<div className="space-y-1.5">
|
||||
|
||||
@@ -63,7 +63,7 @@ const FIELDS_BY_TRIGGER: Record<TriggerType, ConditionField[]> = {
|
||||
reaction_added: [
|
||||
{ label: "Reaction emoji", value: "trigger_emoji" },
|
||||
AUTHOR_FIELD,
|
||||
{ label: "Reacted-to message ID", value: "trigger_message_id" },
|
||||
{ label: "Message ID", value: "trigger_message_id" },
|
||||
],
|
||||
webhook: [{ label: "Webhook field…", value: "webhook_field" }],
|
||||
schedule: [{ label: "Scheduled timestamp", value: "trigger_timestamp" }],
|
||||
|
||||
@@ -277,7 +277,6 @@ test("builds a valid trigger condition from plain-language choices", async ({
|
||||
const inspector = dialog.getByTestId("workflow-node-inspector");
|
||||
|
||||
const conditionFields = inspector.getByRole("group", { name: "Condition" });
|
||||
await expect(inspector.getByText("Run when", { exact: true })).toBeVisible();
|
||||
const conditionOptions = conditionFields.getByRole("button");
|
||||
await expect(conditionOptions).toHaveCount(4);
|
||||
const allMessages = conditionFields.getByRole("button", {
|
||||
@@ -330,6 +329,30 @@ test("builds a valid trigger condition from plain-language choices", async ({
|
||||
await expect(inspector.getByLabel("Custom expression")).not.toBeVisible();
|
||||
});
|
||||
|
||||
test("keeps a step condition separate from its action configuration", async ({
|
||||
page,
|
||||
}) => {
|
||||
await navigateToWorkflows(page);
|
||||
|
||||
await page.getByRole("button", { name: "Create Workflow" }).click();
|
||||
const dialog = page.getByRole("dialog");
|
||||
await dialog.getByRole("button", { name: "Add step" }).click();
|
||||
await page.getByRole("menuitem", { name: "Send Message" }).click();
|
||||
|
||||
const inspector = dialog.getByTestId("workflow-node-inspector");
|
||||
await expect(inspector.getByLabel("Message text")).toBeVisible();
|
||||
await expect(
|
||||
inspector.getByRole("heading", { name: "Step condition" }),
|
||||
).toBeVisible();
|
||||
await inspector.getByRole("button", { name: "Message text" }).click();
|
||||
await inspector.getByLabel("Text to match").fill("deploy");
|
||||
|
||||
await dialog.getByRole("tab", { name: "YAML" }).click();
|
||||
await expect(dialog.getByLabel("Workflow YAML")).toHaveValue(
|
||||
/if: str_contains\(trigger_text, "deploy"\)/,
|
||||
);
|
||||
});
|
||||
|
||||
test("chooses a trigger author condition from live user search", async ({
|
||||
page,
|
||||
}) => {
|
||||
@@ -505,7 +528,7 @@ test("chooses a reaction emoji condition with the app emoji picker", async ({
|
||||
|
||||
inspector = dialog.getByTestId("workflow-node-inspector");
|
||||
await expect(
|
||||
inspector.getByRole("button", { name: "Reacted-to message ID" }),
|
||||
inspector.getByRole("button", { name: "Message ID" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
inspector.getByRole("button", { name: "Channel ID" }),
|
||||
@@ -633,8 +656,15 @@ test("opens node configuration in a contextual inspector", async ({ page }) => {
|
||||
"send_message",
|
||||
);
|
||||
await expect(inspector.getByLabel("Message text")).toBeVisible();
|
||||
await expect(
|
||||
inspector.getByRole("heading", { name: "Step condition" }),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
inspector.getByRole("button", { name: "Always run this step" }),
|
||||
).toHaveAttribute("aria-pressed", "true");
|
||||
await expect(inspector.getByText(/skips only this step/)).toBeVisible();
|
||||
await expect(inspector.getByRole("group", { name: "Condition" })).toHaveCount(
|
||||
0,
|
||||
1,
|
||||
);
|
||||
await expect(
|
||||
inspector.getByRole("heading", { name: "Step timeout" }),
|
||||
|
||||
Reference in New Issue
Block a user