Skip to content

Commit 12a27a8

Browse files
authored
Merge branch 'main' into 4983-correlation-OR-condition-gets-transformed-to-AND
2 parents 3098955 + f04945f commit 12a27a8

15 files changed

+1165
-578
lines changed
Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
import { Definition, V2ActionStep, V2Step } from "../../model/types";
2+
import {
3+
validateAllMustacheVariablesForUIBuilderStep,
4+
validateMustacheVariableForUIBuilderStep,
5+
} from "../validate-mustache-ui-builder";
6+
7+
describe("validateMustacheVariableName", () => {
8+
const mockDefinition: Definition = {
9+
sequence: [
10+
{
11+
id: "step1",
12+
name: "First Step",
13+
componentType: "task",
14+
type: "step-test",
15+
properties: {
16+
actionParams: [],
17+
stepParams: [],
18+
},
19+
},
20+
{
21+
id: "step2",
22+
name: "Second Step",
23+
componentType: "task",
24+
type: "action-test",
25+
properties: {
26+
actionParams: [],
27+
stepParams: [],
28+
},
29+
},
30+
],
31+
properties: {
32+
id: "test-workflow",
33+
name: "Test Workflow",
34+
description: "Test Description",
35+
disabled: false,
36+
isLocked: false,
37+
consts: {},
38+
},
39+
};
40+
const mockSecrets = {};
41+
42+
it("should validate alert variables", () => {
43+
const result = validateMustacheVariableForUIBuilderStep(
44+
"alert.name",
45+
mockDefinition.sequence[0],
46+
mockDefinition,
47+
mockSecrets
48+
);
49+
expect(result).toBeNull();
50+
});
51+
52+
it("should validate incident variables", () => {
53+
const result = validateMustacheVariableForUIBuilderStep(
54+
"incident.title",
55+
mockDefinition.sequence[0],
56+
mockDefinition,
57+
mockSecrets
58+
);
59+
expect(result).toBeNull();
60+
});
61+
62+
it("should validate step results access", () => {
63+
const result = validateMustacheVariableForUIBuilderStep(
64+
"steps.First Step.results",
65+
mockDefinition.sequence[1],
66+
mockDefinition,
67+
mockSecrets
68+
);
69+
expect(result).toBeNull();
70+
});
71+
72+
it("should prevent accessing current step results", () => {
73+
const result = validateMustacheVariableForUIBuilderStep(
74+
"steps.First Step.results",
75+
mockDefinition.sequence[0],
76+
mockDefinition,
77+
mockSecrets
78+
);
79+
expect(result).toBe(
80+
"Variable: 'steps.First Step.results' - You can't access the results of the current step."
81+
);
82+
});
83+
84+
it("should prevent accessing future step results", () => {
85+
const result = validateMustacheVariableForUIBuilderStep(
86+
"steps.Second Step.results",
87+
mockDefinition.sequence[0],
88+
mockDefinition,
89+
mockSecrets
90+
);
91+
expect(result).toBe(
92+
"Variable: 'steps.Second Step.results' - You can't access the results of a step that appears after the current step."
93+
);
94+
});
95+
});
96+
97+
describe("validateAllMustacheVariablesInString", () => {
98+
const mockDefinition: Definition = {
99+
sequence: [
100+
{
101+
id: "step1",
102+
name: "First Step",
103+
componentType: "task",
104+
type: "step-test",
105+
properties: {
106+
actionParams: [],
107+
stepParams: [],
108+
},
109+
},
110+
],
111+
properties: {
112+
id: "test-workflow",
113+
name: "Test Workflow",
114+
description: "Test Description",
115+
disabled: false,
116+
isLocked: false,
117+
consts: {
118+
test: "test",
119+
},
120+
inputs: [
121+
{
122+
name: "test",
123+
description: "Test Input",
124+
type: "string",
125+
},
126+
],
127+
},
128+
};
129+
const mockSecrets = {};
130+
131+
it("should validate multiple variables in a string", () => {
132+
const result = validateAllMustacheVariablesForUIBuilderStep(
133+
"Alert: {{ alert.name }} with severity {{ alert.severity }}",
134+
mockDefinition.sequence[0],
135+
mockDefinition,
136+
mockSecrets
137+
);
138+
expect(result).toEqual([]);
139+
});
140+
141+
it("should detect invalid variables in a string", () => {
142+
const result = validateAllMustacheVariablesForUIBuilderStep(
143+
"Invalid: {{ invalid.var }} and {{ steps.Future Step.results }}",
144+
mockDefinition.sequence[0],
145+
mockDefinition,
146+
mockSecrets
147+
);
148+
expect(result).toContain(
149+
"Variable: 'steps.Future Step.results' - a 'Future Step' step doesn't exist."
150+
);
151+
});
152+
153+
it("should validate reference of variable in step in foreach container", () => {
154+
const pythonStep: V2Step = {
155+
id: "step1",
156+
name: "python-step",
157+
componentType: "task",
158+
type: "step-python",
159+
properties: {
160+
actionParams: [],
161+
stepParams: ["code"],
162+
with: {
163+
code: "[x for x in range(100)]",
164+
},
165+
},
166+
};
167+
const telegramAction: V2ActionStep = {
168+
id: "telegram-action",
169+
name: "telegram-action",
170+
componentType: "task",
171+
type: "step-telegram",
172+
properties: {
173+
if: "keep.dictget({{steps.python-step.results}} , '{{foreach.value.fingerprint}}', 'default') == '{{foreach.value.fingerprint}}'",
174+
actionParams: ["message"],
175+
with: {
176+
message: "{{ foreach.value }}",
177+
},
178+
},
179+
};
180+
const definition: Definition = {
181+
sequence: [
182+
pythonStep,
183+
{
184+
id: "foreach-step",
185+
name: "foreach-step",
186+
componentType: "container",
187+
type: "foreach",
188+
properties: {
189+
value: "{{ steps.python-step.results }}",
190+
},
191+
sequence: [telegramAction],
192+
},
193+
],
194+
properties: {
195+
id: "test-workflow",
196+
name: "Test Workflow",
197+
description: "Test Description",
198+
disabled: false,
199+
isLocked: false,
200+
consts: {},
201+
},
202+
};
203+
const result = validateAllMustacheVariablesForUIBuilderStep(
204+
"keep.dictget({{steps.python-step.results}} , '{{foreach.value.fingerprint}}', 'default') == '{{foreach.value.fingerprint}}'",
205+
telegramAction, // telegram step
206+
definition,
207+
mockSecrets
208+
);
209+
expect(result).toEqual([]);
210+
211+
const resultFailure1 = validateAllMustacheVariablesForUIBuilderStep(
212+
"'{{foreach.value.fingerprint}}', 'default') == '{{foreach.value.fingerprint}}'",
213+
pythonStep,
214+
definition,
215+
mockSecrets
216+
);
217+
expect(resultFailure1).toEqual([
218+
"Variable: 'foreach.value.fingerprint' - 'foreach' can only be used in a step with foreach.",
219+
"Variable: 'foreach.value.fingerprint' - 'foreach' can only be used in a step with foreach.",
220+
]);
221+
222+
// short syntax
223+
const result2 = validateAllMustacheVariablesForUIBuilderStep(
224+
"{{ . }}",
225+
telegramAction, // telegram step
226+
definition,
227+
mockSecrets
228+
);
229+
expect(result2).toEqual([]);
230+
231+
const resultFailure2 = validateAllMustacheVariablesForUIBuilderStep(
232+
"{{ . }}",
233+
pythonStep,
234+
definition,
235+
mockSecrets
236+
);
237+
expect(resultFailure2).toEqual([
238+
"Variable: '.' - short syntax can only be used in a step with foreach.",
239+
]);
240+
241+
const result3 = validateAllMustacheVariablesForUIBuilderStep(
242+
"{{ value }}",
243+
telegramAction,
244+
definition,
245+
mockSecrets
246+
);
247+
expect(result3).toEqual([]);
248+
249+
const resultFailure3 = validateAllMustacheVariablesForUIBuilderStep(
250+
"{{ value }}",
251+
pythonStep,
252+
definition,
253+
mockSecrets
254+
);
255+
expect(resultFailure3).toEqual([
256+
"Variable: 'value' - 'value' can only be used in a step with foreach.",
257+
]);
258+
});
259+
260+
it("should return an error if bracket notation is used", () => {
261+
const result = validateAllMustacheVariablesForUIBuilderStep(
262+
"{{ steps['python-step'].results }}",
263+
mockDefinition.sequence[0],
264+
mockDefinition,
265+
mockSecrets
266+
);
267+
expect(result).toEqual([
268+
"Variable: 'steps[\'python-step\'].results' - bracket notation is not supported, use dot notation instead.",
269+
]);
270+
});
271+
272+
it("should validate vars variables", () => {
273+
const step: V2Step = {
274+
id: "step1",
275+
name: "First Step",
276+
componentType: "task",
277+
type: "step-test",
278+
properties: {
279+
actionParams: [],
280+
stepParams: [],
281+
vars: { test: "test" },
282+
},
283+
};
284+
const definition = {
285+
...mockDefinition,
286+
sequence: [step],
287+
};
288+
const result = validateAllMustacheVariablesForUIBuilderStep(
289+
"{{ vars.test }}",
290+
step,
291+
definition,
292+
mockSecrets
293+
);
294+
expect(result).toEqual([]);
295+
});
296+
297+
it("should return an error if vars variable is not found", () => {
298+
const result = validateAllMustacheVariablesForUIBuilderStep(
299+
"{{ vars.test }}",
300+
mockDefinition.sequence[0],
301+
mockDefinition,
302+
mockSecrets
303+
);
304+
expect(result).toEqual([
305+
"Variable: 'vars.test' - Variable 'test' not found in step definition.",
306+
]);
307+
});
308+
309+
it("should return an error for unknown variables", () => {
310+
const result = validateAllMustacheVariablesForUIBuilderStep(
311+
"{{ unknown.var }}",
312+
mockDefinition.sequence[0],
313+
mockDefinition,
314+
mockSecrets
315+
);
316+
expect(result).toEqual(["Variable: 'unknown.var' - unknown variable."]);
317+
});
318+
319+
it("should validate inputs variable", () => {
320+
const result = validateAllMustacheVariablesForUIBuilderStep(
321+
"{{ inputs.test }}",
322+
mockDefinition.sequence[0],
323+
mockDefinition,
324+
mockSecrets
325+
);
326+
expect(result).toEqual([]);
327+
});
328+
329+
it("should return an error if inputs variable is not found", () => {
330+
const result = validateAllMustacheVariablesForUIBuilderStep(
331+
"{{ inputs.missing }}",
332+
mockDefinition.sequence[0],
333+
mockDefinition,
334+
mockSecrets
335+
);
336+
expect(result).toEqual([
337+
"Variable: 'inputs.missing' - Input 'missing' not defined. Available inputs: test",
338+
]);
339+
});
340+
341+
it("should validate consts variable", () => {
342+
const result = validateAllMustacheVariablesForUIBuilderStep(
343+
"{{ consts.test }}",
344+
mockDefinition.sequence[0],
345+
mockDefinition,
346+
mockSecrets
347+
);
348+
expect(result).toEqual([]);
349+
});
350+
351+
it("should return an error if consts variable is not found", () => {
352+
const result = validateAllMustacheVariablesForUIBuilderStep(
353+
"{{ consts.missing }}",
354+
mockDefinition.sequence[0],
355+
mockDefinition,
356+
mockSecrets
357+
);
358+
expect(result).toEqual([
359+
"Variable: 'consts.missing' - Constant 'missing' not found.",
360+
]);
361+
});
362+
});

0 commit comments

Comments
 (0)