Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ import useWorkflowDataStore from '../stores/useWorkflowDataStore';
import useWorkflowEditorStore from '../stores/useWorkflowEditorStore';
import useWorkflowNodeDetailsPanelStore from '../stores/useWorkflowNodeDetailsPanelStore';
import getDataPillsFromProperties from '../utils/getDataPillsFromProperties';
import getOutputSchemaFromWorkflowNodeOutput from '../utils/getOutputSchemaFromWorkflowNodeOutput';
import getParametersWithDefaultValues from '../utils/getParametersWithDefaultValues';
import saveClusterElementFieldChange from '../utils/saveClusterElementFieldChange';
import saveTaskDispatcherSubtaskFieldChange from '../utils/saveTaskDispatcherSubtaskFieldChange';
Expand Down Expand Up @@ -765,8 +766,7 @@ const WorkflowNodeDetailsPanel = ({

const componentProperties: Array<ComponentPropertiesType> = previousComponentDefinitions.map(
(componentDefinition, index) => {
const outputSchemaDefinition: PropertyAllType | undefined =
workflowNodeOutputs[index]?.outputResponse?.outputSchema;
const outputSchemaDefinition = getOutputSchemaFromWorkflowNodeOutput(workflowNodeOutputs[index]);

const properties = outputSchemaDefinition?.properties?.length
? outputSchemaDefinition.properties
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import {WorkflowNodeOutput} from '@/shared/middleware/platform/configuration';
import {PropertyAllType} from '@/shared/types';
import {describe, expect, test} from 'vitest';

import getOutputSchemaFromWorkflowNodeOutput from './getOutputSchemaFromWorkflowNodeOutput';

describe('getOutputSchemaFromWorkflowNodeOutput', () => {
const mockOutputSchema: PropertyAllType = {
name: 'testOutput',
type: 'OBJECT',
};

const mockVariableOutputSchema: PropertyAllType = {
name: 'variableOutput',
properties: [
{name: 'item', type: 'OBJECT'},
{name: 'index', type: 'INTEGER'},
],
type: 'OBJECT',
};

test('returns undefined when workflowNodeOutput is undefined', () => {
const result = getOutputSchemaFromWorkflowNodeOutput(undefined);

expect(result).toBeUndefined();
});

test('returns outputResponse.outputSchema when available', () => {
const workflowNodeOutput: WorkflowNodeOutput = {
outputResponse: {
outputSchema: mockOutputSchema,
},
workflowNodeName: 'action_1',
};

const result = getOutputSchemaFromWorkflowNodeOutput(workflowNodeOutput);

expect(result).toBe(mockOutputSchema);
});

test('returns variableOutputResponse.outputSchema when outputResponse is not available', () => {
const workflowNodeOutput: WorkflowNodeOutput = {
variableOutputResponse: {
outputSchema: mockVariableOutputSchema,
},
workflowNodeName: 'loop_1',
};

const result = getOutputSchemaFromWorkflowNodeOutput(workflowNodeOutput);

expect(result).toBe(mockVariableOutputSchema);
});

test('prefers outputResponse over variableOutputResponse when both are available', () => {
const workflowNodeOutput: WorkflowNodeOutput = {
outputResponse: {
outputSchema: mockOutputSchema,
},
variableOutputResponse: {
outputSchema: mockVariableOutputSchema,
},
workflowNodeName: 'action_1',
};

const result = getOutputSchemaFromWorkflowNodeOutput(workflowNodeOutput);

expect(result).toBe(mockOutputSchema);
});

test('returns undefined when neither outputResponse nor variableOutputResponse has outputSchema', () => {
const workflowNodeOutput: WorkflowNodeOutput = {
outputResponse: {},
variableOutputResponse: {},
workflowNodeName: 'action_1',
};

const result = getOutputSchemaFromWorkflowNodeOutput(workflowNodeOutput);

expect(result).toBeUndefined();
});

test('returns variableOutputResponse.outputSchema for loop task dispatcher with item and index properties', () => {
const loopVariableSchema: PropertyAllType = {
name: 'loopOutput',
properties: [
{
name: 'item',
properties: [{name: 'id', type: 'STRING'}],
type: 'OBJECT',
},
{name: 'index', type: 'INTEGER'},
],
type: 'OBJECT',
};

const workflowNodeOutput: WorkflowNodeOutput = {
taskDispatcherDefinition: {
name: 'loop',
outputDefined: false,
variablePropertiesDefined: true,
version: 1,
},
variableOutputResponse: {
outputSchema: loopVariableSchema,
},
workflowNodeName: 'loop_1',
};

const result = getOutputSchemaFromWorkflowNodeOutput(workflowNodeOutput);

expect(result).toBe(loopVariableSchema);
expect(result?.properties).toHaveLength(2);
expect(result?.properties?.[0].name).toBe('item');
expect(result?.properties?.[1].name).toBe('index');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {WorkflowNodeOutput} from '@/shared/middleware/platform/configuration';
import {PropertyAllType} from '@/shared/types';

/**
* Gets the output schema from a workflow node output, falling back to variableOutputResponse
* when outputResponse is not available. This is important for loop task dispatchers which
* provide variable properties (item, index) via variableOutputResponse.
*
* @param workflowNodeOutput - The workflow node output containing outputResponse and/or variableOutputResponse
* @returns The output schema from outputResponse or variableOutputResponse, or undefined if neither exists
*/
export default function getOutputSchemaFromWorkflowNodeOutput(
workflowNodeOutput: WorkflowNodeOutput | undefined
): PropertyAllType | undefined {
return workflowNodeOutput?.outputResponse?.outputSchema || workflowNodeOutput?.variableOutputResponse?.outputSchema;
}
Loading