mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-16 17:46:45 +00:00
feat: Add sub-workflow extraction field utilities (no-changelog) (#14956)
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
import type { INode } from '../src/Interfaces';
|
||||
import {
|
||||
hasDotNotationBannedChar,
|
||||
backslashEscape,
|
||||
dollarEscape,
|
||||
applyAccessPatterns,
|
||||
extractReferencesInNodeExpressions,
|
||||
} from '../src/NodeReferenceParserUtils';
|
||||
|
||||
const makeNode = (name: string, expressions?: string[]) =>
|
||||
({
|
||||
parameters: Object.fromEntries(expressions?.map((x, i) => [`p${i}`, `={{ ${x} }}`]) ?? []),
|
||||
name,
|
||||
}) as INode;
|
||||
|
||||
describe('NodeReferenceParserUtils', () => {
|
||||
describe('hasDotNotationBannedChar', () => {
|
||||
it('should return true for strings with banned characters', () => {
|
||||
@@ -131,4 +139,514 @@ describe('NodeReferenceParserUtils', () => {
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
describe('extractReferencesInNodeExpressions', () => {
|
||||
let nodes: INode[] = [];
|
||||
let nodeNames: string[] = [];
|
||||
let startNodeName = 'Start';
|
||||
beforeEach(() => {
|
||||
nodes = [
|
||||
makeNode('B', ['$("A").item.json.myField']),
|
||||
makeNode('C', ['$("A").first().json.myField.anotherField']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C'];
|
||||
startNodeName = 'Start';
|
||||
});
|
||||
it('should extract used expressions', () => {
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField', '$("A").item.json.myField'],
|
||||
['myField_anotherField_firstItem', '$("A").first().json.myField.anotherField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: "={{ $('Start').item.json.myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
parameters: { p0: "={{ $('Start').first().json.myField_anotherField_firstItem }}" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should handle metadata functions', () => {
|
||||
nodes = [
|
||||
makeNode('B', ['$("A").isExecuted ? 1 : 2']),
|
||||
makeNode('C', ['someFunction($("D").params["resource"])']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C', 'D'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['A_isExecuted', '$("A").isExecuted'],
|
||||
['D_params', '$("D").params'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: "={{ $('Start').first().json.A_isExecuted ? 1 : 2 }}" },
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
parameters: { p0: '={{ someFunction($(\'Start\').first().json.D_params["resource"]) }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should not handle standalone node references', () => {
|
||||
nodes = [makeNode('B', ['$("D")'])];
|
||||
nodeNames = ['B', 'D'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName, 'B');
|
||||
expect([...result.variables.entries()]).toEqual([]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: '={{ $("D") }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not handle reference to non-existent node', () => {
|
||||
nodes = [makeNode('B', ['$("E").item.json.x'])];
|
||||
nodeNames = ['B'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName, 'B');
|
||||
expect([...result.variables.entries()]).toEqual([]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: '={{ $("E").item.json.x }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should not handle invalid node references', () => {
|
||||
nodes = [makeNode('B', ['$("D)'])];
|
||||
nodeNames = ['B', 'D'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: '={{ $("D) }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should not handle new fields on the node', () => {
|
||||
nodes = [makeNode('B', ['$("D").thisIsNotAField.json.x.y.z'])];
|
||||
nodeNames = ['B', 'D'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: '={{ $("D").thisIsNotAField.json.x.y.z }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should handle $json in graphInputNodeName only', () => {
|
||||
nodes = [makeNode('B', ['$json.a.b.c_d["e"]["f"]']), makeNode('C', ['$json.x.y.z'])];
|
||||
nodeNames = ['A', 'B', 'C'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName, 'B');
|
||||
expect([...result.variables.entries()]).toEqual([['a_b_c_d', '$json.a.b.c_d']]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: '={{ $json.a_b_c_d["e"]["f"] }}' },
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
parameters: { p0: '={{ $json.x.y.z }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should support different node accessor patterns', () => {
|
||||
nodes = [
|
||||
makeNode('N', ['$("A").item.json.myField']),
|
||||
makeNode('O', ['$node["B"].item.json.myField']),
|
||||
makeNode('P', ['$node.C.item.json.myField']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C', 'N', 'O', 'P'];
|
||||
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField', '$("A").item.json.myField'],
|
||||
['B_myField', '$node["B"].item.json.myField'],
|
||||
['C_myField', '$node.C.item.json.myField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'N',
|
||||
parameters: { p0: "={{ $('Start').item.json.myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'O',
|
||||
parameters: { p0: "={{ $('Start').item.json.B_myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'P',
|
||||
parameters: { p0: "={{ $('Start').item.json.C_myField }}" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should handle simple name clashes', () => {
|
||||
nodes = [
|
||||
makeNode('B', ['$("A").item.json.myField']),
|
||||
makeNode('C', ['$("D").item.json.myField']),
|
||||
makeNode('E', ['$("F").item.json.myField']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C', 'D', 'E', 'F'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField', '$("A").item.json.myField'],
|
||||
['D_myField', '$("D").item.json.myField'],
|
||||
['F_myField', '$("F").item.json.myField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: "={{ $('Start').item.json.myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
parameters: { p0: "={{ $('Start').item.json.D_myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'E',
|
||||
parameters: { p0: "={{ $('Start').item.json.F_myField }}" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle complex name clashes', () => {
|
||||
nodes = [
|
||||
makeNode('F', ['$("A").item.json.myField']),
|
||||
makeNode('B', ['$("A").item.json.Node_Name_With_Gap_myField']),
|
||||
makeNode('C', ['$("D").item.json.Node_Name_With_Gap_myField']),
|
||||
makeNode('E', ['$("Node_Name_With_Gap").item.json.myField']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C', 'D', 'E', 'F', 'Node_Name_With_Gap'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField', '$("A").item.json.myField'],
|
||||
['Node_Name_With_Gap_myField', '$("A").item.json.Node_Name_With_Gap_myField'],
|
||||
['D_Node_Name_With_Gap_myField', '$("D").item.json.Node_Name_With_Gap_myField'],
|
||||
// This is the `myField` variable from node 'E', referencing $("Node_Name_With_Gap").item.json.myField
|
||||
// It first has a clash with A.myField, requiring its node name to come attached
|
||||
// And then has _1 because it clashes B.Node_Name_With_Gap_myField
|
||||
['Node_Name_With_Gap_myField_1', '$("Node_Name_With_Gap").item.json.myField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{ name: 'F', parameters: { p0: "={{ $('Start').item.json.myField }}" } },
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: "={{ $('Start').item.json.Node_Name_With_Gap_myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
parameters: { p0: "={{ $('Start').item.json.D_Node_Name_With_Gap_myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'E',
|
||||
parameters: { p0: "={{ $('Start').item.json.Node_Name_With_Gap_myField_1 }}" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle code node', () => {
|
||||
nodes = [
|
||||
{
|
||||
parameters: {
|
||||
jsCode:
|
||||
"for (const item of $input.all()) {\n item.json.myNewField = $('DebugHelper').first().json.uid;\n}\n\nreturn $input.all();",
|
||||
},
|
||||
type: 'n8n-nodes-base.code',
|
||||
typeVersion: 2,
|
||||
position: [660, 0],
|
||||
id: 'c9de02d0-982a-4f8c-9af7-93f63795aa9b',
|
||||
name: 'Code',
|
||||
},
|
||||
];
|
||||
nodeNames = ['DebugHelper', 'Code'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['uid_firstItem', "$('DebugHelper').first().json.uid"],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
parameters: {
|
||||
jsCode:
|
||||
"for (const item of $input.all()) {\n item.json.myNewField = $('Start').first().json.uid_firstItem;\n}\n\nreturn $input.all();",
|
||||
},
|
||||
type: 'n8n-nodes-base.code',
|
||||
typeVersion: 2,
|
||||
position: [660, 0],
|
||||
id: 'c9de02d0-982a-4f8c-9af7-93f63795aa9b',
|
||||
name: 'Code',
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should not extract expression referencing node in subGraph', () => {
|
||||
nodes = [
|
||||
makeNode('B', ['$("A").item.json.myField']),
|
||||
makeNode('C', ['$("B").first().json.myField.anotherField']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([['myField', '$("A").item.json.myField']]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: { p0: "={{ $('Start').item.json.myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'C',
|
||||
parameters: { p0: '={{ $("B").first().json.myField.anotherField }}' },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should throw if node name clashes with start name', () => {
|
||||
nodes = [makeNode('Start', ['$("A").item.json.myField'])];
|
||||
nodeNames = ['A', 'Start'];
|
||||
expect(() => extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName)).toThrow();
|
||||
});
|
||||
|
||||
it('should support custom Start node name', () => {
|
||||
nodes = [makeNode('Start', ['$("A").item.json.myField'])];
|
||||
nodeNames = ['A', 'Start'];
|
||||
startNodeName = 'A different start name';
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([['myField', '$("A").item.json.myField']]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'Start',
|
||||
parameters: { p0: "={{ $('A different start name').item.json.myField }}" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should throw if called with node in subgraph whose name is not in nodeNames list', () => {
|
||||
nodes = [makeNode('B', ['$("A").item.json.myField'])];
|
||||
nodeNames = ['A'];
|
||||
expect(() => extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName)).toThrow();
|
||||
});
|
||||
it('handles multiple expressions referencing different nodes in the same string', () => {
|
||||
nodes = [makeNode('B', ['$("A").item.json.myField + $("C").item.json.anotherField'])];
|
||||
nodeNames = ['A', 'B', 'C'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['anotherField', '$("C").item.json.anotherField'],
|
||||
['myField', '$("A").item.json.myField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').item.json.myField + $('Start').item.json.anotherField }}",
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('handles multiple expressions referencing different nested bits of the same field', () => {
|
||||
nodes = [
|
||||
makeNode('B', [
|
||||
'$("A").item.json.myField.nestedField',
|
||||
'$("A").item.json.myField.anotherNestedField',
|
||||
'$("A").item.json.myField.anotherNestedField.x.y.z',
|
||||
]),
|
||||
];
|
||||
nodeNames = ['A', 'B'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField_nestedField', '$("A").item.json.myField.nestedField'],
|
||||
['myField_anotherNestedField', '$("A").item.json.myField.anotherNestedField'],
|
||||
['myField_anotherNestedField_x_y_z', '$("A").item.json.myField.anotherNestedField.x.y.z'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').item.json.myField_nestedField }}",
|
||||
p1: "={{ $('Start').item.json.myField_anotherNestedField }}",
|
||||
p2: "={{ $('Start').item.json.myField_anotherNestedField_x_y_z }}",
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('handles first(), last(), all() and items at the same time', () => {
|
||||
nodes = [
|
||||
makeNode('B', [
|
||||
'$("A").first().json.myField',
|
||||
'$("A").last().json.myField',
|
||||
'$("A").all().json.myField',
|
||||
'$("A").item.json.myField',
|
||||
]),
|
||||
];
|
||||
nodeNames = ['A', 'B'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField_firstItem', '$("A").first().json.myField'],
|
||||
['myField_lastItem', '$("A").last().json.myField'],
|
||||
['myField_allItems', '$("A").all().json.myField'],
|
||||
['myField', '$("A").item.json.myField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').first().json.myField_firstItem }}",
|
||||
p1: "={{ $('Start').last().json.myField_lastItem }}",
|
||||
p2: "={{ $('Start').first().json.myField_allItems }}",
|
||||
p3: "={{ $('Start').item.json.myField }}",
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('handles supported itemMatching examples', () => {
|
||||
nodes = [
|
||||
makeNode('B', [
|
||||
'$("A").itemMatching(0).json.myField',
|
||||
'$("A").itemMatching(1).json.myField',
|
||||
'$("C").itemMatching(1).json.myField',
|
||||
'$("A").itemMatching(20).json.myField',
|
||||
]),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField_itemMatching_0', '$("A").itemMatching(0).json.myField'],
|
||||
['myField_itemMatching_1', '$("A").itemMatching(1).json.myField'],
|
||||
['C_myField_itemMatching_1', '$("C").itemMatching(1).json.myField'],
|
||||
['myField_itemMatching_20', '$("A").itemMatching(20).json.myField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').itemMatching(0).json.myField_itemMatching_0 }}",
|
||||
p1: "={{ $('Start').itemMatching(1).json.myField_itemMatching_1 }}",
|
||||
p2: "={{ $('Start').itemMatching(1).json.C_myField_itemMatching_1 }}",
|
||||
p3: "={{ $('Start').itemMatching(20).json.myField_itemMatching_20 }}",
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('does not throw for complex itemMatching example', () => {
|
||||
nodes = [
|
||||
makeNode('B', [
|
||||
'$("A").itemMatching(Math.PI).json.myField',
|
||||
'$("A").itemMatching(eval("const fib = (n) => n < 2 ? 1 : (fib(n - 1) + fib(n-2)); fib(15)")).json.anotherField',
|
||||
'$("A").itemMatching($("A").itemMatch(1).json.myField).json.myField',
|
||||
]),
|
||||
];
|
||||
nodeNames = ['A', 'B'];
|
||||
expect(() =>
|
||||
extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName),
|
||||
).not.toThrow();
|
||||
});
|
||||
it('should handle multiple expressions', () => {
|
||||
nodes = [
|
||||
makeNode('B', ['$("A").item.json.myField', '$("C").item.json.anotherField']),
|
||||
makeNode('D', ['$("A").item.json.myField', '$("B").item.json.someField']),
|
||||
];
|
||||
nodeNames = ['A', 'B', 'C', 'D'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField', '$("A").item.json.myField'],
|
||||
['anotherField', '$("C").item.json.anotherField'],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'B',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').item.json.myField }}",
|
||||
p1: "={{ $('Start').item.json.anotherField }}",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'D',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').item.json.myField }}",
|
||||
p1: '={{ $("B").item.json.someField }}',
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should support handle calls to normal js functions on the data accessor', () => {
|
||||
nodes = [makeNode('A', ['$("B B").first().toJsonObject().randomJSFunction()'])];
|
||||
nodeNames = ['A', 'B B'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([['B_B_firstItem', '$("B B").first()']]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'A',
|
||||
parameters: {
|
||||
p0: "={{ $('Start').first().json.B_B_firstItem.toJsonObject().randomJSFunction() }}",
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should support handle spaces and special characters in nodeNames', () => {
|
||||
nodes = [
|
||||
makeNode('a_=-9-0!@#!%^$%&*(', ['$("A").item.json.myField']),
|
||||
makeNode('A node with spaces', [
|
||||
'$("A \\" |[w.e,i,r$d]| `\' Ñode \\$\\( Name \\)").item.json.myField',
|
||||
]),
|
||||
];
|
||||
nodeNames = [
|
||||
'A',
|
||||
'A node with spaces',
|
||||
'A \\" |[w.e,i,r$d]| `\' Ñode \\$\\( Name \\)',
|
||||
'a_=-9-0!@#!%^$%&*(',
|
||||
];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([
|
||||
['myField', '$("A").item.json.myField'],
|
||||
[
|
||||
'A__weir$d__ode__$_Name__myField',
|
||||
'$("A \\" |[w.e,i,r$d]| `\' Ñode \\$\\( Name \\)").item.json.myField',
|
||||
],
|
||||
]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
name: 'a_=-9-0!@#!%^$%&*(',
|
||||
parameters: { p0: "={{ $('Start').item.json.myField }}" },
|
||||
},
|
||||
{
|
||||
name: 'A node with spaces',
|
||||
parameters: { p0: "={{ $('Start').item.json.A__weir$d__ode__$_Name__myField }}" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
it('should carry over unrelated properties', () => {
|
||||
nodes = [
|
||||
{
|
||||
parameters: {
|
||||
a: 3,
|
||||
b: { c: 4, d: true },
|
||||
d: 'hello',
|
||||
e: "={{ $('goodbye').item.json.f }}",
|
||||
},
|
||||
name: 'A',
|
||||
} as unknown as INode,
|
||||
];
|
||||
nodeNames = ['A', 'goodbye'];
|
||||
const result = extractReferencesInNodeExpressions(nodes, nodeNames, startNodeName);
|
||||
expect([...result.variables.entries()]).toEqual([['f', "$('goodbye').item.json.f"]]);
|
||||
expect(result.nodes).toEqual([
|
||||
{
|
||||
parameters: {
|
||||
a: 3,
|
||||
b: { c: 4, d: true },
|
||||
d: 'hello',
|
||||
e: "={{ $('Start').item.json.f }}",
|
||||
},
|
||||
name: 'A',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user