@@ -85,8 +85,10 @@ describe('ConditionBlockHandler', () => {
8585 { }
8686 ) as Mocked < InputResolver >
8787
88- // Ensure the method exists as a mock function on the instance
88+ // Ensure the methods exist as mock functions on the instance
8989 mockResolver . resolveBlockReferences = vi . fn ( )
90+ mockResolver . resolveVariableReferences = vi . fn ( )
91+ mockResolver . resolveEnvVariables = vi . fn ( )
9092
9193 handler = new ConditionBlockHandler ( mockPathTracker , mockResolver )
9294
@@ -147,16 +149,23 @@ describe('ConditionBlockHandler', () => {
147149 selectedConditionId : 'cond1' ,
148150 }
149151
150- // Mock directly in the test
152+ // Mock the full resolution pipeline
153+ mockResolver . resolveVariableReferences . mockReturnValue ( 'context.value > 5' )
151154 mockResolver . resolveBlockReferences . mockReturnValue ( 'context.value > 5' )
155+ mockResolver . resolveEnvVariables . mockReturnValue ( 'context.value > 5' )
152156
153157 const result = await handler . execute ( mockBlock , inputs , mockContext )
154158
159+ expect ( mockResolver . resolveVariableReferences ) . toHaveBeenCalledWith (
160+ 'context.value > 5' ,
161+ mockBlock
162+ )
155163 expect ( mockResolver . resolveBlockReferences ) . toHaveBeenCalledWith (
156164 'context.value > 5' ,
157165 mockContext ,
158166 mockBlock
159167 )
168+ expect ( mockResolver . resolveEnvVariables ) . toHaveBeenCalledWith ( 'context.value > 5' , true )
160169 expect ( result ) . toEqual ( expectedOutput )
161170 expect ( mockContext . decisions . condition . get ( mockBlock . id ) ) . toBe ( 'cond1' )
162171 } )
@@ -180,16 +189,23 @@ describe('ConditionBlockHandler', () => {
180189 selectedConditionId : 'else1' ,
181190 }
182191
183- // Mock directly in the test
192+ // Mock the full resolution pipeline
193+ mockResolver . resolveVariableReferences . mockReturnValue ( 'context.value < 0' )
184194 mockResolver . resolveBlockReferences . mockReturnValue ( 'context.value < 0' )
195+ mockResolver . resolveEnvVariables . mockReturnValue ( 'context.value < 0' )
185196
186197 const result = await handler . execute ( mockBlock , inputs , mockContext )
187198
199+ expect ( mockResolver . resolveVariableReferences ) . toHaveBeenCalledWith (
200+ 'context.value < 0' ,
201+ mockBlock
202+ )
188203 expect ( mockResolver . resolveBlockReferences ) . toHaveBeenCalledWith (
189204 'context.value < 0' ,
190205 mockContext ,
191206 mockBlock
192207 )
208+ expect ( mockResolver . resolveEnvVariables ) . toHaveBeenCalledWith ( 'context.value < 0' , true )
193209 expect ( result ) . toEqual ( expectedOutput )
194210 expect ( mockContext . decisions . condition . get ( mockBlock . id ) ) . toBe ( 'else1' )
195211 } )
@@ -209,16 +225,77 @@ describe('ConditionBlockHandler', () => {
209225 ]
210226 const inputs = { conditions : JSON . stringify ( conditions ) }
211227
212- // Mock directly in the test
228+ // Mock the full resolution pipeline
229+ mockResolver . resolveVariableReferences . mockReturnValue ( '{{source-block-1.value}} > 5' )
213230 mockResolver . resolveBlockReferences . mockReturnValue ( '10 > 5' )
231+ mockResolver . resolveEnvVariables . mockReturnValue ( '10 > 5' )
214232
215- const _result = await handler . execute ( mockBlock , inputs , mockContext )
233+ await handler . execute ( mockBlock , inputs , mockContext )
216234
235+ expect ( mockResolver . resolveVariableReferences ) . toHaveBeenCalledWith (
236+ '{{source-block-1.value}} > 5' ,
237+ mockBlock
238+ )
217239 expect ( mockResolver . resolveBlockReferences ) . toHaveBeenCalledWith (
218240 '{{source-block-1.value}} > 5' ,
219241 mockContext ,
220242 mockBlock
221243 )
244+ expect ( mockResolver . resolveEnvVariables ) . toHaveBeenCalledWith ( '10 > 5' , true )
245+ expect ( mockContext . decisions . condition . get ( mockBlock . id ) ) . toBe ( 'cond1' )
246+ } )
247+
248+ it ( 'should resolve variable references in conditions' , async ( ) => {
249+ const conditions = [
250+ { id : 'cond1' , title : 'if' , value : '<variable.userName> !== null' } ,
251+ { id : 'else1' , title : 'else' , value : '' } ,
252+ ]
253+ const inputs = { conditions : JSON . stringify ( conditions ) }
254+
255+ // Mock the full resolution pipeline for variable resolution
256+ mockResolver . resolveVariableReferences . mockReturnValue ( '"john" !== null' )
257+ mockResolver . resolveBlockReferences . mockReturnValue ( '"john" !== null' )
258+ mockResolver . resolveEnvVariables . mockReturnValue ( '"john" !== null' )
259+
260+ await handler . execute ( mockBlock , inputs , mockContext )
261+
262+ expect ( mockResolver . resolveVariableReferences ) . toHaveBeenCalledWith (
263+ '<variable.userName> !== null' ,
264+ mockBlock
265+ )
266+ expect ( mockResolver . resolveBlockReferences ) . toHaveBeenCalledWith (
267+ '"john" !== null' ,
268+ mockContext ,
269+ mockBlock
270+ )
271+ expect ( mockResolver . resolveEnvVariables ) . toHaveBeenCalledWith ( '"john" !== null' , true )
272+ expect ( mockContext . decisions . condition . get ( mockBlock . id ) ) . toBe ( 'cond1' )
273+ } )
274+
275+ it ( 'should resolve environment variables in conditions' , async ( ) => {
276+ const conditions = [
277+ { id : 'cond1' , title : 'if' , value : '{{POOP}} === "hi"' } ,
278+ { id : 'else1' , title : 'else' , value : '' } ,
279+ ]
280+ const inputs = { conditions : JSON . stringify ( conditions ) }
281+
282+ // Mock the full resolution pipeline for env variable resolution
283+ mockResolver . resolveVariableReferences . mockReturnValue ( '{{POOP}} === "hi"' )
284+ mockResolver . resolveBlockReferences . mockReturnValue ( '{{POOP}} === "hi"' )
285+ mockResolver . resolveEnvVariables . mockReturnValue ( '"hi" === "hi"' )
286+
287+ await handler . execute ( mockBlock , inputs , mockContext )
288+
289+ expect ( mockResolver . resolveVariableReferences ) . toHaveBeenCalledWith (
290+ '{{POOP}} === "hi"' ,
291+ mockBlock
292+ )
293+ expect ( mockResolver . resolveBlockReferences ) . toHaveBeenCalledWith (
294+ '{{POOP}} === "hi"' ,
295+ mockContext ,
296+ mockBlock
297+ )
298+ expect ( mockResolver . resolveEnvVariables ) . toHaveBeenCalledWith ( '{{POOP}} === "hi"' , true )
222299 expect ( mockContext . decisions . condition . get ( mockBlock . id ) ) . toBe ( 'cond1' )
223300 } )
224301
@@ -230,8 +307,8 @@ describe('ConditionBlockHandler', () => {
230307 const inputs = { conditions : JSON . stringify ( conditions ) }
231308
232309 const resolutionError = new Error ( 'Could not resolve reference: invalid-ref' )
233- // Mock directly in the test
234- mockResolver . resolveBlockReferences . mockImplementation ( ( ) => {
310+ // Mock the pipeline to throw at the variable resolution stage
311+ mockResolver . resolveVariableReferences . mockImplementation ( ( ) => {
235312 throw resolutionError
236313 } )
237314
@@ -247,8 +324,12 @@ describe('ConditionBlockHandler', () => {
247324 ]
248325 const inputs = { conditions : JSON . stringify ( conditions ) }
249326
250- // Mock directly in the test
327+ // Mock the full resolution pipeline
328+ mockResolver . resolveVariableReferences . mockReturnValue (
329+ 'context.nonExistentProperty.doSomething()'
330+ )
251331 mockResolver . resolveBlockReferences . mockReturnValue ( 'context.nonExistentProperty.doSomething()' )
332+ mockResolver . resolveEnvVariables . mockReturnValue ( 'context.nonExistentProperty.doSomething()' )
252333
253334 await expect ( handler . execute ( mockBlock , inputs , mockContext ) ) . rejects . toThrow (
254335 / ^ E v a l u a t i o n e r r o r i n c o n d i t i o n " i f " : C a n n o t r e a d p r o p e r t i e s o f u n d e f i n e d \( r e a d i n g ' d o S o m e t h i n g ' \) \. \( R e s o l v e d : c o n t e x t \. n o n E x i s t e n t P r o p e r t y \. d o S o m e t h i n g \( \) \) $ /
@@ -271,8 +352,10 @@ describe('ConditionBlockHandler', () => {
271352
272353 mockContext . workflow ! . blocks = [ mockSourceBlock , mockBlock , mockTargetBlock2 ]
273354
274- // Mock directly in the test
355+ // Mock the full resolution pipeline
356+ mockResolver . resolveVariableReferences . mockReturnValue ( 'true' )
275357 mockResolver . resolveBlockReferences . mockReturnValue ( 'true' )
358+ mockResolver . resolveEnvVariables . mockReturnValue ( 'true' )
276359
277360 await expect ( handler . execute ( mockBlock , inputs , mockContext ) ) . rejects . toThrow (
278361 `Target block ${ mockTargetBlock1 . id } not found`
@@ -295,10 +378,16 @@ describe('ConditionBlockHandler', () => {
295378 } ,
296379 ]
297380
298- // Mock directly in the test
381+ // Mock the full resolution pipeline
382+ mockResolver . resolveVariableReferences
383+ . mockReturnValueOnce ( 'false' )
384+ . mockReturnValueOnce ( 'context.value === 99' )
299385 mockResolver . resolveBlockReferences
300386 . mockReturnValueOnce ( 'false' )
301387 . mockReturnValueOnce ( 'context.value === 99' )
388+ mockResolver . resolveEnvVariables
389+ . mockReturnValueOnce ( 'false' )
390+ . mockReturnValueOnce ( 'context.value === 99' )
302391
303392 await expect ( handler . execute ( mockBlock , inputs , mockContext ) ) . rejects . toThrow (
304393 `No matching path found for condition block "${ mockBlock . metadata ?. name } ", and no 'else' block exists.`
@@ -314,8 +403,10 @@ describe('ConditionBlockHandler', () => {
314403
315404 mockContext . loopItems . set ( mockBlock . id , { item : 'apple' } )
316405
317- // Mock directly in the test
406+ // Mock the full resolution pipeline
407+ mockResolver . resolveVariableReferences . mockReturnValue ( 'context.item === "apple"' )
318408 mockResolver . resolveBlockReferences . mockReturnValue ( 'context.item === "apple"' )
409+ mockResolver . resolveEnvVariables . mockReturnValue ( 'context.item === "apple"' )
319410
320411 const result = await handler . execute ( mockBlock , inputs , mockContext )
321412
0 commit comments