Skip to content

Commit 55a5ed1

Browse files
ivicacclaude
andcommitted
4761 Add test and tidy import for nested cluster element option resolution
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d39b730 commit 55a5ed1

2 files changed

Lines changed: 89 additions & 4 deletions

File tree

server/libs/platform/platform-configuration/platform-configuration-service/src/main/java/com/bytechef/platform/configuration/facade/WorkflowNodeOptionFacadeImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.bytechef.platform.component.facade.ClusterElementDefinitionFacade;
2929
import com.bytechef.platform.component.facade.TriggerDefinitionFacade;
3030
import com.bytechef.platform.component.service.ClusterElementDefinitionService;
31+
import com.bytechef.platform.configuration.constant.WorkflowExtConstants;
3132
import com.bytechef.platform.configuration.domain.ClusterElement;
3233
import com.bytechef.platform.configuration.domain.ClusterElementMap;
3334
import com.bytechef.platform.configuration.domain.WorkflowTestConfigurationConnection;
@@ -174,9 +175,7 @@ private void addNestedClusterElementParameters(
174175

175176
Map<String, ?> extensions = clusterElement.getExtensions();
176177

177-
if (extensions == null || !extensions.containsKey(
178-
com.bytechef.platform.configuration.constant.WorkflowExtConstants.CLUSTER_ELEMENTS)) {
179-
178+
if (extensions == null || !extensions.containsKey(WorkflowExtConstants.CLUSTER_ELEMENTS)) {
180179
return;
181180
}
182181

server/libs/platform/platform-configuration/platform-configuration-service/src/test/java/com/bytechef/platform/configuration/facade/WorkflowNodeOptionFacadeTest.java

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,29 +31,35 @@
3131
import com.bytechef.atlas.configuration.domain.Workflow;
3232
import com.bytechef.atlas.configuration.domain.WorkflowTask;
3333
import com.bytechef.atlas.configuration.service.WorkflowService;
34+
import com.bytechef.component.definition.ClusterElementDefinition.ClusterElementType;
3435
import com.bytechef.evaluator.Evaluator;
3536
import com.bytechef.platform.component.domain.Option;
3637
import com.bytechef.platform.component.facade.ActionDefinitionFacade;
3738
import com.bytechef.platform.component.facade.ClusterElementDefinitionFacade;
3839
import com.bytechef.platform.component.facade.TriggerDefinitionFacade;
3940
import com.bytechef.platform.component.service.ClusterElementDefinitionService;
41+
import com.bytechef.platform.configuration.constant.WorkflowExtConstants;
4042
import com.bytechef.platform.configuration.domain.WorkflowTrigger;
4143
import com.bytechef.platform.configuration.service.WorkflowTestConfigurationService;
4244
import com.bytechef.platform.workflow.task.dispatcher.service.TaskDispatcherDefinitionService;
45+
import com.bytechef.test.extension.ObjectMapperSetupExtension;
4346
import java.util.List;
4447
import java.util.Map;
4548
import java.util.Optional;
4649
import org.junit.jupiter.api.BeforeEach;
4750
import org.junit.jupiter.api.Test;
4851
import org.junit.jupiter.api.extension.ExtendWith;
52+
import org.mockito.ArgumentCaptor;
4953
import org.mockito.Mock;
5054
import org.mockito.MockedStatic;
5155
import org.mockito.junit.jupiter.MockitoExtension;
5256

5357
/**
5458
* @author Ivica Cardic
5559
*/
56-
@ExtendWith(MockitoExtension.class)
60+
@ExtendWith({
61+
MockitoExtension.class, ObjectMapperSetupExtension.class
62+
})
5763
class WorkflowNodeOptionFacadeTest {
5864

5965
@Mock
@@ -226,4 +232,84 @@ void testGetWorkflowNodeOptionsForTrigger() {
226232
eq("github"), eq(1), eq("newIssue"), eq(propertyName), anyMap(), anyList(), isNull(), eq(connectionId));
227233
}
228234
}
235+
236+
@Test
237+
@SuppressWarnings("unchecked")
238+
void testGetClusterElementNodeOptionsAggregatesNestedClusterElementParameters() {
239+
String workflowId = "workflow1";
240+
String workflowNodeName = "aiAgent_1";
241+
String clusterElementTypeName = "tools";
242+
String clusterElementWorkflowNodeName = "aiAgent_tool_1";
243+
String propertyName = "objectType";
244+
long environmentId = 1L;
245+
246+
Map<String, ?> nestedToolMap = Map.of(
247+
"name", "hubspot_1",
248+
"type", "hubspot/v1/createContact",
249+
"label", "Hubspot",
250+
"parameters", Map.of("apiKey", "secret"));
251+
252+
Map<String, ?> outerToolMap = Map.of(
253+
"name", clusterElementWorkflowNodeName,
254+
"type", "aiAgent/v1/tool",
255+
"label", "AI Agent Tool",
256+
"parameters", Map.of("prompt", "do something"),
257+
WorkflowExtConstants.CLUSTER_ELEMENTS, Map.of("tools", List.of(nestedToolMap)));
258+
259+
Map<String, ?> taskExtensions = Map.of(
260+
WorkflowExtConstants.CLUSTER_ELEMENTS, Map.of("tools", List.of(outerToolMap)));
261+
262+
when(workflowTestConfigurationService.fetchWorkflowTestConfiguration(workflowId, environmentId))
263+
.thenReturn(Optional.empty());
264+
doReturn(Map.of()).when(workflowTestConfigurationService)
265+
.getWorkflowTestConfigurationInputs(workflowId, environmentId);
266+
267+
Workflow workflow = mock(Workflow.class);
268+
WorkflowTask workflowTask = mock(WorkflowTask.class);
269+
270+
when(workflowService.getWorkflow(workflowId)).thenReturn(workflow);
271+
when(workflow.getTask(workflowNodeName)).thenReturn(workflowTask);
272+
when(workflowTask.getType()).thenReturn("aiAgent/v1");
273+
when(workflowTask.getName()).thenReturn(workflowNodeName);
274+
doReturn(taskExtensions).when(workflowTask)
275+
.getExtensions();
276+
277+
doReturn(Map.of()).when(workflowNodeOutputFacade)
278+
.getPreviousWorkflowNodeSampleOutputs(eq(workflowId), eq(workflowNodeName), eq(environmentId));
279+
280+
ClusterElementType clusterElementType = new ClusterElementType(
281+
clusterElementTypeName, "tools", "Tools", true, false);
282+
283+
when(clusterElementDefinitionService.getClusterElementType("aiAgent", 1, clusterElementTypeName))
284+
.thenReturn(clusterElementType);
285+
286+
when(evaluator.evaluate(anyMap(), anyMap()))
287+
.thenAnswer(invocation -> invocation.getArgument(0));
288+
289+
List<Option> expectedOptions = List.of(mock(Option.class));
290+
291+
when(clusterElementDefinitionFacade.executeOptions(
292+
eq("aiAgent"), eq(1), eq("tool"), eq(propertyName), anyMap(), anyMap(), anyList(), isNull(), isNull(),
293+
anyMap(), anyMap()))
294+
.thenReturn(expectedOptions);
295+
296+
List<Option> result = workflowNodeOptionFacade.getClusterElementNodeOptions(
297+
workflowId, workflowNodeName, clusterElementTypeName, clusterElementWorkflowNodeName, propertyName,
298+
List.of(), null, environmentId);
299+
300+
assertEquals(expectedOptions, result);
301+
302+
ArgumentCaptor<Map<String, Map<String, ?>>> captor = ArgumentCaptor.forClass(Map.class);
303+
304+
verify(clusterElementDefinitionFacade).executeOptions(
305+
eq("aiAgent"), eq(1), eq("tool"), eq(propertyName), anyMap(), anyMap(), anyList(), isNull(), isNull(),
306+
anyMap(), captor.capture());
307+
308+
Map<String, Map<String, ?>> capturedInputParameters = captor.getValue();
309+
310+
assertEquals(true, capturedInputParameters.containsKey("aiAgent_tool_1"));
311+
assertEquals(true, capturedInputParameters.containsKey("hubspot_1"));
312+
assertEquals("secret", capturedInputParameters.get("hubspot_1")
313+
.get("apiKey"));
314+
}
229315
}

0 commit comments

Comments
 (0)