feat(core): Add special @tool displayOption (#14318)

Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ <aditya@netroy.in>
This commit is contained in:
Charlie Kolb
2025-04-04 09:22:13 +02:00
committed by GitHub
parent 9104743a5f
commit 73748e300e
24 changed files with 589 additions and 48 deletions

View File

@@ -371,6 +371,7 @@ export class CredentialsHelper extends ICredentialsHelper {
true,
false,
null,
null,
) as ICredentialDataDecryptedObject;
if (decryptedDataOriginal.oauthTokenData !== undefined) {

View File

@@ -219,6 +219,7 @@ export abstract class NodeExecutionContext implements Omit<FunctionsBase, 'getCr
additionalData.currentNodeParameters || node.parameters,
nodeCredentialDescription,
node,
nodeType.description,
node.parameters,
)
) {

View File

@@ -33,7 +33,13 @@ function findPropertyFromParameterName(
return options.find(
(i) =>
i.name === name &&
NodeHelpers.displayParameterPath(nodeParameters, i, currentParamPath, node),
NodeHelpers.displayParameterPath(
nodeParameters,
i,
currentParamPath,
node,
nodeType.description,
),
);
};

View File

@@ -160,7 +160,8 @@ export const validateValueAgainstSchema = (
const propertyDescription = nodeType.description.properties.find(
(prop) =>
parameterPath[0] === prop.name && NodeHelpers.displayParameter(node.parameters, prop, node),
parameterPath[0] === prop.name &&
NodeHelpers.displayParameter(node.parameters, prop, node, nodeType.description),
);
if (!propertyDescription) {

View File

@@ -829,8 +829,16 @@ export class RoutingNode {
};
let basePath = path ? `${path}.` : '';
const { node } = this.context;
if (!NodeHelpers.displayParameter(node.parameters, nodeProperties, node, node.parameters)) {
const { node, nodeType } = this.context;
if (
!NodeHelpers.displayParameter(
node.parameters,
nodeProperties,
node,
nodeType.description,
node.parameters,
)
) {
return undefined;
}
if (nodeProperties.routing) {

View File

@@ -999,6 +999,7 @@ export class WorkflowExecute {
nodeIssues = NodeHelpers.getNodeParametersIssues(
nodeType.description.properties,
node,
nodeType.description,
inputData.pinDataNodeNames,
);
}

View File

@@ -663,6 +663,7 @@ async function saveCredential(): Promise<ICredentialsResponse | null> {
false,
false,
null,
null,
);
assert(credentialTypeName.value);

View File

@@ -337,7 +337,7 @@ const removeMismatchedOptionValues = (
);
}
if (!hasValidOptions && displayParameter(nodeParameterValues, prop, node.value)) {
if (!hasValidOptions && displayParameter(nodeParameterValues, prop, node.value, nodeType)) {
unset(nodeParameterValues as object, prop.name);
}
});
@@ -395,6 +395,7 @@ const valueChanged = (parameterData: IUpdateInformation) => {
false,
false,
_node,
nodeType,
);
const oldNodeParameters = Object.assign({}, nodeParameters);
@@ -453,6 +454,7 @@ const valueChanged = (parameterData: IUpdateInformation) => {
true,
false,
_node,
nodeType,
);
for (const key of Object.keys(nodeParameters as object)) {
@@ -487,6 +489,7 @@ const valueChanged = (parameterData: IUpdateInformation) => {
false,
false,
_node,
nodeType,
);
const oldNodeParameters = Object.assign({}, nodeParameters);
@@ -535,6 +538,7 @@ const valueChanged = (parameterData: IUpdateInformation) => {
true,
false,
_node,
nodeType,
);
for (const key of Object.keys(nodeParameters as object)) {

View File

@@ -81,6 +81,7 @@ describe('ParameterInput.vue', () => {
};
mockNodeTypesState = {
allNodeTypes: [],
getNodeType: vi.fn().mockReturnValue(null),
};
createAppModals();
});

View File

@@ -346,6 +346,7 @@ const getIssues = computed<string[]>(() => {
node.value.parameters,
newPath.join('.'),
node.value,
nodeTypesStore.getNodeType(node.value.type, node.value.typeVersion),
);
if (props.parameter.type === 'credentialsSelect' && displayValue.value === '') {

View File

@@ -466,7 +466,13 @@ function getParameterIssues(parameter: INodeProperties): string[] {
if (!node.value || !showIssuesInLabelFor.includes(parameter.type)) {
return [];
}
const issues = NodeHelpers.getParameterIssues(parameter, node.value.parameters, '', node.value);
const issues = NodeHelpers.getParameterIssues(
parameter,
node.value.parameters,
'',
node.value,
nodeType.value,
);
return issues.parameters?.[parameter.name] ?? [];
}

View File

@@ -407,6 +407,7 @@ function updateNodeIssues(): void {
const parameterIssues = NodeHelpers.getNodeParametersIssues(
nodeType.value?.properties ?? [],
props.node,
nodeType.value,
);
if (parameterIssues) {
ndvStore.updateNodeParameterIssues(parameterIssues);

View File

@@ -874,6 +874,7 @@ export function useCanvasOperations({ router }: { router: ReturnType<typeof useR
true,
false,
node,
nodeTypeDescription,
);
node.parameters = nodeParameters ?? {};

View File

@@ -106,7 +106,17 @@ export function useNodeHelpers() {
node: INodeUi | null,
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
) {
return NodeHelpers.displayParameterPath(nodeValues, parameter, path, node, displayKey);
const nodeTypeDescription = node?.type
? nodeTypesStore.getNodeType(node.type, node.typeVersion)
: null;
return NodeHelpers.displayParameterPath(
nodeValues,
parameter,
path,
node,
nodeTypeDescription,
displayKey,
);
}
function getNodeIssues(
@@ -137,7 +147,7 @@ export function useNodeHelpers() {
// Add potential parameter issues
if (!ignoreIssues.includes('parameters')) {
nodeIssues = NodeHelpers.getNodeParametersIssues(nodeType.properties, node);
nodeIssues = NodeHelpers.getNodeParametersIssues(nodeType.properties, node, nodeType);
}
if (!ignoreIssues.includes('credentials')) {
@@ -287,6 +297,7 @@ export function useNodeHelpers() {
const fullNodeIssues: INodeIssues | null = NodeHelpers.getNodeParametersIssues(
localNodeType.properties,
node,
nodeType ?? null,
);
let newIssues: INodeIssueObjectProperty | null = null;

View File

@@ -589,6 +589,7 @@ export function useWorkflowHelpers(options: { router: ReturnType<typeof useRoute
isCredentialOnly,
false,
node,
nodeType,
);
nodeData.parameters = nodeParameters !== null ? nodeParameters : {};

View File

@@ -1331,6 +1331,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
true,
false,
latestNode,
nodeType,
);
if (latestNode) {

View File

@@ -338,8 +338,7 @@ export function getGenericHints({
true,
false,
node,
undefined,
false,
nodeType,
);
const assignments =

View File

@@ -22,11 +22,17 @@ export function getNodeTypeDisplayableCredentials(
// credentials can have conditional requirements that depend on
// node parameters.
const nodeParameters =
NodeHelpers.getNodeParameters(nodeType.properties, node.parameters, true, false, node) ??
node.parameters;
NodeHelpers.getNodeParameters(
nodeType.properties,
node.parameters,
true,
false,
node,
nodeType,
) ?? node.parameters;
const displayableCredentials = nodeTypeCreds.filter((credentialTypeDescription) => {
return NodeHelpers.displayParameter(nodeParameters, credentialTypeDescription, node);
return NodeHelpers.displayParameter(nodeParameters, credentialTypeDescription, node, nodeType);
});
return displayableCredentials;

View File

@@ -1376,6 +1376,7 @@ export interface IDisplayOptions {
};
show?: {
'@version'?: Array<number | DisplayCondition>;
'@tool'?: [boolean];
[key: string]: Array<NodeParameterValue | DisplayCondition> | undefined;
};

View File

@@ -392,6 +392,7 @@ const getPropertyValues = (
nodeValues: INodeParameters,
propertyName: string,
node: Pick<INode, 'typeVersion'> | null,
nodeTypeDescription: INodeTypeDescription | null,
nodeValuesRoot: INodeParameters,
) => {
let value;
@@ -400,6 +401,8 @@ const getPropertyValues = (
value = get(nodeValuesRoot, propertyName.slice(1));
} else if (propertyName === '@version') {
value = node?.typeVersion || 0;
} else if (propertyName === '@tool') {
value = nodeTypeDescription?.name.endsWith('Tool') ?? false;
} else {
// Get the value from current level
value = get(nodeValues, propertyName);
@@ -487,6 +490,7 @@ export function displayParameter(
nodeValues: INodeParameters,
parameter: INodeProperties | INodeCredentialDescription,
node: Pick<INode, 'typeVersion'> | null, // Allow null as it does also get used by credentials and they do not have versioning yet
nodeTypeDescription: INodeTypeDescription | null,
nodeValuesRoot?: INodeParameters,
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
) {
@@ -501,7 +505,13 @@ export function displayParameter(
if (show) {
// All the defined rules have to match to display parameter
for (const propertyName of Object.keys(show)) {
const values = getPropertyValues(nodeValues, propertyName, node, nodeValuesRoot);
const values = getPropertyValues(
nodeValues,
propertyName,
node,
nodeTypeDescription,
nodeValuesRoot,
);
if (values.some((v) => typeof v === 'string' && v.charAt(0) === '=')) {
return true;
@@ -516,7 +526,13 @@ export function displayParameter(
if (hide) {
// Any of the defined hide rules have to match to hide the parameter
for (const propertyName of Object.keys(hide)) {
const values = getPropertyValues(nodeValues, propertyName, node, nodeValuesRoot);
const values = getPropertyValues(
nodeValues,
propertyName,
node,
nodeTypeDescription,
nodeValuesRoot,
);
if (values.length !== 0 && checkConditions(hide[propertyName]!, values)) {
return false;
@@ -541,6 +557,7 @@ export function displayParameterPath(
parameter: INodeProperties | INodeCredentialDescription,
path: string,
node: Pick<INode, 'typeVersion'> | null,
nodeTypeDescription: INodeTypeDescription | null,
displayKey: 'displayOptions' | 'disabledOptions' = 'displayOptions',
) {
let resolvedNodeValues = nodeValues;
@@ -554,7 +571,14 @@ export function displayParameterPath(
nodeValuesRoot = get(nodeValues, 'parameters') as INodeParameters;
}
return displayParameter(resolvedNodeValues, parameter, node, nodeValuesRoot, displayKey);
return displayParameter(
resolvedNodeValues,
parameter,
node,
nodeTypeDescription,
nodeValuesRoot,
displayKey,
);
}
/**
@@ -698,6 +722,14 @@ export function getParameterResolveOrder(
return executionOrder;
}
export type GetNodeParametersOptions = {
onlySimpleTypes?: boolean;
dataIsResolved?: boolean; // If nodeValues are already fully resolved (so that all default values got added already)
nodeValuesRoot?: INodeParameters;
parentType?: string;
parameterDependencies?: IParameterDependencies;
};
/**
* Returns the node parameter values. Depending on the settings it either just returns the none
* default values or it applies all the default values.
@@ -706,9 +738,7 @@ export function getParameterResolveOrder(
* @param {INodeParameters} nodeValues The node parameter data
* @param {boolean} returnDefaults If default values get added or only none default values returned
* @param {boolean} returnNoneDisplayed If also values which should not be displayed should be returned
* @param {boolean} [onlySimpleTypes=false] If only simple types should be resolved
* @param {boolean} [dataIsResolved=false] If nodeValues are already fully resolved (so that all default values got added already)
* @param {INodeParameters} [nodeValuesRoot] The root node-parameter-data
* @param {GetNodeParametersOptions} options Optional properties
*/
// eslint-disable-next-line complexity
export function getNodeParameters(
@@ -717,12 +747,11 @@ export function getNodeParameters(
returnDefaults: boolean,
returnNoneDisplayed: boolean,
node: Pick<INode, 'typeVersion'> | null,
onlySimpleTypes = false,
dataIsResolved = false,
nodeValuesRoot?: INodeParameters,
parentType?: string,
parameterDependencies?: IParameterDependencies,
nodeTypeDescription: INodeTypeDescription | null,
options?: GetNodeParametersOptions,
): INodeParameters | null {
let { nodeValuesRoot, parameterDependencies } = options ?? {};
const { onlySimpleTypes = false, dataIsResolved = false, parentType } = options ?? {};
if (parameterDependencies === undefined) {
parameterDependencies = getParameterDependencies(nodePropertiesArray);
}
@@ -752,11 +781,14 @@ export function getNodeParameters(
true,
true,
node,
true,
true,
nodeTypeDescription,
{
onlySimpleTypes: true,
dataIsResolved: true,
nodeValuesRoot,
parentType,
parameterDependencies,
},
) as INodeParameters;
}
@@ -781,7 +813,13 @@ export function getNodeParameters(
if (
!returnNoneDisplayed &&
!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)
!displayParameter(
nodeValuesDisplayCheck,
nodeProperties,
node,
nodeTypeDescription,
nodeValuesRoot,
)
) {
if (!returnNoneDisplayed || !returnDefaults) {
continue;
@@ -792,7 +830,15 @@ export function getNodeParameters(
// Is a simple property so can be set as it is
if (duplicateParameterNames.includes(nodeProperties.name)) {
if (!displayParameter(nodeValuesDisplayCheck, nodeProperties, node, nodeValuesRoot)) {
if (
!displayParameter(
nodeValuesDisplayCheck,
nodeProperties,
node,
nodeTypeDescription,
nodeValuesRoot,
)
) {
continue;
}
}
@@ -871,10 +917,13 @@ export function getNodeParameters(
returnDefaults,
returnNoneDisplayed,
node,
false,
false,
nodeTypeDescription,
{
onlySimpleTypes: false,
dataIsResolved: false,
nodeValuesRoot,
nodeProperties.type,
parentType: nodeProperties.type,
},
);
if (tempNodeParameters !== null) {
@@ -944,10 +993,13 @@ export function getNodeParameters(
returnDefaults,
returnNoneDisplayed,
node,
false,
false,
nodeTypeDescription,
{
onlySimpleTypes: false,
dataIsResolved: false,
nodeValuesRoot,
nodeProperties.type,
parentType: nodeProperties.type,
},
);
if (tempValue !== null) {
tempArrayValue.push(tempValue);
@@ -972,10 +1024,13 @@ export function getNodeParameters(
returnDefaults,
returnNoneDisplayed,
node,
false,
false,
nodeTypeDescription,
{
onlySimpleTypes: false,
dataIsResolved: false,
nodeValuesRoot,
nodeProperties.type,
parentType: nodeProperties.type,
},
);
if (tempValue !== null) {
Object.assign(tempNodeParameters, tempValue);
@@ -1236,6 +1291,7 @@ export function getNodeOutputs(
export function getNodeParametersIssues(
nodePropertiesArray: INodeProperties[],
node: INode,
nodeTypeDescription: INodeTypeDescription | null,
pinDataNodeNames?: string[],
): INodeIssues | null {
const foundIssues: INodeIssues = {};
@@ -1247,7 +1303,13 @@ export function getNodeParametersIssues(
}
for (const nodeProperty of nodePropertiesArray) {
propertyIssues = getParameterIssues(nodeProperty, node.parameters, '', node);
propertyIssues = getParameterIssues(
nodeProperty,
node.parameters,
'',
node,
nodeTypeDescription,
);
mergeIssues(foundIssues, propertyIssues);
}
@@ -1456,9 +1518,16 @@ export function getParameterIssues(
nodeValues: INodeParameters,
path: string,
node: INode,
nodeTypeDescription: INodeTypeDescription | null,
): INodeIssues {
const foundIssues: INodeIssues = {};
const isDisplayed = displayParameterPath(nodeValues, nodeProperties, path, node);
const isDisplayed = displayParameterPath(
nodeValues,
nodeProperties,
path,
node,
nodeTypeDescription,
);
if (nodeProperties.required === true) {
if (isDisplayed) {
const value = getParameterValueByPath(nodeValues, nodeProperties.name, path);
@@ -1636,7 +1705,13 @@ export function getParameterIssues(
let propertyIssues;
for (const optionData of checkChildNodeProperties) {
propertyIssues = getParameterIssues(optionData.data, nodeValues, optionData.basePath, node);
propertyIssues = getParameterIssues(
optionData.data,
nodeValues,
optionData.basePath,
node,
nodeTypeDescription,
);
mergeIssues(foundIssues, propertyIssues);
}

View File

@@ -198,6 +198,7 @@ export function generateNodesGraph(
true,
false,
stickyNote,
stickyType.description,
) ?? {};
} catch {
// prevent node param resolution from failing graph generation
@@ -376,6 +377,7 @@ export function generateNodesGraph(
true,
false,
node,
nodeType.description,
);
if (nodeParameters) {

View File

@@ -112,6 +112,7 @@ export class Workflow {
true,
false,
node,
nodeType.description,
);
node.parameters = nodeParameters !== null ? nodeParameters : {};
}

View File

@@ -2166,6 +2166,7 @@ describe('NodeHelpers', () => {
false,
false,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsFalse);
@@ -2176,6 +2177,7 @@ describe('NodeHelpers', () => {
true,
false,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsTrue);
@@ -2186,6 +2188,7 @@ describe('NodeHelpers', () => {
false,
true,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsFalse);
@@ -2196,6 +2199,7 @@ describe('NodeHelpers', () => {
true,
true,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsTrue);
});

View File

@@ -16,6 +16,7 @@ import {
getParameterIssues,
isTriggerNode,
isExecutable,
displayParameter,
} from '@/NodeHelpers';
import type { Workflow } from '@/Workflow';
@@ -3420,6 +3421,7 @@ describe('NodeHelpers', () => {
false,
false,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsFalse);
@@ -3430,6 +3432,7 @@ describe('NodeHelpers', () => {
true,
false,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedFalse.defaultsTrue);
@@ -3440,6 +3443,7 @@ describe('NodeHelpers', () => {
false,
true,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsFalse);
@@ -3450,6 +3454,7 @@ describe('NodeHelpers', () => {
true,
true,
null,
null,
);
expect(result).toEqual(testData.output.noneDisplayedTrue.defaultsTrue);
});
@@ -4193,6 +4198,7 @@ describe('NodeHelpers', () => {
testData.input.nodeValues,
testData.input.path,
testData.input.node,
null,
);
expect(result).toEqual(testData.output);
});
@@ -4209,6 +4215,18 @@ describe('NodeHelpers', () => {
parameters: {},
};
const testNodeType: INodeTypeDescription = {
name: 'Test Node',
version: 0,
defaults: {},
inputs: [],
outputs: [],
properties: [],
displayName: '',
group: [],
description: '',
};
it('Should validate required dateTime parameters if empty string', () => {
const nodeProperties: INodeProperties = {
displayName: 'Date Time',
@@ -4221,7 +4239,7 @@ describe('NodeHelpers', () => {
testDateTime: '',
};
const result = getParameterIssues(nodeProperties, nodeValues, '', testNode);
const result = getParameterIssues(nodeProperties, nodeValues, '', testNode, null);
expect(result).toEqual({
parameters: {
@@ -4242,7 +4260,7 @@ describe('NodeHelpers', () => {
testDateTime: undefined,
};
const result = getParameterIssues(nodeProperties, nodeValues, '', testNode);
const result = getParameterIssues(nodeProperties, nodeValues, '', testNode, testNodeType);
expect(result).toEqual({
parameters: {
@@ -4513,4 +4531,393 @@ describe('NodeHelpers', () => {
});
}
});
describe('displayParameter', () => {
const testNode: INode = {
id: '12345',
name: 'Test Node',
typeVersion: 1,
type: 'n8n-nodes-base.testNode',
position: [1, 1],
parameters: {},
};
const testNodeType: INodeTypeDescription = {
name: 'Test Node',
version: 0,
defaults: {},
inputs: [],
outputs: [],
properties: [],
displayName: '',
group: [],
description: '',
};
const defaultTestInput = {
nodeValues: {},
parameter: {
displayName: 'Test Parameter',
name: 'testParameter',
type: 'string',
default: '',
} as INodeProperties,
node: testNode,
nodeTypeDescription: testNodeType,
nodeValuesRoot: undefined as undefined | INodeParameters,
displayKey: 'displayOptions' as 'displayOptions' | 'disabledOptions',
};
const tests: Array<[string, typeof defaultTestInput, boolean]> = [
['Should return true if no displayOptions are defined', { ...defaultTestInput }, true],
[
'Should return true if displayOptions.show conditions are met',
{
...defaultTestInput,
nodeValues: { condition: 'value1' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
condition: ['value1'],
},
},
},
},
true,
],
[
'Should return false if displayOptions.show conditions are not met',
{
...defaultTestInput,
nodeValues: { condition: 'value2' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
condition: ['value1'],
},
},
},
},
false,
],
[
'Should return false if displayOptions.hide conditions are met',
{
...defaultTestInput,
nodeValues: { condition: 'value1' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
hide: {
condition: ['value1'],
},
},
},
},
false,
],
[
'Should return true if displayOptions.hide conditions are not met',
{
...defaultTestInput,
nodeValues: { condition: 'value2' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
hide: {
condition: ['value1'],
},
},
},
},
true,
],
[
'Should return true if displayOptions.show and hide conditions are both met',
{
...defaultTestInput,
nodeValues: { condition: 'value1' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
condition: ['value1'],
},
hide: {
condition: ['value1'],
},
},
},
},
false, // Hide takes precedence over show
],
[
'Should return true if displayOptions.show conditions are met with multiple values',
{
...defaultTestInput,
nodeValues: { condition: 'value2' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
condition: ['value1', 'value2'],
},
},
},
},
true,
],
[
'Should return false if displayOptions.hide conditions are met with multiple values',
{
...defaultTestInput,
nodeValues: { condition: 'value2' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
hide: {
condition: ['value1', 'value2'],
},
},
},
},
false,
],
[
'Should return true if @tool is true in nodeTypeDescription of tool',
{
...defaultTestInput,
nodeTypeDescription: {
...testNodeType,
name: testNodeType.name + 'Tool',
},
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'@tool': [true],
},
},
},
},
true,
],
[
'Should return false if @tool is true in nodeTypeDescription of non-tool',
{
...defaultTestInput,
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'@tool': [true],
},
},
},
},
false,
],
[
'Should return true if @version condition is met',
{
...defaultTestInput,
node: {
...testNode,
typeVersion: 2,
},
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'@version': [
{
_cnd: {
gte: 2,
},
},
],
},
},
},
},
true,
],
[
'Should return false if @version condition is not met',
{
...defaultTestInput,
node: {
...testNode,
typeVersion: 1,
},
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'@version': [
{
_cnd: {
gte: 2,
},
},
],
},
},
},
},
false,
],
[
'Should return true if @tool and @version conditions are both met',
{
...defaultTestInput,
node: {
...testNode,
typeVersion: 2,
},
nodeTypeDescription: {
...testNodeType,
name: testNodeType.name + 'Tool',
},
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'@tool': [true],
'@version': [
{
_cnd: {
gte: 2,
},
},
],
},
},
},
},
true,
],
[
'Should return false if @tool is true but @version condition is not met',
{
...defaultTestInput,
node: {
...testNode,
typeVersion: 1,
},
nodeTypeDescription: {
...testNodeType,
name: testNodeType.name + 'Tool',
},
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'@tool': [true],
'@version': [
{
_cnd: {
gte: 2,
},
},
],
},
},
},
},
false,
],
[
'Should return true if no disabledOptions are defined',
{
...defaultTestInput,
displayKey: 'disabledOptions',
},
true,
],
[
'Should return false if disabledOptions.hide conditions are met',
{
...defaultTestInput,
nodeValues: { condition: 'value1' },
parameter: {
...defaultTestInput.parameter,
disabledOptions: {
hide: {
condition: ['value1'],
},
},
},
displayKey: 'disabledOptions',
},
false,
],
[
'Should return true if disabledOptions.hide conditions are not met',
{
...defaultTestInput,
nodeValues: { condition: 'value2' },
parameter: {
...defaultTestInput.parameter,
disabledOptions: {
hide: {
condition: ['value1'],
},
},
},
displayKey: 'disabledOptions',
},
true,
],
[
'Should return true if nodeValuesRoot contains a matching value for displayOptions.show',
{
...defaultTestInput,
nodeValues: {},
nodeValuesRoot: { condition: 'value1' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'/condition': ['value1'],
},
},
},
},
true,
],
[
'Should return false if nodeValuesRoot does not contain a matching value for displayOptions.show',
{
...defaultTestInput,
nodeValues: { condition: 'value1' },
nodeValuesRoot: { anotherKey: 'value1' },
parameter: {
...defaultTestInput.parameter,
displayOptions: {
show: {
'/condition': ['value1'],
},
},
},
},
false,
],
];
for (const [description, input, expected] of tests) {
test(description, () => {
const result = displayParameter(
input.nodeValues,
input.parameter,
input.node,
input.nodeTypeDescription,
input.nodeValuesRoot,
input.displayKey,
);
expect(result).toEqual(expected);
});
}
});
});