1// Alchemy modifications are licensed under Apache-2.0.
2// This file includes third-party code; see /THIRD_PARTY_LICENSES.md.
3import { describe, it } from "vitest";
4import {
5 isValidAddressableWorkflowInstanceId,
6 isValidStepConfig,
7 isValidStepName,
8 isValidWorkflowInstanceId,
9 isValidWorkflowName,
10 MAX_ADDRESSABLE_WORKFLOW_INSTANCE_ID_LENGTH,
11 MAX_STEP_NAME_LENGTH,
12 MAX_WORKFLOW_INSTANCE_ID_LENGTH,
13 MAX_WORKFLOW_NAME_LENGTH,
14} from "../lib/validators.ts";
15
16describe("Workflow name validation", () => {
17 it.for([
18 "",
19 NaN,
20 undefined,
21 " ",
22 "\n\nhello",
23 "w".repeat(MAX_WORKFLOW_NAME_LENGTH + 1),
24 "#1231231!!!!",
25 "-badName",
26 ])("should reject invalid names", (value, { expect }) => {
27 expect(isValidWorkflowName(value as string)).toBe(false);
28 });
29
30 it.for([
31 "abc",
32 "NAME_123-hello",
33 "a-valid-string",
34 "w".repeat(MAX_WORKFLOW_NAME_LENGTH),
35 ])("should accept valid names", (value, { expect }) => {
36 expect(isValidWorkflowName(value as string)).toBe(true);
37 });
38});
39
40describe("Workflow instance ID validation", () => {
41 it.for([
42 "",
43 NaN,
44 undefined,
45 " ",
46 "\n\nhello",
47 "w".repeat(MAX_WORKFLOW_INSTANCE_ID_LENGTH + 1),
48 "#1231231!!!!",
49 ])("should reject invalid IDs", (value, { expect }) => {
50 expect(isValidWorkflowInstanceId(value as string)).toBe(false);
51 });
52
53 it.for([
54 "abc",
55 "NAME_123-hello",
56 "a-valid-string",
57 "w".repeat(MAX_WORKFLOW_INSTANCE_ID_LENGTH),
58 ])("should accept valid IDs", (value, { expect }) => {
59 expect(isValidWorkflowInstanceId(value as string)).toBe(true);
60 });
61});
62
63describe("Addressable Workflow instance ID validation", () => {
64 it.for([
65 "",
66 NaN,
67 undefined,
68 "w".repeat(MAX_ADDRESSABLE_WORKFLOW_INSTANCE_ID_LENGTH + 1),
69 "invalid!",
70 "0 0 * * MON?2-1786001400000",
71 ])("should reject invalid IDs", (value, { expect }) => {
72 expect(isValidAddressableWorkflowInstanceId(value as string)).toBe(false);
73 });
74
75 it.for([
76 "abc",
77 "*/30 * * * *-1786001400000",
78 "0 0 * * MON#2-1786001400000",
79 "0 0 1,15 * *-1786001400000",
80 "NAME_123-/cron",
81 "w".repeat(MAX_ADDRESSABLE_WORKFLOW_INSTANCE_ID_LENGTH),
82 ])("should accept valid IDs", (value, { expect }) => {
83 expect(isValidAddressableWorkflowInstanceId(value)).toBe(true);
84 });
85});
86
87describe("Workflow instance step name validation", () => {
88 it.for(["\x00", "w".repeat(MAX_STEP_NAME_LENGTH + 1)])(
89 "should reject invalid names",
90 (value, { expect }) => {
91 expect(isValidStepName(value as string)).toBe(false);
92 },
93 );
94
95 it.for([
96 "abc",
97 "NAME_123-hello",
98 "a-valid-string",
99 "w".repeat(MAX_STEP_NAME_LENGTH),
100 "valid step name",
101 ])("should accept valid names", (value, { expect }) => {
102 expect(isValidStepName(value as string)).toBe(true);
103 });
104});
105
106describe("Workflow step config validation", () => {
107 it.for([
108 { timeout: "5 years", retries: { limit: 1 } },
109 { timeout: "5 years", retries: { delay: 50 } },
110 { timeout: "5 years", retries: { backoff: "exponential" } },
111 {
112 timeout: "5 years",
113 retries: {
114 delay: "10 minutes",
115 limit: 5,
116 "i-like-trains": "yes".repeat(100),
117 },
118 },
119 {
120 retries: { limit: 3, delay: "i like trains", backoff: "constant" },
121 timeout: "10 minutes",
122 },
123 {
124 retries: { limit: 3, delay: 10, backoff: "constant" },
125 timeout: 0,
126 },
127 { timeout: "5 minutes", sensitive: "all" },
128 { timeout: "5 minutes", sensitive: true },
129 ])("should reject invalid step configs", (value, { expect }) => {
130 expect(isValidStepConfig(value)).toBe(false);
131 });
132
133 it("should accept a dynamic delay function", ({ expect }) => {
134 const config = {
135 retries: { limit: 3, delay: () => "10 seconds", backoff: "constant" },
136 timeout: "10 minutes",
137 };
138 expect(isValidStepConfig(config)).toBe(true);
139 });
140
141 it.for([
142 {
143 retries: { limit: 0, delay: 100000, backoff: "exponential" },
144 timeout: "15 minutes",
145 },
146 {
147 retries: { limit: 5, delay: 0, backoff: "constant" },
148 timeout: "2 minutes",
149 },
150 {
151 retries: { limit: 3, delay: 10, backoff: "constant" },
152 timeout: "2 minutes",
153 sensitive: "output",
154 },
155 ])("should accept valid step configs", (value, { expect }) => {
156 expect(isValidStepConfig(value)).toBe(true);
157 });
158});